Updated unrar to version 5.1.7
parent
0ccc0f4dae
commit
bfb319988f
|
@ -111,7 +111,6 @@
|
|||
8359007517FEF40E0060F3ED /* getbits.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8359FFE917FEF40E0060F3ED /* getbits.cpp */; };
|
||||
8359007617FEF40E0060F3ED /* getbits.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 8359FFEA17FEF40E0060F3ED /* getbits.hpp */; };
|
||||
8359007717FEF40E0060F3ED /* headers.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 8359FFEB17FEF40E0060F3ED /* headers.hpp */; };
|
||||
8359007917FEF40E0060F3ED /* model.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8359FFED17FEF40E0060F3ED /* model.cpp */; };
|
||||
8359007A17FEF40E0060F3ED /* model.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 8359FFEE17FEF40E0060F3ED /* model.hpp */; };
|
||||
8359007B17FEF40E0060F3ED /* rar.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 8359FFEF17FEF40E0060F3ED /* rar.hpp */; };
|
||||
8359007C17FEF40E0060F3ED /* rarvm.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8359FFF017FEF40E0060F3ED /* rarvm.cpp */; };
|
||||
|
@ -119,20 +118,29 @@
|
|||
8359007E17FEF40E0060F3ED /* rarvmtbl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8359FFF217FEF40E0060F3ED /* rarvmtbl.cpp */; };
|
||||
8359007F17FEF40E0060F3ED /* rawread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8359FFF317FEF40E0060F3ED /* rawread.cpp */; };
|
||||
8359008017FEF40E0060F3ED /* rawread.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 8359FFF417FEF40E0060F3ED /* rawread.hpp */; };
|
||||
8359008217FEF40E0060F3ED /* suballoc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8359FFF617FEF40E0060F3ED /* suballoc.cpp */; };
|
||||
8359008317FEF40E0060F3ED /* suballoc.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 8359FFF717FEF40E0060F3ED /* suballoc.hpp */; };
|
||||
8359008517FEF40E0060F3ED /* unicode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8359FFF917FEF40E0060F3ED /* unicode.cpp */; };
|
||||
8359008617FEF40E0060F3ED /* unicode.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 8359FFFA17FEF40E0060F3ED /* unicode.hpp */; };
|
||||
8359008717FEF40E0060F3ED /* unpack.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8359FFFB17FEF40E0060F3ED /* unpack.cpp */; };
|
||||
8359008817FEF40E0060F3ED /* unpack.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 8359FFFC17FEF40E0060F3ED /* unpack.hpp */; };
|
||||
8359008917FEF40E0060F3ED /* unpack15.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8359FFFD17FEF40E0060F3ED /* unpack15.cpp */; };
|
||||
8359008A17FEF40E0060F3ED /* unpack20.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8359FFFE17FEF40E0060F3ED /* unpack20.cpp */; };
|
||||
8359008B17FEF40E0060F3ED /* unrar.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8359FFFF17FEF40E0060F3ED /* unrar.cpp */; };
|
||||
8359008C17FEF40E0060F3ED /* unrar.h in Headers */ = {isa = PBXBuildFile; fileRef = 8359000017FEF40E0060F3ED /* unrar.h */; };
|
||||
8359008D17FEF40E0060F3ED /* unrar_misc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8359000117FEF40E0060F3ED /* unrar_misc.cpp */; };
|
||||
8359009117FEF5830060F3ED /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 8359009017FEF5830060F3ED /* libz.dylib */; };
|
||||
8359009F17FF073E0060F3ED /* 7zStream.c in Sources */ = {isa = PBXBuildFile; fileRef = 8359009E17FF073E0060F3ED /* 7zStream.c */; };
|
||||
8359FF4A17FEF39F0060F3ED /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 8359FF4817FEF39F0060F3ED /* InfoPlist.strings */; };
|
||||
83C2109719CD81F50093C461 /* headers.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 83C2108E19CD81F50093C461 /* headers.cpp */; };
|
||||
83C2109819CD81F50093C461 /* headers5.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 83C2108F19CD81F50093C461 /* headers5.hpp */; };
|
||||
83C2109B19CD88A30093C461 /* secpassword.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 83C2109A19CD88A30093C461 /* secpassword.cpp */; };
|
||||
83C210A219CD89C70093C461 /* hash.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 83C2109C19CD89C70093C461 /* hash.cpp */; };
|
||||
83C210A419CD89C70093C461 /* blake2s.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 83C2109E19CD89C70093C461 /* blake2s.cpp */; };
|
||||
83C210A519CD89C70093C461 /* blake2s.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 83C2109F19CD89C70093C461 /* blake2s.hpp */; };
|
||||
83C210A719CD89C70093C461 /* hash.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 83C210A119CD89C70093C461 /* hash.hpp */; };
|
||||
83C210AA19CD8F8F0093C461 /* strfn.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 83C210A819CD8F8F0093C461 /* strfn.cpp */; };
|
||||
83C210AB19CD8F8F0093C461 /* strfn.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 83C210A919CD8F8F0093C461 /* strfn.hpp */; };
|
||||
83C210AD19CD92960093C461 /* pathfn.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 83C210AC19CD92960093C461 /* pathfn.cpp */; };
|
||||
83C210B019CD97DB0093C461 /* timefn.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 83C210AE19CD97DB0093C461 /* timefn.cpp */; };
|
||||
83C210B119CD97DB0093C461 /* timefn.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 83C210AF19CD97DB0093C461 /* timefn.hpp */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
|
@ -247,7 +255,6 @@
|
|||
8359FFE917FEF40E0060F3ED /* getbits.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = getbits.cpp; sourceTree = "<group>"; };
|
||||
8359FFEA17FEF40E0060F3ED /* getbits.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = getbits.hpp; sourceTree = "<group>"; };
|
||||
8359FFEB17FEF40E0060F3ED /* headers.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = headers.hpp; sourceTree = "<group>"; };
|
||||
8359FFED17FEF40E0060F3ED /* model.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = model.cpp; sourceTree = "<group>"; };
|
||||
8359FFEE17FEF40E0060F3ED /* model.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = model.hpp; sourceTree = "<group>"; };
|
||||
8359FFEF17FEF40E0060F3ED /* rar.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = rar.hpp; sourceTree = "<group>"; };
|
||||
8359FFF017FEF40E0060F3ED /* rarvm.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = rarvm.cpp; sourceTree = "<group>"; };
|
||||
|
@ -255,15 +262,24 @@
|
|||
8359FFF217FEF40E0060F3ED /* rarvmtbl.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = rarvmtbl.cpp; sourceTree = "<group>"; };
|
||||
8359FFF317FEF40E0060F3ED /* rawread.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = rawread.cpp; sourceTree = "<group>"; };
|
||||
8359FFF417FEF40E0060F3ED /* rawread.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = rawread.hpp; sourceTree = "<group>"; };
|
||||
8359FFF617FEF40E0060F3ED /* suballoc.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = suballoc.cpp; sourceTree = "<group>"; };
|
||||
8359FFF717FEF40E0060F3ED /* suballoc.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = suballoc.hpp; sourceTree = "<group>"; };
|
||||
8359FFF917FEF40E0060F3ED /* unicode.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = unicode.cpp; sourceTree = "<group>"; };
|
||||
8359FFFA17FEF40E0060F3ED /* unicode.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = unicode.hpp; sourceTree = "<group>"; };
|
||||
8359FFFB17FEF40E0060F3ED /* unpack.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = unpack.cpp; sourceTree = "<group>"; };
|
||||
8359FFFC17FEF40E0060F3ED /* unpack.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = unpack.hpp; sourceTree = "<group>"; };
|
||||
8359FFFD17FEF40E0060F3ED /* unpack15.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = unpack15.cpp; sourceTree = "<group>"; };
|
||||
8359FFFE17FEF40E0060F3ED /* unpack20.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = unpack20.cpp; sourceTree = "<group>"; };
|
||||
8359FFFF17FEF40E0060F3ED /* unrar.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = unrar.cpp; sourceTree = "<group>"; };
|
||||
83C2108E19CD81F50093C461 /* headers.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = headers.cpp; sourceTree = "<group>"; };
|
||||
83C2108F19CD81F50093C461 /* headers5.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = headers5.hpp; sourceTree = "<group>"; };
|
||||
83C2109A19CD88A30093C461 /* secpassword.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = secpassword.cpp; sourceTree = "<group>"; };
|
||||
83C2109C19CD89C70093C461 /* hash.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = hash.cpp; sourceTree = "<group>"; };
|
||||
83C2109E19CD89C70093C461 /* blake2s.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = blake2s.cpp; sourceTree = "<group>"; };
|
||||
83C2109F19CD89C70093C461 /* blake2s.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = blake2s.hpp; sourceTree = "<group>"; };
|
||||
83C210A119CD89C70093C461 /* hash.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = hash.hpp; sourceTree = "<group>"; };
|
||||
83C210A819CD8F8F0093C461 /* strfn.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = strfn.cpp; sourceTree = "<group>"; };
|
||||
83C210A919CD8F8F0093C461 /* strfn.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = strfn.hpp; sourceTree = "<group>"; };
|
||||
83C210AC19CD92960093C461 /* pathfn.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = pathfn.cpp; sourceTree = "<group>"; };
|
||||
83C210AE19CD97DB0093C461 /* timefn.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = timefn.cpp; sourceTree = "<group>"; };
|
||||
83C210AF19CD97DB0093C461 /* timefn.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = timefn.hpp; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
|
@ -447,6 +463,18 @@
|
|||
8359FFDC17FEF40E0060F3ED /* unrar */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
83C210AE19CD97DB0093C461 /* timefn.cpp */,
|
||||
83C210AF19CD97DB0093C461 /* timefn.hpp */,
|
||||
83C210AC19CD92960093C461 /* pathfn.cpp */,
|
||||
83C210A819CD8F8F0093C461 /* strfn.cpp */,
|
||||
83C210A919CD8F8F0093C461 /* strfn.hpp */,
|
||||
83C2109C19CD89C70093C461 /* hash.cpp */,
|
||||
83C2109E19CD89C70093C461 /* blake2s.cpp */,
|
||||
83C2109F19CD89C70093C461 /* blake2s.hpp */,
|
||||
83C210A119CD89C70093C461 /* hash.hpp */,
|
||||
83C2109A19CD88A30093C461 /* secpassword.cpp */,
|
||||
83C2108E19CD81F50093C461 /* headers.cpp */,
|
||||
83C2108F19CD81F50093C461 /* headers5.hpp */,
|
||||
8359FFDD17FEF40E0060F3ED /* archive.cpp */,
|
||||
8359FFDE17FEF40E0060F3ED /* archive.hpp */,
|
||||
8359FFDF17FEF40E0060F3ED /* arcread.cpp */,
|
||||
|
@ -461,7 +489,6 @@
|
|||
8359FFE917FEF40E0060F3ED /* getbits.cpp */,
|
||||
8359FFEA17FEF40E0060F3ED /* getbits.hpp */,
|
||||
8359FFEB17FEF40E0060F3ED /* headers.hpp */,
|
||||
8359FFED17FEF40E0060F3ED /* model.cpp */,
|
||||
8359FFEE17FEF40E0060F3ED /* model.hpp */,
|
||||
8359FFEF17FEF40E0060F3ED /* rar.hpp */,
|
||||
8359FFF017FEF40E0060F3ED /* rarvm.cpp */,
|
||||
|
@ -469,14 +496,11 @@
|
|||
8359FFF217FEF40E0060F3ED /* rarvmtbl.cpp */,
|
||||
8359FFF317FEF40E0060F3ED /* rawread.cpp */,
|
||||
8359FFF417FEF40E0060F3ED /* rawread.hpp */,
|
||||
8359FFF617FEF40E0060F3ED /* suballoc.cpp */,
|
||||
8359FFF717FEF40E0060F3ED /* suballoc.hpp */,
|
||||
8359FFF917FEF40E0060F3ED /* unicode.cpp */,
|
||||
8359FFFA17FEF40E0060F3ED /* unicode.hpp */,
|
||||
8359FFFB17FEF40E0060F3ED /* unpack.cpp */,
|
||||
8359FFFC17FEF40E0060F3ED /* unpack.hpp */,
|
||||
8359FFFD17FEF40E0060F3ED /* unpack15.cpp */,
|
||||
8359FFFE17FEF40E0060F3ED /* unpack20.cpp */,
|
||||
8359FFFF17FEF40E0060F3ED /* unrar.cpp */,
|
||||
8359000017FEF40E0060F3ED /* unrar.h */,
|
||||
8359000117FEF40E0060F3ED /* unrar_misc.cpp */,
|
||||
|
@ -495,6 +519,8 @@
|
|||
8359005517FEF40E0060F3ED /* blargg_errors.h in Headers */,
|
||||
8359003417FEF40E0060F3ED /* Lzma2Enc.h in Headers */,
|
||||
8359008817FEF40E0060F3ED /* unpack.hpp in Headers */,
|
||||
83C210AB19CD8F8F0093C461 /* strfn.hpp in Headers */,
|
||||
83C210A719CD89C70093C461 /* hash.hpp in Headers */,
|
||||
8359001817FEF40E0060F3ED /* 7zIn.h in Headers */,
|
||||
8359003D17FEF40E0060F3ED /* LzmaLib.h in Headers */,
|
||||
8359001417FEF40E0060F3ED /* 7zFile.h in Headers */,
|
||||
|
@ -524,7 +550,9 @@
|
|||
8359007617FEF40E0060F3ED /* getbits.hpp in Headers */,
|
||||
8359001A17FEF40E0060F3ED /* 7zItem.h in Headers */,
|
||||
8359007B17FEF40E0060F3ED /* rar.hpp in Headers */,
|
||||
83C210B119CD97DB0093C461 /* timefn.hpp in Headers */,
|
||||
8359004917FEF40E0060F3ED /* RotateDefs.h in Headers */,
|
||||
83C2109819CD81F50093C461 /* headers5.hpp in Headers */,
|
||||
8359000417FEF40E0060F3ED /* 7z.h in Headers */,
|
||||
8359004A17FEF40E0060F3ED /* Threads.h in Headers */,
|
||||
8359006417FEF40E0060F3ED /* Zip7_Extractor.h in Headers */,
|
||||
|
@ -539,6 +567,7 @@
|
|||
8359008017FEF40E0060F3ED /* rawread.hpp in Headers */,
|
||||
8359008317FEF40E0060F3ED /* suballoc.hpp in Headers */,
|
||||
8359005817FEF40E0060F3ED /* Data_Reader.h in Headers */,
|
||||
83C210A519CD89C70093C461 /* blake2s.hpp in Headers */,
|
||||
8359007D17FEF40E0060F3ED /* rarvm.hpp in Headers */,
|
||||
8359005217FEF40E0060F3ED /* blargg_config.h in Headers */,
|
||||
8359006017FEF40E0060F3ED /* Gzip_Reader.h in Headers */,
|
||||
|
@ -636,7 +665,6 @@
|
|||
8359003A17FEF40E0060F3ED /* LzmaEnc.c in Sources */,
|
||||
8359001E17FEF40E0060F3ED /* Alloc.c in Sources */,
|
||||
8359008D17FEF40E0060F3ED /* unrar_misc.cpp in Sources */,
|
||||
8359007917FEF40E0060F3ED /* model.cpp in Sources */,
|
||||
8359007117FEF40E0060F3ED /* crc.cpp in Sources */,
|
||||
8359003717FEF40E0060F3ED /* Lzma86Enc.c in Sources */,
|
||||
8359006917FEF40E0060F3ED /* archive.cpp in Sources */,
|
||||
|
@ -645,11 +673,12 @@
|
|||
8359007F17FEF40E0060F3ED /* rawread.cpp in Sources */,
|
||||
8359000717FEF40E0060F3ED /* 7zBuf.c in Sources */,
|
||||
8359002917FEF40E0060F3ED /* Delta.c in Sources */,
|
||||
83C2109719CD81F50093C461 /* headers.cpp in Sources */,
|
||||
8359005017FEF40E0060F3ED /* blargg_common.cpp in Sources */,
|
||||
8359005F17FEF40E0060F3ED /* Gzip_Reader.cpp in Sources */,
|
||||
83C210AD19CD92960093C461 /* pathfn.cpp in Sources */,
|
||||
8359002D17FEF40E0060F3ED /* LzFindMt.c in Sources */,
|
||||
8359000B17FEF40E0060F3ED /* 7zCrc.c in Sources */,
|
||||
8359008917FEF40E0060F3ED /* unpack15.cpp in Sources */,
|
||||
8359009F17FF073E0060F3ED /* 7zStream.c in Sources */,
|
||||
8359000917FEF40E0060F3ED /* 7zBuf2.c in Sources */,
|
||||
8359002517FEF40E0060F3ED /* BraIA64.c in Sources */,
|
||||
|
@ -661,7 +690,7 @@
|
|||
8359006117FEF40E0060F3ED /* Rar_Extractor.cpp in Sources */,
|
||||
8359003F17FEF40E0060F3ED /* MtCoder.c in Sources */,
|
||||
8359003317FEF40E0060F3ED /* Lzma2Enc.c in Sources */,
|
||||
8359008217FEF40E0060F3ED /* suballoc.cpp in Sources */,
|
||||
83C210AA19CD8F8F0093C461 /* strfn.cpp in Sources */,
|
||||
8359003617FEF40E0060F3ED /* Lzma86Dec.c in Sources */,
|
||||
8359002217FEF40E0060F3ED /* Bra.c in Sources */,
|
||||
8359000517FEF40E0060F3ED /* 7zAlloc.c in Sources */,
|
||||
|
@ -672,15 +701,18 @@
|
|||
8359003117FEF40E0060F3ED /* Lzma2Dec.c in Sources */,
|
||||
8359007217FEF40E0060F3ED /* encname.cpp in Sources */,
|
||||
8359004117FEF40E0060F3ED /* Threads.c in Sources */,
|
||||
83C210B019CD97DB0093C461 /* timefn.cpp in Sources */,
|
||||
8359008717FEF40E0060F3ED /* unpack.cpp in Sources */,
|
||||
8359003C17FEF40E0060F3ED /* LzmaLib.c in Sources */,
|
||||
8359005917FEF40E0060F3ED /* fex.cpp in Sources */,
|
||||
83C2109B19CD88A30093C461 /* secpassword.cpp in Sources */,
|
||||
83C210A219CD89C70093C461 /* hash.cpp in Sources */,
|
||||
8359004717FEF40E0060F3ED /* Ppmd7Enc.c in Sources */,
|
||||
8359008A17FEF40E0060F3ED /* unpack20.cpp in Sources */,
|
||||
8359004E17FEF40E0060F3ED /* Binary_Extractor.cpp in Sources */,
|
||||
8359007417FEF40E0060F3ED /* extract.cpp in Sources */,
|
||||
8359006517FEF40E0060F3ED /* Zip_Extractor.cpp in Sources */,
|
||||
8359002717FEF40E0060F3ED /* CpuArch.c in Sources */,
|
||||
83C210A419CD89C70093C461 /* blake2s.cpp in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -721,6 +753,7 @@
|
|||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
_UNIX,
|
||||
);
|
||||
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
|
@ -754,6 +787,7 @@
|
|||
ENABLE_NS_ASSERTIONS = NO;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = _UNIX;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
|
|
|
@ -0,0 +1,92 @@
|
|||
ACKNOWLEDGMENTS
|
||||
|
||||
* We used "Screaming Fast Galois Field Arithmetic Using Intel
|
||||
SIMD Instructions" paper by James S. Plank, Kevin M. Greenan
|
||||
and Ethan L. Miller to improve Reed-Solomon coding performance.
|
||||
Also we are grateful to Artem Drobanov and Bulat Ziganshin
|
||||
for samples and ideas allowed to make Reed-Solomon coding
|
||||
more efficient.
|
||||
|
||||
* RAR text compression algorithm is based on Dmitry Shkarin PPMII
|
||||
and Dmitry Subbotin carryless rangecoder public domain source code.
|
||||
You may find it in ftp.elf.stuba.sk/pub/pc/pack.
|
||||
|
||||
* RAR encryption includes parts of code from Szymon Stefanek
|
||||
and Brian Gladman AES implementations also as Steve Reid SHA-1 source.
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
Copyright (c) 2002, Dr Brian Gladman < >, Worcester, UK.
|
||||
All rights reserved.
|
||||
|
||||
LICENSE TERMS
|
||||
|
||||
The free distribution and use of this software in both source and binary
|
||||
form is allowed (with or without changes) provided that:
|
||||
|
||||
1. distributions of this source code include the above copyright
|
||||
notice, this list of conditions and the following disclaimer;
|
||||
|
||||
2. distributions in binary form include the above copyright
|
||||
notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other associated materials;
|
||||
|
||||
3. the copyright holder's name is not used to endorse products
|
||||
built using this software without specific written permission.
|
||||
|
||||
ALTERNATIVELY, provided that this notice is retained in full, this product
|
||||
may be distributed under the terms of the GNU General Public License (GPL),
|
||||
in which case the provisions of the GPL apply INSTEAD OF those given above.
|
||||
|
||||
DISCLAIMER
|
||||
|
||||
This software is provided 'as is' with no explicit or implied warranties
|
||||
in respect of its properties, including, but not limited to, correctness
|
||||
and/or fitness for purpose.
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
Source code of this package also as other cryptographic technology
|
||||
and computing project related links are available on Brian Gladman's
|
||||
web site: http://www.gladman.me.uk
|
||||
|
||||
* RAR uses CRC32 function based on Intel Slicing-by-8 algorithm.
|
||||
Original Intel Slicing-by-8 code is available here:
|
||||
|
||||
http://sourceforge.net/projects/slicing-by-8/
|
||||
|
||||
Original Intel Slicing-by-8 code is licensed under BSD License
|
||||
available at http://www.opensource.org/licenses/bsd-license.html
|
||||
|
||||
Copyright (c) 2004-2006 Intel Corporation.
|
||||
All Rights Reserved
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with
|
||||
the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGE.
|
||||
|
||||
* RAR archives may optionally include BLAKE2sp hash ( https://blake2.net ),
|
||||
designed by Jean-Philippe Aumasson, Samuel Neves, Zooko Wilcox-O'Hearn
|
||||
and Christian Winnerlein.
|
||||
|
||||
* Useful hints provided by Alexander Khoroshev and Bulat Ziganshin allowed
|
||||
to significantly improve RAR compression and speed.
|
|
@ -5,90 +5,87 @@
|
|||
|
||||
Archive::Archive() : Raw( this )
|
||||
{
|
||||
OldFormat=false;
|
||||
Format=RARFMT15;
|
||||
Solid=false;
|
||||
|
||||
CurBlockPos=0;
|
||||
NextBlockPos=0;
|
||||
|
||||
memset(&NewMhd,0,sizeof(NewMhd));
|
||||
NewMhd.HeadType=MAIN_HEAD;
|
||||
NewMhd.HeadSize=SIZEOF_NEWMHD;
|
||||
memset(&MainHead,0,sizeof(MainHead));
|
||||
memset(&EndArcHead,0,sizeof(EndArcHead));
|
||||
|
||||
HeaderCRC=0;
|
||||
}
|
||||
|
||||
bool Archive::IsSignature(byte *D)
|
||||
{
|
||||
bool Valid=false;
|
||||
if (D[0]==0x52)
|
||||
RARFORMAT Archive::IsSignature(const byte *D,size_t Size)
|
||||
{
|
||||
RARFORMAT Type=RARFMT_NONE;
|
||||
if (Size>=1 && D[0]==0x52)
|
||||
#ifndef SFX_MODULE
|
||||
if (D[1]==0x45 && D[2]==0x7e && D[3]==0x5e)
|
||||
{
|
||||
OldFormat=true;
|
||||
Valid=true;
|
||||
}
|
||||
if (Size>=4 && D[1]==0x45 && D[2]==0x7e && D[3]==0x5e)
|
||||
Type=RARFMT14;
|
||||
else
|
||||
#endif
|
||||
if (D[1]==0x61 && D[2]==0x72 && D[3]==0x21 && D[4]==0x1a && D[5]==0x07 && D[6]==0x00)
|
||||
if (Size>=7 && D[1]==0x61 && D[2]==0x72 && D[3]==0x21 && D[4]==0x1a && D[5]==0x07)
|
||||
{
|
||||
OldFormat=false;
|
||||
Valid=true;
|
||||
// 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.
|
||||
if (D[6]==0)
|
||||
Type=RARFMT15;
|
||||
else if (D[6]==1)
|
||||
Type=RARFMT50;
|
||||
else if (D[6]==2)
|
||||
Type=RARFMT_FUTURE;
|
||||
}
|
||||
}
|
||||
return(Valid);
|
||||
return Type;
|
||||
}
|
||||
|
||||
|
||||
unrar_err_t Archive::IsArchive()
|
||||
{
|
||||
if (Read(MarkHead.Mark,SIZEOF_MARKHEAD)!=SIZEOF_MARKHEAD)
|
||||
if (Read(MarkHead.Mark,SIZEOF_MARKHEAD3)!=SIZEOF_MARKHEAD3)
|
||||
return unrar_err_not_arc;
|
||||
|
||||
if (IsSignature(MarkHead.Mark))
|
||||
RARFORMAT Type;
|
||||
if ((Type=IsSignature(MarkHead.Mark,SIZEOF_MARKHEAD3))!=RARFMT_NONE)
|
||||
{
|
||||
if (OldFormat)
|
||||
Seek(0,SEEK_SET);
|
||||
Format=Type;
|
||||
if (Format==RARFMT14)
|
||||
Seek(Tell()-SIZEOF_MARKHEAD3,SEEK_SET);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (SFXSize==0)
|
||||
return unrar_err_not_arc;
|
||||
}
|
||||
if (Format==RARFMT_FUTURE)
|
||||
return unrar_err_new_algo;
|
||||
if (Format==RARFMT50) // RAR 5.0 signature is one byte longer.
|
||||
{
|
||||
Read(MarkHead.Mark+SIZEOF_MARKHEAD3,1);
|
||||
if (MarkHead.Mark[SIZEOF_MARKHEAD3]!=0)
|
||||
return unrar_err_not_arc;
|
||||
MarkHead.HeadSize=SIZEOF_MARKHEAD5;
|
||||
}
|
||||
else
|
||||
MarkHead.HeadSize=SIZEOF_MARKHEAD3;
|
||||
|
||||
unrar_err_t error =
|
||||
ReadHeader();
|
||||
// (no need to seek to next)
|
||||
unrar_err_t error;
|
||||
size_t HeaderSize;
|
||||
while ((error=ReadHeader(&HeaderSize))==unrar_ok && HeaderSize!=0)
|
||||
{
|
||||
HEADER_TYPE Type=GetHeaderType();
|
||||
// In RAR 5.0 we need to quit after reading HEAD_CRYPT if we wish to
|
||||
// avoid the password prompt.
|
||||
if (Type==HEAD_MAIN)
|
||||
break;
|
||||
SeekToNext();
|
||||
}
|
||||
if ( error != unrar_ok )
|
||||
return error;
|
||||
|
||||
#ifndef SFX_MODULE
|
||||
if (OldFormat)
|
||||
{
|
||||
NewMhd.Flags=OldMhd.Flags & 0x3f;
|
||||
NewMhd.HeadSize=OldMhd.HeadSize;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
if (HeaderCRC!=NewMhd.HeadCRC)
|
||||
{
|
||||
return unrar_err_corrupt;
|
||||
}
|
||||
}
|
||||
bool
|
||||
Volume=(NewMhd.Flags & MHD_VOLUME);
|
||||
Solid=(NewMhd.Flags & MHD_SOLID)!=0;
|
||||
bool
|
||||
Encrypted=(NewMhd.Flags & MHD_PASSWORD)!=0;
|
||||
|
||||
// (removed decryption and volume handling)
|
||||
|
||||
if ( Encrypted )
|
||||
return unrar_err_encrypted;
|
||||
|
||||
if ( Volume )
|
||||
return unrar_err_segmented;
|
||||
SeekToNext();
|
||||
|
||||
return unrar_ok;
|
||||
}
|
||||
|
|
|
@ -4,39 +4,49 @@
|
|||
typedef ComprDataIO File;
|
||||
#include "rawread.hpp"
|
||||
|
||||
enum RARFORMAT {RARFMT_NONE,RARFMT14,RARFMT15,RARFMT50,RARFMT_FUTURE};
|
||||
|
||||
class Archive:public File
|
||||
{
|
||||
private:
|
||||
bool IsSignature(byte *D);
|
||||
void ConvertUnknownHeader();
|
||||
int ReadOldHeader();
|
||||
void ConvertFileHeader(FileHeader *hd);
|
||||
void WriteBlock50(HEADER_TYPE HeaderType,BaseBlock *wb,bool OnlySetSize,bool NonFinalWrite);
|
||||
unrar_err_t ReadHeader14(size_t *ReadSize);
|
||||
unrar_err_t ReadHeader15(size_t *ReadSize);
|
||||
unrar_err_t ReadHeader50(size_t *ReadSize);
|
||||
unrar_err_t ProcessExtra50(RawRead *Raw,size_t ExtraSize,BaseBlock *bb);
|
||||
|
||||
RawRead Raw;
|
||||
|
||||
MarkHeader MarkHead;
|
||||
OldMainHeader OldMhd;
|
||||
|
||||
int CurHeaderType;
|
||||
HEADER_TYPE CurHeaderType;
|
||||
|
||||
public:
|
||||
Archive();
|
||||
RARFORMAT IsSignature(const byte *D,size_t Size);
|
||||
unrar_err_t IsArchive();
|
||||
unrar_err_t ReadHeader();
|
||||
size_t SearchBlock(HEADER_TYPE HeaderType);
|
||||
size_t SearchSubBlock(const wchar *Type);
|
||||
size_t SearchRR();
|
||||
unrar_err_t ReadHeader(size_t *ReadSize);
|
||||
void SeekToNext();
|
||||
bool IsArcDir();
|
||||
bool IsArcLabel();
|
||||
int GetHeaderType() {return(CurHeaderType);};
|
||||
int64 GetStartPos();
|
||||
HEADER_TYPE GetHeaderType() {return(CurHeaderType);};
|
||||
|
||||
BaseBlock ShortBlock;
|
||||
MainHeader NewMhd;
|
||||
FileHeader NewLhd;
|
||||
MarkHeader MarkHead;
|
||||
MainHeader MainHead;
|
||||
FileHeader FileHead;
|
||||
EndArcHeader EndArcHead;
|
||||
SubBlockHeader SubBlockHead;
|
||||
FileHeader SubHead;
|
||||
ProtectHeader ProtectHead;
|
||||
|
||||
Int64 CurBlockPos;
|
||||
Int64 NextBlockPos;
|
||||
int64 CurBlockPos;
|
||||
int64 NextBlockPos;
|
||||
|
||||
RARFORMAT Format;
|
||||
bool Solid;
|
||||
enum { SFXSize = 0 }; // self-extracting not supported
|
||||
ushort HeaderCRC;
|
||||
|
|
|
@ -5,310 +5,731 @@
|
|||
#include "encname.hpp"
|
||||
|
||||
// arcread.cpp
|
||||
unrar_err_t Archive::ReadHeader()
|
||||
unrar_err_t Archive::ReadHeader(size_t * ReadSize_)
|
||||
{
|
||||
CurBlockPos=Tell();
|
||||
|
||||
#ifndef SFX_MODULE
|
||||
if (OldFormat)
|
||||
unrar_err_t Error;
|
||||
size_t ReadSize;
|
||||
switch(Format)
|
||||
{
|
||||
ReadOldHeader();
|
||||
#ifndef SFX_MODULE
|
||||
case RARFMT14:
|
||||
Error=ReadHeader14(&ReadSize);
|
||||
break;
|
||||
#endif
|
||||
case RARFMT15:
|
||||
Error=ReadHeader15(&ReadSize);
|
||||
break;
|
||||
case RARFMT50:
|
||||
Error=ReadHeader50(&ReadSize);
|
||||
break;
|
||||
|
||||
if ( Raw.Size() == 0 )
|
||||
return unrar_err_arc_eof; // right at end of file
|
||||
default: // unreachable
|
||||
Error=unrar_err_corrupt;
|
||||
break;
|
||||
}
|
||||
|
||||
if ( Raw.PaddedSize() > 0 ) // added check
|
||||
return unrar_err_corrupt; // missing data
|
||||
if (Error!=unrar_ok)
|
||||
return Error;
|
||||
|
||||
if (ReadSize>0 & NextBlockPos<=CurBlockPos)
|
||||
return unrar_err_corrupt;
|
||||
|
||||
*ReadSize_ = ReadSize;
|
||||
|
||||
return unrar_ok;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
unrar_err_t Archive::ReadHeader15(size_t *ReadSize)
|
||||
{
|
||||
Raw.Reset();
|
||||
|
||||
// (removed decryption)
|
||||
|
||||
Raw.Read(SIZEOF_SHORTBLOCKHEAD);
|
||||
if (Raw.Size()==0)
|
||||
{
|
||||
return unrar_err_arc_eof; // right at end of file
|
||||
}
|
||||
return unrar_err_corrupt;
|
||||
|
||||
Raw.Get(ShortBlock.HeadCRC);
|
||||
byte HeadType;
|
||||
Raw.Get(HeadType);
|
||||
ShortBlock.HeadType=(HEADER_TYPE)HeadType;
|
||||
Raw.Get(ShortBlock.Flags);
|
||||
Raw.Get(ShortBlock.HeadSize);
|
||||
ShortBlock.HeadCRC=Raw.Get2();
|
||||
|
||||
ShortBlock.Reset();
|
||||
|
||||
uint HeaderType=Raw.Get1();
|
||||
ShortBlock.Flags=Raw.Get2();
|
||||
ShortBlock.SkipIfUnknown=(ShortBlock.Flags & SKIP_IF_UNKNOWN)!=0;
|
||||
ShortBlock.HeadSize=Raw.Get2();
|
||||
|
||||
ShortBlock.HeaderType=(HEADER_TYPE)HeaderType;
|
||||
if (ShortBlock.HeadSize<SIZEOF_SHORTBLOCKHEAD)
|
||||
return unrar_err_corrupt;
|
||||
|
||||
// For simpler further processing we map header types common
|
||||
// for RAR 1.5 and 5.0 formats to RAR 5.0 values. It does not include
|
||||
// header types specific for RAR 1.5 - 4.x only.
|
||||
switch(ShortBlock.HeaderType)
|
||||
{
|
||||
return unrar_err_corrupt; // invalid HeadSize
|
||||
case HEAD3_MAIN: ShortBlock.HeaderType=HEAD_MAIN; break;
|
||||
case HEAD3_FILE: ShortBlock.HeaderType=HEAD_FILE; break;
|
||||
case HEAD3_SERVICE: ShortBlock.HeaderType=HEAD_SERVICE; break;
|
||||
case HEAD3_ENDARC: ShortBlock.HeaderType=HEAD_ENDARC; break;
|
||||
default: break;
|
||||
}
|
||||
CurHeaderType=ShortBlock.HeaderType;
|
||||
|
||||
// catches unknown block types and reading something that isn't even a header
|
||||
check( MARK_HEAD <= ShortBlock.HeadType && ShortBlock.HeadType <= ENDARC_HEAD );
|
||||
|
||||
if (ShortBlock.HeadType==COMM_HEAD)
|
||||
if (ShortBlock.HeaderType==HEAD3_CMT)
|
||||
{
|
||||
// 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)
|
||||
Raw.Read(SIZEOF_NEWMHD-SIZEOF_SHORTBLOCKHEAD);
|
||||
if (ShortBlock.HeaderType==HEAD_MAIN && (ShortBlock.Flags & MHD_COMMENT)!=0)
|
||||
{
|
||||
// Old style (up to RAR 2.9) main archive comment embedded into
|
||||
// the main archive header found. While we can read the entire
|
||||
// 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_MAINHEAD3-SIZEOF_SHORTBLOCKHEAD);
|
||||
}
|
||||
else
|
||||
Raw.Read(ShortBlock.HeadSize-SIZEOF_SHORTBLOCKHEAD);
|
||||
|
||||
if ( Raw.PaddedSize() > 0 ) // fewer than requested bytes read above?
|
||||
return unrar_err_corrupt; // missing data
|
||||
|
||||
NextBlockPos=CurBlockPos+ShortBlock.HeadSize;
|
||||
|
||||
switch(ShortBlock.HeadType)
|
||||
switch(ShortBlock.HeaderType)
|
||||
{
|
||||
case MAIN_HEAD:
|
||||
*(BaseBlock *)&NewMhd=ShortBlock;
|
||||
Raw.Get(NewMhd.HighPosAV);
|
||||
Raw.Get(NewMhd.PosAV);
|
||||
check( Raw.ReadPos == Raw.DataSize ); // we should have read all fields
|
||||
case HEAD_MAIN:
|
||||
MainHead.Reset();
|
||||
*(BaseBlock *)&MainHead=ShortBlock;
|
||||
MainHead.HighPosAV=Raw.Get2();
|
||||
MainHead.PosAV=Raw.Get4();
|
||||
|
||||
Solid=(MainHead.Flags & MHD_SOLID)!=0;
|
||||
MainHead.CommentInHeader=(MainHead.Flags & MHD_COMMENT)!=0;
|
||||
break;
|
||||
case FILE_HEAD:
|
||||
case NEWSUB_HEAD:
|
||||
case HEAD_FILE:
|
||||
case HEAD_SERVICE:
|
||||
{
|
||||
FileHeader *hd=ShortBlock.HeadType==FILE_HEAD ? &NewLhd:&SubHead;
|
||||
bool FileBlock=ShortBlock.HeaderType==HEAD_FILE;
|
||||
FileHeader *hd=FileBlock ? &FileHead:&SubHead;
|
||||
hd->Reset();
|
||||
|
||||
*(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)
|
||||
|
||||
hd->SplitBefore=(hd->Flags & LHD_SPLIT_BEFORE)!=0;
|
||||
hd->SplitAfter=(hd->Flags & LHD_SPLIT_AFTER)!=0;
|
||||
hd->Encrypted=(hd->Flags & LHD_PASSWORD)!=0;
|
||||
hd->Solid=FileBlock && (hd->Flags & LHD_SOLID)!=0;
|
||||
hd->SubBlock=!FileBlock && (hd->Flags & LHD_SOLID)!=0;
|
||||
hd->Dir=(hd->Flags & LHD_WINDOWMASK)==LHD_DIRECTORY;
|
||||
hd->WinSize=hd->Dir ? 0:0x10000<<((hd->Flags & LHD_WINDOWMASK)>>5);
|
||||
hd->CommentInHeader=(hd->Flags & LHD_COMMENT)!=0;
|
||||
hd->Version=(hd->Flags & LHD_VERSION)!=0;
|
||||
|
||||
hd->DataSize=Raw.Get4();
|
||||
uint LowUnpSize=Raw.Get4();
|
||||
hd->HostOS=Raw.Get1();
|
||||
|
||||
hd->FileHash.Type=HASH_CRC32;
|
||||
hd->FileHash.CRC32=Raw.Get4();
|
||||
|
||||
uint FileTime=Raw.Get4();
|
||||
hd->UnpVer=Raw.Get1();
|
||||
hd->Method=Raw.Get1()-0x30;
|
||||
size_t NameSize=Raw.Get2();
|
||||
hd->FileAttr=Raw.Get4();
|
||||
|
||||
if (hd->Encrypted)
|
||||
return unrar_err_encrypted;
|
||||
|
||||
hd->HSType=HSYS_UNKNOWN;
|
||||
if (hd->HostOS==HOST_UNIX || hd->HostOS==HOST_BEOS)
|
||||
hd->HSType=HSYS_UNIX;
|
||||
else
|
||||
if (hd->HostOS<HOST_MAX)
|
||||
hd->HSType=HSYS_WINDOWS;
|
||||
|
||||
hd->RedirType=FSREDIR_NONE;
|
||||
|
||||
// RAR 4.x Unix symlink.
|
||||
if (hd->HostOS==HOST_UNIX && (hd->FileAttr & 0xF000)==0xA000)
|
||||
{
|
||||
Raw.Get(hd->HighPackSize);
|
||||
Raw.Get(hd->HighUnpSize);
|
||||
hd->RedirType=FSREDIR_UNIXSYMLINK;
|
||||
*hd->RedirName=0;
|
||||
}
|
||||
|
||||
hd->Inherited=!FileBlock && (hd->SubFlags & SUBHEAD_FLAGS_INHERITED)!=0;
|
||||
|
||||
hd->LargeFile=(hd->Flags & LHD_LARGE)!=0;
|
||||
|
||||
uint HighPackSize,HighUnpSize;
|
||||
if (hd->LargeFile)
|
||||
{
|
||||
HighPackSize=Raw.Get4();
|
||||
HighUnpSize=Raw.Get4();
|
||||
hd->UnknownUnpSize=(LowUnpSize==0xffffffff && HighUnpSize==0xffffffff);
|
||||
}
|
||||
else
|
||||
{
|
||||
hd->HighPackSize=hd->HighUnpSize=0;
|
||||
if (hd->UnpSize==0xffffffff)
|
||||
{
|
||||
// TODO: what the heck is this for anyway?
|
||||
hd->UnpSize=0;
|
||||
hd->HighUnpSize=0x7fffffff;
|
||||
HighPackSize=HighUnpSize=0;
|
||||
// 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->UnknownUnpSize=(LowUnpSize==0xffffffff);
|
||||
}
|
||||
}
|
||||
hd->FullPackSize=int32to64(hd->HighPackSize,hd->PackSize);
|
||||
hd->FullUnpSize=int32to64(hd->HighUnpSize,hd->UnpSize);
|
||||
hd->PackSize=int32to64(HighPackSize,hd->DataSize);
|
||||
hd->UnpSize=int32to64(HighUnpSize,LowUnpSize);
|
||||
if (hd->UnknownUnpSize)
|
||||
hd->UnpSize=INT64NDF;
|
||||
|
||||
if ( int32to64( 1, 0 ) == 0 && (hd->HighPackSize || hd->HighUnpSize) )
|
||||
return unrar_err_huge;
|
||||
char FileName[NM*4];
|
||||
size_t ReadNameSize=Min(NameSize,ASIZE(FileName)-1);
|
||||
Raw.GetB((byte *)FileName,ReadNameSize);
|
||||
FileName[ReadNameSize]=0;
|
||||
|
||||
char (&FileName) [sizeof hd->FileName] = hd->FileName; // eliminated local buffer
|
||||
int NameSize=Min(hd->NameSize,sizeof(FileName)-1);
|
||||
Raw.Get((byte *)FileName,NameSize);
|
||||
FileName[NameSize]=0;
|
||||
|
||||
if (hd->HeadType==NEWSUB_HEAD)
|
||||
if (FileBlock)
|
||||
{
|
||||
// have to adjust this, even through we're ignoring this block
|
||||
NextBlockPos+=hd->FullPackSize;
|
||||
break;
|
||||
}
|
||||
else
|
||||
if (hd->HeadType==FILE_HEAD)
|
||||
{
|
||||
if (hd->Flags & LHD_UNICODE)
|
||||
if ((hd->Flags & LHD_UNICODE)!=0)
|
||||
{
|
||||
EncodeFileName NameCoder;
|
||||
int Length=(int)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
|
||||
{
|
||||
size_t Length=strlen(FileName);
|
||||
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;
|
||||
NameSize-Length,hd->FileName,
|
||||
ASIZE(hd->FileName));
|
||||
}
|
||||
else
|
||||
*hd->FileNameW=0;
|
||||
*hd->FileName=0;
|
||||
|
||||
ConvertUnknownHeader();
|
||||
char AnsiName[NM];
|
||||
IntToExt(FileName,AnsiName,ASIZE(AnsiName));
|
||||
GetWideName(AnsiName,hd->FileName,hd->FileName,ASIZE(hd->FileName));
|
||||
|
||||
ConvertFileHeader(hd);
|
||||
}
|
||||
if (hd->Flags & LHD_SALT)
|
||||
Raw.Get(hd->Salt,SALT_SIZE);
|
||||
hd->mtime.SetDos(hd->FileTime);
|
||||
if (hd->Flags & LHD_EXTTIME)
|
||||
else
|
||||
{
|
||||
ushort Flags;
|
||||
Raw.Get(Flags);
|
||||
// Ignore additional time information
|
||||
CharToWide(FileName,hd->FileName,ASIZE(hd->FileName));
|
||||
|
||||
// Calculate the size of optional data.
|
||||
int DataSize=int(hd->HeadSize-NameSize-SIZEOF_FILEHEAD3);
|
||||
if ((hd->Flags & LHD_SALT)!=0)
|
||||
return unrar_err_encrypted;
|
||||
|
||||
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.GetB(&hd->SubData[0],DataSize);
|
||||
}
|
||||
}
|
||||
if ((hd->Flags & LHD_SALT)!=0)
|
||||
return unrar_err_encrypted;
|
||||
hd->mtime.SetDos(FileTime);
|
||||
if ((hd->Flags & LHD_EXTTIME)!=0)
|
||||
{
|
||||
ushort Flags=Raw.Get2();
|
||||
RarTime *tbl[4];
|
||||
tbl[0]=&FileHead.mtime;
|
||||
tbl[1]=&FileHead.ctime;
|
||||
tbl[2]=&FileHead.atime;
|
||||
tbl[3]=NULL; // Archive time is not used now.
|
||||
for (int I=0;I<4;I++)
|
||||
{
|
||||
RarTime *CurTime=tbl[I];
|
||||
uint rmode=Flags>>(3-I)*4;
|
||||
if ((rmode & 8)==0)
|
||||
if ((rmode & 8)==0 || CurTime==NULL)
|
||||
continue;
|
||||
if (I!=0)
|
||||
{
|
||||
uint DosTime;
|
||||
Raw.Get(DosTime);
|
||||
uint DosTime=Raw.Get4();
|
||||
CurTime->SetDos(DosTime);
|
||||
}
|
||||
|
||||
// skip time info
|
||||
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);
|
||||
byte CurByte=Raw.Get1();
|
||||
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;
|
||||
NextBlockPos+=hd->PackSize;
|
||||
bool CRCProcessedOnly=hd->CommentInHeader;
|
||||
ushort HeaderCRC=Raw.GetCRC15(CRCProcessedOnly);
|
||||
if (hd->HeadCRC!=HeaderCRC)
|
||||
return unrar_err_corrupt;
|
||||
check( CRCProcessedOnly == false ); // I need to test on archives where this doesn't hold
|
||||
check( Raw.ReadPos == Raw.DataSize ); // we should have read all fields
|
||||
}
|
||||
break;
|
||||
#ifndef SFX_MODULE
|
||||
// Handle these block types just so we can adjust NextBlockPos properly
|
||||
case PROTECT_HEAD:
|
||||
Raw.Get(ProtectHead.DataSize);
|
||||
NextBlockPos+=ProtectHead.DataSize;
|
||||
case HEAD_ENDARC:
|
||||
*(BaseBlock *)&EndArcHead=ShortBlock;
|
||||
EndArcHead.NextVolume=(EndArcHead.Flags & EARC_NEXT_VOLUME)!=0;
|
||||
EndArcHead.DataCRC=(EndArcHead.Flags & EARC_DATACRC)!=0;
|
||||
EndArcHead.RevSpace=(EndArcHead.Flags & EARC_REVSPACE)!=0;
|
||||
EndArcHead.StoreVolNumber=(EndArcHead.Flags & EARC_VOLNUMBER)!=0;
|
||||
if (EndArcHead.DataCRC)
|
||||
EndArcHead.ArcDataCRC=Raw.Get4();
|
||||
if (EndArcHead.StoreVolNumber)
|
||||
return unrar_err_segmented;
|
||||
break;
|
||||
case SUB_HEAD:
|
||||
Raw.Get(SubBlockHead.DataSize);
|
||||
NextBlockPos+=SubBlockHead.DataSize;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
if (ShortBlock.Flags & LONG_BLOCK)
|
||||
NextBlockPos+=Raw.Get4();
|
||||
break;
|
||||
}
|
||||
|
||||
ushort HeaderCRC=Raw.GetCRC15(false);
|
||||
|
||||
// Old AV header does not have header CRC properly set.
|
||||
if (ShortBlock.HeadCRC!=HeaderCRC && ShortBlock.HeaderType!=HEAD3_SIGN &&
|
||||
ShortBlock.HeaderType!=HEAD3_AV)
|
||||
return unrar_err_corrupt;
|
||||
|
||||
if (NextBlockPos<=CurBlockPos)
|
||||
return unrar_err_corrupt;
|
||||
|
||||
*ReadSize=Raw.Size();
|
||||
return unrar_ok;
|
||||
}
|
||||
|
||||
|
||||
unrar_err_t Archive::ReadHeader50(size_t *ReadSize)
|
||||
{
|
||||
uint DataSize;
|
||||
Raw.Get(DataSize);
|
||||
NextBlockPos+=DataSize;
|
||||
Raw.Reset();
|
||||
|
||||
// Header size must not occupy more than 3 variable length integer bytes
|
||||
// resulting in 2 MB maximum header size, so here we read 4 byte CRC32
|
||||
// followed by 3 bytes or less of header size.
|
||||
const size_t FirstReadSize=7; // Smallest possible block size.
|
||||
if (Raw.Read(FirstReadSize)<FirstReadSize)
|
||||
return unrar_err_arc_eof;
|
||||
|
||||
ShortBlock.Reset();
|
||||
ShortBlock.HeadCRC=Raw.Get4();
|
||||
uint SizeBytes=Raw.GetVSize(4);
|
||||
uint64 BlockSize=Raw.GetV();
|
||||
|
||||
if (BlockSize==0 || SizeBytes==0)
|
||||
return unrar_err_corrupt;
|
||||
|
||||
int SizeToRead=int(BlockSize);
|
||||
SizeToRead-=FirstReadSize-SizeBytes-4; // Adjust overread size bytes if any.
|
||||
uint HeaderSize=4+SizeBytes+(uint)BlockSize;
|
||||
|
||||
if (SizeToRead<0 || HeaderSize<SIZEOF_SHORTBLOCKHEAD5)
|
||||
return unrar_err_corrupt;
|
||||
|
||||
Raw.Read(SizeToRead);
|
||||
|
||||
if (Raw.Size()<HeaderSize)
|
||||
return unrar_err_arc_eof;
|
||||
|
||||
uint HeaderCRC=Raw.GetCRC50();
|
||||
|
||||
ShortBlock.HeaderType=(HEADER_TYPE)Raw.GetV();
|
||||
ShortBlock.Flags=(uint)Raw.GetV();
|
||||
ShortBlock.SkipIfUnknown=(ShortBlock.Flags & HFL_SKIPIFUNKNOWN)!=0;
|
||||
ShortBlock.HeadSize=HeaderSize;
|
||||
|
||||
CurHeaderType=ShortBlock.HeaderType;
|
||||
|
||||
bool BadCRC=(ShortBlock.HeadCRC!=HeaderCRC);
|
||||
if (BadCRC)
|
||||
return unrar_err_corrupt;
|
||||
|
||||
uint64 ExtraSize=0;
|
||||
if ((ShortBlock.Flags & HFL_EXTRA)!=0)
|
||||
{
|
||||
ExtraSize=Raw.GetV();
|
||||
if (ExtraSize>=ShortBlock.HeadSize)
|
||||
return unrar_err_corrupt;
|
||||
}
|
||||
|
||||
uint64 DataSize=0;
|
||||
if ((ShortBlock.Flags & HFL_DATA)!=0)
|
||||
DataSize=Raw.GetV();
|
||||
|
||||
NextBlockPos=CurBlockPos+ShortBlock.HeadSize+DataSize;
|
||||
|
||||
switch(ShortBlock.HeaderType)
|
||||
{
|
||||
case HEAD_CRYPT:
|
||||
return unrar_err_encrypted;
|
||||
case HEAD_MAIN:
|
||||
{
|
||||
MainHead.Reset();
|
||||
*(BaseBlock *)&MainHead=ShortBlock;
|
||||
uint ArcFlags=(uint)Raw.GetV();
|
||||
|
||||
Solid=(ArcFlags & MHFL_SOLID)!=0;
|
||||
|
||||
if (ExtraSize!=0)
|
||||
{
|
||||
unrar_err_t Error;
|
||||
if ((Error=ProcessExtra50(&Raw,(size_t)ExtraSize,&MainHead))!=unrar_ok)
|
||||
return Error;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case HEAD_FILE:
|
||||
case HEAD_SERVICE:
|
||||
{
|
||||
FileHeader *hd=ShortBlock.HeaderType==HEAD_FILE ? &FileHead:&SubHead;
|
||||
hd->Reset();
|
||||
*(BaseBlock *)hd=ShortBlock;
|
||||
|
||||
bool FileBlock=ShortBlock.HeaderType==HEAD_FILE;
|
||||
|
||||
hd->LargeFile=true;
|
||||
|
||||
hd->PackSize=DataSize;
|
||||
hd->FileFlags=(uint)Raw.GetV();
|
||||
hd->UnpSize=Raw.GetV();
|
||||
|
||||
hd->UnknownUnpSize=(hd->FileFlags & FHFL_UNPUNKNOWN)!=0;
|
||||
if (hd->UnknownUnpSize)
|
||||
hd->UnpSize=INT64NDF;
|
||||
|
||||
hd->MaxSize=Max(hd->PackSize,hd->UnpSize);
|
||||
hd->FileAttr=(uint)Raw.GetV();
|
||||
if ((hd->FileFlags & FHFL_UTIME)!=0)
|
||||
hd->mtime=(time_t)Raw.Get4();
|
||||
|
||||
hd->FileHash.Type=HASH_NONE;
|
||||
if ((hd->FileFlags & FHFL_CRC32)!=0)
|
||||
{
|
||||
hd->FileHash.Type=HASH_CRC32;
|
||||
hd->FileHash.CRC32=Raw.Get4();
|
||||
}
|
||||
|
||||
hd->RedirType=FSREDIR_NONE;
|
||||
|
||||
uint CompInfo=(uint)Raw.GetV();
|
||||
hd->Method=(CompInfo>>7) & 7;
|
||||
hd->UnpVer=CompInfo & 0x3f;
|
||||
|
||||
hd->HostOS=(byte)Raw.GetV();
|
||||
size_t NameSize=(size_t)Raw.GetV();
|
||||
hd->Inherited=(ShortBlock.Flags & HFL_INHERITED)!=0;
|
||||
|
||||
hd->HSType=HSYS_UNKNOWN;
|
||||
if (hd->HostOS==HOST5_UNIX)
|
||||
hd->HSType=HSYS_UNIX;
|
||||
else
|
||||
if (hd->HostOS==HOST5_WINDOWS)
|
||||
hd->HSType=HSYS_WINDOWS;
|
||||
|
||||
hd->SplitBefore=(hd->Flags & HFL_SPLITBEFORE)!=0;
|
||||
hd->SplitAfter=(hd->Flags & HFL_SPLITAFTER)!=0;
|
||||
hd->SubBlock=(hd->Flags & HFL_CHILD)!=0;
|
||||
hd->Solid=FileBlock && (CompInfo & FCI_SOLID)!=0;
|
||||
hd->Dir=(hd->FileFlags & FHFL_DIRECTORY)!=0;
|
||||
hd->WinSize=hd->Dir ? 0:size_t(0x20000)<<((CompInfo>>10)&0xf);
|
||||
|
||||
if (hd->Encrypted)
|
||||
return unrar_err_encrypted;
|
||||
|
||||
char FileName[NM*4];
|
||||
size_t ReadNameSize=Min(NameSize,ASIZE(FileName)-1);
|
||||
Raw.GetB((byte *)FileName,ReadNameSize);
|
||||
FileName[ReadNameSize]=0;
|
||||
|
||||
UtfToWide(FileName,hd->FileName,ASIZE(hd->FileName)-1);
|
||||
|
||||
// Should do it before converting names, because extra fields can
|
||||
// affect name processing, like in case of NTFS streams.
|
||||
if (ExtraSize!=0)
|
||||
ProcessExtra50(&Raw,(size_t)ExtraSize,hd);
|
||||
|
||||
if (FileBlock)
|
||||
ConvertFileHeader(hd);
|
||||
|
||||
if (BadCRC) // Add the file name to broken header message displayed above.
|
||||
return unrar_err_corrupt;
|
||||
}
|
||||
break;
|
||||
case HEAD_ENDARC:
|
||||
{
|
||||
*(BaseBlock *)&EndArcHead=ShortBlock;
|
||||
uint ArcFlags=(uint)Raw.GetV();
|
||||
EndArcHead.NextVolume=(ArcFlags & EHFL_NEXTVOLUME)!=0;
|
||||
EndArcHead.StoreVolNumber=false;
|
||||
EndArcHead.DataCRC=false;
|
||||
EndArcHead.RevSpace=false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
HeaderCRC=~Raw.GetCRC(false)&0xffff;
|
||||
CurHeaderType=ShortBlock.HeadType;
|
||||
// (removed decryption)
|
||||
|
||||
if (NextBlockPos<CurBlockPos+Raw.Size())
|
||||
return unrar_err_corrupt; // next block isn't past end of current block's header
|
||||
if (NextBlockPos<=CurBlockPos)
|
||||
return unrar_err_corrupt;
|
||||
|
||||
// If pos went negative, then unrar_pos_t is only 32 bits and it overflowed
|
||||
if ( NextBlockPos < 0 )
|
||||
return unrar_err_huge;
|
||||
*ReadSize=Raw.Size();
|
||||
|
||||
return unrar_ok;
|
||||
}
|
||||
|
||||
// Rar.Read()s are checked by caller of ReadOldHeader() (see above)
|
||||
|
||||
unrar_err_t Archive::ProcessExtra50(RawRead *Raw,size_t ExtraSize,BaseBlock *bb)
|
||||
{
|
||||
// Read extra data from the end of block skipping any fields before it.
|
||||
size_t ExtraStart=Raw->Size()-ExtraSize;
|
||||
if (ExtraStart<Raw->GetPos())
|
||||
return unrar_err_corrupt;
|
||||
Raw->SetPos(ExtraStart);
|
||||
while (Raw->DataLeft()>=2)
|
||||
{
|
||||
int64 FieldSize=Raw->GetV();
|
||||
if (FieldSize==0 || Raw->DataLeft()==0 || FieldSize>(int64)Raw->DataLeft())
|
||||
break;
|
||||
size_t NextPos=size_t(Raw->GetPos()+FieldSize);
|
||||
uint64 FieldType=Raw->GetV();
|
||||
|
||||
FieldSize=Raw->DataLeft(); // Field size without size and type fields.
|
||||
|
||||
if (bb->HeaderType==HEAD_MAIN)
|
||||
{
|
||||
MainHeader *hd=(MainHeader *)bb;
|
||||
if (FieldType==MHEXTRA_LOCATOR)
|
||||
{
|
||||
hd->Locator=true;
|
||||
uint Flags=(uint)Raw->GetV();
|
||||
if ((Flags & MHEXTRA_LOCATOR_QLIST)!=0)
|
||||
{
|
||||
uint64 Offset=Raw->GetV();
|
||||
if (Offset!=0) // 0 means that reserved space was not enough to write the offset.
|
||||
hd->QOpenOffset=Offset+CurBlockPos;
|
||||
}
|
||||
if ((Flags & MHEXTRA_LOCATOR_RR)!=0)
|
||||
{
|
||||
uint64 Offset=Raw->GetV();
|
||||
if (Offset!=0) // 0 means that reserved space was not enough to write the offset.
|
||||
hd->RROffset=Offset+CurBlockPos;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (bb->HeaderType==HEAD_FILE || bb->HeaderType==HEAD_SERVICE)
|
||||
{
|
||||
FileHeader *hd=(FileHeader *)bb;
|
||||
switch(FieldType)
|
||||
{
|
||||
case FHEXTRA_CRYPT:
|
||||
return unrar_err_encrypted;
|
||||
case FHEXTRA_HASH:
|
||||
{
|
||||
FileHeader *hd=(FileHeader *)bb;
|
||||
uint Type=(uint)Raw->GetV();
|
||||
if (Type==FHEXTRA_HASH_BLAKE2)
|
||||
{
|
||||
hd->FileHash.Type=HASH_BLAKE2;
|
||||
Raw->GetB(hd->FileHash.Digest,BLAKE2_DIGEST_SIZE);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case FHEXTRA_HTIME:
|
||||
if (FieldSize>=9)
|
||||
{
|
||||
byte Flags=(byte)Raw->GetV();
|
||||
bool UnixTime=(Flags & FHEXTRA_HTIME_UNIXTIME)!=0;
|
||||
if ((Flags & FHEXTRA_HTIME_MTIME)!=0)
|
||||
{
|
||||
if (UnixTime)
|
||||
hd->mtime=(time_t)Raw->Get4();
|
||||
else
|
||||
hd->mtime.SetRaw(Raw->Get8());
|
||||
}
|
||||
if ((Flags & FHEXTRA_HTIME_CTIME)!=0)
|
||||
{
|
||||
if (UnixTime)
|
||||
hd->ctime=(time_t)Raw->Get4();
|
||||
else
|
||||
hd->ctime.SetRaw(Raw->Get8());
|
||||
}
|
||||
if ((Flags & FHEXTRA_HTIME_ATIME)!=0)
|
||||
{
|
||||
if (UnixTime)
|
||||
hd->atime=(time_t)Raw->Get4();
|
||||
else
|
||||
hd->atime.SetRaw(Raw->Get8());
|
||||
}
|
||||
}
|
||||
break;
|
||||
case FHEXTRA_REDIR:
|
||||
{
|
||||
hd->RedirType=(FILE_SYSTEM_REDIRECT)Raw->GetV();
|
||||
uint Flags=(uint)Raw->GetV();
|
||||
hd->DirTarget=(Flags & FHEXTRA_REDIR_DIR)!=0;
|
||||
size_t NameSize=(size_t)Raw->GetV();
|
||||
|
||||
char UtfName[NM*4];
|
||||
*UtfName=0;
|
||||
if (NameSize<ASIZE(UtfName)-1)
|
||||
{
|
||||
Raw->GetB(UtfName,NameSize);
|
||||
UtfName[NameSize]=0;
|
||||
}
|
||||
#ifdef _WIN_ALL
|
||||
UnixSlashToDos(UtfName,UtfName,ASIZE(UtfName));
|
||||
#endif
|
||||
UtfToWide(UtfName,hd->RedirName,ASIZE(hd->RedirName));
|
||||
}
|
||||
break;
|
||||
case FHEXTRA_UOWNER:
|
||||
{
|
||||
uint Flags=(uint)Raw->GetV();
|
||||
hd->UnixOwnerNumeric=(Flags & FHEXTRA_UOWNER_NUMUID)!=0;
|
||||
hd->UnixGroupNumeric=(Flags & FHEXTRA_UOWNER_NUMGID)!=0;
|
||||
*hd->UnixOwnerName=*hd->UnixGroupName=0;
|
||||
if ((Flags & FHEXTRA_UOWNER_UNAME)!=0)
|
||||
{
|
||||
size_t Length=(size_t)Raw->GetV();
|
||||
Length=Min(Length,ASIZE(hd->UnixOwnerName)-1);
|
||||
Raw->GetB(hd->UnixOwnerName,Length);
|
||||
hd->UnixOwnerName[Length]=0;
|
||||
}
|
||||
if ((Flags & FHEXTRA_UOWNER_GNAME)!=0)
|
||||
{
|
||||
size_t Length=(size_t)Raw->GetV();
|
||||
Length=Min(Length,ASIZE(hd->UnixGroupName)-1);
|
||||
Raw->GetB(hd->UnixGroupName,Length);
|
||||
hd->UnixGroupName[Length]=0;
|
||||
}
|
||||
#ifdef _UNIX
|
||||
if (hd->UnixOwnerNumeric)
|
||||
hd->UnixOwnerID=(uid_t)Raw->GetV();
|
||||
if (hd->UnixGroupNumeric)
|
||||
hd->UnixGroupID=(uid_t)Raw->GetV();
|
||||
#else
|
||||
// Need these fields in Windows too for 'list' command,
|
||||
// but uid_t and gid_t are not defined.
|
||||
if (hd->UnixOwnerNumeric)
|
||||
hd->UnixOwnerID=(uint)Raw->GetV();
|
||||
if (hd->UnixGroupNumeric)
|
||||
hd->UnixGroupID=(uint)Raw->GetV();
|
||||
#endif
|
||||
hd->UnixOwnerSet=true;
|
||||
}
|
||||
break;
|
||||
case FHEXTRA_SUBDATA:
|
||||
{
|
||||
hd->SubData.Alloc((size_t)FieldSize);
|
||||
Raw->GetB(hd->SubData.Addr(0),(size_t)FieldSize);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Raw->SetPos(NextPos);
|
||||
}
|
||||
|
||||
return unrar_ok;
|
||||
}
|
||||
|
||||
|
||||
#ifndef SFX_MODULE
|
||||
int Archive::ReadOldHeader()
|
||||
unrar_err_t Archive::ReadHeader14(size_t *ReadSize)
|
||||
{
|
||||
Raw.Reset();
|
||||
if (CurBlockPos<=SFXSize)
|
||||
|
||||
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;
|
||||
Raw.Read(SIZEOF_MAINHEAD14);
|
||||
MainHead.Reset();
|
||||
byte Mark[4];
|
||||
Raw.GetB(Mark,4);
|
||||
uint HeadSize=Raw.Get2();
|
||||
byte Flags=Raw.Get1();
|
||||
NextBlockPos=CurBlockPos+HeadSize;
|
||||
CurHeaderType=HEAD_MAIN;
|
||||
|
||||
Solid=(Flags & MHD_SOLID)!=0;
|
||||
MainHead.CommentInHeader=(Flags & MHD_COMMENT)!=0;
|
||||
MainHead.PackComment=(Flags & MHD_PACK_COMMENT)!=0;
|
||||
}
|
||||
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);
|
||||
Raw.Read(SIZEOF_FILEHEAD14);
|
||||
FileHead.Reset();
|
||||
|
||||
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;
|
||||
FileHead.HeaderType=HEAD_FILE;
|
||||
FileHead.DataSize=Raw.Get4();
|
||||
FileHead.UnpSize=Raw.Get4();
|
||||
FileHead.FileHash.Type=HASH_RAR14;
|
||||
FileHead.FileHash.CRC32=Raw.Get2();
|
||||
FileHead.HeadSize=Raw.Get2();
|
||||
uint FileTime=Raw.Get4();
|
||||
FileHead.FileAttr=Raw.Get1();
|
||||
FileHead.Flags=Raw.Get1()|LONG_BLOCK;
|
||||
FileHead.UnpVer=(Raw.Get1()==2) ? 13 : 10;
|
||||
size_t NameSize=Raw.Get1();
|
||||
FileHead.Method=Raw.Get1();
|
||||
|
||||
NewLhd.mtime.SetDos(NewLhd.FileTime);
|
||||
// (removed other times)
|
||||
FileHead.SplitBefore=(FileHead.Flags & LHD_SPLIT_BEFORE)!=0;
|
||||
FileHead.SplitAfter=(FileHead.Flags & LHD_SPLIT_AFTER)!=0;
|
||||
FileHead.Encrypted=(FileHead.Flags & LHD_PASSWORD)!=0;
|
||||
if (FileHead.Encrypted)
|
||||
return unrar_err_encrypted;
|
||||
|
||||
Raw.Read(OldLhd.NameSize);
|
||||
Raw.Get((byte *)NewLhd.FileName,OldLhd.NameSize);
|
||||
NewLhd.FileName[OldLhd.NameSize]=0;
|
||||
// (removed name case conversion)
|
||||
*NewLhd.FileNameW=0;
|
||||
FileHead.PackSize=FileHead.DataSize;
|
||||
FileHead.WinSize=0x10000;
|
||||
|
||||
FileHead.mtime.SetDos(FileTime);
|
||||
|
||||
Raw.Read(NameSize);
|
||||
|
||||
char FileName[NM];
|
||||
Raw.GetB((byte *)FileName,Min(NameSize,ASIZE(FileName)));
|
||||
FileName[NameSize]=0;
|
||||
IntToExt(FileName,FileName,ASIZE(FileName));
|
||||
CharToWide(FileName,FileHead.FileName,ASIZE(FileHead.FileName));
|
||||
|
||||
if (Raw.Size()!=0)
|
||||
NextBlockPos=CurBlockPos+NewLhd.HeadSize+NewLhd.PackSize;
|
||||
CurHeaderType=FILE_HEAD;
|
||||
NextBlockPos=CurBlockPos+FileHead.HeadSize+FileHead.PackSize;
|
||||
CurHeaderType=HEAD_FILE;
|
||||
}
|
||||
return(NextBlockPos>CurBlockPos ? Raw.Size():0);
|
||||
*ReadSize=(NextBlockPos>CurBlockPos ? Raw.Size():0);
|
||||
return unrar_ok;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// (removed name case and attribute conversion)
|
||||
|
||||
bool Archive::IsArcDir()
|
||||
{
|
||||
return((NewLhd.Flags & LHD_WINDOWMASK)==LHD_DIRECTORY);
|
||||
return FileHead.Dir;
|
||||
}
|
||||
|
||||
|
||||
bool Archive::IsArcLabel()
|
||||
{
|
||||
return(NewLhd.HostOS<=HOST_WIN32 && (NewLhd.FileAttr & 8));
|
||||
return(FileHead.HostOS<=HOST_WIN32 && (FileHead.FileAttr & 8));
|
||||
}
|
||||
|
||||
// TODO: use '\\' on Windows?
|
||||
char const CPATHDIVIDER = '/';
|
||||
#define charnext(s) ((s)+1)
|
||||
|
||||
void Archive::ConvertUnknownHeader()
|
||||
void Archive::ConvertFileHeader(FileHeader *hd)
|
||||
{
|
||||
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;
|
||||
if (Format==RARFMT15 && hd->UnpVer<20 && (hd->FileAttr & 0x10))
|
||||
hd->Dir=true;
|
||||
if (hd->HSType==HSYS_UNKNOWN)
|
||||
if (hd->Dir)
|
||||
hd->FileAttr=0x10;
|
||||
else
|
||||
NewLhd.FileAttr=0x20;
|
||||
hd->FileAttr=0x20;
|
||||
}
|
||||
|
||||
|
||||
int64 Archive::GetStartPos()
|
||||
{
|
||||
for (char *s=NewLhd.FileName;*s!=0;s=charnext(s))
|
||||
{
|
||||
if (*s=='/' || *s=='\\')
|
||||
*s=CPATHDIVIDER;
|
||||
}
|
||||
}
|
||||
// (removed Apple Unicode handling)
|
||||
for (wchar *s=NewLhd.FileNameW;*s!=0;s++)
|
||||
{
|
||||
if (*s=='/' || *s=='\\')
|
||||
*s=CPATHDIVIDER;
|
||||
}
|
||||
int64 StartPos=SFXSize+MarkHead.HeadSize;
|
||||
StartPos+=MainHead.HeadSize;
|
||||
return StartPos;
|
||||
}
|
||||
|
|
|
@ -1,26 +1,33 @@
|
|||
#ifndef _RAR_ARRAY_
|
||||
#define _RAR_ARRAY_
|
||||
|
||||
#include <new>
|
||||
|
||||
template <class T> class Array
|
||||
{
|
||||
private:
|
||||
T *Buffer;
|
||||
int BufSize;
|
||||
int AllocSize;
|
||||
size_t BufSize;
|
||||
size_t AllocSize;
|
||||
size_t MaxSize;
|
||||
public:
|
||||
Rar_Error_Handler& ErrHandler;
|
||||
Array(Rar_Error_Handler*);
|
||||
Array(int Size,Rar_Error_Handler*);
|
||||
Array();
|
||||
Array(size_t Size);
|
||||
Array(const Array &Src); // Copy constructor.
|
||||
~Array();
|
||||
inline void CleanData();
|
||||
inline T& operator [](int Item);
|
||||
inline int Size();
|
||||
void Add(int Items);
|
||||
void Alloc(int Items);
|
||||
inline T& operator [](size_t Item) const;
|
||||
inline T* operator + (size_t Pos);
|
||||
inline size_t Size();
|
||||
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);}
|
||||
void Append(T *Item,size_t Count);
|
||||
T* Addr(size_t Item) {return Buffer+Item;}
|
||||
void SetMaxSize(size_t Size) {MaxSize=Size;}
|
||||
};
|
||||
|
||||
template <class T> void Array<T>::CleanData()
|
||||
|
@ -28,22 +35,30 @@ template <class T> void Array<T>::CleanData()
|
|||
Buffer=NULL;
|
||||
BufSize=0;
|
||||
AllocSize=0;
|
||||
MaxSize=0;
|
||||
}
|
||||
|
||||
|
||||
template <class T> Array<T>::Array(Rar_Error_Handler* eh) : ErrHandler( *eh )
|
||||
template <class T> Array<T>::Array()
|
||||
{
|
||||
CleanData();
|
||||
}
|
||||
|
||||
|
||||
template <class T> Array<T>::Array(int Size, Rar_Error_Handler* eh) : ErrHandler( *eh )
|
||||
template <class T> Array<T>::Array(size_t Size)
|
||||
{
|
||||
Buffer=(T *)rarmalloc(sizeof(T)*Size);
|
||||
if (Buffer==NULL && Size!=0)
|
||||
ErrHandler.MemoryError();
|
||||
CleanData();
|
||||
Add(Size);
|
||||
}
|
||||
|
||||
AllocSize=BufSize=Size;
|
||||
|
||||
// Copy constructor in case we need to pass an object as value.
|
||||
template <class T> Array<T>::Array(const Array &Src)
|
||||
{
|
||||
CleanData();
|
||||
Alloc(Src.BufSize);
|
||||
if (Src.BufSize!=0)
|
||||
memcpy((void *)Buffer,(void *)Src.Buffer,Src.BufSize*sizeof(T));
|
||||
}
|
||||
|
||||
|
||||
|
@ -54,41 +69,46 @@ template <class T> Array<T>::~Array()
|
|||
}
|
||||
|
||||
|
||||
template <class T> inline T& Array<T>::operator [](int Item)
|
||||
template <class T> inline T& Array<T>::operator [](size_t Item) const
|
||||
{
|
||||
return(Buffer[Item]);
|
||||
return Buffer[Item];
|
||||
}
|
||||
|
||||
|
||||
template <class T> inline int Array<T>::Size()
|
||||
template <class T> inline T* Array<T>::operator +(size_t Pos)
|
||||
{
|
||||
return(BufSize);
|
||||
return Buffer+Pos;
|
||||
}
|
||||
|
||||
|
||||
template <class T> void Array<T>::Add(int Items)
|
||||
template <class T> inline size_t Array<T>::Size()
|
||||
{
|
||||
int BufSize = this->BufSize; // don't change actual vars until alloc succeeds
|
||||
T* Buffer = this->Buffer;
|
||||
return BufSize;
|
||||
}
|
||||
|
||||
BufSize+=Items;
|
||||
if (BufSize>AllocSize)
|
||||
|
||||
template <class T> void Array<T>::Add(size_t Items)
|
||||
{
|
||||
int Suggested=AllocSize+AllocSize/4+32;
|
||||
int NewSize=Max(BufSize,Suggested);
|
||||
size_t NewBufSize=BufSize+Items;
|
||||
if (NewBufSize>AllocSize)
|
||||
{
|
||||
if (MaxSize!=0 && NewBufSize>MaxSize)
|
||||
throw std::bad_alloc();
|
||||
|
||||
Buffer=(T *)rarrealloc(Buffer,NewSize*sizeof(T));
|
||||
if (Buffer==NULL)
|
||||
ErrHandler.MemoryError();
|
||||
size_t Suggested=AllocSize+AllocSize/4+32;
|
||||
size_t NewSize=Max(NewBufSize,Suggested);
|
||||
|
||||
T *NewBuffer=(T *)rarrealloc(Buffer,NewSize*sizeof(T));
|
||||
if (NewBuffer==NULL)
|
||||
throw std::bad_alloc();
|
||||
Buffer=NewBuffer;
|
||||
AllocSize=NewSize;
|
||||
}
|
||||
|
||||
this->Buffer = Buffer;
|
||||
this->BufSize = BufSize;
|
||||
BufSize=NewBufSize;
|
||||
}
|
||||
|
||||
|
||||
template <class T> void Array<T>::Alloc(int Items)
|
||||
template <class T> void Array<T>::Alloc(size_t Items)
|
||||
{
|
||||
if (Items>AllocSize)
|
||||
Add(Items-BufSize);
|
||||
|
@ -117,6 +137,14 @@ template <class T> void Array<T>::Reset()
|
|||
}
|
||||
|
||||
|
||||
// Reset buffer size, but preserve already allocated memory if any,
|
||||
// so we can reuse it without wasting time to allocation.
|
||||
template <class T> void Array<T>::SoftReset()
|
||||
{
|
||||
BufSize=0;
|
||||
}
|
||||
|
||||
|
||||
template <class T> void Array<T>::operator =(Array<T> &Src)
|
||||
{
|
||||
Reset();
|
||||
|
@ -132,4 +160,12 @@ template <class T> void Array<T>::Push(T Item)
|
|||
(*this)[Size()-1]=Item;
|
||||
}
|
||||
|
||||
|
||||
template <class T> void Array<T>::Append(T *Items,size_t Count)
|
||||
{
|
||||
size_t CurSize=Size();
|
||||
Add(Count);
|
||||
memcpy(Buffer+CurSize,Items,Count*sizeof(T));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,189 @@
|
|||
// Based on public domain code written in 2012 by Samuel Neves
|
||||
|
||||
#include "rar.hpp"
|
||||
|
||||
#ifdef USE_SSE
|
||||
#include "blake2s_sse.cpp"
|
||||
#endif
|
||||
|
||||
static void blake2s_init_param( blake2s_state *S, uint32 node_offset, uint32 node_depth);
|
||||
static void blake2s_update( blake2s_state *S, const byte *in, size_t inlen );
|
||||
static void blake2s_final( blake2s_state *S, byte *digest );
|
||||
|
||||
#include "blake2sp.cpp"
|
||||
|
||||
static const uint32 blake2s_IV[8] =
|
||||
{
|
||||
0x6A09E667UL, 0xBB67AE85UL, 0x3C6EF372UL, 0xA54FF53AUL,
|
||||
0x510E527FUL, 0x9B05688CUL, 0x1F83D9ABUL, 0x5BE0CD19UL
|
||||
};
|
||||
|
||||
static const byte blake2s_sigma[10][16] =
|
||||
{
|
||||
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } ,
|
||||
{ 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } ,
|
||||
{ 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 } ,
|
||||
{ 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 } ,
|
||||
{ 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 } ,
|
||||
{ 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 } ,
|
||||
{ 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 } ,
|
||||
{ 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 } ,
|
||||
{ 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 } ,
|
||||
{ 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13 , 0 } ,
|
||||
};
|
||||
|
||||
static inline void blake2s_set_lastnode( blake2s_state *S )
|
||||
{
|
||||
S->f[1] = ~0U;
|
||||
}
|
||||
|
||||
|
||||
/* Some helper functions, not necessarily useful */
|
||||
static inline void blake2s_set_lastblock( blake2s_state *S )
|
||||
{
|
||||
if( S->last_node ) blake2s_set_lastnode( S );
|
||||
|
||||
S->f[0] = ~0U;
|
||||
}
|
||||
|
||||
|
||||
static inline void blake2s_increment_counter( blake2s_state *S, const uint32 inc )
|
||||
{
|
||||
S->t[0] += inc;
|
||||
S->t[1] += ( S->t[0] < inc );
|
||||
}
|
||||
|
||||
|
||||
/* init2 xors IV with input parameter block */
|
||||
void blake2s_init_param( blake2s_state *S, uint32 node_offset, uint32 node_depth)
|
||||
{
|
||||
#ifdef USE_SSE
|
||||
if (_SSE_Version>=SSE_SSE2)
|
||||
blake2s_init_sse();
|
||||
#endif
|
||||
|
||||
S->init(); // Clean data.
|
||||
for( int i = 0; i < 8; ++i )
|
||||
S->h[i] = blake2s_IV[i];
|
||||
|
||||
S->h[0] ^= 0x02080020; // We use BLAKE2sp parameters block.
|
||||
S->h[2] ^= node_offset;
|
||||
S->h[3] ^= (node_depth<<16)|0x20000000;
|
||||
}
|
||||
|
||||
|
||||
static inline uint32 rotr32( const uint32 w, const unsigned c )
|
||||
{
|
||||
return ( w >> c ) | ( w << ( 32 - c ) );
|
||||
}
|
||||
|
||||
|
||||
#define G(r,i,m,a,b,c,d) \
|
||||
a = a + b + m[blake2s_sigma[r][2*i+0]]; \
|
||||
d = rotr32(d ^ a, 16); \
|
||||
c = c + d; \
|
||||
b = rotr32(b ^ c, 12); \
|
||||
a = a + b + m[blake2s_sigma[r][2*i+1]]; \
|
||||
d = rotr32(d ^ a, 8); \
|
||||
c = c + d; \
|
||||
b = rotr32(b ^ c, 7);
|
||||
|
||||
|
||||
static void blake2s_compress( blake2s_state *S, const byte block[BLAKE2S_BLOCKBYTES] )
|
||||
{
|
||||
uint32 m[16];
|
||||
uint32 v[16];
|
||||
|
||||
for( size_t i = 0; i < 16; ++i )
|
||||
m[i] = RawGet4( block + i * 4 );
|
||||
|
||||
for( size_t i = 0; i < 8; ++i )
|
||||
v[i] = S->h[i];
|
||||
|
||||
v[ 8] = blake2s_IV[0];
|
||||
v[ 9] = blake2s_IV[1];
|
||||
v[10] = blake2s_IV[2];
|
||||
v[11] = blake2s_IV[3];
|
||||
v[12] = S->t[0] ^ blake2s_IV[4];
|
||||
v[13] = S->t[1] ^ blake2s_IV[5];
|
||||
v[14] = S->f[0] ^ blake2s_IV[6];
|
||||
v[15] = S->f[1] ^ blake2s_IV[7];
|
||||
|
||||
for ( uint r = 0; r <= 9; ++r ) // No gain on i7 if unrolled, but exe size grows.
|
||||
{
|
||||
G(r,0,m,v[ 0],v[ 4],v[ 8],v[12]);
|
||||
G(r,1,m,v[ 1],v[ 5],v[ 9],v[13]);
|
||||
G(r,2,m,v[ 2],v[ 6],v[10],v[14]);
|
||||
G(r,3,m,v[ 3],v[ 7],v[11],v[15]);
|
||||
G(r,4,m,v[ 0],v[ 5],v[10],v[15]);
|
||||
G(r,5,m,v[ 1],v[ 6],v[11],v[12]);
|
||||
G(r,6,m,v[ 2],v[ 7],v[ 8],v[13]);
|
||||
G(r,7,m,v[ 3],v[ 4],v[ 9],v[14]);
|
||||
}
|
||||
|
||||
for( size_t i = 0; i < 8; ++i )
|
||||
S->h[i] = S->h[i] ^ v[i] ^ v[i + 8];
|
||||
}
|
||||
|
||||
|
||||
void blake2s_update( blake2s_state *S, const byte *in, size_t inlen )
|
||||
{
|
||||
while( inlen > 0 )
|
||||
{
|
||||
size_t left = S->buflen;
|
||||
size_t fill = 2 * BLAKE2S_BLOCKBYTES - left;
|
||||
|
||||
if( inlen > fill )
|
||||
{
|
||||
memcpy( S->buf + left, in, fill ); // Fill buffer
|
||||
S->buflen += fill;
|
||||
blake2s_increment_counter( S, BLAKE2S_BLOCKBYTES );
|
||||
|
||||
#ifdef USE_SSE
|
||||
#ifdef _WIN_32 // We use SSSE3 _mm_shuffle_epi8 only in x64 mode.
|
||||
if (_SSE_Version>=SSE_SSE2)
|
||||
#else
|
||||
if (_SSE_Version>=SSE_SSSE3)
|
||||
#endif
|
||||
blake2s_compress_sse( S, S->buf );
|
||||
else
|
||||
blake2s_compress( S, S->buf ); // Compress
|
||||
#else
|
||||
blake2s_compress( S, S->buf ); // Compress
|
||||
#endif
|
||||
|
||||
memcpy( S->buf, S->buf + BLAKE2S_BLOCKBYTES, BLAKE2S_BLOCKBYTES ); // Shift buffer left
|
||||
S->buflen -= BLAKE2S_BLOCKBYTES;
|
||||
in += fill;
|
||||
inlen -= fill;
|
||||
}
|
||||
else // inlen <= fill
|
||||
{
|
||||
memcpy( S->buf + left, in, (size_t)inlen );
|
||||
S->buflen += (size_t)inlen; // Be lazy, do not compress
|
||||
in += inlen;
|
||||
inlen -= inlen;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void blake2s_final( blake2s_state *S, byte *digest )
|
||||
{
|
||||
if( S->buflen > BLAKE2S_BLOCKBYTES )
|
||||
{
|
||||
blake2s_increment_counter( S, BLAKE2S_BLOCKBYTES );
|
||||
blake2s_compress( S, S->buf );
|
||||
S->buflen -= BLAKE2S_BLOCKBYTES;
|
||||
memcpy( S->buf, S->buf + BLAKE2S_BLOCKBYTES, S->buflen );
|
||||
}
|
||||
|
||||
blake2s_increment_counter( S, ( uint32 )S->buflen );
|
||||
blake2s_set_lastblock( S );
|
||||
memset( S->buf + S->buflen, 0, 2 * BLAKE2S_BLOCKBYTES - S->buflen ); /* Padding */
|
||||
blake2s_compress( S, S->buf );
|
||||
|
||||
for( int i = 0; i < 8; ++i ) /* Output full hash */
|
||||
RawPut4( S->h[i], digest + 4 * i );
|
||||
}
|
||||
|
|
@ -0,0 +1,101 @@
|
|||
// Based on public domain code written in 2012 by Samuel Neves
|
||||
#ifndef _RAR_BLAKE2_
|
||||
#define _RAR_BLAKE2_
|
||||
|
||||
#define BLAKE2_DIGEST_SIZE 32
|
||||
|
||||
enum blake2s_constant
|
||||
{
|
||||
BLAKE2S_BLOCKBYTES = 64,
|
||||
BLAKE2S_OUTBYTES = 32
|
||||
};
|
||||
|
||||
|
||||
// Alignment to 64 improves performance of both SSE and non-SSE versions.
|
||||
// Alignment to n*16 is required for SSE version, so we selected 64.
|
||||
// We use the custom alignment scheme instead of __declspec(align(x)),
|
||||
// because it is less compiler dependent. Also the compiler directive
|
||||
// does not help if structure is a member of class allocated through
|
||||
// 'new' operator.
|
||||
struct blake2s_state
|
||||
{
|
||||
enum { BLAKE_ALIGNMENT = 64 };
|
||||
|
||||
// buffer and uint32 h[8], t[2], f[2];
|
||||
enum { BLAKE_DATA_SIZE = 48 + 2 * BLAKE2S_BLOCKBYTES };
|
||||
|
||||
byte ubuf[BLAKE_DATA_SIZE + BLAKE_ALIGNMENT];
|
||||
|
||||
byte *buf; // byte buf[2 * BLAKE2S_BLOCKBYTES].
|
||||
uint32 *h, *t, *f; // uint32 h[8], t[2], f[2].
|
||||
|
||||
size_t buflen;
|
||||
byte last_node;
|
||||
|
||||
blake2s_state()
|
||||
{
|
||||
set_pointers();
|
||||
}
|
||||
|
||||
// Required when we declare and assign in the same command.
|
||||
blake2s_state(blake2s_state &st)
|
||||
{
|
||||
set_pointers();
|
||||
*this=st;
|
||||
}
|
||||
|
||||
void set_pointers()
|
||||
{
|
||||
// Set aligned pointers. Must be done in constructor, not in Init(),
|
||||
// so assignments like 'blake2sp_state res=blake2ctx' work correctly
|
||||
// even if blake2sp_init is not called for 'res'.
|
||||
buf = (byte *) ALIGN_VALUE(ubuf, BLAKE_ALIGNMENT);
|
||||
h = (uint32 *) (buf + 2 * BLAKE2S_BLOCKBYTES);
|
||||
t = h + 8;
|
||||
f = t + 2;
|
||||
}
|
||||
|
||||
void init()
|
||||
{
|
||||
memset( ubuf, 0, sizeof( ubuf ) );
|
||||
buflen = 0;
|
||||
last_node = 0;
|
||||
}
|
||||
|
||||
// Since we use pointers, the default = would work incorrectly.
|
||||
blake2s_state& operator = (blake2s_state &st)
|
||||
{
|
||||
if (this != &st)
|
||||
{
|
||||
memcpy(buf, st.buf, BLAKE_DATA_SIZE);
|
||||
buflen = st.buflen;
|
||||
last_node = st.last_node;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#ifdef RAR_SMP
|
||||
class ThreadPool;
|
||||
#endif
|
||||
|
||||
struct blake2sp_state
|
||||
{
|
||||
blake2s_state S[8];
|
||||
blake2s_state R;
|
||||
byte buf[8 * BLAKE2S_BLOCKBYTES];
|
||||
size_t buflen;
|
||||
|
||||
#ifdef RAR_SMP
|
||||
ThreadPool *ThPool;
|
||||
uint MaxThreads;
|
||||
#endif
|
||||
};
|
||||
|
||||
void blake2sp_init( blake2sp_state *S );
|
||||
void blake2sp_update( blake2sp_state *S, const byte *in, size_t inlen );
|
||||
void blake2sp_final( blake2sp_state *S, byte *digest );
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,127 @@
|
|||
// Based on public domain code written in 2012 by Samuel Neves
|
||||
|
||||
extern const byte blake2s_sigma[10][16];
|
||||
|
||||
// Initialization vector.
|
||||
static __m128i blake2s_IV_0_3, blake2s_IV_4_7;
|
||||
|
||||
#ifdef _WIN_64
|
||||
// Constants for cyclic rotation. Used in 64-bit mode in mm_rotr_epi32 macro.
|
||||
static __m128i crotr8, crotr16;
|
||||
#endif
|
||||
|
||||
static void blake2s_init_sse()
|
||||
{
|
||||
// We cannot initialize these 128 bit variables in place when declaring
|
||||
// them globally, because global scope initialization is performed before
|
||||
// our SSE check and it would make code incompatible with older non-SSE2
|
||||
// CPUs. Also we cannot initialize them as static inside of function
|
||||
// using these variables, because SSE static initialization is not thread
|
||||
// safe: first thread starts initialization and sets "init done" flag even
|
||||
// if it is not done yet, second thread can attempt to access half-init
|
||||
// SSE data. So we moved init code here.
|
||||
|
||||
blake2s_IV_0_3 = _mm_setr_epi32( 0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A );
|
||||
blake2s_IV_4_7 = _mm_setr_epi32( 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19 );
|
||||
|
||||
#ifdef _WIN_64
|
||||
crotr8 = _mm_set_epi8( 12, 15, 14, 13, 8, 11, 10, 9, 4, 7, 6, 5, 0, 3, 2, 1 );
|
||||
crotr16 = _mm_set_epi8( 13, 12, 15, 14, 9, 8, 11, 10, 5, 4, 7, 6, 1, 0, 3, 2 );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#define LOAD(p) _mm_load_si128( (__m128i *)(p) )
|
||||
#define STORE(p,r) _mm_store_si128((__m128i *)(p), r)
|
||||
|
||||
#ifdef _WIN_32
|
||||
// 32-bit mode has less SSE2 registers and in MSVC2008 it is more efficient
|
||||
// to not use _mm_shuffle_epi8 here.
|
||||
#define mm_rotr_epi32(r, c) ( \
|
||||
_mm_xor_si128(_mm_srli_epi32( (r), c ),_mm_slli_epi32( (r), 32-c )) )
|
||||
#else
|
||||
#define mm_rotr_epi32(r, c) ( \
|
||||
c==8 ? _mm_shuffle_epi8(r,crotr8) \
|
||||
: c==16 ? _mm_shuffle_epi8(r,crotr16) \
|
||||
: _mm_xor_si128(_mm_srli_epi32( (r), c ),_mm_slli_epi32( (r), 32-c )) )
|
||||
#endif
|
||||
|
||||
|
||||
#define G1(row1,row2,row3,row4,buf) \
|
||||
row1 = _mm_add_epi32( _mm_add_epi32( row1, buf), row2 ); \
|
||||
row4 = _mm_xor_si128( row4, row1 ); \
|
||||
row4 = mm_rotr_epi32(row4, 16); \
|
||||
row3 = _mm_add_epi32( row3, row4 ); \
|
||||
row2 = _mm_xor_si128( row2, row3 ); \
|
||||
row2 = mm_rotr_epi32(row2, 12);
|
||||
|
||||
#define G2(row1,row2,row3,row4,buf) \
|
||||
row1 = _mm_add_epi32( _mm_add_epi32( row1, buf), row2 ); \
|
||||
row4 = _mm_xor_si128( row4, row1 ); \
|
||||
row4 = mm_rotr_epi32(row4, 8); \
|
||||
row3 = _mm_add_epi32( row3, row4 ); \
|
||||
row2 = _mm_xor_si128( row2, row3 ); \
|
||||
row2 = mm_rotr_epi32(row2, 7);
|
||||
|
||||
#define DIAGONALIZE(row1,row2,row3,row4) \
|
||||
row4 = _mm_shuffle_epi32( row4, _MM_SHUFFLE(2,1,0,3) ); \
|
||||
row3 = _mm_shuffle_epi32( row3, _MM_SHUFFLE(1,0,3,2) ); \
|
||||
row2 = _mm_shuffle_epi32( row2, _MM_SHUFFLE(0,3,2,1) );
|
||||
|
||||
#define UNDIAGONALIZE(row1,row2,row3,row4) \
|
||||
row4 = _mm_shuffle_epi32( row4, _MM_SHUFFLE(0,3,2,1) ); \
|
||||
row3 = _mm_shuffle_epi32( row3, _MM_SHUFFLE(1,0,3,2) ); \
|
||||
row2 = _mm_shuffle_epi32( row2, _MM_SHUFFLE(2,1,0,3) );
|
||||
|
||||
#ifdef _WIN_64
|
||||
// MSVC 2008 in x64 mode expands _mm_set_epi32 to store to stack and load
|
||||
// from stack operations, which are slower than this code.
|
||||
#define _mm_set_epi32(i3,i2,i1,i0) \
|
||||
_mm_unpacklo_epi32(_mm_unpacklo_epi32(_mm_cvtsi32_si128(i0),_mm_cvtsi32_si128(i2)), \
|
||||
_mm_unpacklo_epi32(_mm_cvtsi32_si128(i1),_mm_cvtsi32_si128(i3)))
|
||||
#endif
|
||||
|
||||
// Original BLAKE2 SSE4.1 message loading code was a little slower in x86 mode
|
||||
// and about the same in x64 mode in our test. Perhaps depends on compiler.
|
||||
#define SSE_ROUND(m,row,r) \
|
||||
{ \
|
||||
__m128i buf; \
|
||||
buf=_mm_set_epi32(m[blake2s_sigma[r][6]],m[blake2s_sigma[r][4]],m[blake2s_sigma[r][2]],m[blake2s_sigma[r][0]]); \
|
||||
G1(row[0],row[1],row[2],row[3],buf); \
|
||||
buf=_mm_set_epi32(m[blake2s_sigma[r][7]],m[blake2s_sigma[r][5]],m[blake2s_sigma[r][3]],m[blake2s_sigma[r][1]]); \
|
||||
G2(row[0],row[1],row[2],row[3],buf); \
|
||||
DIAGONALIZE(row[0],row[1],row[2],row[3]); \
|
||||
buf=_mm_set_epi32(m[blake2s_sigma[r][14]],m[blake2s_sigma[r][12]],m[blake2s_sigma[r][10]],m[blake2s_sigma[r][8]]); \
|
||||
G1(row[0],row[1],row[2],row[3],buf); \
|
||||
buf=_mm_set_epi32(m[blake2s_sigma[r][15]],m[blake2s_sigma[r][13]],m[blake2s_sigma[r][11]],m[blake2s_sigma[r][9]]); \
|
||||
G2(row[0],row[1],row[2],row[3],buf); \
|
||||
UNDIAGONALIZE(row[0],row[1],row[2],row[3]); \
|
||||
}
|
||||
|
||||
|
||||
static int blake2s_compress_sse( blake2s_state *S, const byte block[BLAKE2S_BLOCKBYTES] )
|
||||
{
|
||||
__m128i row[4];
|
||||
__m128i ff0, ff1;
|
||||
|
||||
const uint32 *m = ( uint32 * )block;
|
||||
|
||||
row[0] = ff0 = LOAD( &S->h[0] );
|
||||
row[1] = ff1 = LOAD( &S->h[4] );
|
||||
|
||||
row[2] = blake2s_IV_0_3;
|
||||
row[3] = _mm_xor_si128( blake2s_IV_4_7, LOAD( &S->t[0] ) );
|
||||
SSE_ROUND( m, row, 0 );
|
||||
SSE_ROUND( m, row, 1 );
|
||||
SSE_ROUND( m, row, 2 );
|
||||
SSE_ROUND( m, row, 3 );
|
||||
SSE_ROUND( m, row, 4 );
|
||||
SSE_ROUND( m, row, 5 );
|
||||
SSE_ROUND( m, row, 6 );
|
||||
SSE_ROUND( m, row, 7 );
|
||||
SSE_ROUND( m, row, 8 );
|
||||
SSE_ROUND( m, row, 9 );
|
||||
STORE( &S->h[0], _mm_xor_si128( ff0, _mm_xor_si128( row[0], row[2] ) ) );
|
||||
STORE( &S->h[4], _mm_xor_si128( ff1, _mm_xor_si128( row[1], row[3] ) ) );
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,153 @@
|
|||
/*
|
||||
BLAKE2 reference source code package - reference C implementations
|
||||
|
||||
Written in 2012 by Samuel Neves <sneves@dei.uc.pt>
|
||||
|
||||
To the extent possible under law, the author(s) have dedicated all copyright
|
||||
and related and neighboring rights to this software to the public domain
|
||||
worldwide. This software is distributed without any warranty.
|
||||
|
||||
You should have received a copy of the CC0 Public Domain Dedication along with
|
||||
this software. If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
|
||||
*/
|
||||
|
||||
#define PARALLELISM_DEGREE 8
|
||||
|
||||
void blake2sp_init( blake2sp_state *S )
|
||||
{
|
||||
memset( S->buf, 0, sizeof( S->buf ) );
|
||||
S->buflen = 0;
|
||||
|
||||
blake2s_init_param( &S->R, 0, 1 ); // Init root.
|
||||
|
||||
for( uint i = 0; i < PARALLELISM_DEGREE; ++i )
|
||||
blake2s_init_param( &S->S[i], i, 0 ); // Init leaf.
|
||||
|
||||
S->R.last_node = 1;
|
||||
S->S[PARALLELISM_DEGREE - 1].last_node = 1;
|
||||
}
|
||||
|
||||
|
||||
struct Blake2ThreadData
|
||||
{
|
||||
void Update();
|
||||
blake2s_state *S;
|
||||
const byte *in;
|
||||
size_t inlen;
|
||||
};
|
||||
|
||||
|
||||
void Blake2ThreadData::Update()
|
||||
{
|
||||
size_t inlen__ = inlen;
|
||||
const byte *in__ = ( const byte * )in;
|
||||
|
||||
while( inlen__ >= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES )
|
||||
{
|
||||
#ifdef USE_SSE
|
||||
// We gain 5% in i7 SSE mode by prefetching next data block.
|
||||
if (_SSE_Version>=SSE_SSE && inlen__ >= 2 * PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES)
|
||||
_mm_prefetch((char*)(in__ + PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES), _MM_HINT_T0);
|
||||
#endif
|
||||
blake2s_update( S, in__, BLAKE2S_BLOCKBYTES );
|
||||
in__ += PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;
|
||||
inlen__ -= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef RAR_SMP
|
||||
THREAD_PROC(Blake2Thread)
|
||||
{
|
||||
Blake2ThreadData *td=(Blake2ThreadData *)Data;
|
||||
td->Update();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void blake2sp_update( blake2sp_state *S, const byte *in, size_t inlen )
|
||||
{
|
||||
size_t left = S->buflen;
|
||||
size_t fill = sizeof( S->buf ) - left;
|
||||
|
||||
if( left && inlen >= fill )
|
||||
{
|
||||
memcpy( S->buf + left, in, fill );
|
||||
|
||||
for( size_t i = 0; i < PARALLELISM_DEGREE; ++i )
|
||||
blake2s_update( &S->S[i], S->buf + i * BLAKE2S_BLOCKBYTES, BLAKE2S_BLOCKBYTES );
|
||||
|
||||
in += fill;
|
||||
inlen -= fill;
|
||||
left = 0;
|
||||
}
|
||||
|
||||
Blake2ThreadData btd_array[PARALLELISM_DEGREE];
|
||||
|
||||
#ifdef RAR_SMP
|
||||
uint ThreadNumber = inlen < 0x1000 ? 1 : S->MaxThreads;
|
||||
|
||||
if (ThreadNumber==6 || ThreadNumber==7) // 6 and 7 threads work slower than 4 here.
|
||||
ThreadNumber=4;
|
||||
#else
|
||||
uint ThreadNumber=1;
|
||||
#endif
|
||||
|
||||
for (size_t id__=0;id__<PARALLELISM_DEGREE;)
|
||||
{
|
||||
for (uint Thread=0;Thread<ThreadNumber && id__<PARALLELISM_DEGREE;Thread++)
|
||||
{
|
||||
Blake2ThreadData *btd=btd_array+Thread;
|
||||
|
||||
btd->inlen = inlen;
|
||||
btd->in = in + id__ * BLAKE2S_BLOCKBYTES;
|
||||
btd->S = &S->S[id__];
|
||||
|
||||
#ifdef RAR_SMP
|
||||
if (ThreadNumber>1)
|
||||
S->ThPool->AddTask(Blake2Thread,(void*)btd);
|
||||
else
|
||||
btd->Update();
|
||||
#else
|
||||
btd->Update();
|
||||
#endif
|
||||
id__++;
|
||||
}
|
||||
#ifdef RAR_SMP
|
||||
if (S->ThPool!=NULL) // Can be NULL in -mt1 mode.
|
||||
S->ThPool->WaitDone();
|
||||
#endif // RAR_SMP
|
||||
}
|
||||
|
||||
in += inlen - inlen % ( PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES );
|
||||
inlen %= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;
|
||||
|
||||
if( inlen > 0 )
|
||||
memcpy( S->buf + left, in, (size_t)inlen );
|
||||
|
||||
S->buflen = left + (size_t)inlen;
|
||||
}
|
||||
|
||||
|
||||
void blake2sp_final( blake2sp_state *S, byte *digest )
|
||||
{
|
||||
byte hash[PARALLELISM_DEGREE][BLAKE2S_OUTBYTES];
|
||||
|
||||
for( size_t i = 0; i < PARALLELISM_DEGREE; ++i )
|
||||
{
|
||||
if( S->buflen > i * BLAKE2S_BLOCKBYTES )
|
||||
{
|
||||
size_t left = S->buflen - i * BLAKE2S_BLOCKBYTES;
|
||||
|
||||
if( left > BLAKE2S_BLOCKBYTES ) left = BLAKE2S_BLOCKBYTES;
|
||||
|
||||
blake2s_update( &S->S[i], S->buf + i * BLAKE2S_BLOCKBYTES, left );
|
||||
}
|
||||
|
||||
blake2s_final( &S->S[i], hash[i] );
|
||||
}
|
||||
|
||||
for( size_t i = 0; i < PARALLELISM_DEGREE; ++i )
|
||||
blake2s_update( &S->R, hash[i], BLAKE2S_OUTBYTES );
|
||||
|
||||
blake2s_final( &S->R, digest );
|
||||
}
|
|
@ -18,9 +18,10 @@ void RangeCoder::InitDecoder(Unpack *UnpackRead)
|
|||
}
|
||||
|
||||
|
||||
// (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=-low&(BOT-1)),1)) \
|
||||
while ((low^(low+range))<TOP || range<BOT && ((range=-(int)low&(BOT-1)),1)) \
|
||||
{ \
|
||||
code=(code << 8) | read->GetChar(); \
|
||||
range <<= 8; \
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
* Contents: 'Carryless rangecoder' by Dmitry Subbotin *
|
||||
****************************************************************************/
|
||||
|
||||
const uint TOP=1 << 24, BOT=1 << 15;
|
||||
|
||||
class RangeCoder
|
||||
{
|
||||
|
|
|
@ -1,36 +1,50 @@
|
|||
#ifndef _RAR_COMPRESS_
|
||||
#define _RAR_COMPRESS_
|
||||
|
||||
class ComprDataIO;
|
||||
class PackingFileTable;
|
||||
// Combine pack and unpack constants to class to avoid polluting global
|
||||
// namespace with numerous short names.
|
||||
class PackDef
|
||||
{
|
||||
public:
|
||||
static const uint MAX_LZ_MATCH = 0x1001;
|
||||
static const uint MAX3_LZ_MATCH = 0x101; // Maximum match length for RAR v3.
|
||||
static const uint LOW_DIST_REP_COUNT = 16;
|
||||
|
||||
#define CODEBUFSIZE 0x4000
|
||||
#define MAXWINSIZE 0x400000
|
||||
#define MAXWINMASK (MAXWINSIZE-1)
|
||||
static const uint NC = 306; /* alphabet = {0, 1, 2, ..., NC - 1} */
|
||||
static const uint DC = 64;
|
||||
static const uint LDC = 16;
|
||||
static const uint RC = 44;
|
||||
static const uint HUFF_TABLE_SIZE = NC + DC + RC + LDC;
|
||||
static const uint BC = 20;
|
||||
|
||||
#define LOW_DIST_REP_COUNT 16
|
||||
static const uint NC30 = 299; /* alphabet = {0, 1, 2, ..., NC - 1} */
|
||||
static const uint DC30 = 60;
|
||||
static const uint LDC30 = 17;
|
||||
static const uint RC30 = 28;
|
||||
static const uint BC30 = 20;
|
||||
static const uint HUFF_TABLE_SIZE30 = NC30 + DC30 + RC30 + LDC30;
|
||||
|
||||
#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
|
||||
static const uint NC20 = 298; /* alphabet = {0, 1, 2, ..., NC - 1} */
|
||||
static const uint DC20 = 48;
|
||||
static const uint RC20 = 28;
|
||||
static const uint BC20 = 19;
|
||||
static const uint MC20 = 257;
|
||||
|
||||
#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.
|
||||
static const uint LARGEST_TABLE_SIZE = 306;
|
||||
|
||||
enum {CODE_HUFFMAN,CODE_LZ,CODE_LZ2,CODE_REPEATLZ,CODE_CACHELZ,
|
||||
CODE_STARTFILE,CODE_ENDFILE,CODE_VM,CODE_VMDATA};
|
||||
enum {
|
||||
CODE_HUFFMAN, CODE_LZ, CODE_REPEATLZ, CODE_CACHELZ, CODE_STARTFILE,
|
||||
CODE_ENDFILE, CODE_FILTER, CODE_FILTERDATA
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
enum FilterType {
|
||||
FILTER_NONE, FILTER_PPM /*dummy*/, FILTER_E8, FILTER_E8E9,
|
||||
FILTER_UPCASETOLOW, FILTER_AUDIO, FILTER_RGB, FILTER_DELTA,
|
||||
FILTER_ITANIUM, FILTER_E8E9V2
|
||||
// These values must not be changed, because we use them directly
|
||||
// in RAR5 compression and decompression code.
|
||||
FILTER_DELTA=0, FILTER_E8, FILTER_E8E9, FILTER_ARM,
|
||||
FILTER_AUDIO, FILTER_RGB, FILTER_ITANIUM, FILTER_PPM, FILTER_NONE
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,62 +1,90 @@
|
|||
// 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"
|
||||
|
||||
uint CRCTab[256];
|
||||
uint crc_tables[8][256]; // Tables for Slicing-by-8.
|
||||
|
||||
void InitCRC()
|
||||
|
||||
// Build the classic CRC32 lookup table.
|
||||
// We also provide this function to legacy RAR and ZIP decryption code.
|
||||
void InitCRC32(uint *CRCTab)
|
||||
{
|
||||
for (int I=0;I<256;I++)
|
||||
if (CRCTab[1]!=0)
|
||||
return;
|
||||
for (uint I=0;I<256;I++)
|
||||
{
|
||||
uint C=I;
|
||||
for (int J=0;J<8;J++)
|
||||
C=(C & 1) ? (C>>1)^0xEDB88320L : (C>>1);
|
||||
for (uint J=0;J<8;J++)
|
||||
C=(C & 1) ? (C>>1)^0xEDB88320 : (C>>1);
|
||||
CRCTab[I]=C;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
uint CRC(uint StartCRC,const void *Addr,size_t Size)
|
||||
void InitCRCTables()
|
||||
{
|
||||
InitCRC32(crc_tables[0]);
|
||||
|
||||
for (uint I=0;I<256;I++) // Build additional lookup tables.
|
||||
{
|
||||
uint C=crc_tables[0][I];
|
||||
for (uint J=1;J<8;J++)
|
||||
{
|
||||
C=crc_tables[0][(byte)C]^(C>>8);
|
||||
crc_tables[J][I]=C;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint CRC32(uint StartCRC,const void *Addr,size_t Size)
|
||||
{
|
||||
// Always initialized ahead of time, and this func call makes it a non-leaf func.
|
||||
if (false)
|
||||
if (CRCTab[1]==0)
|
||||
InitCRC();
|
||||
byte *Data=(byte *)Addr;
|
||||
#if defined(LITTLE_ENDIAN) && defined(PRESENT_INT32) && defined(ALLOW_NOT_ALIGNED_INT)
|
||||
|
||||
#ifdef _MSC_VER
|
||||
// avoid a warning about 'Data' pointer truncation in 64 bit mode
|
||||
#pragma warning( disable : 4311 )
|
||||
#endif
|
||||
// Align Data to 8 for better performance.
|
||||
for (;Size>0 && ((size_t)Data & 7);Size--,Data++)
|
||||
StartCRC=crc_tables[0][(byte)(StartCRC^Data[0])]^(StartCRC>>8);
|
||||
|
||||
while (Size>0 && ((long)Data & 7))
|
||||
{
|
||||
StartCRC=CRCTab[(byte)(StartCRC^Data[0])]^(StartCRC>>8);
|
||||
Size--;
|
||||
Data++;
|
||||
}
|
||||
while (Size>=8)
|
||||
for (;Size>=8;Size-=8,Data+=8)
|
||||
{
|
||||
#ifdef BIG_ENDIAN
|
||||
StartCRC ^= Data[0]|(Data[1] << 8)|(Data[2] << 16)|(Data[3] << 24);
|
||||
uint NextData = Data[4]|(Data[5] << 8)|(Data[6] << 16)|(Data[7] << 24);
|
||||
#else
|
||||
StartCRC ^= *(uint32 *) Data;
|
||||
StartCRC=CRCTab[(byte)StartCRC]^(StartCRC>>8);
|
||||
StartCRC=CRCTab[(byte)StartCRC]^(StartCRC>>8);
|
||||
StartCRC=CRCTab[(byte)StartCRC]^(StartCRC>>8);
|
||||
StartCRC=CRCTab[(byte)StartCRC]^(StartCRC>>8);
|
||||
StartCRC^=*(uint32 *)(Data+4);
|
||||
StartCRC=CRCTab[(byte)StartCRC]^(StartCRC>>8);
|
||||
StartCRC=CRCTab[(byte)StartCRC]^(StartCRC>>8);
|
||||
StartCRC=CRCTab[(byte)StartCRC]^(StartCRC>>8);
|
||||
StartCRC=CRCTab[(byte)StartCRC]^(StartCRC>>8);
|
||||
Data+=8;
|
||||
Size-=8;
|
||||
}
|
||||
uint NextData = *(uint32 *) (Data +4);
|
||||
#endif
|
||||
for (size_t I=0;I<Size;I++)
|
||||
StartCRC=CRCTab[(byte)(StartCRC^Data[I])]^(StartCRC>>8);
|
||||
return(StartCRC);
|
||||
StartCRC = crc_tables[7][(byte) StartCRC ] ^
|
||||
crc_tables[6][(byte)(StartCRC >> 8) ] ^
|
||||
crc_tables[5][(byte)(StartCRC >> 16)] ^
|
||||
crc_tables[4][(byte)(StartCRC >> 24)] ^
|
||||
crc_tables[3][(byte) NextData ] ^
|
||||
crc_tables[2][(byte)(NextData >>8 ) ] ^
|
||||
crc_tables[1][(byte)(NextData >> 16)] ^
|
||||
crc_tables[0][(byte)(NextData >> 24)];
|
||||
}
|
||||
|
||||
for (;Size>0;Size--,Data++) // Process left data.
|
||||
StartCRC=crc_tables[0][(byte)(StartCRC^Data[0])]^(StartCRC>>8);
|
||||
|
||||
return StartCRC;
|
||||
}
|
||||
|
||||
|
||||
#ifndef SFX_MODULE
|
||||
ushort OldCRC(ushort StartCRC,const void *Addr,size_t Size)
|
||||
// For RAR 1.4 archives in case somebody still has them.
|
||||
ushort Checksum14(ushort StartCRC,const void *Addr,size_t Size)
|
||||
{
|
||||
byte *Data=(byte *)Addr;
|
||||
for (size_t I=0;I<Size;I++)
|
||||
|
@ -64,6 +92,6 @@ ushort OldCRC(ushort StartCRC,const void *Addr,size_t Size)
|
|||
StartCRC=(StartCRC+Data[I])&0xffff;
|
||||
StartCRC=((StartCRC<<1)|(StartCRC>>15))&0xffff;
|
||||
}
|
||||
return(StartCRC);
|
||||
return StartCRC;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -11,10 +11,10 @@ EncodeFileName::EncodeFileName()
|
|||
|
||||
|
||||
|
||||
void EncodeFileName::Decode(char *Name,byte *EncName,int EncSize,wchar *NameW,
|
||||
int MaxDecSize)
|
||||
void EncodeFileName::Decode(char *Name,byte *EncName,size_t EncSize,wchar *NameW,
|
||||
size_t MaxDecSize)
|
||||
{
|
||||
int EncPos=0,DecPos=0;
|
||||
size_t EncPos=0,DecPos=0;
|
||||
byte HighByte=EncName[EncPos++];
|
||||
while (EncPos<EncSize && DecPos<MaxDecSize)
|
||||
{
|
||||
|
|
|
@ -8,13 +8,13 @@ class EncodeFileName
|
|||
|
||||
byte *EncName;
|
||||
byte Flags;
|
||||
int FlagBits;
|
||||
int FlagsPos;
|
||||
int DestSize;
|
||||
size_t FlagBits;
|
||||
size_t FlagsPos;
|
||||
size_t DestSize;
|
||||
public:
|
||||
EncodeFileName();
|
||||
int Encode(char *Name,wchar *NameW,byte *EncName);
|
||||
void Decode(char *Name,byte *EncName,int EncSize,wchar *NameW,int MaxDecSize);
|
||||
size_t Encode(char *Name,wchar *NameW,byte *EncName);
|
||||
void Decode(char *Name,byte *EncName,size_t EncSize,wchar *NameW,size_t MaxDecSize);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -9,28 +9,29 @@ unrar_err_t CmdExtract::ExtractCurrentFile( bool SkipSolid, bool check_compatibi
|
|||
{
|
||||
check( Arc.GetHeaderType() == FILE_HEAD );
|
||||
|
||||
if ( Arc.NewLhd.Flags & (LHD_SPLIT_AFTER | LHD_SPLIT_BEFORE) )
|
||||
if ( Arc.FileHead.SplitBefore || Arc.FileHead.SplitAfter )
|
||||
return unrar_err_segmented;
|
||||
|
||||
if ( Arc.NewLhd.Flags & LHD_PASSWORD )
|
||||
if ( Arc.FileHead.Encrypted )
|
||||
return unrar_err_encrypted;
|
||||
|
||||
if ( !check_compatibility_only )
|
||||
{
|
||||
check( Arc.NextBlockPos-Arc.NewLhd.FullPackSize == Arc.Tell() );
|
||||
Arc.Seek(Arc.NextBlockPos-Arc.NewLhd.FullPackSize,SEEK_SET);
|
||||
check( Arc.NextBlockPos-Arc.FileHead.PackSize == Arc.Tell() );
|
||||
Arc.Seek(Arc.NextBlockPos-Arc.FileHead.PackSize,SEEK_SET);
|
||||
}
|
||||
|
||||
// (removed lots of command-line handling)
|
||||
|
||||
#ifdef SFX_MODULE
|
||||
if ((Arc.NewLhd.UnpVer!=UNP_VER && Arc.NewLhd.UnpVer!=29) &&
|
||||
Arc.NewLhd.Method!=0x30)
|
||||
if ((Arc.FileHead.UnpVer!=UNP_VER && Arc.FileHead.UnpVer!=29) &&
|
||||
Arc.FileHead.Method!=0x30)
|
||||
#else
|
||||
if (Arc.NewLhd.UnpVer<13 || Arc.NewLhd.UnpVer>UNP_VER)
|
||||
if (Arc.FileHead.UnpVer!=VER_UNPACK5 &&
|
||||
(Arc.FileHead.UnpVer<13 || Arc.FileHead.UnpVer>VER_UNPACK))
|
||||
#endif
|
||||
{
|
||||
if (Arc.NewLhd.UnpVer>UNP_VER)
|
||||
if (Arc.FileHead.UnpVer>VER_UNPACK)
|
||||
return unrar_err_new_algo;
|
||||
return unrar_err_old_algo;
|
||||
}
|
||||
|
@ -44,12 +45,15 @@ unrar_err_t CmdExtract::ExtractCurrentFile( bool SkipSolid, bool check_compatibi
|
|||
FileCount++;
|
||||
DataIO.UnpFileCRC=Arc.OldFormat ? 0 : 0xffffffff;
|
||||
// (removed decryption)
|
||||
DataIO.SetPackedSizeToRead(Arc.NewLhd.FullPackSize);
|
||||
DataIO.UnpHash.Init(Arc.FileHead.FileHash.Type,1);
|
||||
DataIO.PackedDataHash.Init(Arc.FileHead.FileHash.Type,1);
|
||||
DataIO.SetPackedSizeToRead(Arc.FileHead.PackSize);
|
||||
DataIO.SetSkipUnpCRC(SkipSolid);
|
||||
// (removed command-line handling)
|
||||
DataIO.SetSkipUnpCRC(SkipSolid);
|
||||
|
||||
if (Arc.NewLhd.Method==0x30)
|
||||
UnstoreFile(Arc.NewLhd.FullUnpSize);
|
||||
if (Arc.FileHead.Method==0)
|
||||
UnstoreFile(Arc.FileHead.UnpSize);
|
||||
else
|
||||
{
|
||||
// Defer creation of Unpack until first extraction
|
||||
|
@ -59,24 +63,25 @@ unrar_err_t CmdExtract::ExtractCurrentFile( bool SkipSolid, bool check_compatibi
|
|||
if ( !Unp )
|
||||
return unrar_err_memory;
|
||||
|
||||
Unp->Init( NULL );
|
||||
Unp->Init(Arc.FileHead.WinSize,Arc.FileHead.Solid);
|
||||
}
|
||||
|
||||
Unp->SetDestSize(Arc.NewLhd.FullUnpSize);
|
||||
Unp->SetDestSize(Arc.FileHead.UnpSize);
|
||||
#ifndef SFX_MODULE
|
||||
if (Arc.NewLhd.UnpVer<=15)
|
||||
if (Arc.FileHead.UnpVer>=13 && Arc.FileHead.UnpVer<=15)
|
||||
Unp->DoUnpack(15,FileCount>1 && Arc.Solid);
|
||||
else
|
||||
#endif
|
||||
Unp->DoUnpack(Arc.NewLhd.UnpVer,Arc.NewLhd.Flags & LHD_SOLID);
|
||||
Unp->DoUnpack(Arc.FileHead.UnpVer,Arc.FileHead.Flags & LHD_SOLID);
|
||||
}
|
||||
|
||||
// (no need to seek to next file)
|
||||
|
||||
if (!SkipSolid)
|
||||
{
|
||||
if ((Arc.OldFormat && UINT32(DataIO.UnpFileCRC)==UINT32(Arc.NewLhd.FileCRC)) ||
|
||||
(!Arc.OldFormat && UINT32(DataIO.UnpFileCRC)==UINT32(Arc.NewLhd.FileCRC^0xffffffff)))
|
||||
HashValue UnpHash;
|
||||
DataIO.UnpHash.Result(&UnpHash);
|
||||
if (UnpHash==Arc.FileHead.FileHash)
|
||||
{
|
||||
// CRC is correct
|
||||
}
|
||||
|
@ -93,12 +98,12 @@ unrar_err_t CmdExtract::ExtractCurrentFile( bool SkipSolid, bool check_compatibi
|
|||
}
|
||||
|
||||
|
||||
void CmdExtract::UnstoreFile(Int64 DestUnpSize)
|
||||
void CmdExtract::UnstoreFile(int64 DestUnpSize)
|
||||
{
|
||||
Buffer.Alloc((int)Min(DestUnpSize,0x10000));
|
||||
Buffer.Alloc(Min(DestUnpSize,0x10000));
|
||||
while (1)
|
||||
{
|
||||
unsigned int Code=DataIO.UnpRead(&Buffer[0],Buffer.Size());
|
||||
unsigned int Code=DataIO.UnpRead(&Buffer[0],(uint)Buffer.Size());
|
||||
if (Code==0 || (int)Code==-1)
|
||||
break;
|
||||
Code=Code<DestUnpSize ? Code:int64to32(DestUnpSize);
|
||||
|
|
|
@ -1,19 +1,29 @@
|
|||
#include "rar.hpp"
|
||||
|
||||
BitInput::BitInput()
|
||||
BitInput::BitInput(bool AllocBuffer)
|
||||
{
|
||||
InBuf = (byte*) rarmalloc( MAX_SIZE );
|
||||
ExternalBuffer=false;
|
||||
if (AllocBuffer)
|
||||
{
|
||||
// getbits32 attempts to read data from InAddr, ... InAddr+3 positions.
|
||||
// So let's allocate 3 additional bytes for situation, when we need to
|
||||
// read only 1 byte from the last position of buffer and avoid a crash
|
||||
// from access to next 3 bytes, which contents we do not need.
|
||||
size_t BufSize=MAX_SIZE+3;
|
||||
InBuf=new byte[BufSize];
|
||||
|
||||
// Otherwise getbits() reads uninitialized memory
|
||||
// TODO: instead of clearing entire block, just clear last two
|
||||
// bytes after reading from file
|
||||
if ( InBuf )
|
||||
memset( InBuf, 0, MAX_SIZE );
|
||||
// Ensure that we get predictable results when accessing bytes in area
|
||||
// not filled with read data.
|
||||
memset(InBuf,0,BufSize);
|
||||
}
|
||||
else
|
||||
InBuf=NULL;
|
||||
}
|
||||
|
||||
BitInput::~BitInput()
|
||||
{
|
||||
rarfree( InBuf );
|
||||
if (!ExternalBuffer)
|
||||
delete[] InBuf;
|
||||
}
|
||||
|
||||
void BitInput::handle_mem_error( Rar_Error_Handler& ErrHandler )
|
||||
|
@ -22,13 +32,25 @@ void BitInput::handle_mem_error( Rar_Error_Handler& ErrHandler )
|
|||
ErrHandler.MemoryError();
|
||||
}
|
||||
|
||||
void BitInput::faddbits(int Bits)
|
||||
void BitInput::faddbits(uint Bits)
|
||||
{
|
||||
// Function wrapped version of inline addbits to save code size.
|
||||
addbits(Bits);
|
||||
}
|
||||
|
||||
|
||||
unsigned int BitInput::fgetbits()
|
||||
uint BitInput::fgetbits()
|
||||
{
|
||||
// Function wrapped version of inline getbits to save code size.
|
||||
return(getbits());
|
||||
}
|
||||
|
||||
|
||||
void BitInput::SetExternalBuffer(byte *Buf)
|
||||
{
|
||||
if (InBuf!=NULL && !ExternalBuffer)
|
||||
delete[] InBuf;
|
||||
InBuf=Buf;
|
||||
ExternalBuffer=true;
|
||||
}
|
||||
|
||||
|
|
|
@ -5,36 +5,66 @@ class BitInput
|
|||
: public Rar_Allocator
|
||||
{
|
||||
public:
|
||||
enum BufferSize {MAX_SIZE=0x8000};
|
||||
protected:
|
||||
int InAddr,InBit;
|
||||
enum BufferSize {MAX_SIZE=0x8000}; // Size of input buffer.
|
||||
|
||||
int InAddr; // Curent byte position in the buffer.
|
||||
int InBit; // Current bit position in the current byte.
|
||||
|
||||
bool ExternalBuffer;
|
||||
public:
|
||||
BitInput();
|
||||
BitInput(bool AllocBuffer);
|
||||
~BitInput();
|
||||
void handle_mem_error( Rar_Error_Handler& );
|
||||
|
||||
byte *InBuf;
|
||||
byte *InBuf; // Dynamically allocated input buffer.
|
||||
|
||||
void InitBitInput()
|
||||
{
|
||||
InAddr=InBit=0;
|
||||
}
|
||||
void addbits(int Bits)
|
||||
|
||||
// Move forward by 'Bits' bits.
|
||||
void addbits(uint Bits)
|
||||
{
|
||||
Bits+=InBit;
|
||||
InAddr+=Bits>>3;
|
||||
InBit=Bits&7;
|
||||
}
|
||||
unsigned int getbits()
|
||||
|
||||
// Return 16 bits from current position in the buffer.
|
||||
// Bit at (InAddr,InBit) has the highest position in returning data.
|
||||
uint getbits()
|
||||
{
|
||||
unsigned int BitField=(uint)InBuf[InAddr] << 16;
|
||||
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(int Bits);
|
||||
unsigned int fgetbits();
|
||||
bool Overflow(int IncPtr) {return(InAddr+IncPtr>=MAX_SIZE);}
|
||||
|
||||
// Return 32 bits from current position in the buffer.
|
||||
// Bit at (InAddr,InBit) has the highest position in returning data.
|
||||
uint getbits32()
|
||||
{
|
||||
uint BitField=(uint)InBuf[InAddr] << 24;
|
||||
BitField|=(uint)InBuf[InAddr+1] << 16;
|
||||
BitField|=(uint)InBuf[InAddr+2] << 8;
|
||||
BitField|=(uint)InBuf[InAddr+3];
|
||||
BitField <<= InBit;
|
||||
BitField|=(uint)InBuf[InAddr+4] >> (8-InBit);
|
||||
return(BitField & 0xffffffff);
|
||||
}
|
||||
|
||||
void faddbits(uint Bits);
|
||||
uint fgetbits();
|
||||
|
||||
// Check if buffer has enough space for IncPtr bytes. Returns 'true'
|
||||
// if buffer will be overflown.
|
||||
bool Overflow(uint IncPtr)
|
||||
{
|
||||
return(InAddr+IncPtr>=MAX_SIZE);
|
||||
}
|
||||
|
||||
void SetExternalBuffer(byte *Buf);
|
||||
};
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,118 @@
|
|||
#include "rar.hpp"
|
||||
|
||||
void HashValue::Init(HASH_TYPE Type)
|
||||
{
|
||||
HashValue::Type=Type;
|
||||
|
||||
// Zero length data CRC32 is 0. It is important to set it when creating
|
||||
// headers with no following data like directories or symlinks.
|
||||
if (Type==HASH_RAR14 || Type==HASH_CRC32)
|
||||
CRC32=0;
|
||||
if (Type==HASH_BLAKE2)
|
||||
{
|
||||
// dd0e891776933f43c7d032b08a917e25741f8aa9a12c12e1cac8801500f2ca4f
|
||||
// is BLAKE2sp hash of empty data. We init the structure to this value,
|
||||
// so if we create a file or service header with no following data like
|
||||
// "file copy" or "symlink", we set the checksum to proper value avoiding
|
||||
// additional header type or size checks when extracting.
|
||||
static byte EmptyHash[32]={
|
||||
0xdd, 0x0e, 0x89, 0x17, 0x76, 0x93, 0x3f, 0x43,
|
||||
0xc7, 0xd0, 0x32, 0xb0, 0x8a, 0x91, 0x7e, 0x25,
|
||||
0x74, 0x1f, 0x8a, 0xa9, 0xa1, 0x2c, 0x12, 0xe1,
|
||||
0xca, 0xc8, 0x80, 0x15, 0x00, 0xf2, 0xca, 0x4f
|
||||
};
|
||||
memcpy(Digest,EmptyHash,sizeof(Digest));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool HashValue::operator == (const HashValue &cmp)
|
||||
{
|
||||
if (Type==HASH_NONE || cmp.Type==HASH_NONE)
|
||||
return true;
|
||||
if ((Type==HASH_RAR14 && cmp.Type==HASH_RAR14) ||
|
||||
(Type==HASH_CRC32 && cmp.Type==HASH_CRC32))
|
||||
return CRC32==cmp.CRC32;
|
||||
if (Type==HASH_BLAKE2 && cmp.Type==HASH_BLAKE2)
|
||||
return memcmp(Digest,cmp.Digest,sizeof(Digest))==0;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
DataHash::DataHash()
|
||||
{
|
||||
HashType=HASH_NONE;
|
||||
#ifdef RAR_SMP
|
||||
ThPool=NULL;
|
||||
MaxThreads=0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
DataHash::~DataHash()
|
||||
{
|
||||
#ifdef RAR_SMP
|
||||
DestroyThreadPool(ThPool);
|
||||
#endif
|
||||
cleandata(&blake2ctx, sizeof(blake2ctx));
|
||||
cleandata(&CurCRC32, sizeof(CurCRC32));
|
||||
}
|
||||
|
||||
|
||||
void DataHash::Init(HASH_TYPE Type,uint MaxThreads)
|
||||
{
|
||||
HashType=Type;
|
||||
if (Type==HASH_RAR14)
|
||||
CurCRC32=0;
|
||||
if (Type==HASH_CRC32)
|
||||
CurCRC32=0xffffffff; // Initial CRC32 value.
|
||||
if (Type==HASH_BLAKE2)
|
||||
blake2sp_init( &blake2ctx );
|
||||
#ifdef RAR_SMP
|
||||
DataHash::MaxThreads=Min(MaxThreads,MaxHashThreads);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void DataHash::Update(const void *Data,size_t DataSize)
|
||||
{
|
||||
#ifndef SFX_MODULE
|
||||
if (HashType==HASH_RAR14)
|
||||
CurCRC32=Checksum14((ushort)CurCRC32,Data,DataSize);
|
||||
#endif
|
||||
if (HashType==HASH_CRC32)
|
||||
CurCRC32=CRC32(CurCRC32,Data,DataSize);
|
||||
|
||||
if (HashType==HASH_BLAKE2)
|
||||
{
|
||||
#ifdef RAR_SMP
|
||||
if (MaxThreads>1 && ThPool==NULL)
|
||||
ThPool=CreateThreadPool();
|
||||
blake2ctx.ThPool=ThPool;
|
||||
blake2ctx.MaxThreads=MaxThreads;
|
||||
#endif
|
||||
blake2sp_update( &blake2ctx, (byte *)Data, DataSize);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DataHash::Result(HashValue *Result)
|
||||
{
|
||||
Result->Type=HashType;
|
||||
if (HashType==HASH_RAR14)
|
||||
Result->CRC32=CurCRC32;
|
||||
if (HashType==HASH_CRC32)
|
||||
Result->CRC32=CurCRC32^0xffffffff;
|
||||
if (HashType==HASH_BLAKE2)
|
||||
{
|
||||
// Preserve the original context, so we can continue hashing if necessary.
|
||||
blake2sp_state res=blake2ctx;
|
||||
blake2sp_final( &res, Result->Digest );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
uint DataHash::GetCRC32()
|
||||
{
|
||||
return HashType==HASH_CRC32 ? CurCRC32^0xffffffff : 0;
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
#ifndef _RAR_DATAHASH_
|
||||
#define _RAR_DATAHASH_
|
||||
|
||||
enum HASH_TYPE {HASH_NONE,HASH_RAR14,HASH_CRC32,HASH_BLAKE2};
|
||||
|
||||
struct HashValue
|
||||
{
|
||||
void Init(HASH_TYPE Type);
|
||||
bool operator == (const HashValue &cmp);
|
||||
bool operator != (const HashValue &cmp) {return !(*this==cmp);}
|
||||
|
||||
HASH_TYPE Type;
|
||||
union
|
||||
{
|
||||
uint CRC32;
|
||||
byte Digest[SHA256_DIGEST_SIZE];
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
#ifdef RAR_SMP
|
||||
class ThreadPool;
|
||||
class DataHash;
|
||||
#endif
|
||||
|
||||
|
||||
class DataHash
|
||||
{
|
||||
private:
|
||||
HASH_TYPE HashType;
|
||||
uint CurCRC32;
|
||||
blake2sp_state blake2ctx;
|
||||
|
||||
#ifdef RAR_SMP
|
||||
ThreadPool *ThPool;
|
||||
|
||||
uint MaxThreads;
|
||||
// Upper limit for maximum threads to prevent wasting threads in pool.
|
||||
static const uint MaxHashThreads=8;
|
||||
#endif
|
||||
public:
|
||||
DataHash();
|
||||
~DataHash();
|
||||
void Init(HASH_TYPE Type,uint MaxThreads);
|
||||
void Update(const void *Data,size_t DataSize);
|
||||
void Result(HashValue *Result);
|
||||
uint GetCRC32();
|
||||
bool Cmp(HashValue *CmpValue,byte *Key);
|
||||
HASH_TYPE Type() {return HashType;}
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,60 @@
|
|||
#include "rar.hpp"
|
||||
|
||||
void FileHeader::Reset(size_t SubDataSize)
|
||||
{
|
||||
SubData.Alloc(SubDataSize);
|
||||
BaseBlock::Reset();
|
||||
#ifndef SHELL_EXT
|
||||
FileHash.Init(HASH_NONE);
|
||||
#endif
|
||||
mtime.Reset();
|
||||
atime.Reset();
|
||||
ctime.Reset();
|
||||
SplitBefore=false;
|
||||
SplitAfter=false;
|
||||
|
||||
UnknownUnpSize=0;
|
||||
|
||||
SubFlags=0; // Important for RAR 3.0 subhead.
|
||||
|
||||
Encrypted=false;
|
||||
UsePswCheck=false;
|
||||
UseHashKey=false;
|
||||
Lg2Count=0;
|
||||
|
||||
Solid=false;
|
||||
Dir=false;
|
||||
WinSize=0;
|
||||
Inherited=false;
|
||||
SubBlock=false;
|
||||
CommentInHeader=false;
|
||||
Version=false;
|
||||
LargeFile=false;
|
||||
|
||||
RedirType=FSREDIR_NONE;
|
||||
UnixOwnerSet=false;
|
||||
}
|
||||
|
||||
|
||||
FileHeader& FileHeader::operator = (FileHeader &hd)
|
||||
{
|
||||
SubData.Reset();
|
||||
memcpy(this,&hd,sizeof(*this));
|
||||
SubData.CleanData();
|
||||
SubData=hd.SubData;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
void MainHeader::Reset()
|
||||
{
|
||||
HighPosAV=0;
|
||||
PosAV=0;
|
||||
CommentInHeader=false;
|
||||
PackComment=false;
|
||||
Locator=false;
|
||||
QOpenOffset=0;
|
||||
QOpenMaxSize=0;
|
||||
RROffset=0;
|
||||
RRMaxSize=0;
|
||||
}
|
|
@ -1,92 +1,161 @@
|
|||
#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_MARKHEAD3 7 // Size of RAR 4.x archive mark header.
|
||||
#define SIZEOF_MAINHEAD14 7 // Size of RAR 1.4 main archive header.
|
||||
#define SIZEOF_MAINHEAD3 13 // Size of RAR 4.x main archive header.
|
||||
#define SIZEOF_FILEHEAD14 21 // Size of RAR 1.4 file header.
|
||||
#define SIZEOF_FILEHEAD3 32 // Size of RAR 3.0 file header.
|
||||
#define SIZEOF_SHORTBLOCKHEAD 7
|
||||
#define SIZEOF_LONGBLOCKHEAD 11
|
||||
#define SIZEOF_SUBBLOCKHEAD 14
|
||||
#define SIZEOF_COMMHEAD 13
|
||||
#define SIZEOF_PROTECTHEAD 26
|
||||
#define SIZEOF_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 UNP_VER 36
|
||||
#define VER_PACK 29
|
||||
#define VER_PACK5 0
|
||||
#define VER_UNPACK 29
|
||||
#define VER_UNPACK5 0
|
||||
|
||||
#define MHD_VOLUME 0x0001
|
||||
#define MHD_COMMENT 0x0002
|
||||
#define MHD_SOLID 0x0008
|
||||
#define MHD_PASSWORD 0x0080
|
||||
#define MHD_VOLUME 0x0001U
|
||||
|
||||
#define LHD_SPLIT_BEFORE 0x0001
|
||||
#define LHD_SPLIT_AFTER 0x0002
|
||||
#define LHD_PASSWORD 0x0004
|
||||
#define LHD_COMMENT 0x0008
|
||||
#define LHD_SOLID 0x0010
|
||||
// Old style main archive comment embed into main archive header. Must not
|
||||
// be used in new archives anymore.
|
||||
#define MHD_COMMENT 0x0002U
|
||||
|
||||
#define LHD_WINDOWMASK 0x00e0
|
||||
#define LHD_DIRECTORY 0x00e0
|
||||
#define MHD_LOCK 0x0004U
|
||||
#define MHD_SOLID 0x0008U
|
||||
#define MHD_PACK_COMMENT 0x0010U
|
||||
#define MHD_NEWNUMBERING 0x0010U
|
||||
#define MHD_AV 0x0020U
|
||||
#define MHD_PROTECT 0x0040U
|
||||
#define MHD_PASSWORD 0x0080U
|
||||
#define MHD_FIRSTVOLUME 0x0100U
|
||||
|
||||
#define LHD_LARGE 0x0100
|
||||
#define LHD_UNICODE 0x0200
|
||||
#define LHD_SALT 0x0400
|
||||
#define LHD_EXTTIME 0x1000
|
||||
#define LHD_SPLIT_BEFORE 0x0001U
|
||||
#define LHD_SPLIT_AFTER 0x0002U
|
||||
#define LHD_PASSWORD 0x0004U
|
||||
|
||||
#define LONG_BLOCK 0x8000
|
||||
// Old style file comment embed into file header. Must not be used
|
||||
// in new archives anymore.
|
||||
#define LHD_COMMENT 0x0008U
|
||||
|
||||
// For non-file subheaders it denotes 'subblock having a parent file' flag.
|
||||
#define LHD_SOLID 0x0010U
|
||||
|
||||
|
||||
#define LHD_WINDOWMASK 0x00e0U
|
||||
#define LHD_WINDOW64 0x0000U
|
||||
#define LHD_WINDOW128 0x0020U
|
||||
#define LHD_WINDOW256 0x0040U
|
||||
#define LHD_WINDOW512 0x0060U
|
||||
#define LHD_WINDOW1024 0x0080U
|
||||
#define LHD_WINDOW2048 0x00a0U
|
||||
#define LHD_WINDOW4096 0x00c0U
|
||||
#define LHD_DIRECTORY 0x00e0U
|
||||
|
||||
#define LHD_LARGE 0x0100U
|
||||
#define LHD_UNICODE 0x0200U
|
||||
#define LHD_SALT 0x0400U
|
||||
#define LHD_VERSION 0x0800U
|
||||
#define LHD_EXTTIME 0x1000U
|
||||
|
||||
#define SKIP_IF_UNKNOWN 0x4000U
|
||||
#define LONG_BLOCK 0x8000U
|
||||
|
||||
#define EARC_NEXT_VOLUME 0x0001U // Not last volume.
|
||||
#define EARC_DATACRC 0x0002U // Store CRC32 of RAR archive (now is used only in volumes).
|
||||
#define EARC_REVSPACE 0x0004U // Reserve space for end of REV file 7 byte record.
|
||||
#define EARC_VOLNUMBER 0x0008U // Store a number of current volume.
|
||||
|
||||
enum HEADER_TYPE {
|
||||
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
|
||||
// RAR 5.0 header types.
|
||||
HEAD_MARK=0x00, HEAD_MAIN=0x01, HEAD_FILE=0x02, HEAD_SERVICE=0x03,
|
||||
HEAD_CRYPT=0x04, HEAD_ENDARC=0x05, HEAD_UNKNOWN=0xff,
|
||||
|
||||
// RAR 1.5 - 4.x header types.
|
||||
HEAD3_MARK=0x72,HEAD3_MAIN=0x73,HEAD3_FILE=0x74,HEAD3_CMT=0x75,
|
||||
HEAD3_AV=0x76,HEAD3_OLDSERVICE=0x77,HEAD3_PROTECT=0x78,HEAD3_SIGN=0x79,
|
||||
HEAD3_SERVICE=0x7a,HEAD3_ENDARC=0x7b
|
||||
};
|
||||
|
||||
enum { EA_HEAD=0x100,UO_HEAD=0x101,MAC_HEAD=0x102,BEEA_HEAD=0x103,
|
||||
NTACL_HEAD=0x104,STREAM_HEAD=0x105 };
|
||||
|
||||
|
||||
// Internal implementation, depends on archive format version.
|
||||
enum HOST_SYSTEM {
|
||||
// RAR 5.0 host OS
|
||||
HOST5_WINDOWS=0,HOST5_UNIX=1,
|
||||
|
||||
// RAR 3.0 host OS.
|
||||
HOST_MSDOS=0,HOST_OS2=1,HOST_WIN32=2,HOST_UNIX=3,HOST_MACOS=4,
|
||||
HOST_BEOS=5,HOST_MAX
|
||||
};
|
||||
|
||||
struct OldMainHeader
|
||||
{
|
||||
byte Mark[4];
|
||||
ushort HeadSize;
|
||||
byte Flags;
|
||||
// Unified archive format independent implementation.
|
||||
enum HOST_SYSTEM_TYPE {
|
||||
HSYS_WINDOWS, HSYS_UNIX, HSYS_UNKNOWN
|
||||
};
|
||||
|
||||
|
||||
struct OldFileHeader
|
||||
{
|
||||
uint PackSize;
|
||||
uint UnpSize;
|
||||
ushort FileCRC;
|
||||
ushort HeadSize;
|
||||
uint FileTime;
|
||||
byte FileAttr;
|
||||
byte Flags;
|
||||
byte UnpVer;
|
||||
byte NameSize;
|
||||
byte Method;
|
||||
// We also use these values in extra field, so do not modify them.
|
||||
enum FILE_SYSTEM_REDIRECT {
|
||||
FSREDIR_NONE=0, FSREDIR_UNIXSYMLINK, FSREDIR_WINSYMLINK, FSREDIR_JUNCTION,
|
||||
FSREDIR_HARDLINK, FSREDIR_FILECOPY
|
||||
};
|
||||
|
||||
|
||||
static const wchar SUBHEAD_TYPE_CMT[] = {'C', 'M', 'T', 0};
|
||||
static const wchar SUBHEAD_TYPE_QOPEN[] = {'Q', 'O', 0};
|
||||
static const wchar SUBHEAD_TYPE_ACL[] = {'A', 'C', 'L', 0};
|
||||
static const wchar SUBHEAD_TYPE_STREAM[] = {'S', 'T', 'M', 0};
|
||||
static const wchar SUBHEAD_TYPE_UOWNER[] = {'U', 'O', 'W', 0};
|
||||
static const wchar SUBHEAD_TYPE_AV[] = {'A', 'V', 0};
|
||||
static const wchar SUBHEAD_TYPE_RR[] = {'R', 'R', 0};
|
||||
static const wchar SUBHEAD_TYPE_OS2EA[] = {'E', 'A', '2', 0};
|
||||
|
||||
/* new file inherits a subblock when updating a host file */
|
||||
#define SUBHEAD_FLAGS_INHERITED 0x80000000
|
||||
|
||||
#define SUBHEAD_FLAGS_CMT_UNICODE 0x00000001
|
||||
|
||||
|
||||
struct MarkHeader
|
||||
{
|
||||
byte Mark[7];
|
||||
byte Mark[8];
|
||||
|
||||
// Following fields are virtual and not present in real blocks.
|
||||
uint HeadSize;
|
||||
};
|
||||
|
||||
|
||||
struct BaseBlock
|
||||
{
|
||||
ushort HeadCRC;
|
||||
HEADER_TYPE HeadType;//byte
|
||||
ushort Flags;
|
||||
ushort HeadSize;
|
||||
uint HeadCRC; // 'ushort' for RAR 1.5.
|
||||
HEADER_TYPE HeaderType; // 1 byte for RAR 1.5.
|
||||
uint Flags; // 'ushort' for RAR 1.5.
|
||||
uint HeadSize; // 'ushort' for RAR 1.5, up to 2 MB for RAR 5.0.
|
||||
|
||||
bool SkipIfUnknown;
|
||||
|
||||
void Reset()
|
||||
{
|
||||
SkipIfUnknown=false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct BlockHeader:BaseBlock
|
||||
{
|
||||
union {
|
||||
uint DataSize;
|
||||
uint PackSize;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
|
@ -94,46 +163,139 @@ struct MainHeader:BaseBlock
|
|||
{
|
||||
ushort HighPosAV;
|
||||
uint PosAV;
|
||||
bool CommentInHeader;
|
||||
bool PackComment; // For RAR 1.4 archive format only.
|
||||
bool Locator;
|
||||
uint64 QOpenOffset; // Offset of quick list record.
|
||||
uint64 QOpenMaxSize; // Maximum size of QOpen offset in locator extra field.
|
||||
uint64 RROffset; // Offset of recovery record.
|
||||
uint64 RRMaxSize; // Maximum size of RR offset in locator extra field.
|
||||
void Reset();
|
||||
};
|
||||
|
||||
#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*4]; // *4 to avoid using lots of stack in arcread
|
||||
wchar FileNameW[NM];
|
||||
/* optional */
|
||||
byte Salt[SALT_SIZE];
|
||||
wchar FileName[NM];
|
||||
|
||||
Array<byte> SubData;
|
||||
|
||||
RarTime mtime;
|
||||
/* dummy */
|
||||
Int64 FullPackSize;
|
||||
Int64 FullUnpSize;
|
||||
RarTime ctime;
|
||||
RarTime atime;
|
||||
|
||||
int64 PackSize;
|
||||
int64 UnpSize;
|
||||
int64 MaxSize; // Reserve size bytes for vint of this size.
|
||||
|
||||
HashValue FileHash;
|
||||
|
||||
uint FileFlags;
|
||||
|
||||
bool SplitBefore;
|
||||
bool SplitAfter;
|
||||
|
||||
bool UnknownUnpSize;
|
||||
|
||||
bool Encrypted;
|
||||
bool UsePswCheck;
|
||||
|
||||
// Use HMAC calculated from HashKey and checksum instead of plain checksum.
|
||||
bool UseHashKey;
|
||||
|
||||
uint Lg2Count; // Log2 of PBKDF2 repetition count.
|
||||
|
||||
bool Solid;
|
||||
bool Dir;
|
||||
bool CommentInHeader; // RAR 2.0 file comment.
|
||||
bool Version; // name.ext;ver file name containing the version number.
|
||||
size_t WinSize;
|
||||
bool Inherited; // New file inherits a subblock when updating a host file (for subblocks only).
|
||||
|
||||
// 'true' if file sizes use 8 bytes instead of 4. Not used in RAR 5.0.
|
||||
bool LargeFile;
|
||||
|
||||
// 'true' for HEAD_SERVICE block, which is a child of preceding file block.
|
||||
// RAR 4.x uses 'solid' flag to indicate child subheader blocks in archives.
|
||||
bool SubBlock;
|
||||
|
||||
HOST_SYSTEM_TYPE HSType;
|
||||
|
||||
FILE_SYSTEM_REDIRECT RedirType;
|
||||
wchar RedirName[NM];
|
||||
bool DirTarget;
|
||||
|
||||
bool UnixOwnerSet,UnixOwnerNumeric,UnixGroupNumeric;
|
||||
char UnixOwnerName[256],UnixGroupName[256];
|
||||
#ifdef _UNIX
|
||||
uid_t UnixOwnerID;
|
||||
uid_t UnixGroupID;
|
||||
#else // Need these Unix fields in Windows too for 'list' command.
|
||||
uint UnixOwnerID;
|
||||
uint UnixGroupID;
|
||||
#endif
|
||||
|
||||
void Reset(size_t SubDataSize=0);
|
||||
|
||||
bool CmpName(const wchar *Name)
|
||||
{
|
||||
return(my_wcscmp(FileName,Name)==0);
|
||||
}
|
||||
|
||||
FileHeader& operator = (FileHeader &hd);
|
||||
};
|
||||
|
||||
|
||||
struct EndArcHeader:BaseBlock
|
||||
{
|
||||
// Optional CRC32 of entire archive up to start of EndArcHeader block.
|
||||
// Present in RAR 4.x archives if EARC_DATACRC flag is set.
|
||||
uint ArcDataCRC;
|
||||
|
||||
uint VolNumber; // Optional number of current volume.
|
||||
|
||||
// 7 additional zero bytes can be stored here if EARC_REVSPACE is set.
|
||||
|
||||
bool NextVolume; // Not last volume.
|
||||
bool DataCRC;
|
||||
bool RevSpace;
|
||||
bool StoreVolNumber;
|
||||
void Reset()
|
||||
{
|
||||
BaseBlock::Reset();
|
||||
NextVolume=false;
|
||||
DataCRC=false;
|
||||
RevSpace=false;
|
||||
StoreVolNumber=false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// SubBlockHeader and its successors were used in RAR 2.x format.
|
||||
// RAR 3.x uses FileHeader with NEWSUB_HEAD HeadType for subblocks.
|
||||
// RAR 4.x uses FileHeader with HEAD_SERVICE HeaderType for subblocks.
|
||||
struct SubBlockHeader:BlockHeader
|
||||
{
|
||||
ushort SubType;
|
||||
byte Level;
|
||||
};
|
||||
|
||||
|
||||
struct CommentHeader:BaseBlock
|
||||
{
|
||||
ushort UnpSize;
|
||||
byte UnpVer;
|
||||
byte Method;
|
||||
ushort CommCRC;
|
||||
};
|
||||
|
||||
|
||||
struct ProtectHeader:BlockHeader
|
||||
{
|
||||
byte Version;
|
||||
|
@ -142,4 +304,59 @@ struct ProtectHeader:BlockHeader
|
|||
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[256];
|
||||
char GroupName[256];
|
||||
};
|
||||
|
||||
|
||||
struct EAHeader:SubBlockHeader
|
||||
{
|
||||
uint UnpSize;
|
||||
byte UnpVer;
|
||||
byte Method;
|
||||
uint EACRC;
|
||||
};
|
||||
|
||||
|
||||
struct StreamHeader:SubBlockHeader
|
||||
{
|
||||
uint UnpSize;
|
||||
byte UnpVer;
|
||||
byte Method;
|
||||
uint StreamCRC;
|
||||
ushort StreamNameSize;
|
||||
char StreamName[260];
|
||||
};
|
||||
|
||||
|
||||
struct MacFInfoHeader:SubBlockHeader
|
||||
{
|
||||
uint fileType;
|
||||
uint fileCreator;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,99 @@
|
|||
#ifndef _RAR_HEADERS5_
|
||||
#define _RAR_HEADERS5_
|
||||
|
||||
#define SIZEOF_MARKHEAD5 8 // RAR 5.0 signature length.
|
||||
#define SIZEOF_SHORTBLOCKHEAD5 7 // Smallest RAR 5.0 block size.
|
||||
|
||||
// RAR 5.0 block flags common for all blocks.
|
||||
|
||||
// Additional extra area is present in the end of block header.
|
||||
#define HFL_EXTRA 0x0001
|
||||
// Additional data area is present in the end of block header.
|
||||
#define HFL_DATA 0x0002
|
||||
// Unknown blocks with this flag must be skipped when updating an archive.
|
||||
#define HFL_SKIPIFUNKNOWN 0x0004
|
||||
// Data area of this block is continuing from previous volume.
|
||||
#define HFL_SPLITBEFORE 0x0008
|
||||
// Data area of this block is continuing in next volume.
|
||||
#define HFL_SPLITAFTER 0x0010
|
||||
// Block depends on preceding file block.
|
||||
#define HFL_CHILD 0x0020
|
||||
// Preserve a child block if host is modified.
|
||||
#define HFL_INHERITED 0x0040
|
||||
|
||||
// RAR 5.0 main archive header specific flags.
|
||||
#define MHFL_VOLUME 0x0001 // Volume.
|
||||
#define MHFL_VOLNUMBER 0x0002 // Volume number field is present. True for all volumes except first.
|
||||
#define MHFL_SOLID 0x0004 // Solid archive.
|
||||
#define MHFL_PROTECT 0x0008 // Recovery record is present.
|
||||
#define MHFL_LOCK 0x0010 // Locked archive.
|
||||
|
||||
// RAR 5.0 file header specific flags.
|
||||
#define FHFL_DIRECTORY 0x0001 // Directory.
|
||||
#define FHFL_UTIME 0x0002 // Time field in Unix format is present.
|
||||
#define FHFL_CRC32 0x0004 // CRC32 field is present.
|
||||
#define FHFL_UNPUNKNOWN 0x0008 // Unknown unpacked size.
|
||||
|
||||
// RAR 5.0 end of archive header specific flags.
|
||||
#define EHFL_NEXTVOLUME 0x0001 // Not last volume.
|
||||
|
||||
// RAR 5.0 archive encryption header specific flags.
|
||||
#define CHFL_CRYPT_PSWCHECK 0x0001 // Password check data is present.
|
||||
|
||||
|
||||
// RAR 5.0 file compression flags.
|
||||
#define FCI_ALGO_BIT0 0x0001 // Version of compression algorithm.
|
||||
#define FCI_ALGO_BIT1 0x0002 // 0 .. 63.
|
||||
#define FCI_ALGO_BIT2 0x0004
|
||||
#define FCI_ALGO_BIT3 0x0008
|
||||
#define FCI_ALGO_BIT4 0x0010
|
||||
#define FCI_ALGO_BIT5 0x0020
|
||||
#define FCI_SOLID 0x0040 // Solid flag.
|
||||
#define FCI_METHOD_BIT0 0x0080 // Compression method.
|
||||
#define FCI_METHOD_BIT1 0x0100 // 0 .. 5 (6 and 7 are not used).
|
||||
#define FCI_METHOD_BIT2 0x0200
|
||||
#define FCI_DICT_BIT0 0x0400 // Dictionary size.
|
||||
#define FCI_DICT_BIT1 0x0800 // 128 KB .. 4 GB.
|
||||
#define FCI_DICT_BIT2 0x1000
|
||||
#define FCI_DICT_BIT3 0x2000
|
||||
|
||||
// Main header extra field values.
|
||||
#define MHEXTRA_LOCATOR 0x01 // Position of quick list and other blocks.
|
||||
|
||||
// Flags for MHEXTRA_LOCATOR.
|
||||
#define MHEXTRA_LOCATOR_QLIST 0x01 // Quick open offset is present.
|
||||
#define MHEXTRA_LOCATOR_RR 0x02 // Recovery record offset is present.
|
||||
|
||||
// File and service header extra field values.
|
||||
#define FHEXTRA_CRYPT 0x01 // Encryption parameters.
|
||||
#define FHEXTRA_HASH 0x02 // File hash.
|
||||
#define FHEXTRA_HTIME 0x03 // High precision file time.
|
||||
#define FHEXTRA_VERSION 0x04 // File version information.
|
||||
#define FHEXTRA_REDIR 0x05 // File system redirection (links, etc.).
|
||||
#define FHEXTRA_UOWNER 0x06 // Unix owner and group information.
|
||||
#define FHEXTRA_SUBDATA 0x07 // Service header subdata array.
|
||||
|
||||
|
||||
// Hash type values for FHEXTRA_HASH.
|
||||
#define FHEXTRA_HASH_BLAKE2 0x00
|
||||
|
||||
// Flags for FHEXTRA_HTIME.
|
||||
#define FHEXTRA_HTIME_UNIXTIME 0x01 // Use Unix time_t format.
|
||||
#define FHEXTRA_HTIME_MTIME 0x02 // mtime is present.
|
||||
#define FHEXTRA_HTIME_CTIME 0x04 // ctime is present.
|
||||
#define FHEXTRA_HTIME_ATIME 0x08 // atime is present.
|
||||
|
||||
// Flags for FHEXTRA_CRYPT.
|
||||
#define FHEXTRA_CRYPT_PSWCHECK 0x01 // Store password check data.
|
||||
#define FHEXTRA_CRYPT_HASHMAC 0x02 // Use MAC for unpacked data checksums.
|
||||
|
||||
// Flags for FHEXTRA_REDIR.
|
||||
#define FHEXTRA_REDIR_DIR 0x01 // Link target is directory.
|
||||
|
||||
// Flags for FHEXTRA_UOWNER.
|
||||
#define FHEXTRA_UOWNER_UNAME 0x01 // User name string is present.
|
||||
#define FHEXTRA_UOWNER_GNAME 0x02 // Group name string is present.
|
||||
#define FHEXTRA_UOWNER_NUMUID 0x04 // Numeric user ID is present.
|
||||
#define FHEXTRA_UOWNER_NUMGID 0x08 // Numeric group ID is present.
|
||||
|
||||
#endif
|
|
@ -10,13 +10,15 @@
|
|||
1. All copyrights to RAR and the utility UnRAR are exclusively
|
||||
owned by the author - Alexander Roshal.
|
||||
|
||||
2. The UnRAR sources 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 sources 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.
|
||||
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.
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
// #included by unpack.cpp
|
||||
#ifdef RAR_COMMON_HPP
|
||||
/****************************************************************************
|
||||
* This file is part of PPMd project *
|
||||
* Written and distributed to public domain by Dmitry Shkarin 1997, *
|
||||
|
@ -7,10 +5,17 @@
|
|||
* Contents: model description and encoding/decoding routines *
|
||||
****************************************************************************/
|
||||
|
||||
inline PPM_CONTEXT* PPM_CONTEXT::createChild(ModelPPM *Model,STATE* pStats,
|
||||
STATE& FirstState)
|
||||
static const int MAX_O=64; /* maximum allowed model order */
|
||||
const uint TOP=1 << 24, BOT=1 << 15;
|
||||
|
||||
template <class T>
|
||||
inline void _PPMD_SWAP(T& t1,T& t2) { T tmp=t1; t1=t2; t2=tmp; }
|
||||
|
||||
|
||||
inline RARPPM_CONTEXT* RARPPM_CONTEXT::createChild(ModelPPM *Model,RARPPM_STATE* pStats,
|
||||
RARPPM_STATE& FirstState)
|
||||
{
|
||||
PPM_CONTEXT* pc = (PPM_CONTEXT*) Model->SubAlloc.AllocContext();
|
||||
RARPPM_CONTEXT* pc = (RARPPM_CONTEXT*) Model->SubAlloc.AllocContext();
|
||||
if ( pc )
|
||||
{
|
||||
pc->NumStats=1;
|
||||
|
@ -36,11 +41,11 @@ void ModelPPM::RestartModelRare()
|
|||
memset(CharMask,0,sizeof(CharMask));
|
||||
SubAlloc.InitSubAllocator();
|
||||
InitRL=-(MaxOrder < 12 ? MaxOrder:12)-1;
|
||||
MinContext = MaxContext = (PPM_CONTEXT*) SubAlloc.AllocContext();
|
||||
MinContext = MaxContext = (RARPPM_CONTEXT*) SubAlloc.AllocContext();
|
||||
MinContext->Suffix=NULL;
|
||||
OrderFall=MaxOrder;
|
||||
MinContext->U.SummFreq=(MinContext->NumStats=256)+1;
|
||||
FoundState=MinContext->U.Stats=(STATE*)SubAlloc.AllocUnits(256/2);
|
||||
FoundState=MinContext->U.Stats=(RARPPM_STATE*)SubAlloc.AllocUnits(256/2);
|
||||
for (RunLength=InitRL, PrevSuccess=i=0;i < 256;i++)
|
||||
{
|
||||
MinContext->U.Stats[i].Symbol=i;
|
||||
|
@ -107,10 +112,10 @@ void ModelPPM::StartModelRare(int MaxOrder)
|
|||
}
|
||||
|
||||
|
||||
void PPM_CONTEXT::rescale(ModelPPM *Model)
|
||||
void RARPPM_CONTEXT::rescale(ModelPPM *Model)
|
||||
{
|
||||
int OldNS=NumStats, i=NumStats-1, Adder, EscFreq;
|
||||
STATE* p1, * p;
|
||||
RARPPM_STATE* p1, * p;
|
||||
for (p=Model->FoundState;p != U.Stats;p--)
|
||||
_PPMD_SWAP(p[0],p[-1]);
|
||||
U.Stats->Freq += 4;
|
||||
|
@ -124,7 +129,7 @@ void PPM_CONTEXT::rescale(ModelPPM *Model)
|
|||
U.SummFreq += (p->Freq=(p->Freq+Adder) >> 1);
|
||||
if (p[0].Freq > p[-1].Freq)
|
||||
{
|
||||
STATE tmp=*(p1=p);
|
||||
RARPPM_STATE tmp=*(p1=p);
|
||||
do
|
||||
{
|
||||
p1[0]=p1[-1];
|
||||
|
@ -141,7 +146,7 @@ void PPM_CONTEXT::rescale(ModelPPM *Model)
|
|||
EscFreq += i;
|
||||
if ((NumStats -= i) == 1)
|
||||
{
|
||||
STATE tmp=*U.Stats;
|
||||
RARPPM_STATE tmp=*U.Stats;
|
||||
do
|
||||
{
|
||||
tmp.Freq-=(tmp.Freq >> 1);
|
||||
|
@ -154,17 +159,19 @@ void PPM_CONTEXT::rescale(ModelPPM *Model)
|
|||
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);
|
||||
U.Stats = (RARPPM_STATE*) Model->SubAlloc.ShrinkUnits(U.Stats,n0,n1);
|
||||
Model->FoundState=U.Stats;
|
||||
}
|
||||
|
||||
|
||||
inline PPM_CONTEXT* ModelPPM::CreateSuccessors(bool Skip,STATE* p1)
|
||||
inline RARPPM_CONTEXT* ModelPPM::CreateSuccessors(bool Skip,RARPPM_STATE* p1)
|
||||
{
|
||||
// (removed conditional static)
|
||||
STATE UpState;
|
||||
PPM_CONTEXT* pc=MinContext, * UpBranch=FoundState->Successor;
|
||||
STATE * p, * ps[MAX_O], ** pps=ps;
|
||||
#ifdef __ICL
|
||||
static
|
||||
#endif
|
||||
RARPPM_STATE UpState;
|
||||
RARPPM_CONTEXT* pc=MinContext, * UpBranch=FoundState->Successor;
|
||||
RARPPM_STATE * p, * ps[MAX_O], ** pps=ps;
|
||||
if ( !Skip )
|
||||
{
|
||||
*pps++ = FoundState;
|
||||
|
@ -202,7 +209,7 @@ NO_LOOP:
|
|||
if (pps == ps)
|
||||
return pc;
|
||||
UpState.Symbol=*(byte*) UpBranch;
|
||||
UpState.Successor=(PPM_CONTEXT*) (((byte*) UpBranch)+1);
|
||||
UpState.Successor=(RARPPM_CONTEXT*) (((byte*) UpBranch)+1);
|
||||
if (pc->NumStats != 1)
|
||||
{
|
||||
if ((byte*) pc <= SubAlloc.pText)
|
||||
|
@ -230,8 +237,8 @@ NO_LOOP:
|
|||
|
||||
inline void ModelPPM::UpdateModel()
|
||||
{
|
||||
STATE fs = *FoundState, *p = NULL;
|
||||
PPM_CONTEXT *pc, *Successor;
|
||||
RARPPM_STATE fs = *FoundState, *p = NULL;
|
||||
RARPPM_CONTEXT *pc, *Successor;
|
||||
uint ns1, ns, cf, sf, s0;
|
||||
if (fs.Freq < MAX_FREQ/4 && (pc=MinContext->Suffix) != NULL)
|
||||
{
|
||||
|
@ -263,19 +270,19 @@ inline void ModelPPM::UpdateModel()
|
|||
}
|
||||
if ( !OrderFall )
|
||||
{
|
||||
MinContext=MaxContext=FoundState->Successor=CreateSuccessors(true,p);
|
||||
MinContext=MaxContext=FoundState->Successor=CreateSuccessors(TRUE,p);
|
||||
if ( !MinContext )
|
||||
goto RESTART_MODEL;
|
||||
return;
|
||||
}
|
||||
*SubAlloc.pText++ = fs.Symbol;
|
||||
Successor = (PPM_CONTEXT*) SubAlloc.pText;
|
||||
Successor = (RARPPM_CONTEXT*) SubAlloc.pText;
|
||||
if (SubAlloc.pText >= SubAlloc.FakeUnitsStart)
|
||||
goto RESTART_MODEL;
|
||||
if ( fs.Successor )
|
||||
{
|
||||
if ((byte*) fs.Successor <= SubAlloc.pText &&
|
||||
(fs.Successor=CreateSuccessors(false,p)) == NULL)
|
||||
(fs.Successor=CreateSuccessors(FALSE,p)) == NULL)
|
||||
goto RESTART_MODEL;
|
||||
if ( !--OrderFall )
|
||||
{
|
||||
|
@ -295,7 +302,7 @@ inline void ModelPPM::UpdateModel()
|
|||
{
|
||||
if ((ns1 & 1) == 0)
|
||||
{
|
||||
pc->U.Stats=(STATE*) SubAlloc.ExpandUnits(pc->U.Stats,ns1 >> 1);
|
||||
pc->U.Stats=(RARPPM_STATE*) SubAlloc.ExpandUnits(pc->U.Stats,ns1 >> 1);
|
||||
if ( !pc->U.Stats )
|
||||
goto RESTART_MODEL;
|
||||
}
|
||||
|
@ -303,7 +310,7 @@ inline void ModelPPM::UpdateModel()
|
|||
}
|
||||
else
|
||||
{
|
||||
p=(STATE*) SubAlloc.AllocUnits(1);
|
||||
p=(RARPPM_STATE*) SubAlloc.AllocUnits(1);
|
||||
if ( !p )
|
||||
goto RESTART_MODEL;
|
||||
*p=pc->OneState;
|
||||
|
@ -346,9 +353,9 @@ static const byte ExpEscape[16]={ 25,14, 9, 7, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2,
|
|||
|
||||
|
||||
|
||||
inline void PPM_CONTEXT::decodeBinSymbol(ModelPPM *Model)
|
||||
inline void RARPPM_CONTEXT::decodeBinSymbol(ModelPPM *Model)
|
||||
{
|
||||
STATE& rs=OneState;
|
||||
RARPPM_STATE& rs=OneState;
|
||||
Model->HiBitsFlag=Model->HB2Flag[Model->FoundState->Symbol];
|
||||
ushort& bs=Model->BinSumm[rs.Freq-1][Model->PrevSuccess+
|
||||
Model->NS2BSIndx[Suffix->NumStats-1]+
|
||||
|
@ -360,14 +367,14 @@ inline void PPM_CONTEXT::decodeBinSymbol(ModelPPM *Model)
|
|||
rs.Freq += (rs.Freq < 128);
|
||||
Model->Coder.SubRange.LowCount=0;
|
||||
Model->Coder.SubRange.HighCount=bs;
|
||||
bs = SHORT16(bs+INTERVAL-GET_MEAN(bs,PERIOD_BITS,2));
|
||||
bs = GET_SHORT16(bs+INTERVAL-GET_MEAN(bs,PERIOD_BITS,2));
|
||||
Model->PrevSuccess=1;
|
||||
Model->RunLength++;
|
||||
}
|
||||
else
|
||||
{
|
||||
Model->Coder.SubRange.LowCount=bs;
|
||||
bs = SHORT16(bs-GET_MEAN(bs,PERIOD_BITS,2));
|
||||
bs = GET_SHORT16(bs-GET_MEAN(bs,PERIOD_BITS,2));
|
||||
Model->Coder.SubRange.HighCount=BIN_SCALE;
|
||||
Model->InitEsc=ExpEscape[bs >> 10];
|
||||
Model->NumMasked=1;
|
||||
|
@ -378,7 +385,7 @@ inline void PPM_CONTEXT::decodeBinSymbol(ModelPPM *Model)
|
|||
}
|
||||
|
||||
|
||||
inline void PPM_CONTEXT::update1(ModelPPM *Model,STATE* p)
|
||||
inline void RARPPM_CONTEXT::update1(ModelPPM *Model,RARPPM_STATE* p)
|
||||
{
|
||||
(Model->FoundState=p)->Freq += 4;
|
||||
U.SummFreq += 4;
|
||||
|
@ -394,13 +401,13 @@ inline void PPM_CONTEXT::update1(ModelPPM *Model,STATE* p)
|
|||
|
||||
|
||||
|
||||
inline bool PPM_CONTEXT::decodeSymbol1(ModelPPM *Model)
|
||||
inline bool RARPPM_CONTEXT::decodeSymbol1(ModelPPM *Model)
|
||||
{
|
||||
Model->Coder.SubRange.scale=U.SummFreq;
|
||||
STATE* p=U.Stats;
|
||||
RARPPM_STATE* p=U.Stats;
|
||||
int i, HiCnt;
|
||||
int count=Model->Coder.GetCurrentCount();
|
||||
if (count>=Model->Coder.SubRange.scale)
|
||||
if (count>=(int)Model->Coder.SubRange.scale)
|
||||
return(false);
|
||||
if (count < (HiCnt=p->Freq))
|
||||
{
|
||||
|
@ -439,7 +446,7 @@ inline bool PPM_CONTEXT::decodeSymbol1(ModelPPM *Model)
|
|||
}
|
||||
|
||||
|
||||
inline void PPM_CONTEXT::update2(ModelPPM *Model,STATE* p)
|
||||
inline void RARPPM_CONTEXT::update2(ModelPPM *Model,RARPPM_STATE* p)
|
||||
{
|
||||
(Model->FoundState=p)->Freq += 4;
|
||||
U.SummFreq += 4;
|
||||
|
@ -450,9 +457,9 @@ inline void PPM_CONTEXT::update2(ModelPPM *Model,STATE* p)
|
|||
}
|
||||
|
||||
|
||||
inline SEE2_CONTEXT* PPM_CONTEXT::makeEscFreq2(ModelPPM *Model,int Diff)
|
||||
inline RARPPM_SEE2_CONTEXT* RARPPM_CONTEXT::makeEscFreq2(ModelPPM *Model,int Diff)
|
||||
{
|
||||
SEE2_CONTEXT* psee2c;
|
||||
RARPPM_SEE2_CONTEXT* psee2c;
|
||||
if (NumStats != 256)
|
||||
{
|
||||
psee2c=Model->SEE2Cont[Model->NS2Indx[Diff-1]]+
|
||||
|
@ -472,11 +479,11 @@ inline SEE2_CONTEXT* PPM_CONTEXT::makeEscFreq2(ModelPPM *Model,int Diff)
|
|||
|
||||
|
||||
|
||||
inline bool PPM_CONTEXT::decodeSymbol2(ModelPPM *Model)
|
||||
inline bool RARPPM_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;
|
||||
RARPPM_SEE2_CONTEXT* psee2c=makeEscFreq2(Model,i);
|
||||
RARPPM_STATE* ps[256], ** pps=ps, * p=U.Stats-1;
|
||||
HiCnt=0;
|
||||
do
|
||||
{
|
||||
|
@ -489,7 +496,7 @@ inline bool PPM_CONTEXT::decodeSymbol2(ModelPPM *Model)
|
|||
} while ( --i );
|
||||
Model->Coder.SubRange.scale += HiCnt;
|
||||
count=Model->Coder.GetCurrentCount();
|
||||
if (count>=Model->Coder.SubRange.scale)
|
||||
if (count>=(int)Model->Coder.SubRange.scale)
|
||||
return(false);
|
||||
p=*(pps=ps);
|
||||
if (count < HiCnt)
|
||||
|
@ -540,10 +547,9 @@ void ModelPPM::CleanUp()
|
|||
bool ModelPPM::DecodeInit(Unpack *UnpackRead,int &EscChar)
|
||||
{
|
||||
int MaxOrder=UnpackRead->GetChar();
|
||||
bool Reset=MaxOrder & 0x20;
|
||||
bool Reset=(MaxOrder & 0x20)!=0;
|
||||
|
||||
int MaxMB;
|
||||
MaxMB = 0; // avoids warning of being uninitialized
|
||||
if (Reset)
|
||||
MaxMB=UnpackRead->GetChar();
|
||||
else
|
||||
|
@ -609,4 +615,3 @@ int ModelPPM::DecodeChar()
|
|||
ARI_DEC_NORMALIZE(Coder.code,Coder.low,Coder.range,Coder.UnpackRead);
|
||||
return(Symbol);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -4,16 +4,17 @@
|
|||
#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
|
||||
#ifdef ALLOW_MISALIGNED
|
||||
#pragma pack(1)
|
||||
#endif
|
||||
|
||||
struct SEE2_CONTEXT
|
||||
struct RARPPM_DEF
|
||||
{
|
||||
static const int INT_BITS=7, PERIOD_BITS=7, TOT_BITS=INT_BITS+PERIOD_BITS,
|
||||
INTERVAL=1 << INT_BITS, BIN_SCALE=1 << TOT_BITS, MAX_FREQ=124;
|
||||
};
|
||||
|
||||
struct RARPPM_SEE2_CONTEXT : RARPPM_DEF
|
||||
{ // SEE-contexts for PPM-contexts with masked symbols
|
||||
ushort Summ;
|
||||
byte Shift, Count;
|
||||
|
@ -24,7 +25,7 @@ struct SEE2_CONTEXT
|
|||
}
|
||||
uint getMean()
|
||||
{
|
||||
uint RetVal=SHORT16(Summ) >> Shift;
|
||||
uint RetVal=GET_SHORT16(Summ) >> Shift;
|
||||
Summ -= RetVal;
|
||||
return RetVal+(RetVal == 0);
|
||||
}
|
||||
|
@ -40,45 +41,47 @@ struct SEE2_CONTEXT
|
|||
|
||||
|
||||
class ModelPPM;
|
||||
struct PPM_CONTEXT;
|
||||
struct RARPPM_CONTEXT;
|
||||
|
||||
struct STATE
|
||||
struct RARPPM_STATE
|
||||
{
|
||||
byte Symbol;
|
||||
byte Freq;
|
||||
PPM_CONTEXT* Successor;
|
||||
RARPPM_CONTEXT* Successor;
|
||||
};
|
||||
|
||||
|
||||
struct RARPPM_CONTEXT : RARPPM_DEF
|
||||
{
|
||||
ushort NumStats;
|
||||
|
||||
struct FreqData
|
||||
{
|
||||
ushort SummFreq;
|
||||
STATE _PACK_ATTR * Stats;
|
||||
RARPPM_STATE RARPPM_PACK_ATTR * Stats;
|
||||
};
|
||||
|
||||
struct PPM_CONTEXT
|
||||
{
|
||||
ushort NumStats;
|
||||
union
|
||||
{
|
||||
FreqData U;
|
||||
STATE OneState;
|
||||
RARPPM_STATE OneState;
|
||||
};
|
||||
|
||||
PPM_CONTEXT* Suffix;
|
||||
RARPPM_CONTEXT* Suffix;
|
||||
inline void encodeBinSymbol(ModelPPM *Model,int symbol); // MaxOrder:
|
||||
inline void encodeSymbol1(ModelPPM *Model,int symbol); // ABCD context
|
||||
inline void encodeSymbol2(ModelPPM *Model,int symbol); // BCD suffix
|
||||
inline void decodeBinSymbol(ModelPPM *Model); // BCDE successor
|
||||
inline bool decodeSymbol1(ModelPPM *Model); // other orders:
|
||||
inline bool decodeSymbol2(ModelPPM *Model); // BCD context
|
||||
inline void update1(ModelPPM *Model,STATE* p); // CD suffix
|
||||
inline void update2(ModelPPM *Model,STATE* p); // BCDE successor
|
||||
inline void update1(ModelPPM *Model,RARPPM_STATE* p); // CD suffix
|
||||
inline void update2(ModelPPM *Model,RARPPM_STATE* p); // BCDE successor
|
||||
void rescale(ModelPPM *Model);
|
||||
inline PPM_CONTEXT* createChild(ModelPPM *Model,STATE* pStats,STATE& FirstState);
|
||||
inline SEE2_CONTEXT* makeEscFreq2(ModelPPM *Model,int Diff);
|
||||
inline RARPPM_CONTEXT* createChild(ModelPPM *Model,RARPPM_STATE* pStats,RARPPM_STATE& FirstState);
|
||||
inline RARPPM_SEE2_CONTEXT* makeEscFreq2(ModelPPM *Model,int Diff);
|
||||
};
|
||||
|
||||
#ifndef STRICT_ALIGNMENT_REQUIRED
|
||||
#ifdef ALLOW_MISALIGNED
|
||||
#ifdef _AIX
|
||||
#pragma pack(pop)
|
||||
#else
|
||||
|
@ -86,28 +89,15 @@ struct PPM_CONTEXT
|
|||
#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
|
||||
class ModelPPM : RARPPM_DEF
|
||||
{
|
||||
private:
|
||||
friend struct PPM_CONTEXT;
|
||||
friend struct RARPPM_CONTEXT;
|
||||
|
||||
/*_PACK_ATTR*/ SEE2_CONTEXT SEE2Cont[25][16], DummySEE2Cont;
|
||||
RARPPM_SEE2_CONTEXT SEE2Cont[25][16], DummySEE2Cont;
|
||||
|
||||
struct PPM_CONTEXT *MinContext, *MedContext, *MaxContext;
|
||||
STATE* FoundState; // found next state transition
|
||||
struct RARPPM_CONTEXT *MinContext, *MedContext, *MaxContext;
|
||||
RARPPM_STATE* FoundState; // found next state transition
|
||||
int NumMasked, InitEsc, OrderFall, MaxOrder, RunLength, InitRL;
|
||||
byte CharMask[256], NS2Indx[256], NS2BSIndx[256], HB2Flag[256];
|
||||
byte EscCount, PrevSuccess, HiBitsFlag;
|
||||
|
@ -118,11 +108,10 @@ class ModelPPM
|
|||
|
||||
void RestartModelRare();
|
||||
void StartModelRare(int MaxOrder);
|
||||
inline PPM_CONTEXT* CreateSuccessors(bool Skip,STATE* p1);
|
||||
inline RARPPM_CONTEXT* CreateSuccessors(bool Skip,RARPPM_STATE* p1);
|
||||
|
||||
inline void UpdateModel();
|
||||
inline void ClearMask();
|
||||
friend class Unpack;
|
||||
public:
|
||||
ModelPPM();
|
||||
void CleanUp(); // reset PPM variables after data error
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
#include "rar.hpp"
|
||||
|
||||
wchar* GetWideName(const char *Name,const wchar *NameW,wchar *DestW,size_t DestSize)
|
||||
{
|
||||
if (NameW!=NULL && *NameW!=0)
|
||||
{
|
||||
if (DestW!=NameW)
|
||||
my_wcsncpy(DestW,NameW,DestSize);
|
||||
}
|
||||
else
|
||||
if (Name!=NULL)
|
||||
CharToWide(Name,DestW,DestSize);
|
||||
else
|
||||
*DestW=0;
|
||||
|
||||
// Ensure that we return a zero terminate string for security reasons.
|
||||
if (DestSize>0)
|
||||
DestW[DestSize-1]=0;
|
||||
|
||||
return(DestW);
|
||||
}
|
|
@ -2,12 +2,13 @@
|
|||
// It may NOT be used to develop a RAR (WinRAR) compatible archiver.
|
||||
// See license.txt for copyright and licensing.
|
||||
|
||||
// unrar_core 3.8.5
|
||||
// unrar_core 5.1.7
|
||||
#ifndef RAR_COMMON_HPP
|
||||
#define RAR_COMMON_HPP
|
||||
|
||||
#include "unrar.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <setjmp.h>
|
||||
|
@ -21,7 +22,7 @@
|
|||
// These names are too generic and might clash (or have already, hmpf)
|
||||
#define Array Rar_Array
|
||||
#define uint32 rar_uint32
|
||||
#define sint32 rar_sint32
|
||||
#define int32 rar_int32
|
||||
#define Unpack Rar_Unpack
|
||||
#define Archive Rar_Archive
|
||||
#define RawRead Rar_RawRead
|
||||
|
@ -73,6 +74,8 @@ struct Rar_Allocator
|
|||
};
|
||||
|
||||
//// os.hpp
|
||||
#define FALSE 0
|
||||
#define TRUE 1
|
||||
#undef STRICT_ALIGNMENT_REQUIRED
|
||||
#undef LITTLE_ENDIAN
|
||||
#define NM 1024
|
||||
|
@ -92,7 +95,7 @@ struct Rar_Allocator
|
|||
//// rartypes.hpp
|
||||
#if INT_MAX == 0x7FFFFFFF && UINT_MAX == 0xFFFFFFFF
|
||||
typedef unsigned int uint32; //32 bits exactly
|
||||
typedef int sint32; //signed 32 bits exactly
|
||||
typedef int int32; //signed 32 bits exactly
|
||||
#define PRESENT_INT32
|
||||
#endif
|
||||
|
||||
|
@ -102,34 +105,35 @@ typedef unsigned int uint; //32 bits or more
|
|||
|
||||
typedef blargg_wchar_t wchar;
|
||||
|
||||
#define SHORT16(x) (sizeof(ushort)==2 ? (ushort)(x):((x)&0xffff))
|
||||
#define UINT32(x) (sizeof(uint )==4 ? (uint )(x):((x)&0xffffffff))
|
||||
#define GET_SHORT16(x) (sizeof(ushort)==2 ? (ushort)(x):((x)&0xffff))
|
||||
#define GET_UINT32(x) (sizeof(uint )==4 ? (uint )(x):((x)&0xffffffff))
|
||||
|
||||
//// rardefs.hpp
|
||||
#define Min(x,y) (((x)<(y)) ? (x):(y))
|
||||
#define Max(x,y) (((x)>(y)) ? (x):(y))
|
||||
#define ALIGN_VALUE(v,a) (size_t(v) + ( (~size_t(v) + 1) & (a - 1) ) )
|
||||
#define ASIZE(x) (sizeof(x)/sizeof(x[0]))
|
||||
|
||||
//// int64.hpp
|
||||
typedef unrar_long_long Int64;
|
||||
typedef unrar_long_long int64;
|
||||
typedef unrar_ulong_long uint64;
|
||||
|
||||
#define int64to32(x) ((uint)(x))
|
||||
#define int32to64(high,low) ((((Int64)(high))<<31<<1)+(low))
|
||||
#define int32to64(high,low) ((((int64)(high))<<31<<1)+(low))
|
||||
#define is64plus(x) (x>=0)
|
||||
|
||||
#define INT64MAX int32to64(0x7fffffff,0)
|
||||
#define INT64NDF int32to64(0x7fffffff,0x7fffffff)
|
||||
|
||||
//// crc.hpp
|
||||
extern uint CRCTab[256];
|
||||
void InitCRC();
|
||||
uint CRC(uint StartCRC,const void *Addr,size_t Size);
|
||||
ushort OldCRC(ushort StartCRC,const void *Addr,size_t Size);
|
||||
extern uint crc_tables[8][256];
|
||||
void InitCRCTables();
|
||||
uint CRC32(uint StartCRC,const void *Addr,size_t Size);
|
||||
ushort Checksum14(ushort StartCRC,const void *Addr,size_t Size);
|
||||
|
||||
//// rartime.hpp
|
||||
struct RarTime
|
||||
{
|
||||
unsigned time;
|
||||
void SetDos(uint DosTime) { time = DosTime; }
|
||||
};
|
||||
#define SHA256_DIGEST_SIZE 32
|
||||
#include "blake2s.hpp"
|
||||
#include "hash.hpp"
|
||||
|
||||
//// rdwrfn.hpp
|
||||
class ComprDataIO
|
||||
|
@ -141,30 +145,43 @@ public:
|
|||
void* user_read_data;
|
||||
void* user_write_data;
|
||||
unrar_err_t write_error; // once write error occurs, no more writes are made
|
||||
Int64 Tell_;
|
||||
int64 Tell_;
|
||||
bool OldFormat;
|
||||
|
||||
private:
|
||||
Int64 UnpPackedSize;
|
||||
int64 UnpPackedSize;
|
||||
bool SkipUnpCRC;
|
||||
|
||||
public:
|
||||
int UnpRead(byte *Addr,uint Count);
|
||||
void UnpWrite(byte *Addr,uint Count);
|
||||
void SetSkipUnpCRC( bool b ) { SkipUnpCRC = b; }
|
||||
void SetPackedSizeToRead( Int64 n ) { UnpPackedSize = n; }
|
||||
void SetPackedSizeToRead( int64 n ) { UnpPackedSize = n; }
|
||||
|
||||
uint UnpFileCRC;
|
||||
|
||||
void Seek(Int64 Offset, int Method = 0 ) { (void)Method; Tell_ = Offset; }
|
||||
Int64 Tell() { return Tell_; }
|
||||
void Seek(int64 Offset, int Method = 0 ) { (void)Method; Tell_ = Offset; }
|
||||
int64 Tell() { return Tell_; }
|
||||
int Read( void* p, int n );
|
||||
|
||||
DataHash PackedDataHash; // Packed write and unpack read hash.
|
||||
DataHash PackHash; // Pack read hash.
|
||||
DataHash UnpHash; // Unpack write hash.
|
||||
};
|
||||
|
||||
//// secpassword.hpp
|
||||
void cleandata(void *data,size_t size);
|
||||
|
||||
//// pathfn.hpp
|
||||
wchar* GetWideName(const char *Name,const wchar *NameW,wchar *DestW,size_t DestSize);
|
||||
|
||||
//// rar.hpp
|
||||
class Unpack;
|
||||
#include "array.hpp"
|
||||
#include "unicode.hpp"
|
||||
#include "timefn.hpp"
|
||||
#include "headers.hpp"
|
||||
#include "headers5.hpp"
|
||||
#include "getbits.hpp"
|
||||
#include "archive.hpp"
|
||||
#include "rawread.hpp"
|
||||
|
@ -172,8 +189,27 @@ class Unpack;
|
|||
#include "compress.hpp"
|
||||
#include "rarvm.hpp"
|
||||
#include "model.hpp"
|
||||
#include "strfn.hpp"
|
||||
#include "unpack.hpp"
|
||||
|
||||
//// savepos.hpp
|
||||
class SaveFilePos
|
||||
{
|
||||
private:
|
||||
File *SaveFile;
|
||||
int64 SavePos;
|
||||
public:
|
||||
SaveFilePos(File &Src)
|
||||
{
|
||||
SaveFile=&Src;
|
||||
SavePos=Src.Tell();
|
||||
}
|
||||
~SaveFilePos()
|
||||
{
|
||||
SaveFile->Seek(SavePos,SEEK_SET);
|
||||
}
|
||||
};
|
||||
|
||||
//// extract.hpp
|
||||
/** RAR archive */
|
||||
struct unrar_t
|
||||
|
@ -195,7 +231,7 @@ struct unrar_t
|
|||
|
||||
unrar_t();
|
||||
~unrar_t();
|
||||
void UnstoreFile( Int64 );
|
||||
void UnstoreFile( int64 );
|
||||
unrar_err_t ExtractCurrentFile( bool SkipSolid = false, bool check_compatibility_only = false );
|
||||
void update_first_file_pos()
|
||||
{
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#define VM_FS ((unsigned) VM_FS)
|
||||
|
||||
RarVM::RarVM()
|
||||
:BitInput(true)
|
||||
{
|
||||
Mem=NULL;
|
||||
}
|
||||
|
@ -55,24 +56,24 @@ inline uint RarVM::GetValue(bool ByteMode,uint *Addr)
|
|||
}
|
||||
else
|
||||
{
|
||||
#if defined(BIG_ENDIAN) || !defined(ALLOW_NOT_ALIGNED_INT)
|
||||
#if defined(BIG_ENDIAN) || !defined(ALLOW_MISALIGNED)
|
||||
if (IS_VM_MEM(Addr))
|
||||
{
|
||||
byte *B=(byte *)Addr;
|
||||
return UINT32((uint)B[0]|((uint)B[1]<<8)|((uint)B[2]<<16)|((uint)B[3]<<24));
|
||||
return GET_UINT32((uint)B[0]|((uint)B[1]<<8)|((uint)B[2]<<16)|((uint)B[3]<<24));
|
||||
}
|
||||
else
|
||||
return UINT32(*Addr);
|
||||
return GET_UINT32(*Addr);
|
||||
#else
|
||||
return UINT32(*Addr);
|
||||
return GET_UINT32(*Addr);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(BIG_ENDIAN) || !defined(ALLOW_NOT_ALIGNED_INT)
|
||||
#if defined(BIG_ENDIAN) || !defined(ALLOW_MISALIGNED)
|
||||
#define GET_VALUE(ByteMode,Addr) GetValue(ByteMode,(uint *)Addr)
|
||||
#else
|
||||
#define GET_VALUE(ByteMode,Addr) ((ByteMode) ? (*(byte *)(Addr)):UINT32(*(uint *)(Addr)))
|
||||
#define GET_VALUE(ByteMode,Addr) ((ByteMode) ? (*(byte *)(Addr)):GET_UINT32(*(uint *)(Addr)))
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -91,7 +92,7 @@ inline void RarVM::SetValue(bool ByteMode,uint *Addr,uint Value)
|
|||
}
|
||||
else
|
||||
{
|
||||
#if defined(BIG_ENDIAN) || !defined(ALLOW_NOT_ALIGNED_INT) || !defined(PRESENT_INT32)
|
||||
#if defined(BIG_ENDIAN) || !defined(ALLOW_MISALIGNED) || !defined(PRESENT_INT32)
|
||||
if (IS_VM_MEM(Addr))
|
||||
{
|
||||
((byte *)Addr)[0]=(byte)Value;
|
||||
|
@ -107,16 +108,16 @@ inline void RarVM::SetValue(bool ByteMode,uint *Addr,uint Value)
|
|||
}
|
||||
}
|
||||
|
||||
#if defined(BIG_ENDIAN) || !defined(ALLOW_NOT_ALIGNED_INT) || !defined(PRESENT_INT32)
|
||||
#if defined(BIG_ENDIAN) || !defined(ALLOW_MISALIGNED) || !defined(PRESENT_INT32)
|
||||
#define SET_VALUE(ByteMode,Addr,Value) SetValue(ByteMode,(uint *)Addr,Value)
|
||||
#else
|
||||
#define SET_VALUE(ByteMode,Addr,Value) ((ByteMode) ? (*(byte *)(Addr)=(Value)):(*(uint32 *)(Addr)=((uint32)(Value))))
|
||||
#define SET_VALUE(ByteMode,Addr,Value) ((ByteMode) ? (*(byte *)(Addr)=((byte)(Value))):(*(uint32 *)(Addr)=((uint32)(Value))))
|
||||
#endif
|
||||
|
||||
|
||||
void RarVM::SetLowEndianValue(uint *Addr,uint Value)
|
||||
{
|
||||
#if defined(BIG_ENDIAN) || !defined(ALLOW_NOT_ALIGNED_INT) || !defined(PRESENT_INT32)
|
||||
#if defined(BIG_ENDIAN) || !defined(ALLOW_MISALIGNED) || !defined(PRESENT_INT32)
|
||||
((byte *)Addr)[0]=(byte)Value;
|
||||
((byte *)Addr)[1]=(byte)(Value>>8);
|
||||
((byte *)Addr)[2]=(byte)(Value>>16);
|
||||
|
@ -139,10 +140,10 @@ inline uint* RarVM::GetOperand(VM_PreparedOperand *CmdOp)
|
|||
void RarVM::Execute(VM_PreparedProgram *Prg)
|
||||
{
|
||||
memcpy(R,Prg->InitR,sizeof(Prg->InitR));
|
||||
unsigned int GlobalSize=Min(Prg->GlobalData.Size(),VM_GLOBALMEMSIZE);
|
||||
size_t GlobalSize=Min(Prg->GlobalData.Size(),VM_GLOBALMEMSIZE);
|
||||
if (GlobalSize)
|
||||
memcpy(Mem+VM_GLOBALMEMADDR,&Prg->GlobalData[0],GlobalSize);
|
||||
unsigned int StaticSize=Min(Prg->StaticData.Size(),VM_GLOBALMEMSIZE-GlobalSize);
|
||||
size_t StaticSize=Min(Prg->StaticData.Size(),VM_GLOBALMEMSIZE-GlobalSize);
|
||||
if (StaticSize)
|
||||
memcpy(Mem+VM_GLOBALMEMADDR+GlobalSize,&Prg->StaticData[0],StaticSize);
|
||||
|
||||
|
@ -150,8 +151,11 @@ void RarVM::Execute(VM_PreparedProgram *Prg)
|
|||
Flags=0;
|
||||
|
||||
VM_PreparedCommand *PreparedCode=Prg->AltCmd ? Prg->AltCmd:&Prg->Cmd[0];
|
||||
if (!ExecuteCode(PreparedCode,Prg->CmdCount))
|
||||
if (Prg->CmdCount>0 && !ExecuteCode(PreparedCode,Prg->CmdCount))
|
||||
{
|
||||
// Invalid VM program. Let's replace it with 'return' command.
|
||||
PreparedCode[0].OpCode=VM_RET;
|
||||
}
|
||||
uint NewBlockPos=GET_VALUE(false,&Mem[VM_GLOBALMEMADDR+0x20])&VM_MEMMASK;
|
||||
uint NewBlockSize=GET_VALUE(false,&Mem[VM_GLOBALMEMADDR+0x1c])&VM_MEMMASK;
|
||||
if (NewBlockPos+NewBlockSize>=VM_MEMSIZE)
|
||||
|
@ -185,7 +189,7 @@ Note:
|
|||
return(false); \
|
||||
Cmd=PreparedCode+(IP);
|
||||
|
||||
bool RarVM::ExecuteCode(VM_PreparedCommand *PreparedCode,int CodeSize)
|
||||
bool RarVM::ExecuteCode(VM_PreparedCommand *PreparedCode,uint CodeSize)
|
||||
{
|
||||
int MaxOpCount=25000000;
|
||||
VM_PreparedCommand *Cmd=PreparedCode;
|
||||
|
@ -213,7 +217,7 @@ bool RarVM::ExecuteCode(VM_PreparedCommand *PreparedCode,int CodeSize)
|
|||
case VM_CMP:
|
||||
{
|
||||
uint Value1=GET_VALUE(Cmd->ByteMode,Op1);
|
||||
uint Result=UINT32(Value1-GET_VALUE(Cmd->ByteMode,Op2));
|
||||
uint Result=GET_UINT32(Value1-GET_VALUE(Cmd->ByteMode,Op2));
|
||||
Flags=Result==0 ? VM_FZ:(Result>Value1)|(Result&VM_FS);
|
||||
}
|
||||
break;
|
||||
|
@ -221,14 +225,14 @@ bool RarVM::ExecuteCode(VM_PreparedCommand *PreparedCode,int CodeSize)
|
|||
case VM_CMPB:
|
||||
{
|
||||
uint Value1=GET_VALUE(true,Op1);
|
||||
uint Result=UINT32(Value1-GET_VALUE(true,Op2));
|
||||
uint Result=GET_UINT32(Value1-GET_VALUE(true,Op2));
|
||||
Flags=Result==0 ? VM_FZ:(Result>Value1)|(Result&VM_FS);
|
||||
}
|
||||
break;
|
||||
case VM_CMPD:
|
||||
{
|
||||
uint Value1=GET_VALUE(false,Op1);
|
||||
uint Result=UINT32(Value1-GET_VALUE(false,Op2));
|
||||
uint Result=GET_UINT32(Value1-GET_VALUE(false,Op2));
|
||||
Flags=Result==0 ? VM_FZ:(Result>Value1)|(Result&VM_FS);
|
||||
}
|
||||
break;
|
||||
|
@ -236,7 +240,7 @@ bool RarVM::ExecuteCode(VM_PreparedCommand *PreparedCode,int CodeSize)
|
|||
case VM_ADD:
|
||||
{
|
||||
uint Value1=GET_VALUE(Cmd->ByteMode,Op1);
|
||||
uint Result=UINT32(Value1+GET_VALUE(Cmd->ByteMode,Op2));
|
||||
uint Result=GET_UINT32(Value1+GET_VALUE(Cmd->ByteMode,Op2));
|
||||
if (Cmd->ByteMode)
|
||||
{
|
||||
Result&=0xff;
|
||||
|
@ -258,7 +262,7 @@ bool RarVM::ExecuteCode(VM_PreparedCommand *PreparedCode,int CodeSize)
|
|||
case VM_SUB:
|
||||
{
|
||||
uint Value1=GET_VALUE(Cmd->ByteMode,Op1);
|
||||
uint Result=UINT32(Value1-GET_VALUE(Cmd->ByteMode,Op2));
|
||||
uint Result=GET_UINT32(Value1-GET_VALUE(Cmd->ByteMode,Op2));
|
||||
Flags=Result==0 ? VM_FZ:(Result>Value1)|(Result&VM_FS);
|
||||
SET_VALUE(Cmd->ByteMode,Op1,Result);
|
||||
}
|
||||
|
@ -287,7 +291,7 @@ bool RarVM::ExecuteCode(VM_PreparedCommand *PreparedCode,int CodeSize)
|
|||
break;
|
||||
case VM_INC:
|
||||
{
|
||||
uint Result=UINT32(GET_VALUE(Cmd->ByteMode,Op1)+1);
|
||||
uint Result=GET_UINT32(GET_VALUE(Cmd->ByteMode,Op1)+1);
|
||||
if (Cmd->ByteMode)
|
||||
Result&=0xff;
|
||||
SET_VALUE(Cmd->ByteMode,Op1,Result);
|
||||
|
@ -304,7 +308,7 @@ bool RarVM::ExecuteCode(VM_PreparedCommand *PreparedCode,int CodeSize)
|
|||
#endif
|
||||
case VM_DEC:
|
||||
{
|
||||
uint Result=UINT32(GET_VALUE(Cmd->ByteMode,Op1)-1);
|
||||
uint Result=GET_UINT32(GET_VALUE(Cmd->ByteMode,Op1)-1);
|
||||
SET_VALUE(Cmd->ByteMode,Op1,Result);
|
||||
Flags=Result==0 ? VM_FZ:Result&VM_FS;
|
||||
}
|
||||
|
@ -322,28 +326,28 @@ bool RarVM::ExecuteCode(VM_PreparedCommand *PreparedCode,int CodeSize)
|
|||
continue;
|
||||
case VM_XOR:
|
||||
{
|
||||
uint Result=UINT32(GET_VALUE(Cmd->ByteMode,Op1)^GET_VALUE(Cmd->ByteMode,Op2));
|
||||
uint Result=GET_UINT32(GET_VALUE(Cmd->ByteMode,Op1)^GET_VALUE(Cmd->ByteMode,Op2));
|
||||
Flags=Result==0 ? VM_FZ:Result&VM_FS;
|
||||
SET_VALUE(Cmd->ByteMode,Op1,Result);
|
||||
}
|
||||
break;
|
||||
case VM_AND:
|
||||
{
|
||||
uint Result=UINT32(GET_VALUE(Cmd->ByteMode,Op1)&GET_VALUE(Cmd->ByteMode,Op2));
|
||||
uint Result=GET_UINT32(GET_VALUE(Cmd->ByteMode,Op1)&GET_VALUE(Cmd->ByteMode,Op2));
|
||||
Flags=Result==0 ? VM_FZ:Result&VM_FS;
|
||||
SET_VALUE(Cmd->ByteMode,Op1,Result);
|
||||
}
|
||||
break;
|
||||
case VM_OR:
|
||||
{
|
||||
uint Result=UINT32(GET_VALUE(Cmd->ByteMode,Op1)|GET_VALUE(Cmd->ByteMode,Op2));
|
||||
uint Result=GET_UINT32(GET_VALUE(Cmd->ByteMode,Op1)|GET_VALUE(Cmd->ByteMode,Op2));
|
||||
Flags=Result==0 ? VM_FZ:Result&VM_FS;
|
||||
SET_VALUE(Cmd->ByteMode,Op1,Result);
|
||||
}
|
||||
break;
|
||||
case VM_TEST:
|
||||
{
|
||||
uint Result=UINT32(GET_VALUE(Cmd->ByteMode,Op1)&GET_VALUE(Cmd->ByteMode,Op2));
|
||||
uint Result=GET_UINT32(GET_VALUE(Cmd->ByteMode,Op1)&GET_VALUE(Cmd->ByteMode,Op2));
|
||||
Flags=Result==0 ? VM_FZ:Result&VM_FS;
|
||||
}
|
||||
break;
|
||||
|
@ -399,7 +403,7 @@ bool RarVM::ExecuteCode(VM_PreparedCommand *PreparedCode,int CodeSize)
|
|||
break;
|
||||
case VM_CALL:
|
||||
R[7]-=4;
|
||||
SET_VALUE(false,(uint *)&Mem[R[7]&VM_MEMMASK],(uint)(Cmd-PreparedCode+1));
|
||||
SET_VALUE(false,(uint *)&Mem[R[7]&VM_MEMMASK],Cmd-PreparedCode+1);
|
||||
SET_IP(GET_VALUE(false,Op1));
|
||||
continue;
|
||||
case VM_NOT:
|
||||
|
@ -409,7 +413,7 @@ bool RarVM::ExecuteCode(VM_PreparedCommand *PreparedCode,int CodeSize)
|
|||
{
|
||||
uint Value1=GET_VALUE(Cmd->ByteMode,Op1);
|
||||
uint Value2=GET_VALUE(Cmd->ByteMode,Op2);
|
||||
uint Result=UINT32(Value1<<Value2);
|
||||
uint Result=GET_UINT32(Value1<<Value2);
|
||||
Flags=(Result==0 ? VM_FZ:(Result&VM_FS))|((Value1<<(Value2-1))&0x80000000 ? VM_FC:0);
|
||||
SET_VALUE(Cmd->ByteMode,Op1,Result);
|
||||
}
|
||||
|
@ -418,7 +422,7 @@ bool RarVM::ExecuteCode(VM_PreparedCommand *PreparedCode,int CodeSize)
|
|||
{
|
||||
uint Value1=GET_VALUE(Cmd->ByteMode,Op1);
|
||||
uint Value2=GET_VALUE(Cmd->ByteMode,Op2);
|
||||
uint Result=UINT32(Value1>>Value2);
|
||||
uint Result=GET_UINT32(Value1>>Value2);
|
||||
Flags=(Result==0 ? VM_FZ:(Result&VM_FS))|((Value1>>(Value2-1))&VM_FC);
|
||||
SET_VALUE(Cmd->ByteMode,Op1,Result);
|
||||
}
|
||||
|
@ -427,24 +431,26 @@ bool RarVM::ExecuteCode(VM_PreparedCommand *PreparedCode,int CodeSize)
|
|||
{
|
||||
uint Value1=GET_VALUE(Cmd->ByteMode,Op1);
|
||||
uint Value2=GET_VALUE(Cmd->ByteMode,Op2);
|
||||
uint Result=UINT32(((int)Value1)>>Value2);
|
||||
uint Result=GET_UINT32(((int)Value1)>>Value2);
|
||||
Flags=(Result==0 ? VM_FZ:(Result&VM_FS))|((Value1>>(Value2-1))&VM_FC);
|
||||
SET_VALUE(Cmd->ByteMode,Op1,Result);
|
||||
}
|
||||
break;
|
||||
case VM_NEG:
|
||||
{
|
||||
uint Result=UINT32(-GET_VALUE(Cmd->ByteMode,Op1));
|
||||
// We use "0-value" expression to suppress "unary minus to unsigned"
|
||||
// compiler warning.
|
||||
uint Result=GET_UINT32(0-GET_VALUE(Cmd->ByteMode,Op1));
|
||||
Flags=Result==0 ? VM_FZ:VM_FC|(Result&VM_FS);
|
||||
SET_VALUE(Cmd->ByteMode,Op1,Result);
|
||||
}
|
||||
break;
|
||||
#ifdef VM_OPTIMIZE
|
||||
case VM_NEGB:
|
||||
SET_VALUE(true,Op1,-GET_VALUE(true,Op1));
|
||||
SET_VALUE(true,Op1,0-GET_VALUE(true,Op1));
|
||||
break;
|
||||
case VM_NEGD:
|
||||
SET_VALUE(false,Op1,-GET_VALUE(false,Op1));
|
||||
SET_VALUE(false,Op1,0-GET_VALUE(false,Op1));
|
||||
break;
|
||||
#endif
|
||||
case VM_PUSHA:
|
||||
|
@ -503,10 +509,10 @@ bool RarVM::ExecuteCode(VM_PreparedCommand *PreparedCode,int CodeSize)
|
|||
{
|
||||
uint Value1=GET_VALUE(Cmd->ByteMode,Op1);
|
||||
uint FC=(Flags&VM_FC);
|
||||
uint Result=UINT32(Value1+GET_VALUE(Cmd->ByteMode,Op2)+FC);
|
||||
uint Result=GET_UINT32(Value1+GET_VALUE(Cmd->ByteMode,Op2)+FC);
|
||||
if (Cmd->ByteMode)
|
||||
Result&=0xff;
|
||||
Flags=(Result<Value1 || (Result==Value1 && FC))|(Result==0 ? VM_FZ:(Result&VM_FS));
|
||||
Flags=(Result<Value1 || Result==Value1 && FC)|(Result==0 ? VM_FZ:(Result&VM_FS));
|
||||
SET_VALUE(Cmd->ByteMode,Op1,Result);
|
||||
}
|
||||
break;
|
||||
|
@ -514,10 +520,10 @@ bool RarVM::ExecuteCode(VM_PreparedCommand *PreparedCode,int CodeSize)
|
|||
{
|
||||
uint Value1=GET_VALUE(Cmd->ByteMode,Op1);
|
||||
uint FC=(Flags&VM_FC);
|
||||
uint Result=UINT32(Value1-GET_VALUE(Cmd->ByteMode,Op2)-FC);
|
||||
uint Result=GET_UINT32(Value1-GET_VALUE(Cmd->ByteMode,Op2)-FC);
|
||||
if (Cmd->ByteMode)
|
||||
Result&=0xff;
|
||||
Flags=(Result>Value1 || (Result==Value1 && FC))|(Result==0 ? VM_FZ:(Result&VM_FS));
|
||||
Flags=(Result>Value1 || Result==Value1 && FC)|(Result==0 ? VM_FZ:(Result&VM_FS));
|
||||
SET_VALUE(Cmd->ByteMode,Op1,Result);
|
||||
}
|
||||
break;
|
||||
|
@ -531,7 +537,7 @@ bool RarVM::ExecuteCode(VM_PreparedCommand *PreparedCode,int CodeSize)
|
|||
#ifdef VM_STANDARDFILTERS
|
||||
case VM_STANDARD:
|
||||
ExecuteStandardFilter((VM_StandardFilters)Cmd->Op1.Data);
|
||||
break;
|
||||
return true;
|
||||
#endif
|
||||
case VM_PRINT:
|
||||
break;
|
||||
|
@ -544,7 +550,7 @@ bool RarVM::ExecuteCode(VM_PreparedCommand *PreparedCode,int CodeSize)
|
|||
|
||||
|
||||
|
||||
void RarVM::Prepare(byte *Code,int CodeSize,VM_PreparedProgram *Prg)
|
||||
void RarVM::Prepare(byte *Code,uint CodeSize,VM_PreparedProgram *Prg)
|
||||
{
|
||||
InitBitInput();
|
||||
memcpy(InBuf,Code,Min(CodeSize,BitInput::MAX_SIZE));
|
||||
|
@ -552,7 +558,7 @@ void RarVM::Prepare(byte *Code,int CodeSize,VM_PreparedProgram *Prg)
|
|||
// Calculate the single byte XOR checksum to check validity of VM code.
|
||||
byte XorSum=0;
|
||||
{
|
||||
for (int I=1;I<CodeSize;I++)
|
||||
for (uint I=1;I<CodeSize;I++)
|
||||
XorSum^=Code[I];
|
||||
}
|
||||
faddbits(8);
|
||||
|
@ -573,6 +579,7 @@ void RarVM::Prepare(byte *Code,int CodeSize,VM_PreparedProgram *Prg)
|
|||
CurCmd->Op2.Addr=&CurCmd->Op2.Data;
|
||||
CurCmd->Op1.Type=CurCmd->Op2.Type=VM_OPNONE;
|
||||
CodeSize=0;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
uint DataFlag=fgetbits();
|
||||
|
@ -583,8 +590,8 @@ void RarVM::Prepare(byte *Code,int CodeSize,VM_PreparedProgram *Prg)
|
|||
|
||||
if (DataFlag&0x8000)
|
||||
{
|
||||
int DataSize=ReadData(*this)+1;
|
||||
for (int I=0;InAddr<CodeSize && I<DataSize;I++)
|
||||
uint DataSize=ReadData(*this)+1;
|
||||
for (uint I=0;(uint)InAddr<CodeSize && I<DataSize;I++)
|
||||
{
|
||||
Prg->StaticData.Add(1);
|
||||
Prg->StaticData[I]=fgetbits()>>8;
|
||||
|
@ -592,7 +599,7 @@ void RarVM::Prepare(byte *Code,int CodeSize,VM_PreparedProgram *Prg)
|
|||
}
|
||||
}
|
||||
|
||||
while (InAddr<CodeSize)
|
||||
while ((uint)InAddr<CodeSize)
|
||||
{
|
||||
Prg->Cmd.Add(1);
|
||||
VM_PreparedCommand *CurCmd=&Prg->Cmd[Prg->CmdCount];
|
||||
|
@ -609,7 +616,7 @@ void RarVM::Prepare(byte *Code,int CodeSize,VM_PreparedProgram *Prg)
|
|||
}
|
||||
if (VM_CmdFlags[CurCmd->OpCode] & VMCF_BYTEMODE)
|
||||
{
|
||||
CurCmd->ByteMode=fgetbits()>>15;
|
||||
CurCmd->ByteMode=(fgetbits()>>15)!=0;
|
||||
faddbits(1);
|
||||
}
|
||||
else
|
||||
|
@ -773,7 +780,7 @@ uint RarVM::ReadData(BitInput &Inp)
|
|||
}
|
||||
|
||||
|
||||
void RarVM::SetMemory(unsigned int Pos,byte *Data,unsigned int DataSize)
|
||||
void RarVM::SetMemory(size_t Pos,byte *Data,size_t DataSize)
|
||||
{
|
||||
if (Pos<VM_MEMSIZE && Data!=Mem+Pos)
|
||||
memmove(Mem+Pos,Data,Min(DataSize,VM_MEMSIZE-Pos));
|
||||
|
@ -784,9 +791,9 @@ void RarVM::SetMemory(unsigned int Pos,byte *Data,unsigned int DataSize)
|
|||
void RarVM::Optimize(VM_PreparedProgram *Prg)
|
||||
{
|
||||
VM_PreparedCommand *Code=&Prg->Cmd[0];
|
||||
int CodeSize=Prg->CmdCount;
|
||||
uint CodeSize=Prg->CmdCount;
|
||||
|
||||
for (int I=0;I<CodeSize;I++)
|
||||
for (uint I=0;I<CodeSize;I++)
|
||||
{
|
||||
VM_PreparedCommand *Cmd=Code+I;
|
||||
|
||||
|
@ -800,8 +807,6 @@ void RarVM::Optimize(VM_PreparedProgram *Prg)
|
|||
case VM_CMP:
|
||||
Cmd->OpCode=Cmd->ByteMode ? VM_CMPB:VM_CMPD;
|
||||
continue;
|
||||
|
||||
default: break;
|
||||
}
|
||||
if ((VM_CmdFlags[Cmd->OpCode] & VMCF_CHFLAGS)==0)
|
||||
continue;
|
||||
|
@ -811,7 +816,7 @@ void RarVM::Optimize(VM_PreparedProgram *Prg)
|
|||
// the current command with faster version which does not need to
|
||||
// modify flags.
|
||||
bool FlagsRequired=false;
|
||||
for (int J=I+1;J<CodeSize;J++)
|
||||
for (uint J=I+1;J<CodeSize;J++)
|
||||
{
|
||||
int Flags=VM_CmdFlags[Code[J].OpCode];
|
||||
if (Flags & (VMCF_JUMP|VMCF_PROC|VMCF_USEFLAGS))
|
||||
|
@ -845,8 +850,6 @@ void RarVM::Optimize(VM_PreparedProgram *Prg)
|
|||
case VM_NEG:
|
||||
Cmd->OpCode=Cmd->ByteMode ? VM_NEGB:VM_NEGD;
|
||||
continue;
|
||||
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -854,7 +857,7 @@ void RarVM::Optimize(VM_PreparedProgram *Prg)
|
|||
|
||||
|
||||
#ifdef VM_STANDARDFILTERS
|
||||
VM_StandardFilters RarVM::IsStandardFilter(byte *Code,int CodeSize)
|
||||
VM_StandardFilters RarVM::IsStandardFilter(byte *Code,uint CodeSize)
|
||||
{
|
||||
static const
|
||||
struct StandardFilterSignature
|
||||
|
@ -875,12 +878,10 @@ VM_StandardFilters RarVM::IsStandardFilter(byte *Code,int CodeSize)
|
|||
149, 0x1c2c5dc8, VMSF_RGB,
|
||||
},{
|
||||
216, 0xbc85e701, VMSF_AUDIO,
|
||||
},{
|
||||
40, 0x46b9c560, VMSF_UPCASE
|
||||
}
|
||||
};
|
||||
uint CodeCRC=CRC(0xffffffff,Code,CodeSize)^0xffffffff;
|
||||
for (int I=0;I<sizeof(StdList)/sizeof(StdList[0]);I++)
|
||||
uint CodeCRC=CRC32(0xffffffff,Code,CodeSize)^0xffffffff;
|
||||
for (uint I=0;I<ASIZE(StdList);I++)
|
||||
if (StdList[I].CRC==CodeCRC && StdList[I].Length==CodeSize)
|
||||
return(StdList[I].Type);
|
||||
return(VMSF_NONE);
|
||||
|
@ -898,7 +899,7 @@ void RarVM::ExecuteStandardFilter(VM_StandardFilters FilterType)
|
|||
int DataSize=R[4];
|
||||
uint FileOffset=R[6];
|
||||
|
||||
if (DataSize>=VM_GLOBALMEMADDR || DataSize<4)
|
||||
if ((uint)DataSize>=VM_GLOBALMEMADDR || DataSize<4)
|
||||
break;
|
||||
|
||||
const int FileSize=0x1000000;
|
||||
|
@ -910,8 +911,8 @@ void RarVM::ExecuteStandardFilter(VM_StandardFilters FilterType)
|
|||
if (CurByte==0xe8 || CurByte==CmpByte2)
|
||||
{
|
||||
#ifdef PRESENT_INT32
|
||||
sint32 Offset=CurPos+FileOffset;
|
||||
sint32 Addr=GET_VALUE(false,Data);
|
||||
int32 Offset=CurPos+FileOffset;
|
||||
int32 Addr=GET_VALUE(false,Data);
|
||||
if (Addr<0)
|
||||
{
|
||||
if (Addr+Offset>=0)
|
||||
|
@ -944,7 +945,7 @@ void RarVM::ExecuteStandardFilter(VM_StandardFilters FilterType)
|
|||
int DataSize=R[4];
|
||||
uint FileOffset=R[6];
|
||||
|
||||
if (DataSize>=VM_GLOBALMEMADDR || DataSize<21)
|
||||
if ((uint)DataSize>=VM_GLOBALMEMADDR || DataSize<21)
|
||||
break;
|
||||
|
||||
int CurPos=0;
|
||||
|
@ -982,7 +983,7 @@ void RarVM::ExecuteStandardFilter(VM_StandardFilters FilterType)
|
|||
{
|
||||
int DataSize=R[4],Channels=R[0],SrcPos=0,Border=DataSize*2;
|
||||
SET_VALUE(false,&Mem[VM_GLOBALMEMADDR+0x20],DataSize);
|
||||
if (DataSize>=VM_GLOBALMEMADDR/2)
|
||||
if ((uint)DataSize>=VM_GLOBALMEMADDR/2)
|
||||
break;
|
||||
|
||||
// Bytes from same channels are grouped to continual data blocks,
|
||||
|
@ -1001,21 +1002,21 @@ void RarVM::ExecuteStandardFilter(VM_StandardFilters FilterType)
|
|||
byte *SrcData=Mem,*DestData=SrcData+DataSize;
|
||||
const int Channels=3;
|
||||
SET_VALUE(false,&Mem[VM_GLOBALMEMADDR+0x20],DataSize);
|
||||
if (DataSize>=VM_GLOBALMEMADDR/2 || PosR<0)
|
||||
if ((uint)DataSize>=VM_GLOBALMEMADDR/2 || Width<0 || PosR<0)
|
||||
break;
|
||||
for (int CurChannel=0;CurChannel<Channels;CurChannel++)
|
||||
{
|
||||
unsigned int PrevByte=0;
|
||||
uint PrevByte=0;
|
||||
|
||||
for (int I=CurChannel;I<DataSize;I+=Channels)
|
||||
{
|
||||
unsigned int Predicted;
|
||||
uint Predicted;
|
||||
int UpperPos=I-Width;
|
||||
if (UpperPos>=3)
|
||||
{
|
||||
byte *UpperData=DestData+UpperPos;
|
||||
unsigned int UpperByte=*UpperData;
|
||||
unsigned int UpperLeftByte=*(UpperData-3);
|
||||
uint UpperByte=*UpperData;
|
||||
uint UpperLeftByte=*(UpperData-3);
|
||||
Predicted=PrevByte+UpperByte-UpperLeftByte;
|
||||
int pa=abs((int)(Predicted-PrevByte));
|
||||
int pb=abs((int)(Predicted-UpperByte));
|
||||
|
@ -1046,11 +1047,11 @@ void RarVM::ExecuteStandardFilter(VM_StandardFilters FilterType)
|
|||
int DataSize=R[4],Channels=R[0];
|
||||
byte *SrcData=Mem,*DestData=SrcData+DataSize;
|
||||
SET_VALUE(false,&Mem[VM_GLOBALMEMADDR+0x20],DataSize);
|
||||
if (DataSize>=VM_GLOBALMEMADDR/2)
|
||||
if ((uint)DataSize>=VM_GLOBALMEMADDR/2)
|
||||
break;
|
||||
for (int CurChannel=0;CurChannel<Channels;CurChannel++)
|
||||
{
|
||||
unsigned int PrevByte=0,PrevDelta=0,Dif[7];
|
||||
uint PrevByte=0,PrevDelta=0,Dif[7];
|
||||
int D1=0,D2=0,D3;
|
||||
int K1=0,K2=0,K3=0;
|
||||
memset(Dif,0,sizeof(Dif));
|
||||
|
@ -1061,10 +1062,10 @@ void RarVM::ExecuteStandardFilter(VM_StandardFilters FilterType)
|
|||
D2=PrevDelta-D1;
|
||||
D1=PrevDelta;
|
||||
|
||||
unsigned int Predicted=8*PrevByte+K1*D1+K2*D2+K3*D3;
|
||||
uint Predicted=8*PrevByte+K1*D1+K2*D2+K3*D3;
|
||||
Predicted=(Predicted>>3) & 0xff;
|
||||
|
||||
unsigned int CurByte=*(SrcData++);
|
||||
uint CurByte=*(SrcData++);
|
||||
|
||||
Predicted-=CurByte;
|
||||
DestData[I]=Predicted;
|
||||
|
@ -1083,7 +1084,7 @@ void RarVM::ExecuteStandardFilter(VM_StandardFilters FilterType)
|
|||
|
||||
if ((ByteCount & 0x1f)==0)
|
||||
{
|
||||
unsigned int MinDif=Dif[0],NumMinDif=0;
|
||||
uint MinDif=Dif[0],NumMinDif=0;
|
||||
Dif[0]=0;
|
||||
for (int J=1;J<sizeof(Dif)/sizeof(Dif[0]);J++)
|
||||
{
|
||||
|
@ -1108,33 +1109,15 @@ void RarVM::ExecuteStandardFilter(VM_StandardFilters FilterType)
|
|||
}
|
||||
}
|
||||
break;
|
||||
case VMSF_UPCASE:
|
||||
{
|
||||
int DataSize=R[4],SrcPos=0,DestPos=DataSize;
|
||||
if (DataSize>=VM_GLOBALMEMADDR/2)
|
||||
break;
|
||||
while (SrcPos<DataSize)
|
||||
{
|
||||
byte CurByte=Mem[SrcPos++];
|
||||
if (CurByte==2 && (CurByte=Mem[SrcPos++])!=2)
|
||||
CurByte-=32;
|
||||
Mem[DestPos++]=CurByte;
|
||||
}
|
||||
SET_VALUE(false,&Mem[VM_GLOBALMEMADDR+0x1c],DestPos-DataSize);
|
||||
SET_VALUE(false,&Mem[VM_GLOBALMEMADDR+0x20],DataSize);
|
||||
}
|
||||
break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
unsigned int RarVM::FilterItanium_GetBits(byte *Data,int BitPos,int BitCount)
|
||||
uint RarVM::FilterItanium_GetBits(byte *Data,int BitPos,int BitCount)
|
||||
{
|
||||
int InAddr=BitPos/8;
|
||||
int InBit=BitPos&7;
|
||||
unsigned int BitField=(uint)Data[InAddr++];
|
||||
uint BitField=(uint)Data[InAddr++];
|
||||
BitField|=(uint)Data[InAddr++] << 8;
|
||||
BitField|=(uint)Data[InAddr++] << 16;
|
||||
BitField|=(uint)Data[InAddr] << 24;
|
||||
|
@ -1143,17 +1126,16 @@ unsigned int RarVM::FilterItanium_GetBits(byte *Data,int BitPos,int BitCount)
|
|||
}
|
||||
|
||||
|
||||
void RarVM::FilterItanium_SetBits(byte *Data,unsigned int BitField,int BitPos,
|
||||
int BitCount)
|
||||
void RarVM::FilterItanium_SetBits(byte *Data,uint BitField,int BitPos,int BitCount)
|
||||
{
|
||||
int InAddr=BitPos/8;
|
||||
int InBit=BitPos&7;
|
||||
unsigned int AndMask=0xffffffff>>(32-BitCount);
|
||||
uint AndMask=0xffffffff>>(32-BitCount);
|
||||
AndMask=~(AndMask<<InBit);
|
||||
|
||||
BitField<<=InBit;
|
||||
|
||||
for (int I=0;I<4;I++)
|
||||
for (uint I=0;I<4;I++)
|
||||
{
|
||||
Data[InAddr+I]&=AndMask;
|
||||
Data[InAddr+I]|=BitField;
|
||||
|
|
|
@ -34,7 +34,7 @@ enum VM_Commands
|
|||
|
||||
enum VM_StandardFilters {
|
||||
VMSF_NONE, VMSF_E8, VMSF_E8E9, VMSF_ITANIUM, VMSF_RGB, VMSF_AUDIO,
|
||||
VMSF_DELTA, VMSF_UPCASE
|
||||
VMSF_DELTA
|
||||
};
|
||||
|
||||
enum VM_Flags {VM_FC=1,VM_FZ=2,VM_FS=0x80000000};
|
||||
|
@ -59,8 +59,12 @@ struct VM_PreparedCommand
|
|||
|
||||
struct VM_PreparedProgram
|
||||
{
|
||||
VM_PreparedProgram( Rar_Error_Handler* eh ) : Cmd( eh ), GlobalData( eh ), StaticData( eh )
|
||||
{AltCmd=NULL;}
|
||||
VM_PreparedProgram()
|
||||
{
|
||||
AltCmd=NULL;
|
||||
FilteredDataSize=0;
|
||||
CmdCount=0;
|
||||
}
|
||||
|
||||
Array<VM_PreparedCommand> Cmd;
|
||||
VM_PreparedCommand *AltCmd;
|
||||
|
@ -71,7 +75,7 @@ struct VM_PreparedProgram
|
|||
uint InitR[7];
|
||||
|
||||
byte *FilteredData;
|
||||
unsigned int FilteredDataSize;
|
||||
uint FilteredDataSize;
|
||||
};
|
||||
|
||||
class RarVM:private BitInput
|
||||
|
@ -84,13 +88,12 @@ class RarVM:private BitInput
|
|||
#ifdef VM_OPTIMIZE
|
||||
void Optimize(VM_PreparedProgram *Prg);
|
||||
#endif
|
||||
bool ExecuteCode(VM_PreparedCommand *PreparedCode,int CodeSize);
|
||||
bool ExecuteCode(VM_PreparedCommand *PreparedCode,uint CodeSize);
|
||||
#ifdef VM_STANDARDFILTERS
|
||||
VM_StandardFilters IsStandardFilter(byte *Code,int CodeSize);
|
||||
VM_StandardFilters IsStandardFilter(byte *Code,uint CodeSize);
|
||||
void ExecuteStandardFilter(VM_StandardFilters FilterType);
|
||||
unsigned int FilterItanium_GetBits(byte *Data,int BitPos,int BitCount);
|
||||
void FilterItanium_SetBits(byte *Data,unsigned int BitField,int BitPos,
|
||||
int BitCount);
|
||||
void FilterItanium_SetBits(byte *Data,uint BitField,int BitPos,int BitCount);
|
||||
#endif
|
||||
|
||||
byte *Mem;
|
||||
|
@ -102,10 +105,10 @@ class RarVM:private BitInput
|
|||
void Init();
|
||||
void handle_mem_error( Rar_Error_Handler& );
|
||||
friend class Unpack;
|
||||
void Prepare(byte *Code,int CodeSize,VM_PreparedProgram *Prg);
|
||||
void Prepare(byte *Code,uint CodeSize,VM_PreparedProgram *Prg);
|
||||
void Execute(VM_PreparedProgram *Prg);
|
||||
void SetLowEndianValue(uint *Addr,uint Value);
|
||||
void SetMemory(unsigned int Pos,byte *Data,unsigned int DataSize);
|
||||
void SetMemory(size_t Pos,byte *Data,size_t DataSize);
|
||||
static uint ReadData(BitInput &Inp);
|
||||
};
|
||||
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
#include "rar.hpp"
|
||||
|
||||
RawRead::RawRead(ComprDataIO *SrcFile) : Data( SrcFile )
|
||||
RawRead::RawRead(ComprDataIO *SrcFile)
|
||||
{
|
||||
RawRead::SrcFile=SrcFile;
|
||||
ReadPos=0;
|
||||
DataSize=0;
|
||||
Reset();
|
||||
}
|
||||
|
||||
void RawRead::Reset()
|
||||
|
@ -14,73 +13,147 @@ void RawRead::Reset()
|
|||
Data.Reset();
|
||||
}
|
||||
|
||||
void RawRead::Read(int Size)
|
||||
size_t RawRead::Read(size_t Size)
|
||||
{
|
||||
size_t ReadSize=0;
|
||||
// (removed decryption)
|
||||
if (Size!=0)
|
||||
{
|
||||
Data.Add(Size);
|
||||
DataSize+=SrcFile->Read(&Data[DataSize],Size);
|
||||
ReadSize=SrcFile->Read(&Data[DataSize],Size);
|
||||
DataSize+=ReadSize;
|
||||
}
|
||||
return ReadSize;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void RawRead::Get(byte &Field)
|
||||
void RawRead::Read(byte *SrcData,size_t Size)
|
||||
{
|
||||
if (ReadPos<DataSize)
|
||||
if (Size!=0)
|
||||
{
|
||||
Field=Data[ReadPos];
|
||||
ReadPos++;
|
||||
Data.Add(Size);
|
||||
memcpy(&Data[DataSize],SrcData,Size);
|
||||
DataSize+=Size;
|
||||
}
|
||||
else
|
||||
Field=0;
|
||||
}
|
||||
|
||||
|
||||
void RawRead::Get(ushort &Field)
|
||||
byte RawRead::Get1()
|
||||
{
|
||||
return ReadPos<DataSize ? Data[ReadPos++]:0;
|
||||
}
|
||||
|
||||
|
||||
ushort RawRead::Get2()
|
||||
{
|
||||
if (ReadPos+1<DataSize)
|
||||
{
|
||||
Field=Data[ReadPos]+(Data[ReadPos+1]<<8);
|
||||
ushort Result=Data[ReadPos]+(Data[ReadPos+1]<<8);
|
||||
ReadPos+=2;
|
||||
return Result;
|
||||
}
|
||||
else
|
||||
Field=0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void RawRead::Get(uint &Field)
|
||||
uint RawRead::Get4()
|
||||
{
|
||||
if (ReadPos+3<DataSize)
|
||||
{
|
||||
Field=Data[ReadPos]+(Data[ReadPos+1]<<8)+(Data[ReadPos+2]<<16)+
|
||||
uint Result=Data[ReadPos]+(Data[ReadPos+1]<<8)+(Data[ReadPos+2]<<16)+
|
||||
(Data[ReadPos+3]<<24);
|
||||
ReadPos+=4;
|
||||
return Result;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
uint64 RawRead::Get8()
|
||||
{
|
||||
uint Low=Get4(),High=Get4();
|
||||
return int32to64(High,Low);
|
||||
}
|
||||
|
||||
|
||||
uint64 RawRead::GetV()
|
||||
{
|
||||
uint64 Result=0;
|
||||
for (uint Shift=0;ReadPos<DataSize;Shift+=7)
|
||||
{
|
||||
byte CurByte=Data[ReadPos++];
|
||||
Result+=uint64(CurByte & 0x7f)<<Shift;
|
||||
if ((CurByte & 0x80)==0)
|
||||
return Result; // Decoded successfully.
|
||||
}
|
||||
return 0; // Out of buffer border.
|
||||
}
|
||||
|
||||
|
||||
// Return a number of bytes in current variable length integer.
|
||||
uint RawRead::GetVSize(size_t Pos)
|
||||
{
|
||||
for (size_t CurPos=Pos;CurPos<DataSize;CurPos++)
|
||||
if ((Data[CurPos] & 0x80)==0)
|
||||
return int(CurPos-Pos+1);
|
||||
return 0; // Buffer overflow.
|
||||
}
|
||||
|
||||
|
||||
size_t RawRead::GetB(void *Field,size_t Size)
|
||||
{
|
||||
byte *F=(byte *)Field;
|
||||
size_t CopySize=Min(DataSize-ReadPos,Size);
|
||||
if (CopySize>0)
|
||||
memcpy(F,&Data[ReadPos],CopySize);
|
||||
if (Size>CopySize)
|
||||
memset(F+CopySize,0,Size-CopySize);
|
||||
ReadPos+=CopySize;
|
||||
return CopySize;
|
||||
}
|
||||
|
||||
|
||||
void RawRead::GetW(wchar *Field,size_t Size)
|
||||
{
|
||||
if (ReadPos+2*Size-1<DataSize)
|
||||
{
|
||||
RawToWide(&Data[ReadPos],Field,Size);
|
||||
ReadPos+=sizeof(wchar)*Size;
|
||||
}
|
||||
else
|
||||
Field=0;
|
||||
memset(Field,0,sizeof(wchar)*Size);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void RawRead::Get(byte *Field,int Size)
|
||||
uint RawRead::GetCRC15(bool ProcessedOnly) // RAR 1.5 block CRC.
|
||||
{
|
||||
if (ReadPos+Size-1<DataSize)
|
||||
if (DataSize<=2)
|
||||
return 0;
|
||||
uint HeaderCRC=CRC32(0xffffffff,&Data[2],(ProcessedOnly ? ReadPos:DataSize)-2);
|
||||
return ~HeaderCRC & 0xffff;
|
||||
}
|
||||
|
||||
|
||||
uint RawRead::GetCRC50() // RAR 5.0 block CRC.
|
||||
{
|
||||
memcpy(Field,&Data[ReadPos],Size);
|
||||
ReadPos+=Size;
|
||||
}
|
||||
else
|
||||
memset(Field,0,Size);
|
||||
if (DataSize<=4)
|
||||
return 0xffffffff;
|
||||
return CRC32(0xffffffff,&Data[4],DataSize-4) ^ 0xffffffff;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
uint RawRead::GetCRC(bool ProcessedOnly)
|
||||
// Read vint from arbitrary byte array.
|
||||
uint64 RawGetV(const byte *Data,uint &ReadPos,uint DataSize,bool &Overflow)
|
||||
{
|
||||
return(DataSize>2 ? CRC(0xffffffff,&Data[2],(ProcessedOnly ? ReadPos:DataSize)-2):0xffffffff);
|
||||
Overflow=false;
|
||||
uint64 Result=0;
|
||||
for (uint Shift=0;ReadPos<DataSize;Shift+=7)
|
||||
{
|
||||
byte CurByte=Data[ReadPos++];
|
||||
Result+=uint64(CurByte & 0x7f)<<Shift;
|
||||
if ((CurByte & 0x80)==0)
|
||||
return Result; // Decoded successfully.
|
||||
}
|
||||
Overflow=true;
|
||||
return 0; // Out of buffer border.
|
||||
}
|
||||
|
|
|
@ -6,20 +6,93 @@ class RawRead
|
|||
private:
|
||||
Array<byte> Data;
|
||||
File *SrcFile;
|
||||
int DataSize;
|
||||
int ReadPos;
|
||||
friend class Archive;
|
||||
size_t DataSize;
|
||||
size_t ReadPos;
|
||||
public:
|
||||
RawRead(File *SrcFile);
|
||||
void Reset();
|
||||
void Read(int Size);
|
||||
void Get(byte &Field);
|
||||
void Get(ushort &Field);
|
||||
void Get(uint &Field);
|
||||
void Get(byte *Field,int Size);
|
||||
uint GetCRC(bool ProcessedOnly);
|
||||
int Size() {return DataSize;}
|
||||
int PaddedSize() {return Data.Size()-DataSize;}
|
||||
size_t Read(size_t Size);
|
||||
void Read(byte *SrcData,size_t Size);
|
||||
byte Get1();
|
||||
ushort Get2();
|
||||
uint Get4();
|
||||
uint64 Get8();
|
||||
uint64 GetV();
|
||||
uint GetVSize(size_t Pos);
|
||||
size_t GetB(void *Field,size_t Size);
|
||||
void GetW(wchar *Field,size_t Size);
|
||||
uint GetCRC15(bool ProcessedOnly);
|
||||
uint GetCRC50();
|
||||
byte* GetDataPtr() {return &Data[0];}
|
||||
size_t Size() {return DataSize;}
|
||||
size_t PaddedSize() {return Data.Size()-DataSize;}
|
||||
size_t DataLeft() {return DataSize-ReadPos;}
|
||||
size_t GetPos() {return ReadPos;}
|
||||
void SetPos(size_t Pos) {ReadPos=Pos;}
|
||||
void Skip(size_t Size) {ReadPos+=Size;}
|
||||
void Rewind() {SetPos(0);}
|
||||
};
|
||||
|
||||
uint64 RawGetV(const byte *Data,uint &ReadPos,uint DataSize,bool &Overflow);
|
||||
|
||||
inline uint RawGet2(const void *Data)
|
||||
{
|
||||
byte *D=(byte *)Data;
|
||||
return D[0]+(D[1]<<8);
|
||||
}
|
||||
|
||||
inline uint RawGet4(const void *Data)
|
||||
{
|
||||
byte *D=(byte *)Data;
|
||||
#if defined(BIG_ENDIAN) || !defined(ALLOW_MISALIGNED) || !defined(PRESENT_INT32)
|
||||
return D[0]+(D[1]<<8)+(D[2]<<16)+(D[3]<<24);
|
||||
#else
|
||||
return GET_UINT32(*(uint32 *)D);
|
||||
#endif
|
||||
}
|
||||
|
||||
inline uint64 RawGet8(const void *Data)
|
||||
{
|
||||
byte *D=(byte *)Data;
|
||||
return int32to64(RawGet4(D+4),RawGet4(D));
|
||||
}
|
||||
|
||||
|
||||
// We need these "put" functions also in UnRAR code. This is why they are
|
||||
// in rawread.hpp file even though they are "write" functions.
|
||||
inline void RawPut2(uint Field,void *Data)
|
||||
{
|
||||
byte *D=(byte *)Data;
|
||||
D[0]=(byte)(Field);
|
||||
D[1]=(byte)(Field>>8);
|
||||
}
|
||||
|
||||
|
||||
inline void RawPut4(uint Field,void *Data)
|
||||
{
|
||||
byte *D=(byte *)Data;
|
||||
#if defined(BIG_ENDIAN) || !defined(ALLOW_MISALIGNED) || !defined(PRESENT_INT32)
|
||||
D[0]=(byte)(Field);
|
||||
D[1]=(byte)(Field>>8);
|
||||
D[2]=(byte)(Field>>16);
|
||||
D[3]=(byte)(Field>>24);
|
||||
#else
|
||||
*(uint32 *)D=Field;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
inline void RawPut8(uint64 Field,void *Data)
|
||||
{
|
||||
byte *D=(byte *)Data;
|
||||
D[0]=(byte)(Field);
|
||||
D[1]=(byte)(Field>>8);
|
||||
D[2]=(byte)(Field>>16);
|
||||
D[3]=(byte)(Field>>24);
|
||||
D[4]=(byte)(Field>>32);
|
||||
D[5]=(byte)(Field>>40);
|
||||
D[6]=(byte)(Field>>48);
|
||||
D[7]=(byte)(Field>>56);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -4,12 +4,13 @@
|
|||
|
||||
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,
|
||||
This package includes freeware Unrar C++ source and makefile for
|
||||
several Unix compilers.
|
||||
|
||||
Unrar source is subset of RAR and generated from RAR source automatically,
|
||||
by a small program removing blocks like '#ifndef UNRAR ... #endif'.
|
||||
Such method is not perfect and you may find some RAR related
|
||||
stuff unnecessary in Unrar, especially in header files.
|
||||
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
|
||||
|
@ -17,16 +18,10 @@
|
|||
|
||||
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.
|
||||
STRICT_ALIGNMENT_REQUIRED in os.h.
|
||||
|
||||
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
|
||||
|
@ -38,16 +33,8 @@
|
|||
|
||||
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
|
||||
This source includes parts of code written by other authors.
|
||||
Please see acknow.txt file for details.
|
||||
|
||||
|
||||
4. Legal stuff
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
#include "rar.hpp"
|
||||
|
||||
// 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
|
||||
}
|
||||
|
|
@ -0,0 +1,411 @@
|
|||
#include "rar.hpp"
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
const char *NullToEmpty(const char *Str)
|
||||
{
|
||||
return Str==NULL ? "":Str;
|
||||
}
|
||||
|
||||
static const wchar Empty[] = {0};
|
||||
|
||||
const wchar *NullToEmpty(const wchar *Str)
|
||||
{
|
||||
return Str==NULL ? Empty:Str;
|
||||
}
|
||||
|
||||
|
||||
void IntToExt(const char *Src,char *Dest,size_t DestSize)
|
||||
{
|
||||
#ifdef _WIN_ALL
|
||||
OemToCharBuffA(Src,Dest,(DWORD)DestSize);
|
||||
Dest[DestSize-1]=0;
|
||||
#elif defined(_ANDROID)
|
||||
wchar DestW[NM];
|
||||
UnkToWide(Src,DestW,ASIZE(DestW));
|
||||
WideToChar(DestW,Dest,DestSize);
|
||||
#else
|
||||
if (Dest!=Src)
|
||||
strncpyz(Dest,Src,DestSize);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
int stricomp(const char *s1,const char *s2)
|
||||
{
|
||||
#ifdef _WIN_ALL
|
||||
return CompareStringA(LOCALE_USER_DEFAULT,NORM_IGNORECASE|SORT_STRINGSORT,s1,-1,s2,-1)-2;
|
||||
#else
|
||||
while (toupper(*s1)==toupper(*s2))
|
||||
{
|
||||
if (*s1==0)
|
||||
return 0;
|
||||
s1++;
|
||||
s2++;
|
||||
}
|
||||
return s1 < s2 ? -1 : 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
int strnicomp(const char *s1,const char *s2,size_t n)
|
||||
{
|
||||
#ifdef _WIN_ALL
|
||||
// If we specify 'n' exceeding the actual string length, CompareString goes
|
||||
// beyond the trailing zero and compares garbage. So we need to limit 'n'
|
||||
// to real string length.
|
||||
// It is important to use strnlen (or memchr(...,0)) instead of strlen,
|
||||
// because data can be not zero terminated.
|
||||
size_t l1=Min(strnlen(s1,n),n);
|
||||
size_t l2=Min(strnlen(s2,n),n);
|
||||
return CompareStringA(LOCALE_USER_DEFAULT,NORM_IGNORECASE|SORT_STRINGSORT,s1,(int)l1,s2,(int)l2)-2;
|
||||
#else
|
||||
if (n==0)
|
||||
return 0;
|
||||
while (toupper(*s1)==toupper(*s2))
|
||||
{
|
||||
if (*s1==0 || --n==0)
|
||||
return 0;
|
||||
s1++;
|
||||
s2++;
|
||||
}
|
||||
return s1 < s2 ? -1 : 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
wchar* RemoveEOL(wchar *Str)
|
||||
{
|
||||
for (int I=(int)my_wcslen(Str)-1;I>=0 && (Str[I]=='\r' || Str[I]=='\n' || Str[I]==' ' || Str[I]=='\t');I--)
|
||||
Str[I]=0;
|
||||
return Str;
|
||||
}
|
||||
|
||||
|
||||
wchar* RemoveLF(wchar *Str)
|
||||
{
|
||||
for (int I=(int)my_wcslen(Str)-1;I>=0 && (Str[I]=='\r' || Str[I]=='\n');I--)
|
||||
Str[I]=0;
|
||||
return(Str);
|
||||
}
|
||||
|
||||
|
||||
unsigned char loctolower(unsigned char ch)
|
||||
{
|
||||
#ifdef _WIN_ALL
|
||||
// Convert to LPARAM first to avoid a warning in 64 bit mode.
|
||||
return((int)(LPARAM)CharLowerA((LPSTR)ch));
|
||||
#else
|
||||
return(tolower(ch));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
unsigned char loctoupper(unsigned char ch)
|
||||
{
|
||||
#ifdef _WIN_ALL
|
||||
// Convert to LPARAM first to avoid a warning in 64 bit mode.
|
||||
return((int)(LPARAM)CharUpperA((LPSTR)ch));
|
||||
#else
|
||||
return(toupper(ch));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
// toupper with English only results if English input is provided.
|
||||
// It avoids Turkish (small i) -> (big I with dot) conversion problem.
|
||||
// We do not define 'ch' as 'int' to avoid necessity to cast all
|
||||
// signed chars passed to this function to unsigned char.
|
||||
unsigned char etoupper(unsigned char ch)
|
||||
{
|
||||
if (ch=='i')
|
||||
return('I');
|
||||
return(toupper(ch));
|
||||
}
|
||||
|
||||
|
||||
// Unicode version of etoupper.
|
||||
wchar etoupperw(wchar ch)
|
||||
{
|
||||
if (ch=='i')
|
||||
return('I');
|
||||
#ifdef __APPLE__
|
||||
return(toupper(ch));
|
||||
#else
|
||||
return(toupperw(ch));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
// We do not want to cast every signed char to unsigned when passing to
|
||||
// isdigit, so we implement the replacement. Shall work for Unicode too.
|
||||
// If chars are signed, conversion from char to int could generate negative
|
||||
// values, resulting in undefined behavior in standard isdigit.
|
||||
bool IsDigit(int ch)
|
||||
{
|
||||
return(ch>='0' && ch<='9');
|
||||
}
|
||||
|
||||
|
||||
// We do not want to cast every signed char to unsigned when passing to
|
||||
// isspace, so we implement the replacement. Shall work for Unicode too.
|
||||
// If chars are signed, conversion from char to int could generate negative
|
||||
// values, resulting in undefined behavior in standard isspace.
|
||||
bool IsSpace(int ch)
|
||||
{
|
||||
return(ch==' ' || ch=='\t');
|
||||
}
|
||||
|
||||
|
||||
// We do not want to cast every signed char to unsigned when passing to
|
||||
// isalpha, so we implement the replacement. Shall work for Unicode too.
|
||||
// If chars are signed, conversion from char to int could generate negative
|
||||
// values, resulting in undefined behavior in standard function.
|
||||
bool IsAlpha(int ch)
|
||||
{
|
||||
return((ch>='A' && ch<='Z') || (ch>='a' && ch<='z'));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void BinToHex(const byte *Bin,size_t BinSize,char *HexA,wchar *HexW,size_t HexSize)
|
||||
{
|
||||
uint A=0,W=0; // ASCII and Unicode hex output positions.
|
||||
for (uint I=0;I<BinSize;I++)
|
||||
{
|
||||
uint High=Bin[I] >> 4;
|
||||
uint Low=Bin[I] & 0xf;
|
||||
uint HighHex=High>9 ? 'a'+High-10:'0'+High;
|
||||
uint LowHex=Low>9 ? 'a'+Low-10:'0'+Low;
|
||||
if (HexA!=NULL && A<HexSize-2) // Need space for 2 chars and final zero.
|
||||
{
|
||||
HexA[A++]=(char)HighHex;
|
||||
HexA[A++]=(char)LowHex;
|
||||
}
|
||||
if (HexW!=NULL && W<HexSize-2) // Need space for 2 chars and final zero.
|
||||
{
|
||||
HexW[W++]=HighHex;
|
||||
HexW[W++]=LowHex;
|
||||
}
|
||||
}
|
||||
if (HexA!=NULL && HexSize>0)
|
||||
HexA[A]=0;
|
||||
if (HexW!=NULL && HexSize>0)
|
||||
HexW[W]=0;
|
||||
}
|
||||
|
||||
|
||||
#ifndef SFX_MODULE
|
||||
uint GetDigits(uint Number)
|
||||
{
|
||||
uint Digits=1;
|
||||
while (Number>=10)
|
||||
{
|
||||
Number/=10;
|
||||
Digits++;
|
||||
}
|
||||
return Digits;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
bool LowAscii(const char *Str)
|
||||
{
|
||||
for (int I=0;Str[I]!=0;I++)
|
||||
if ((byte)Str[I]<32 || (byte)Str[I]>127)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool LowAscii(const wchar *Str)
|
||||
{
|
||||
for (int I=0;Str[I]!=0;I++)
|
||||
{
|
||||
// We convert wchar_t to uint just in case if some compiler
|
||||
// uses signed wchar_t.
|
||||
if ((uint)Str[I]<32 || (uint)Str[I]>127)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
int wcsicompc(const wchar *Str1,const wchar *Str2)
|
||||
{
|
||||
#if defined(_UNIX)
|
||||
return my_wcscmp(Str1,Str2);
|
||||
#else
|
||||
return wcsicomp(Str1,Str2);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
// safe strncpy: copies maxlen-1 max and always returns zero terminated dest
|
||||
char* strncpyz(char *dest, const char *src, size_t maxlen)
|
||||
{
|
||||
if (maxlen>0)
|
||||
{
|
||||
strncpy(dest,src,maxlen-1);
|
||||
dest[maxlen-1]=0;
|
||||
}
|
||||
return dest;
|
||||
}
|
||||
|
||||
|
||||
// Safe wcsncpy: copies maxlen-1 max and always returns zero terminated dest.
|
||||
wchar* wcsncpyz(wchar *dest, const wchar *src, size_t maxlen)
|
||||
{
|
||||
if (maxlen>0)
|
||||
{
|
||||
my_wcsncpy(dest,src,maxlen-1);
|
||||
dest[maxlen-1]=0;
|
||||
}
|
||||
return dest;
|
||||
}
|
||||
|
||||
|
||||
// Safe strncat: resulting dest length cannot exceed maxlen and dest
|
||||
// is always zero terminated. Note that 'maxlen' parameter defines the entire
|
||||
// dest buffer size and is not compatible with standard strncat.
|
||||
char* strncatz(char* dest, const char* src, size_t maxlen)
|
||||
{
|
||||
size_t Length = strlen(dest);
|
||||
if (Length + 1 < maxlen)
|
||||
strncat(dest, src, maxlen - Length - 1);
|
||||
return dest;
|
||||
}
|
||||
|
||||
|
||||
// Safe wcsncat: resulting dest length cannot exceed maxlen and dest
|
||||
// is always zero terminated. Note that 'maxlen' parameter defines the entire
|
||||
// dest buffer size and is not compatible with standard wcsncat.
|
||||
wchar* wcsncatz(wchar* dest, const wchar* src, size_t maxlen)
|
||||
{
|
||||
size_t Length = my_wcslen(dest);
|
||||
if (Length + 1 < maxlen)
|
||||
my_wcsncat(dest, src, maxlen - Length - 1);
|
||||
return dest;
|
||||
}
|
||||
|
||||
|
||||
void itoa(int64 n,char *Str)
|
||||
{
|
||||
char NumStr[50];
|
||||
size_t Pos=0;
|
||||
|
||||
do
|
||||
{
|
||||
NumStr[Pos++]=char(n%10)+'0';
|
||||
n=n/10;
|
||||
} while (n!=0);
|
||||
|
||||
for (size_t I=0;I<Pos;I++)
|
||||
Str[I]=NumStr[Pos-I-1];
|
||||
Str[Pos]=0;
|
||||
}
|
||||
|
||||
|
||||
void itoa(int64 n,wchar *Str)
|
||||
{
|
||||
wchar NumStr[50];
|
||||
size_t Pos=0;
|
||||
|
||||
do
|
||||
{
|
||||
NumStr[Pos++]=wchar(n%10)+'0';
|
||||
n=n/10;
|
||||
} while (n!=0);
|
||||
|
||||
for (size_t I=0;I<Pos;I++)
|
||||
Str[I]=NumStr[Pos-I-1];
|
||||
Str[Pos]=0;
|
||||
}
|
||||
|
||||
|
||||
const wchar* GetWide(const char *Src)
|
||||
{
|
||||
const size_t MaxLength=NM;
|
||||
static wchar StrTable[4][MaxLength];
|
||||
static uint StrNum=0;
|
||||
if (++StrNum >= ASIZE(StrTable))
|
||||
StrNum=0;
|
||||
wchar *Str=StrTable[StrNum];
|
||||
CharToWide(Src,Str,MaxLength);
|
||||
Str[MaxLength-1]=0;
|
||||
return Str;
|
||||
}
|
||||
|
||||
|
||||
// Parse string containing parameters separated with spaces.
|
||||
// Support quote marks. Param can be NULL to return the pointer to next
|
||||
// parameter, which can be used to estimate the buffer size for Param.
|
||||
const wchar* GetCmdParam(const wchar *CmdLine,wchar *Param,size_t MaxSize)
|
||||
{
|
||||
while (IsSpace(*CmdLine))
|
||||
CmdLine++;
|
||||
if (*CmdLine==0)
|
||||
return NULL;
|
||||
|
||||
size_t ParamSize=0;
|
||||
bool Quote=false;
|
||||
while (*CmdLine!=0 && (Quote || !IsSpace(*CmdLine)))
|
||||
{
|
||||
if (*CmdLine=='\"')
|
||||
{
|
||||
if (CmdLine[1]=='\"')
|
||||
{
|
||||
// Insert the quote character instead of two adjoining quote characters.
|
||||
if (Param!=NULL && ParamSize<MaxSize-1)
|
||||
Param[ParamSize++]='\"';
|
||||
CmdLine++;
|
||||
}
|
||||
else
|
||||
Quote=!Quote;
|
||||
}
|
||||
else
|
||||
if (Param!=NULL && ParamSize<MaxSize-1)
|
||||
Param[ParamSize++]=*CmdLine;
|
||||
CmdLine++;
|
||||
}
|
||||
if (Param!=NULL)
|
||||
Param[ParamSize]=0;
|
||||
return CmdLine;
|
||||
}
|
||||
|
||||
|
||||
#ifndef SILENT
|
||||
// For compatibility with existing translations we use %s to print Unicode
|
||||
// strings in format strings and convert them to %ls here. %s could work
|
||||
// without such conversion in Windows, but not in Unix wprintf.
|
||||
void PrintfPrepareFmt(const wchar *Org,wchar *Cvt,size_t MaxSize)
|
||||
{
|
||||
uint Src=0,Dest=0;
|
||||
while (Org[Src]!=0 && Dest<MaxSize-1)
|
||||
{
|
||||
if (Org[Src]=='%' && (Src==0 || Org[Src-1]!='%'))
|
||||
{
|
||||
uint SPos=Src+1;
|
||||
// Skipping a possible width specifier like %-50s.
|
||||
while (IsDigit(Org[SPos]) || Org[SPos]=='-')
|
||||
SPos++;
|
||||
if (Org[SPos]=='s' && Dest<MaxSize-(SPos-Src+1))
|
||||
{
|
||||
while (Src<SPos)
|
||||
Cvt[Dest++]=Org[Src++];
|
||||
Cvt[Dest++]='l';
|
||||
}
|
||||
}
|
||||
#ifdef _WIN_ALL
|
||||
// Convert \n to \r\n in Windows. Important when writing to log,
|
||||
// so other tools like Notebook can view resulting log properly.
|
||||
if (Org[Src]=='\n' && (Src==0 || Org[Src-1]!='\r'))
|
||||
Cvt[Dest++]='\r';
|
||||
#endif
|
||||
|
||||
Cvt[Dest++]=Org[Src++];
|
||||
}
|
||||
Cvt[Dest]=0;
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,45 @@
|
|||
#ifndef _RAR_STRFN_
|
||||
#define _RAR_STRFN_
|
||||
|
||||
const char* NullToEmpty(const char *Str);
|
||||
const wchar* NullToEmpty(const wchar *Str);
|
||||
void IntToExt(const char *Src,char *Dest,size_t DestSize);
|
||||
int stricomp(const char *s1,const char *s2);
|
||||
int strnicomp(const char *s1,const char *s2,size_t n);
|
||||
wchar* RemoveEOL(wchar *Str);
|
||||
wchar* RemoveLF(wchar *Str);
|
||||
unsigned char loctolower(unsigned char ch);
|
||||
unsigned char loctoupper(unsigned char ch);
|
||||
|
||||
char* strncpyz(char *dest, const char *src, size_t maxlen);
|
||||
wchar* wcsncpyz(wchar *dest, const wchar *src, size_t maxlen);
|
||||
char* strncatz(char* dest, const char* src, size_t maxlen);
|
||||
wchar* wcsncatz(wchar* dest, const wchar* src, size_t maxlen);
|
||||
|
||||
unsigned char etoupper(unsigned char ch);
|
||||
wchar etoupperw(wchar ch);
|
||||
|
||||
bool IsDigit(int ch);
|
||||
bool IsSpace(int ch);
|
||||
bool IsAlpha(int ch);
|
||||
|
||||
void BinToHex(const byte *Bin,size_t BinSize,char *Hex,wchar *HexW,size_t HexSize);
|
||||
|
||||
#ifndef SFX_MODULE
|
||||
uint GetDigits(uint Number);
|
||||
#endif
|
||||
|
||||
bool LowAscii(const char *Str);
|
||||
bool LowAscii(const wchar *Str);
|
||||
|
||||
int wcsicompc(const wchar *Str1,const wchar *Str2);
|
||||
|
||||
void itoa(int64 n,char *Str);
|
||||
void itoa(int64 n,wchar *Str);
|
||||
const wchar* GetWide(const char *Src);
|
||||
const wchar* GetCmdParam(const wchar *CmdLine,wchar *Param,size_t MaxSize);
|
||||
#ifndef SILENT
|
||||
void PrintfPrepareFmt(const wchar *Org,wchar *Cvt,size_t MaxSize);
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -7,6 +7,9 @@
|
|||
|
||||
// #included by unpack.cpp
|
||||
#ifdef RAR_COMMON_HPP
|
||||
static const uint UNIT_SIZE=Max(sizeof(RARPPM_CONTEXT),sizeof(RARPPM_MEM_BLK));
|
||||
static const uint FIXED_UNIT_SIZE=12;
|
||||
|
||||
SubAllocator::SubAllocator()
|
||||
{
|
||||
Clean();
|
||||
|
@ -41,12 +44,12 @@ inline uint SubAllocator::U2B(int NU)
|
|||
|
||||
|
||||
/*
|
||||
calculate RAR_MEM_BLK + Items address. Real RAR_MEM_BLK size must be
|
||||
equal to UNIT_SIZE, so we cannot just add Items to RAR_MEM_BLK address
|
||||
calculate RARPPM_MEM_BLK + Items address. Real RARPPM_MEM_BLK size must be
|
||||
equal to UNIT_SIZE, so we cannot just add Items to RARPPM_MEM_BLK address
|
||||
*/
|
||||
inline RAR_MEM_BLK* SubAllocator::MBPtr(RAR_MEM_BLK *BasePtr,int Items)
|
||||
inline RARPPM_MEM_BLK* SubAllocator::MBPtr(RARPPM_MEM_BLK *BasePtr,int Items)
|
||||
{
|
||||
return((RAR_MEM_BLK*)( ((byte *)(BasePtr))+U2B(Items) ));
|
||||
return((RARPPM_MEM_BLK*)( ((byte *)(BasePtr))+U2B(Items) ));
|
||||
}
|
||||
|
||||
|
||||
|
@ -102,9 +105,9 @@ void SubAllocator::InitSubAllocator()
|
|||
int i, k;
|
||||
memset(FreeList,0,sizeof(FreeList));
|
||||
pText=HeapStart;
|
||||
uint Size2=(uint)(FIXED_UNIT_SIZE*(SubAllocatorSize/8/FIXED_UNIT_SIZE*7));
|
||||
uint Size2=FIXED_UNIT_SIZE*(SubAllocatorSize/8/FIXED_UNIT_SIZE*7);
|
||||
uint RealSize2=Size2/FIXED_UNIT_SIZE*UNIT_SIZE;
|
||||
uint Size1=(uint)(SubAllocatorSize-Size2);
|
||||
uint Size1=SubAllocatorSize-Size2;
|
||||
uint RealSize1=Size1/FIXED_UNIT_SIZE*UNIT_SIZE+Size1%FIXED_UNIT_SIZE;
|
||||
#ifdef STRICT_ALIGNMENT_REQUIRED
|
||||
if (Size1%FIXED_UNIT_SIZE!=0)
|
||||
|
@ -132,14 +135,14 @@ void SubAllocator::InitSubAllocator()
|
|||
|
||||
inline void SubAllocator::GlueFreeBlocks()
|
||||
{
|
||||
RAR_MEM_BLK s0, * p, * p1;
|
||||
RARPPM_MEM_BLK s0, * p, * p1;
|
||||
int i, k, sz;
|
||||
if (LoUnit != HiUnit)
|
||||
*LoUnit=0;
|
||||
for (i=0, s0.next=s0.prev=&s0;i < N_INDEXES;i++)
|
||||
while ( FreeList[i].next )
|
||||
{
|
||||
p=(RAR_MEM_BLK*)RemoveNode(i);
|
||||
p=(RARPPM_MEM_BLK*)RemoveNode(i);
|
||||
p->insertAt(&s0);
|
||||
p->Stamp=0xFFFF;
|
||||
p->NU=Indx2Units[i];
|
||||
|
|
|
@ -10,21 +10,21 @@
|
|||
const int N1=4, N2=4, N3=4, N4=(128+3-1*N1-2*N2-3*N3)/4;
|
||||
const int N_INDEXES=N1+N2+N3+N4;
|
||||
|
||||
#if defined(__GNUC__) && !defined(STRICT_ALIGNMENT_REQUIRED)
|
||||
#define _PACK_ATTR __attribute__ ((packed))
|
||||
#if defined(__GNUC__) && defined(ALLOW_MISALIGNED)
|
||||
#define RARPPM_PACK_ATTR __attribute__ ((packed))
|
||||
#else
|
||||
#define _PACK_ATTR
|
||||
#define RARPPM_PACK_ATTR
|
||||
#endif /* defined(__GNUC__) */
|
||||
|
||||
#ifndef STRICT_ALIGNMENT_REQUIRED
|
||||
#ifdef ALLOW_MISALIGNED
|
||||
#pragma pack(1)
|
||||
#endif
|
||||
|
||||
struct RAR_MEM_BLK
|
||||
struct RARPPM_MEM_BLK
|
||||
{
|
||||
ushort Stamp, NU;
|
||||
RAR_MEM_BLK* next, * prev;
|
||||
void insertAt(RAR_MEM_BLK* p)
|
||||
RARPPM_MEM_BLK* next, * prev;
|
||||
void insertAt(RARPPM_MEM_BLK* p)
|
||||
{
|
||||
next=(prev=p)->next;
|
||||
p->next=next->prev=this;
|
||||
|
@ -34,9 +34,9 @@ struct RAR_MEM_BLK
|
|||
prev->next=next;
|
||||
next->prev=prev;
|
||||
}
|
||||
} _PACK_ATTR;
|
||||
} RARPPM_PACK_ATTR;
|
||||
|
||||
#ifndef STRICT_ALIGNMENT_REQUIRED
|
||||
#ifndef ALLOW_MISALIGNED
|
||||
#ifdef _AIX
|
||||
#pragma pack(pop)
|
||||
#else
|
||||
|
@ -60,7 +60,7 @@ class SubAllocator
|
|||
uint GetUsedMemory();
|
||||
inline void GlueFreeBlocks();
|
||||
void* AllocUnitsRare(int indx);
|
||||
inline RAR_MEM_BLK* MBPtr(RAR_MEM_BLK *BasePtr,int Items);
|
||||
inline RARPPM_MEM_BLK* MBPtr(RARPPM_MEM_BLK *BasePtr,int Items);
|
||||
|
||||
long SubAllocatorSize;
|
||||
byte Indx2Units[N_INDEXES], Units2Indx[128], GlueCount;
|
||||
|
|
|
@ -0,0 +1,298 @@
|
|||
#include "rar.hpp"
|
||||
|
||||
#ifdef _WIN_ALL
|
||||
RarTime& RarTime::operator =(FILETIME &ft)
|
||||
{
|
||||
_ULARGE_INTEGER ul = {ft.dwLowDateTime, ft.dwHighDateTime};
|
||||
itime=ul.QuadPart;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
void RarTime::GetWin32(FILETIME *ft)
|
||||
{
|
||||
_ULARGE_INTEGER ul;
|
||||
ul.QuadPart=itime;
|
||||
ft->dwLowDateTime=ul.LowPart;
|
||||
ft->dwHighDateTime=ul.HighPart;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
RarTime& RarTime::operator =(time_t ut)
|
||||
{
|
||||
uint64 ushift=int32to64(0x19DB1DE,0xD53E8000); // 116444736000000000.
|
||||
itime=uint64(ut)*10000000+ushift;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
time_t RarTime::GetUnix()
|
||||
{
|
||||
uint64 ushift=int32to64(0x19DB1DE,0xD53E8000); // 116444736000000000.
|
||||
time_t ut=(itime-ushift)/10000000;
|
||||
return ut;
|
||||
}
|
||||
|
||||
|
||||
void RarTime::GetLocal(RarLocalTime *lt)
|
||||
{
|
||||
#ifdef _WIN_ALL
|
||||
FILETIME ft;
|
||||
GetWin32(&ft);
|
||||
FILETIME lft;
|
||||
|
||||
if (WinNT() < WNT_VISTA)
|
||||
{
|
||||
// SystemTimeToTzSpecificLocalTime based code produces 1 hour error on XP.
|
||||
FileTimeToLocalFileTime(&ft,&lft);
|
||||
}
|
||||
else
|
||||
{
|
||||
// We use these functions instead of FileTimeToLocalFileTime according to
|
||||
// MSDN recommendation: "To account for daylight saving time
|
||||
// when converting a file time to a local time ..."
|
||||
SYSTEMTIME st1,st2;
|
||||
FileTimeToSystemTime(&ft,&st1);
|
||||
SystemTimeToTzSpecificLocalTime(NULL,&st1,&st2);
|
||||
SystemTimeToFileTime(&st2,&lft);
|
||||
|
||||
// Correct precision loss (low 4 decimal digits) in FileTimeToSystemTime.
|
||||
FILETIME rft;
|
||||
SystemTimeToFileTime(&st1,&rft);
|
||||
int64 Corrected=INT32TO64(ft.dwHighDateTime,ft.dwLowDateTime)-
|
||||
INT32TO64(rft.dwHighDateTime,rft.dwLowDateTime)+
|
||||
INT32TO64(lft.dwHighDateTime,lft.dwLowDateTime);
|
||||
lft.dwLowDateTime=(DWORD)Corrected;
|
||||
lft.dwHighDateTime=(DWORD)(Corrected>>32);
|
||||
}
|
||||
|
||||
SYSTEMTIME st;
|
||||
FileTimeToSystemTime(&lft,&st);
|
||||
lt->Year=st.wYear;
|
||||
lt->Month=st.wMonth;
|
||||
lt->Day=st.wDay;
|
||||
lt->Hour=st.wHour;
|
||||
lt->Minute=st.wMinute;
|
||||
lt->Second=st.wSecond;
|
||||
lt->wDay=st.wDayOfWeek;
|
||||
lt->yDay=lt->Day-1;
|
||||
|
||||
static int mdays[12]={31,28,31,30,31,30,31,31,30,31,30,31};
|
||||
for (uint I=1;I<lt->Month && I<=ASIZE(mdays);I++)
|
||||
lt->yDay+=mdays[I-1];
|
||||
|
||||
if (lt->Month>2 && IsLeapYear(lt->Year))
|
||||
lt->yDay++;
|
||||
|
||||
st.wMilliseconds=0;
|
||||
FILETIME zft;
|
||||
SystemTimeToFileTime(&st,&zft);
|
||||
|
||||
// Calculate the time reminder, which is the part of time smaller
|
||||
// than 1 second, represented in 100-nanosecond intervals.
|
||||
lt->Reminder=INT32TO64(lft.dwHighDateTime,lft.dwLowDateTime)-
|
||||
INT32TO64(zft.dwHighDateTime,zft.dwLowDateTime);
|
||||
#else
|
||||
time_t ut=GetUnix();
|
||||
struct tm *t;
|
||||
t=localtime(&ut);
|
||||
|
||||
lt->Year=t->tm_year+1900;
|
||||
lt->Month=t->tm_mon+1;
|
||||
lt->Day=t->tm_mday;
|
||||
lt->Hour=t->tm_hour;
|
||||
lt->Minute=t->tm_min;
|
||||
lt->Second=t->tm_sec;
|
||||
lt->Reminder=itime % 10000000;
|
||||
lt->wDay=t->tm_wday;
|
||||
lt->yDay=t->tm_yday;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void RarTime::SetLocal(RarLocalTime *lt)
|
||||
{
|
||||
#ifdef _WIN_ALL
|
||||
SYSTEMTIME st;
|
||||
st.wYear=lt->Year;
|
||||
st.wMonth=lt->Month;
|
||||
st.wDay=lt->Day;
|
||||
st.wHour=lt->Hour;
|
||||
st.wMinute=lt->Minute;
|
||||
st.wSecond=lt->Second;
|
||||
st.wMilliseconds=0;
|
||||
FILETIME lft;
|
||||
if (SystemTimeToFileTime(&st,&lft))
|
||||
{
|
||||
lft.dwLowDateTime+=lt->Reminder;
|
||||
if (lft.dwLowDateTime<lt->Reminder)
|
||||
lft.dwHighDateTime++;
|
||||
|
||||
FILETIME ft;
|
||||
|
||||
if (WinNT() < WNT_VISTA)
|
||||
{
|
||||
// TzSpecificLocalTimeToSystemTime based code produces 1 hour error on XP.
|
||||
LocalFileTimeToFileTime(&lft,&ft);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Reverse procedure which we do in GetLocal.
|
||||
SYSTEMTIME st1,st2;
|
||||
FileTimeToSystemTime(&lft,&st2);
|
||||
TzSpecificLocalTimeToSystemTime(NULL,&st2,&st1);
|
||||
SystemTimeToFileTime(&st1,&ft);
|
||||
|
||||
// Correct precision loss (low 4 decimal digits) in FileTimeToSystemTime.
|
||||
FILETIME rft;
|
||||
SystemTimeToFileTime(&st2,&rft);
|
||||
int64 Corrected=INT32TO64(lft.dwHighDateTime,lft.dwLowDateTime)-
|
||||
INT32TO64(rft.dwHighDateTime,rft.dwLowDateTime)+
|
||||
INT32TO64(ft.dwHighDateTime,ft.dwLowDateTime);
|
||||
ft.dwLowDateTime=(DWORD)Corrected;
|
||||
ft.dwHighDateTime=(DWORD)(Corrected>>32);
|
||||
}
|
||||
|
||||
*this=ft;
|
||||
}
|
||||
else
|
||||
Reset();
|
||||
#else
|
||||
struct tm t;
|
||||
|
||||
t.tm_sec=lt->Second;
|
||||
t.tm_min=lt->Minute;
|
||||
t.tm_hour=lt->Hour;
|
||||
t.tm_mday=lt->Day;
|
||||
t.tm_mon=lt->Month-1;
|
||||
t.tm_year=lt->Year-1900;
|
||||
t.tm_isdst=-1;
|
||||
*this=mktime(&t);
|
||||
itime+=lt->Reminder;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
// Return the stored time as 64-bit number of 100-nanosecond intervals since
|
||||
// 01.01.1601. Actually we do not care since which date this time starts from
|
||||
// as long as this date is the same for GetRaw and SetRaw. We use the value
|
||||
// returned by GetRaw() for time comparisons, for relative operations
|
||||
// like SetRaw(GetRaw()-C) and for compact time storage when necessary.
|
||||
uint64 RarTime::GetRaw()
|
||||
{
|
||||
return itime;
|
||||
}
|
||||
|
||||
|
||||
void RarTime::SetRaw(uint64 RawTime)
|
||||
{
|
||||
itime=RawTime;
|
||||
}
|
||||
|
||||
|
||||
uint RarTime::GetDos()
|
||||
{
|
||||
RarLocalTime lt;
|
||||
GetLocal(<);
|
||||
uint DosTime=(lt.Second/2)|(lt.Minute<<5)|(lt.Hour<<11)|
|
||||
(lt.Day<<16)|(lt.Month<<21)|((lt.Year-1980)<<25);
|
||||
return DosTime;
|
||||
}
|
||||
|
||||
|
||||
void RarTime::SetDos(uint DosTime)
|
||||
{
|
||||
RarLocalTime lt;
|
||||
lt.Second=(DosTime & 0x1f)*2;
|
||||
lt.Minute=(DosTime>>5) & 0x3f;
|
||||
lt.Hour=(DosTime>>11) & 0x1f;
|
||||
lt.Day=(DosTime>>16) & 0x1f;
|
||||
lt.Month=(DosTime>>21) & 0x0f;
|
||||
lt.Year=(DosTime>>25)+1980;
|
||||
lt.Reminder=0;
|
||||
SetLocal(<);
|
||||
}
|
||||
|
||||
|
||||
#ifndef SFX_MODULE
|
||||
void RarTime::SetIsoText(const wchar *TimeText)
|
||||
{
|
||||
int Field[6];
|
||||
memset(Field,0,sizeof(Field));
|
||||
for (uint DigitCount=0;*TimeText!=0;TimeText++)
|
||||
if (IsDigit(*TimeText))
|
||||
{
|
||||
int FieldPos=DigitCount<4 ? 0:(DigitCount-4)/2+1;
|
||||
if (FieldPos<ASIZE(Field))
|
||||
Field[FieldPos]=Field[FieldPos]*10+*TimeText-'0';
|
||||
DigitCount++;
|
||||
}
|
||||
RarLocalTime lt;
|
||||
lt.Second=Field[5];
|
||||
lt.Minute=Field[4];
|
||||
lt.Hour=Field[3];
|
||||
lt.Day=Field[2]==0 ? 1:Field[2];
|
||||
lt.Month=Field[1]==0 ? 1:Field[1];
|
||||
lt.Year=Field[0];
|
||||
lt.Reminder=0;
|
||||
SetLocal(<);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef SFX_MODULE
|
||||
void RarTime::SetAgeText(const wchar *TimeText)
|
||||
{
|
||||
uint Seconds=0,Value=0;
|
||||
for (int I=0;TimeText[I]!=0;I++)
|
||||
{
|
||||
int Ch=TimeText[I];
|
||||
if (IsDigit(Ch))
|
||||
Value=Value*10+Ch-'0';
|
||||
else
|
||||
{
|
||||
switch(etoupper(Ch))
|
||||
{
|
||||
case 'D':
|
||||
Seconds+=Value*24*3600;
|
||||
break;
|
||||
case 'H':
|
||||
Seconds+=Value*3600;
|
||||
break;
|
||||
case 'M':
|
||||
Seconds+=Value*60;
|
||||
break;
|
||||
case 'S':
|
||||
Seconds+=Value;
|
||||
break;
|
||||
}
|
||||
Value=0;
|
||||
}
|
||||
}
|
||||
SetCurrentTime();
|
||||
SetRaw(itime-uint64(Seconds)*10000000);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void RarTime::SetCurrentTime()
|
||||
{
|
||||
#ifdef _WIN_ALL
|
||||
FILETIME ft;
|
||||
SYSTEMTIME st;
|
||||
GetSystemTime(&st);
|
||||
SystemTimeToFileTime(&st,&ft);
|
||||
*this=ft;
|
||||
#else
|
||||
time_t st;
|
||||
time(&st);
|
||||
*this=st;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
bool IsLeapYear(int Year)
|
||||
{
|
||||
return (Year&3)==0 && (Year%100!=0 || Year%400==0);
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
#ifndef _RAR_TIMEFN_
|
||||
#define _RAR_TIMEFN_
|
||||
|
||||
#include <time.h>
|
||||
|
||||
struct RarLocalTime
|
||||
{
|
||||
uint Year;
|
||||
uint Month;
|
||||
uint Day;
|
||||
uint Hour;
|
||||
uint Minute;
|
||||
uint Second;
|
||||
uint Reminder; // Part of time smaller than 1 second, represented in 100-nanosecond intervals.
|
||||
uint wDay;
|
||||
uint yDay;
|
||||
};
|
||||
|
||||
|
||||
class RarTime
|
||||
{
|
||||
private:
|
||||
// Internal FILETIME like time representation in 100 nanoseconds
|
||||
// since 01.01.1601.
|
||||
uint64 itime;
|
||||
public:
|
||||
RarTime() {Reset();}
|
||||
#ifdef _WIN_ALL
|
||||
RarTime(FILETIME &ft) {*this=ft;}
|
||||
RarTime& operator =(FILETIME &ft);
|
||||
void GetWin32(FILETIME *ft);
|
||||
#endif
|
||||
RarTime(time_t ut) {*this=ut;}
|
||||
RarTime& operator =(time_t ut);
|
||||
time_t GetUnix();
|
||||
bool operator == (RarTime &rt) {return itime==rt.itime;}
|
||||
bool operator < (RarTime &rt) {return itime<rt.itime;}
|
||||
bool operator <= (RarTime &rt) {return itime<rt.itime || itime==rt.itime;}
|
||||
bool operator > (RarTime &rt) {return itime>rt.itime;}
|
||||
bool operator >= (RarTime &rt) {return itime>rt.itime || itime==rt.itime;}
|
||||
void GetLocal(RarLocalTime *lt);
|
||||
void SetLocal(RarLocalTime *lt);
|
||||
uint64 GetRaw();
|
||||
void SetRaw(uint64 RawTime);
|
||||
uint GetDos();
|
||||
void SetDos(uint DosTime);
|
||||
void SetIsoText(const wchar *TimeText);
|
||||
void SetAgeText(const wchar *TimeText);
|
||||
void SetCurrentTime();
|
||||
void Reset() {itime=0;}
|
||||
bool IsSet() {return itime!=0;}
|
||||
};
|
||||
|
||||
bool IsLeapYear(int Year);
|
||||
|
||||
#endif
|
|
@ -2,6 +2,48 @@
|
|||
|
||||
#include "unicode.hpp"
|
||||
|
||||
bool CharToWide(const char *Src,wchar *Dest,int DestSize)
|
||||
{
|
||||
bool RetCode=true;
|
||||
#ifdef _WIN_32
|
||||
if (MultiByteToWideChar(CP_ACP,0,Src,-1,Dest,DestSize,NULL,NULL)==0)
|
||||
RetCode=false;
|
||||
#else
|
||||
#ifdef _APPLE
|
||||
UtfToWide(Src,Dest,DestSize);
|
||||
#else
|
||||
#ifdef MBFUNCTIONS
|
||||
|
||||
size_t ResultingSize=mbstowcs(Dest,Src,DestSize);
|
||||
if (ResultingSize==(size_t)-1)
|
||||
RetCode=false;
|
||||
if (ResultingSize==0 && *Src!=0)
|
||||
RetCode=false;
|
||||
|
||||
if ((!RetCode || *Dest==0 && *Src!=0) && DestSize>NM && strlen(Src)<NM)
|
||||
{
|
||||
/* Workaround for strange Linux Unicode functions bug.
|
||||
Some of wcstombs and mbstowcs implementations in some situations
|
||||
(we are yet to find out what it depends on) can return an empty
|
||||
string and success code if buffer size value is too large.
|
||||
*/
|
||||
return(CharToWide(Src,Dest,NM));
|
||||
}
|
||||
|
||||
#else
|
||||
// TODO: convert to UTF-8? Would need conversion routine. Ugh.
|
||||
for (int I=0;I<DestSize;I++)
|
||||
{
|
||||
Dest[I]=(wchar)Src[I];
|
||||
if (Src[I]==0)
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
return(RetCode);
|
||||
}
|
||||
|
||||
bool WideToChar(const wchar *Src,char *Dest,int DestSize)
|
||||
{
|
||||
bool RetCode=true;
|
||||
|
@ -94,6 +136,15 @@ void UtfToWide(const char *Src,wchar *Dest,int DestSize)
|
|||
}
|
||||
|
||||
|
||||
wchar* RawToWide(const byte *Src,wchar *Dest,size_t DestSize)
|
||||
{
|
||||
for (size_t I=0;I<DestSize;I++)
|
||||
if ((Dest[I]=Src[I*2]+(Src[I*2+1]<<8))==0)
|
||||
break;
|
||||
return Dest;
|
||||
}
|
||||
|
||||
|
||||
// strfn.cpp
|
||||
void ExtToInt(const char *Src,char *Dest)
|
||||
{
|
||||
|
@ -104,3 +155,44 @@ void ExtToInt(const char *Src,char *Dest)
|
|||
strcpy(Dest,Src);
|
||||
#endif
|
||||
}
|
||||
|
||||
size_t my_wcslen(const wchar *a)
|
||||
{
|
||||
size_t I;
|
||||
for (I=0; a[I]; ++I);
|
||||
return I;
|
||||
}
|
||||
|
||||
int my_wcsncmp(const wchar *a, const wchar *b, size_t Max)
|
||||
{
|
||||
for (size_t I=0; I<Max && (a[I] || b[I]); ++I)
|
||||
{
|
||||
if (a[I] != b[I])
|
||||
return a[I] - b[I];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int my_wcscmp(const wchar *a, const wchar *b)
|
||||
{
|
||||
return my_wcsncmp(a, b, ~0UL);
|
||||
}
|
||||
|
||||
void my_wcsncpy(wchar *Dest, const wchar *Src, size_t DestSize)
|
||||
{
|
||||
size_t I;
|
||||
for (I=0; I<DestSize && Src[I]; ++I)
|
||||
Dest[I] = Src[I];
|
||||
if (I<DestSize)
|
||||
Dest[I] = 0;
|
||||
}
|
||||
|
||||
void my_wcsncat(wchar *Dest, const wchar *Src, size_t DestSize)
|
||||
{
|
||||
size_t I, J;
|
||||
for (I=0; I<DestSize && Dest[I]; ++I);
|
||||
for (J=0; I<DestSize && Src[J]; ++I, ++J)
|
||||
Dest[I] = Src[J];
|
||||
if (I<DestSize)
|
||||
Dest[I] = 0;
|
||||
}
|
||||
|
|
|
@ -1,10 +1,18 @@
|
|||
#ifndef _RAR_UNICODE_
|
||||
#define _RAR_UNICODE_
|
||||
|
||||
bool CharToWide(const char *Src,wchar *Dest,int DestSize);
|
||||
bool WideToChar(const wchar *Src,char *Dest,int DestSize=0x1000000);
|
||||
void UtfToWide(const char *Src,wchar *Dest,int DestSize);
|
||||
wchar* RawToWide(const byte *Src,wchar *Dest,size_t DestSize);
|
||||
|
||||
// strfn.cpp
|
||||
void ExtToInt(const char *Src,char *Dest);
|
||||
|
||||
size_t my_wcslen(const wchar *a);
|
||||
int my_wcscmp(const wchar *a, const wchar *b);
|
||||
int my_wcsncmp(const wchar *a, const wchar *b, size_t DestSize);
|
||||
void my_wcsncpy(wchar *Dest, const wchar *Src, size_t DestSize);
|
||||
void my_wcsncat(wchar *Dest, const wchar *Src, size_t DestSize);
|
||||
|
||||
#endif
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,58 +1,145 @@
|
|||
#ifndef _RAR_UNPACK_
|
||||
#define _RAR_UNPACK_
|
||||
|
||||
enum BLOCK_TYPES {BLOCK_LZ,BLOCK_PPM};
|
||||
// Maximum allowed number of compressed bits processed in quick mode.
|
||||
#define MAX_QUICK_DECODE_BITS 10
|
||||
|
||||
struct Decode
|
||||
// Maximum number of filters per entire data block.
|
||||
#define MAX_UNPACK_FILTERS 8192
|
||||
|
||||
// Maximum number of filters per entire data block for RAR3 unpack.
|
||||
#define MAX3_FILTERS 1024
|
||||
|
||||
// Write data in 4 MB or smaller blocks.
|
||||
#define UNPACK_MAX_WRITE 0x400000
|
||||
|
||||
// Decode compressed bit fields to alphabet numbers.
|
||||
struct DecodeTable:PackDef
|
||||
{
|
||||
unsigned int MaxNum;
|
||||
unsigned int DecodeLen[16];
|
||||
unsigned int DecodePos[16];
|
||||
unsigned int DecodeNum[2];
|
||||
// Real size of DecodeNum table.
|
||||
uint MaxNum;
|
||||
|
||||
// Left aligned start and upper limit codes defining code space
|
||||
// ranges for bit lengths. DecodeLen[BitLength-1] defines the start of
|
||||
// range for bit length and DecodeLen[BitLength] defines next code
|
||||
// after the end of range or in other words the upper limit code
|
||||
// for specified bit length.
|
||||
uint DecodeLen[16];
|
||||
|
||||
// Every item of this array contains the sum of all preceding items.
|
||||
// So it contains the start position in code list for every bit length.
|
||||
uint DecodePos[16];
|
||||
|
||||
// Number of compressed bits processed in quick mode.
|
||||
// Must not exceed MAX_QUICK_DECODE_BITS.
|
||||
uint QuickBits;
|
||||
|
||||
// Translates compressed bits (up to QuickBits length)
|
||||
// to bit length in quick mode.
|
||||
byte QuickLen[1<<MAX_QUICK_DECODE_BITS];
|
||||
|
||||
// Translates compressed bits (up to QuickBits length)
|
||||
// to position in alphabet in quick mode.
|
||||
// 'ushort' saves some memory and even provides a little speed gain
|
||||
// comparting to 'uint' here.
|
||||
ushort QuickNum[1<<MAX_QUICK_DECODE_BITS];
|
||||
|
||||
// Translate the position in code list to position in alphabet.
|
||||
// We do not allocate it dynamically to avoid performance overhead
|
||||
// introduced by pointer, so we use the largest possible table size
|
||||
// as array dimension. Real size of this array is defined in MaxNum.
|
||||
// We use this array if compressed bit field is too lengthy
|
||||
// for QuickLen based translation.
|
||||
// 'ushort' saves some memory and even provides a little speed gain
|
||||
// comparting to 'uint' here.
|
||||
ushort DecodeNum[LARGEST_TABLE_SIZE];
|
||||
};
|
||||
|
||||
struct LitDecode
|
||||
|
||||
struct UnpackBlockHeader
|
||||
{
|
||||
unsigned int MaxNum;
|
||||
unsigned int DecodeLen[16];
|
||||
unsigned int DecodePos[16];
|
||||
unsigned int DecodeNum[NC];
|
||||
int BlockSize;
|
||||
int BlockBitSize;
|
||||
int BlockStart;
|
||||
int HeaderSize;
|
||||
bool LastBlockInFile;
|
||||
bool TablePresent;
|
||||
};
|
||||
|
||||
struct DistDecode
|
||||
|
||||
struct UnpackBlockTables
|
||||
{
|
||||
unsigned int MaxNum;
|
||||
unsigned int DecodeLen[16];
|
||||
unsigned int DecodePos[16];
|
||||
unsigned int DecodeNum[DC];
|
||||
DecodeTable LD; // Decode literals.
|
||||
DecodeTable DD; // Decode distances.
|
||||
DecodeTable LDD; // Decode lower bits of distances.
|
||||
DecodeTable RD; // Decode repeating distances.
|
||||
DecodeTable BD; // Decode bit lengths in Huffman table.
|
||||
};
|
||||
|
||||
struct LowDistDecode
|
||||
{
|
||||
unsigned int MaxNum;
|
||||
unsigned int DecodeLen[16];
|
||||
unsigned int DecodePos[16];
|
||||
unsigned int DecodeNum[LDC];
|
||||
|
||||
#ifdef RAR_SMP
|
||||
enum UNP_DEC_TYPE {
|
||||
UNPDT_LITERAL,UNPDT_MATCH,UNPDT_FULLREP,UNPDT_REP,UNPDT_FILTER
|
||||
};
|
||||
|
||||
struct RepDecode
|
||||
struct UnpackDecodedItem
|
||||
{
|
||||
unsigned int MaxNum;
|
||||
unsigned int DecodeLen[16];
|
||||
unsigned int DecodePos[16];
|
||||
unsigned int DecodeNum[RC];
|
||||
UNP_DEC_TYPE Type;
|
||||
ushort Length;
|
||||
union
|
||||
{
|
||||
uint Distance;
|
||||
byte Literal[4];
|
||||
};
|
||||
};
|
||||
|
||||
struct BitDecode
|
||||
|
||||
struct UnpackThreadData
|
||||
{
|
||||
unsigned int MaxNum;
|
||||
unsigned int DecodeLen[16];
|
||||
unsigned int DecodePos[16];
|
||||
unsigned int DecodeNum[BC];
|
||||
Unpack *UnpackPtr;
|
||||
BitInput Inp;
|
||||
bool HeaderRead;
|
||||
UnpackBlockHeader BlockHeader;
|
||||
bool TableRead;
|
||||
UnpackBlockTables BlockTables;
|
||||
int DataSize; // Data left in buffer. Can be less than block size.
|
||||
bool DamagedData;
|
||||
bool LargeBlock;
|
||||
bool NoDataLeft; // 'true' if file is read completely.
|
||||
bool Incomplete; // Not entire block was processed, need to read more data.
|
||||
|
||||
UnpackDecodedItem *Decoded;
|
||||
uint DecodedSize;
|
||||
uint DecodedAllocated;
|
||||
uint ThreadNumber; // For debugging.
|
||||
|
||||
UnpackThreadData()
|
||||
:Inp(false)
|
||||
{
|
||||
Decoded=NULL;
|
||||
}
|
||||
~UnpackThreadData()
|
||||
{
|
||||
if (Decoded!=NULL)
|
||||
free(Decoded);
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
struct UnpackFilter
|
||||
: Rar_Allocator
|
||||
{
|
||||
byte Type;
|
||||
uint BlockStart;
|
||||
uint BlockLength;
|
||||
byte Channels;
|
||||
// uint Width;
|
||||
// byte PosR;
|
||||
bool NextWindow;
|
||||
};
|
||||
|
||||
|
||||
struct UnpackFilter30
|
||||
{
|
||||
unsigned int BlockStart;
|
||||
unsigned int BlockLength;
|
||||
|
@ -64,19 +151,10 @@ struct UnpackFilter
|
|||
unsigned int ParentFilter;
|
||||
|
||||
VM_PreparedProgram Prg;
|
||||
UnpackFilter( Rar_Error_Handler* eh ) : Prg( eh ) { }
|
||||
};
|
||||
|
||||
/***************************** Unpack v 2.0 *********************************/
|
||||
struct MultDecode
|
||||
{
|
||||
unsigned int MaxNum;
|
||||
unsigned int DecodeLen[16];
|
||||
unsigned int DecodePos[16];
|
||||
unsigned int DecodeNum[MC20];
|
||||
};
|
||||
|
||||
struct AudioVariables
|
||||
struct AudioVariables // For RAR 2.0 archives only.
|
||||
{
|
||||
int K1,K2,K3,K4,K5;
|
||||
int D1,D2,D3,D4;
|
||||
|
@ -85,90 +163,103 @@ struct AudioVariables
|
|||
unsigned int ByteCount;
|
||||
int LastChar;
|
||||
};
|
||||
/***************************** Unpack v 2.0 *********************************/
|
||||
|
||||
|
||||
// public so operator new/delete will be accessible, argh
|
||||
class Unpack:public BitInput
|
||||
// We can use the fragmented dictionary in case heap does not have the single
|
||||
// large enough memory block. It is slower than normal dictionary.
|
||||
class FragmentedWindow
|
||||
{
|
||||
private:
|
||||
friend class Pack;
|
||||
enum {MAX_MEM_BLOCKS=32};
|
||||
|
||||
void Unpack29(bool Solid);
|
||||
void Reset();
|
||||
byte *Mem[MAX_MEM_BLOCKS];
|
||||
size_t MemSize[MAX_MEM_BLOCKS];
|
||||
public:
|
||||
FragmentedWindow();
|
||||
~FragmentedWindow();
|
||||
void Init(size_t WinSize);
|
||||
byte& operator [](size_t Item);
|
||||
void CopyString(uint Length,uint Distance,size_t &UnpPtr,size_t MaxWinMask);
|
||||
void CopyData(byte *Dest,size_t WinPos,size_t Size);
|
||||
size_t GetBlockSize(size_t StartPos,size_t RequiredSize);
|
||||
};
|
||||
|
||||
|
||||
class Unpack:PackDef
|
||||
{
|
||||
public:
|
||||
static void init_tables();
|
||||
|
||||
private:
|
||||
|
||||
void Unpack5(bool Solid);
|
||||
void Unpack5MT(bool Solid);
|
||||
bool UnpReadBuf();
|
||||
void UnpWriteBuf();
|
||||
void ExecuteCode(VM_PreparedProgram *Prg);
|
||||
void UnpWriteArea(unsigned int StartPtr,unsigned int EndPtr);
|
||||
void UnpWriteData(byte *Data,int Size);
|
||||
bool ReadTables();
|
||||
void MakeDecodeTables(unsigned char *LenTab,struct Decode *Dec,int Size);
|
||||
int DecodeNumber(struct Decode *Dec);
|
||||
byte* ApplyFilter(byte *Data,uint DataSize,UnpackFilter *Flt);
|
||||
void UnpWriteArea(size_t StartPtr,size_t EndPtr);
|
||||
void UnpWriteData(byte *Data,size_t Size);
|
||||
uint SlotToLength(BitInput &Inp,uint Slot);
|
||||
bool ReadBlockHeader(BitInput &Inp,UnpackBlockHeader &Header);
|
||||
bool ReadTables(BitInput &Inp,UnpackBlockHeader &Header,UnpackBlockTables &Tables);
|
||||
void MakeDecodeTables(byte *LengthTable,DecodeTable *Dec,uint Size);
|
||||
uint DecodeNumber(BitInput &Inp,DecodeTable *Dec);
|
||||
void CopyString();
|
||||
inline void InsertOldDist(unsigned int Distance);
|
||||
inline void InsertLastMatch(unsigned int Length,unsigned int Distance);
|
||||
void UnpInitData(int Solid);
|
||||
void CopyString(unsigned int Length,unsigned int Distance);
|
||||
bool ReadEndOfBlock();
|
||||
bool ReadVMCode();
|
||||
bool ReadVMCodePPM();
|
||||
bool AddVMCode(unsigned int FirstByte,byte *Code,int CodeSize);
|
||||
void UnpInitData(bool Solid);
|
||||
void CopyString(uint Length,uint Distance);
|
||||
uint ReadFilterData(BitInput &Inp);
|
||||
bool ReadFilter(BitInput &Inp,UnpackFilter &Filter);
|
||||
bool AddFilter(UnpackFilter &Filter);
|
||||
bool AddFilter();
|
||||
void InitFilters();
|
||||
|
||||
ComprDataIO *UnpIO;
|
||||
ModelPPM PPM;
|
||||
int PPMEscChar;
|
||||
BitInput Inp;
|
||||
|
||||
Array<byte> VMCode; // here to avoid leaks
|
||||
BitInput Inp; // here to avoid leaks
|
||||
Array<byte> FilterSrcMemory;
|
||||
Array<byte> FilterDstMemory;
|
||||
|
||||
RarVM VM;
|
||||
// Filters code, one entry per filter.
|
||||
Array<UnpackFilter> Filters;
|
||||
|
||||
UnpackFilter* LastStackFilter; // avoids leak for stack-based filter
|
||||
uint OldDist[4],OldDistPtr;
|
||||
uint LastLength;
|
||||
|
||||
/* Filters code, one entry per filter */
|
||||
Array<UnpackFilter*> Filters;
|
||||
// LastDist is necessary only for RAR2 and older with circular OldDist
|
||||
// array. In RAR3 last distance is always stored in OldDist[0].
|
||||
uint LastDist;
|
||||
|
||||
/* Filters stack, several entrances of same filter are possible */
|
||||
Array<UnpackFilter*> PrgStack;
|
||||
|
||||
/* lengths of preceding blocks, one length per filter. Used to reduce
|
||||
size required to write block length if lengths are repeating */
|
||||
Array<int> OldFilterLengths;
|
||||
|
||||
int LastFilter;
|
||||
|
||||
bool TablesRead;
|
||||
struct LitDecode LD;
|
||||
struct DistDecode DD;
|
||||
struct LowDistDecode LDD;
|
||||
struct RepDecode RD;
|
||||
struct BitDecode BD;
|
||||
|
||||
unsigned int OldDist[4],OldDistPtr;
|
||||
unsigned int LastDist,LastLength;
|
||||
|
||||
unsigned int UnpPtr,WrPtr;
|
||||
size_t UnpPtr,WrPtr;
|
||||
|
||||
// Top border of read packed data.
|
||||
int ReadTop;
|
||||
|
||||
// Border to call UnpReadBuf. We use it instead of (ReadTop-C)
|
||||
// for optimization reasons. Ensures that we have C bytes in buffer
|
||||
// unless we are at the end of file.
|
||||
int ReadBorder;
|
||||
|
||||
unsigned char UnpOldTable[HUFF_TABLE_SIZE];
|
||||
UnpackBlockHeader BlockHeader;
|
||||
UnpackBlockTables BlockTables;
|
||||
|
||||
int UnpBlockType;
|
||||
size_t WriteBorder;
|
||||
|
||||
byte *Window;
|
||||
bool ExternalWindow;
|
||||
|
||||
FragmentedWindow FragWindow;
|
||||
bool Fragmented;
|
||||
|
||||
|
||||
Int64 DestUnpSize;
|
||||
int64 DestUnpSize;
|
||||
|
||||
enum { Suspended = false }; // original source could never set to true
|
||||
bool Suspended;
|
||||
bool UnpAllBuf;
|
||||
bool UnpSomeRead;
|
||||
Int64 WrittenFileSize;
|
||||
int64 WrittenFileSize;
|
||||
bool FileExtracted;
|
||||
|
||||
int PrevLowDist,LowDistRepCount;
|
||||
|
||||
/***************************** Unpack v 1.5 *********************************/
|
||||
void Unpack15(bool Solid);
|
||||
|
@ -176,51 +267,102 @@ private:
|
|||
void LongLZ();
|
||||
void HuffDecode();
|
||||
void GetFlagsBuf();
|
||||
void OldUnpInitData(int Solid);
|
||||
void UnpInitData15(int Solid);
|
||||
void InitHuff();
|
||||
void CorrHuff(unsigned int *CharSet,unsigned int *NumToPlace);
|
||||
void OldCopyString(unsigned int Distance,unsigned int Length);
|
||||
unsigned int DecodeNum(int Num,unsigned int StartPos,
|
||||
const unsigned int *DecTab,const unsigned int *PosTab);
|
||||
void OldUnpWriteBuf();
|
||||
void CorrHuff(ushort *CharSet,byte *NumToPlace);
|
||||
void CopyString15(uint Distance,uint Length);
|
||||
uint DecodeNum(uint Num,uint StartPos,uint *DecTab,uint *PosTab);
|
||||
|
||||
unsigned int ChSet[256],ChSetA[256],ChSetB[256],ChSetC[256];
|
||||
unsigned int Place[256],PlaceA[256],PlaceB[256],PlaceC[256];
|
||||
unsigned int NToPl[256],NToPlB[256],NToPlC[256];
|
||||
unsigned int FlagBuf,AvrPlc,AvrPlcB,AvrLn1,AvrLn2,AvrLn3;
|
||||
ushort ChSet[256],ChSetA[256],ChSetB[256],ChSetC[256];
|
||||
byte NToPl[256],NToPlB[256],NToPlC[256];
|
||||
uint FlagBuf,AvrPlc,AvrPlcB,AvrLn1,AvrLn2,AvrLn3;
|
||||
int Buf60,NumHuf,StMode,LCount,FlagsCnt;
|
||||
unsigned int Nhfb,Nlzb,MaxDist3;
|
||||
uint Nhfb,Nlzb,MaxDist3;
|
||||
/***************************** Unpack v 1.5 *********************************/
|
||||
|
||||
/***************************** Unpack v 2.0 *********************************/
|
||||
void Unpack20(bool Solid);
|
||||
struct MultDecode MD[4];
|
||||
|
||||
DecodeTable MD[4]; // Decode multimedia data, up to 4 channels.
|
||||
|
||||
unsigned char UnpOldTable20[MC20*4];
|
||||
int UnpAudioBlock,UnpChannels,UnpCurChannel,UnpChannelDelta;
|
||||
void CopyString20(unsigned int Length,unsigned int Distance);
|
||||
uint UnpAudioBlock,UnpChannels,UnpCurChannel;
|
||||
int UnpChannelDelta;
|
||||
void CopyString20(uint Length,uint Distance);
|
||||
bool ReadTables20();
|
||||
void UnpWriteBuf20();
|
||||
void UnpInitData20(int Solid);
|
||||
void ReadLastTables();
|
||||
byte DecodeAudio(int Delta);
|
||||
struct AudioVariables AudV[4];
|
||||
/***************************** Unpack v 2.0 *********************************/
|
||||
|
||||
public:
|
||||
Rar_Error_Handler& ErrHandler;
|
||||
byte const* window_wrptr() const { return &Window [WrPtr & MAXWINMASK]; }
|
||||
/***************************** Unpack v 3.0 *********************************/
|
||||
enum BLOCK_TYPES {BLOCK_LZ,BLOCK_PPM};
|
||||
|
||||
static void init_tables();
|
||||
void UnpInitData30(bool Solid);
|
||||
void Unpack29(bool Solid);
|
||||
void InitFilters30();
|
||||
bool ReadEndOfBlock();
|
||||
bool ReadVMCode();
|
||||
bool ReadVMCodePPM();
|
||||
bool AddVMCode(uint FirstByte,byte *Code,int CodeSize);
|
||||
int SafePPMDecodeChar();
|
||||
bool ReadTables30();
|
||||
bool UnpReadBuf30();
|
||||
void UnpWriteBuf30();
|
||||
void ExecuteCode(VM_PreparedProgram *Prg);
|
||||
|
||||
int PrevLowDist,LowDistRepCount;
|
||||
|
||||
ModelPPM PPM;
|
||||
int PPMEscChar;
|
||||
|
||||
byte UnpOldTable[HUFF_TABLE_SIZE30];
|
||||
int UnpBlockType;
|
||||
|
||||
bool TablesRead;
|
||||
|
||||
// Virtual machine to execute filters code.
|
||||
RarVM VM;
|
||||
|
||||
// Buffer to read VM filters code. We moved it here from AddVMCode
|
||||
// function to reduce time spent in BitInput constructor.
|
||||
BitInput VMCodeInp;
|
||||
|
||||
// Filters code, one entry per filter.
|
||||
Array<UnpackFilter30 *> Filters30;
|
||||
|
||||
// Filters stack, several entrances of same filter are possible.
|
||||
Array<UnpackFilter30 *> PrgStack;
|
||||
|
||||
// Lengths of preceding data blocks, one length of one last block
|
||||
// for every filter. Used to reduce the size required to write
|
||||
// the data block length if lengths are repeating.
|
||||
Array<int> OldFilterLengths;
|
||||
|
||||
int LastFilter;
|
||||
/***************************** Unpack v 3.0 *********************************/
|
||||
|
||||
public:
|
||||
Unpack(ComprDataIO *DataIO);
|
||||
~Unpack();
|
||||
void Init(byte *Window=NULL);
|
||||
void Init(size_t WinSize,bool Solid);
|
||||
void DoUnpack(int Method,bool Solid);
|
||||
void SetDestSize(Int64 DestSize) {DestUnpSize=DestSize;FileExtracted=false;}
|
||||
bool IsFileExtracted() {return(FileExtracted);}
|
||||
void SetDestSize(int64 DestSize) {DestUnpSize=DestSize;FileExtracted=false;}
|
||||
void SetSuspended(bool Suspended) {Unpack::Suspended=Suspended;}
|
||||
|
||||
unsigned int GetChar()
|
||||
byte const* window_wrptr() const { return &Window [WrPtr & MaxWinMask]; }
|
||||
|
||||
size_t MaxWinSize;
|
||||
size_t MaxWinMask;
|
||||
|
||||
uint GetChar()
|
||||
{
|
||||
if (InAddr>BitInput::MAX_SIZE-30)
|
||||
if (Inp.InAddr>BitInput::MAX_SIZE-30)
|
||||
UnpReadBuf();
|
||||
return(InBuf[InAddr++]);
|
||||
return(Inp.InBuf[Inp.InAddr++]);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -1,66 +1,46 @@
|
|||
// #included by unpack.cpp
|
||||
#ifdef RAR_COMMON_HPP
|
||||
#define STARTL1 2
|
||||
const
|
||||
static unsigned int DecL1[]={0x8000,0xa000,0xc000,0xd000,0xe000,0xea00,
|
||||
0xee00,0xf000,0xf200,0xf200,0xffff};
|
||||
const
|
||||
static unsigned int PosL1[]={0,0,0,2,3,5,7,11,16,20,24,32,32};
|
||||
|
||||
#define STARTL2 3
|
||||
const
|
||||
static unsigned int DecL2[]={0xa000,0xc000,0xd000,0xe000,0xea00,0xee00,
|
||||
0xf000,0xf200,0xf240,0xffff};
|
||||
const
|
||||
static unsigned int PosL2[]={0,0,0,0,5,7,9,13,18,22,26,34,36};
|
||||
|
||||
#define STARTHF0 4
|
||||
const
|
||||
static unsigned int DecHf0[]={0x8000,0xc000,0xe000,0xf200,0xf200,0xf200,
|
||||
0xf200,0xf200,0xffff};
|
||||
const
|
||||
static unsigned int PosHf0[]={0,0,0,0,0,8,16,24,33,33,33,33,33};
|
||||
|
||||
|
||||
#define STARTHF1 5
|
||||
const
|
||||
static unsigned int DecHf1[]={0x2000,0xc000,0xe000,0xf000,0xf200,0xf200,
|
||||
0xf7e0,0xffff};
|
||||
const
|
||||
static unsigned int PosHf1[]={0,0,0,0,0,0,4,44,60,76,80,80,127};
|
||||
|
||||
|
||||
#define STARTHF2 5
|
||||
const
|
||||
static unsigned int DecHf2[]={0x1000,0x2400,0x8000,0xc000,0xfa00,0xffff,
|
||||
0xffff,0xffff};
|
||||
const
|
||||
static unsigned int PosHf2[]={0,0,0,0,0,0,2,7,53,117,233,0,0};
|
||||
|
||||
|
||||
#define STARTHF3 6
|
||||
const
|
||||
static unsigned int DecHf3[]={0x800,0x2400,0xee00,0xfe80,0xffff,0xffff,
|
||||
0xffff};
|
||||
const
|
||||
static unsigned int PosHf3[]={0,0,0,0,0,0,0,2,16,218,251,0,0};
|
||||
|
||||
|
||||
#define STARTHF4 8
|
||||
const
|
||||
static unsigned int DecHf4[]={0xff00,0xffff,0xffff,0xffff,0xffff,0xffff};
|
||||
const
|
||||
static unsigned int PosHf4[]={0,0,0,0,0,0,0,0,0,255,0,0,0};
|
||||
|
||||
|
||||
void Unpack::Unpack15(bool Solid)
|
||||
{
|
||||
if (Suspended)
|
||||
UnpPtr=WrPtr;
|
||||
else
|
||||
{
|
||||
UnpInitData(Solid);
|
||||
OldUnpInitData(Solid);
|
||||
UnpInitData15(Solid);
|
||||
UnpReadBuf();
|
||||
if (!Solid)
|
||||
{
|
||||
|
@ -70,7 +50,6 @@ void Unpack::Unpack15(bool Solid)
|
|||
else
|
||||
UnpPtr=WrPtr;
|
||||
--DestUnpSize;
|
||||
}
|
||||
if (DestUnpSize>=0)
|
||||
{
|
||||
GetFlagsBuf();
|
||||
|
@ -79,16 +58,12 @@ void Unpack::Unpack15(bool Solid)
|
|||
|
||||
while (DestUnpSize>=0)
|
||||
{
|
||||
UnpPtr&=MAXWINMASK;
|
||||
UnpPtr&=MaxWinMask;
|
||||
|
||||
if (InAddr>ReadTop-30 && !UnpReadBuf())
|
||||
if (Inp.InAddr>ReadTop-30 && !UnpReadBuf())
|
||||
break;
|
||||
if (((WrPtr-UnpPtr) & MAXWINMASK)<270 && WrPtr!=UnpPtr)
|
||||
{
|
||||
OldUnpWriteBuf();
|
||||
if (Suspended)
|
||||
return;
|
||||
}
|
||||
if (((WrPtr-UnpPtr) & MaxWinMask)<270 && WrPtr!=UnpPtr)
|
||||
UnpWriteBuf20();
|
||||
if (StMode)
|
||||
{
|
||||
HuffDecode();
|
||||
|
@ -132,23 +107,7 @@ void Unpack::Unpack15(bool Solid)
|
|||
}
|
||||
}
|
||||
}
|
||||
OldUnpWriteBuf();
|
||||
}
|
||||
|
||||
|
||||
void Unpack::OldUnpWriteBuf()
|
||||
{
|
||||
if (UnpPtr!=WrPtr)
|
||||
UnpSomeRead=true;
|
||||
if (UnpPtr<WrPtr)
|
||||
{
|
||||
UnpIO->UnpWrite(&Window[WrPtr],-WrPtr & MAXWINMASK);
|
||||
UnpIO->UnpWrite(Window,UnpPtr);
|
||||
UnpAllBuf=true;
|
||||
}
|
||||
else
|
||||
UnpIO->UnpWrite(&Window[WrPtr],UnpPtr-WrPtr);
|
||||
WrPtr=UnpPtr;
|
||||
UnpWriteBuf20();
|
||||
}
|
||||
|
||||
|
||||
|
@ -157,14 +116,10 @@ void Unpack::OldUnpWriteBuf()
|
|||
|
||||
void Unpack::ShortLZ()
|
||||
{
|
||||
const
|
||||
static unsigned int ShortLen1[]={1,3,4,4,5,6,7,8,8,4,4,5,6,6,4,0};
|
||||
const
|
||||
static unsigned int ShortXor1[]={0,0xa0,0xd0,0xe0,0xf0,0xf8,0xfc,0xfe,
|
||||
0xff,0xc0,0x80,0x90,0x98,0x9c,0xb0};
|
||||
const
|
||||
static unsigned int ShortLen2[]={2,3,3,3,4,4,5,6,6,4,4,5,6,6,4,0};
|
||||
const
|
||||
static unsigned int ShortXor2[]={0,0x40,0x60,0xa0,0xd0,0xe0,0xf0,0xf8,
|
||||
0xfc,0xc0,0x80,0x90,0x98,0x9c,0xb0};
|
||||
|
||||
|
@ -175,13 +130,13 @@ void Unpack::ShortLZ()
|
|||
int DistancePlace;
|
||||
NumHuf=0;
|
||||
|
||||
unsigned int BitField=fgetbits();
|
||||
unsigned int BitField=Inp.fgetbits();
|
||||
if (LCount==2)
|
||||
{
|
||||
faddbits(1);
|
||||
Inp.faddbits(1);
|
||||
if (BitField >= 0x8000)
|
||||
{
|
||||
OldCopyString((unsigned int)LastDist,LastLength);
|
||||
CopyString15((unsigned int)LastDist,LastLength);
|
||||
return;
|
||||
}
|
||||
BitField <<= 1;
|
||||
|
@ -198,14 +153,14 @@ void Unpack::ShortLZ()
|
|||
for (Length=0;;Length++)
|
||||
if (((BitField^ShortXor1[Length]) & (~(0xff>>GetShortLen1(Length))))==0)
|
||||
break;
|
||||
faddbits(GetShortLen1(Length));
|
||||
Inp.faddbits(GetShortLen1(Length));
|
||||
}
|
||||
else
|
||||
{
|
||||
for (Length=0;;Length++)
|
||||
if (((BitField^ShortXor2[Length]) & (~(0xff>>GetShortLen2(Length))))==0)
|
||||
break;
|
||||
faddbits(GetShortLen2(Length));
|
||||
Inp.faddbits(GetShortLen2(Length));
|
||||
}
|
||||
|
||||
if (Length >= 9)
|
||||
|
@ -213,25 +168,25 @@ void Unpack::ShortLZ()
|
|||
if (Length == 9)
|
||||
{
|
||||
LCount++;
|
||||
OldCopyString((unsigned int)LastDist,LastLength);
|
||||
CopyString15((unsigned int)LastDist,LastLength);
|
||||
return;
|
||||
}
|
||||
if (Length == 14)
|
||||
{
|
||||
LCount=0;
|
||||
Length=DecodeNum(fgetbits(),STARTL2,DecL2,PosL2)+5;
|
||||
Distance=(fgetbits()>>1) | 0x8000;
|
||||
faddbits(15);
|
||||
Length=DecodeNum(Inp.fgetbits(),STARTL2,DecL2,PosL2)+5;
|
||||
Distance=(Inp.fgetbits()>>1) | 0x8000;
|
||||
Inp.faddbits(15);
|
||||
LastLength=Length;
|
||||
LastDist=Distance;
|
||||
OldCopyString(Distance,Length);
|
||||
CopyString15(Distance,Length);
|
||||
return;
|
||||
}
|
||||
|
||||
LCount=0;
|
||||
SaveLength=Length;
|
||||
Distance=OldDist[(OldDistPtr-(Length-9)) & 3];
|
||||
Length=DecodeNum(fgetbits(),STARTL1,DecL1,PosL1)+2;
|
||||
Length=DecodeNum(Inp.fgetbits(),STARTL1,DecL1,PosL1)+2;
|
||||
if (Length==0x101 && SaveLength==10)
|
||||
{
|
||||
Buf60 ^= 1;
|
||||
|
@ -246,7 +201,7 @@ void Unpack::ShortLZ()
|
|||
OldDistPtr = OldDistPtr & 3;
|
||||
LastLength=Length;
|
||||
LastDist=Distance;
|
||||
OldCopyString(Distance,Length);
|
||||
CopyString15(Distance,Length);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -254,13 +209,11 @@ void Unpack::ShortLZ()
|
|||
AvrLn1 += Length;
|
||||
AvrLn1 -= AvrLn1 >> 4;
|
||||
|
||||
DistancePlace=DecodeNum(fgetbits(),STARTHF2,DecHf2,PosHf2) & 0xff;
|
||||
DistancePlace=DecodeNum(Inp.fgetbits(),STARTHF2,DecHf2,PosHf2) & 0xff;
|
||||
Distance=ChSetA[DistancePlace];
|
||||
if (--DistancePlace != -1)
|
||||
{
|
||||
PlaceA[Distance]--;
|
||||
LastDistance=ChSetA[DistancePlace];
|
||||
PlaceA[LastDistance]++;
|
||||
ChSetA[DistancePlace+1]=LastDistance;
|
||||
ChSetA[DistancePlace]=Distance;
|
||||
}
|
||||
|
@ -269,7 +222,7 @@ void Unpack::ShortLZ()
|
|||
OldDistPtr = OldDistPtr & 3;
|
||||
LastLength=Length;
|
||||
LastDist=Distance;
|
||||
OldCopyString(Distance,Length);
|
||||
CopyString15(Distance,Length);
|
||||
}
|
||||
|
||||
|
||||
|
@ -289,7 +242,7 @@ void Unpack::LongLZ()
|
|||
}
|
||||
OldAvr2=AvrLn2;
|
||||
|
||||
unsigned int BitField=fgetbits();
|
||||
unsigned int BitField=Inp.fgetbits();
|
||||
if (AvrLn2 >= 122)
|
||||
Length=DecodeNum(BitField,STARTL2,DecL2,PosL2);
|
||||
else
|
||||
|
@ -299,19 +252,19 @@ void Unpack::LongLZ()
|
|||
if (BitField < 0x100)
|
||||
{
|
||||
Length=BitField;
|
||||
faddbits(16);
|
||||
Inp.faddbits(16);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (Length=0;((BitField<<Length)&0x8000)==0;Length++)
|
||||
;
|
||||
faddbits(Length+1);
|
||||
Inp.faddbits(Length+1);
|
||||
}
|
||||
|
||||
AvrLn2 += Length;
|
||||
AvrLn2 -= AvrLn2 >> 5;
|
||||
|
||||
BitField=fgetbits();
|
||||
BitField=Inp.fgetbits();
|
||||
if (AvrPlcB > 0x28ff)
|
||||
DistancePlace=DecodeNum(BitField,STARTHF2,DecHf2,PosHf2);
|
||||
else
|
||||
|
@ -335,12 +288,11 @@ void Unpack::LongLZ()
|
|||
ChSetB[DistancePlace]=ChSetB[NewDistancePlace];
|
||||
ChSetB[NewDistancePlace]=Distance;
|
||||
|
||||
Distance=((Distance & 0xff00) | (fgetbits() >> 8)) >> 1;
|
||||
faddbits(7);
|
||||
Distance=((Distance & 0xff00) | (Inp.fgetbits() >> 8)) >> 1;
|
||||
Inp.faddbits(7);
|
||||
|
||||
OldAvr3=AvrLn3;
|
||||
if (Length!=1 && Length!=4)
|
||||
{
|
||||
if (Length==0 && Distance <= MaxDist3)
|
||||
{
|
||||
AvrLn3++;
|
||||
|
@ -349,7 +301,6 @@ void Unpack::LongLZ()
|
|||
else
|
||||
if (AvrLn3 > 0)
|
||||
AvrLn3--;
|
||||
}
|
||||
Length+=3;
|
||||
if (Distance >= MaxDist3)
|
||||
Length++;
|
||||
|
@ -363,7 +314,7 @@ void Unpack::LongLZ()
|
|||
OldDistPtr = OldDistPtr & 3;
|
||||
LastLength=Length;
|
||||
LastDist=Distance;
|
||||
OldCopyString(Distance,Length);
|
||||
CopyString15(Distance,Length);
|
||||
}
|
||||
|
||||
|
||||
|
@ -374,7 +325,7 @@ void Unpack::HuffDecode()
|
|||
unsigned int Distance;
|
||||
int BytePlace;
|
||||
|
||||
unsigned int BitField=fgetbits();
|
||||
unsigned int BitField=Inp.fgetbits();
|
||||
|
||||
if (AvrPlc > 0x75ff)
|
||||
BytePlace=DecodeNum(BitField,STARTHF4,DecHf4,PosHf4);
|
||||
|
@ -396,8 +347,8 @@ void Unpack::HuffDecode()
|
|||
BytePlace=0x100;
|
||||
if (--BytePlace==-1)
|
||||
{
|
||||
BitField=fgetbits();
|
||||
faddbits(1);
|
||||
BitField=Inp.fgetbits();
|
||||
Inp.faddbits(1);
|
||||
if (BitField & 0x8000)
|
||||
{
|
||||
NumHuf=StMode=0;
|
||||
|
@ -406,11 +357,11 @@ void Unpack::HuffDecode()
|
|||
else
|
||||
{
|
||||
Length = (BitField & 0x4000) ? 4 : 3;
|
||||
faddbits(1);
|
||||
Distance=DecodeNum(fgetbits(),STARTHF2,DecHf2,PosHf2);
|
||||
Distance = (Distance << 5) | (fgetbits() >> 11);
|
||||
faddbits(5);
|
||||
OldCopyString(Distance,Length);
|
||||
Inp.faddbits(1);
|
||||
Distance=DecodeNum(Inp.fgetbits(),STARTHF2,DecHf2,PosHf2);
|
||||
Distance = (Distance << 5) | (Inp.fgetbits() >> 11);
|
||||
Inp.faddbits(5);
|
||||
CopyString15(Distance,Length);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -448,7 +399,7 @@ void Unpack::HuffDecode()
|
|||
void Unpack::GetFlagsBuf()
|
||||
{
|
||||
unsigned int Flags,NewFlagsPlace;
|
||||
unsigned int FlagsPlace=DecodeNum(fgetbits(),STARTHF2,DecHf2,PosHf2);
|
||||
unsigned int FlagsPlace=DecodeNum(Inp.fgetbits(),STARTHF2,DecHf2,PosHf2);
|
||||
|
||||
while (1)
|
||||
{
|
||||
|
@ -465,7 +416,7 @@ void Unpack::GetFlagsBuf()
|
|||
}
|
||||
|
||||
|
||||
void Unpack::OldUnpInitData(int Solid)
|
||||
void Unpack::UnpInitData15(int Solid)
|
||||
{
|
||||
if (!Solid)
|
||||
{
|
||||
|
@ -486,8 +437,6 @@ void Unpack::InitHuff()
|
|||
{
|
||||
for (unsigned int I=0;I<256;I++)
|
||||
{
|
||||
Place[I]=PlaceA[I]=PlaceB[I]=I;
|
||||
PlaceC[I]=(~I+1) & 0xff;
|
||||
ChSet[I]=ChSetB[I]=I<<8;
|
||||
ChSetA[I]=I;
|
||||
ChSetC[I]=((~I+1) & 0xff)<<8;
|
||||
|
@ -499,7 +448,7 @@ void Unpack::InitHuff()
|
|||
}
|
||||
|
||||
|
||||
void Unpack::CorrHuff(unsigned int *CharSet,unsigned int *NumToPlace)
|
||||
void Unpack::CorrHuff(ushort *CharSet,byte *NumToPlace)
|
||||
{
|
||||
int I,J;
|
||||
for (I=7;I>=0;I--)
|
||||
|
@ -511,24 +460,22 @@ void Unpack::CorrHuff(unsigned int *CharSet,unsigned int *NumToPlace)
|
|||
}
|
||||
|
||||
|
||||
void Unpack::OldCopyString(unsigned int Distance,unsigned int Length)
|
||||
void Unpack::CopyString15(uint Distance,uint Length)
|
||||
{
|
||||
DestUnpSize-=Length;
|
||||
while (Length--)
|
||||
{
|
||||
Window[UnpPtr]=Window[(UnpPtr-Distance) & MAXWINMASK];
|
||||
UnpPtr=(UnpPtr+1) & MAXWINMASK;
|
||||
Window[UnpPtr]=Window[(UnpPtr-Distance) & MaxWinMask];
|
||||
UnpPtr=(UnpPtr+1) & MaxWinMask;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
unsigned int Unpack::DecodeNum(int Num,unsigned int StartPos,
|
||||
const unsigned int *DecTab,const unsigned int *PosTab)
|
||||
uint Unpack::DecodeNum(uint Num,uint StartPos,uint *DecTab,uint *PosTab)
|
||||
{
|
||||
int I;
|
||||
for (Num&=0xfff0,I=0;DecTab[I]<=Num;I++)
|
||||
StartPos++;
|
||||
faddbits(StartPos);
|
||||
Inp.faddbits(StartPos);
|
||||
return(((Num-(I ? DecTab[I-1]:0))>>(16-StartPos))+PosTab[StartPos]);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -1,61 +1,21 @@
|
|||
// #included by unpack.cpp
|
||||
#ifdef RAR_COMMON_HPP
|
||||
#include "rar.hpp"
|
||||
|
||||
// Presumably these optimizations give similar speedup as those for CopyString in unpack.cpp
|
||||
void Unpack::CopyString20(unsigned int Length,unsigned int Distance)
|
||||
void Unpack::CopyString20(uint Length,uint Distance)
|
||||
{
|
||||
LastDist=OldDist[OldDistPtr++ & 3]=Distance;
|
||||
LastLength=Length;
|
||||
DestUnpSize-=Length;
|
||||
|
||||
unsigned UnpPtr = this->UnpPtr; // cache in register
|
||||
byte* const Window = this->Window; // cache in register
|
||||
|
||||
unsigned int DestPtr=UnpPtr-Distance;
|
||||
if (UnpPtr<MAXWINSIZE-300 && DestPtr<MAXWINSIZE-300)
|
||||
{
|
||||
this->UnpPtr += Length;
|
||||
if ( Distance < Length ) // can't use memcpy when source and dest overlap
|
||||
{
|
||||
Window[UnpPtr++]=Window[DestPtr++];
|
||||
Window[UnpPtr++]=Window[DestPtr++];
|
||||
while (Length>2)
|
||||
{
|
||||
Length--;
|
||||
Window[UnpPtr++]=Window[DestPtr++];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy( &Window[UnpPtr], &Window[DestPtr], Length );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (Length--)
|
||||
{
|
||||
Window[UnpPtr]=Window[DestPtr++ & MAXWINMASK];
|
||||
UnpPtr=(UnpPtr+1) & MAXWINMASK;
|
||||
}
|
||||
this->UnpPtr = UnpPtr;
|
||||
}
|
||||
CopyString(Length,Distance);
|
||||
}
|
||||
|
||||
|
||||
void Unpack::Unpack20(bool Solid)
|
||||
{
|
||||
const
|
||||
static unsigned char LDecode[]={0,1,2,3,4,5,6,7,8,10,12,14,16,20,24,28,32,40,48,56,64,80,96,112,128,160,192,224};
|
||||
const
|
||||
static unsigned char LBits[]= {0,0,0,0,0,0,0,0,1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5};
|
||||
const
|
||||
static int DDecode[]={0,1,2,3,4,6,8,12,16,24,32,48,64,96,128,192,256,384,512,768,1024,1536,2048,3072,4096,6144,8192,12288,16384,24576,32768U,49152U,65536,98304,131072,196608,262144,327680,393216,458752,524288,589824,655360,720896,786432,851968,917504,983040};
|
||||
const
|
||||
static unsigned char DBits[]= {0,0,0,0,1,1,2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16};
|
||||
const
|
||||
static unsigned char SDDecode[]={0,4,8,16,32,64,128,192};
|
||||
const
|
||||
static unsigned char SDBits[]= {2,2,3, 4, 5, 6, 6, 6};
|
||||
unsigned int Bits;
|
||||
|
||||
|
@ -72,22 +32,22 @@ void Unpack::Unpack20(bool Solid)
|
|||
--DestUnpSize;
|
||||
}
|
||||
|
||||
while (is64plus(DestUnpSize))
|
||||
while (DestUnpSize>=0)
|
||||
{
|
||||
UnpPtr&=MAXWINMASK;
|
||||
UnpPtr&=MaxWinMask;
|
||||
|
||||
if (InAddr>ReadTop-30)
|
||||
if (Inp.InAddr>ReadTop-30)
|
||||
if (!UnpReadBuf())
|
||||
break;
|
||||
if (((WrPtr-UnpPtr) & MAXWINMASK)<270 && WrPtr!=UnpPtr)
|
||||
if (((WrPtr-UnpPtr) & MaxWinMask)<270 && WrPtr!=UnpPtr)
|
||||
{
|
||||
OldUnpWriteBuf();
|
||||
UnpWriteBuf20();
|
||||
if (Suspended)
|
||||
return;
|
||||
}
|
||||
if (UnpAudioBlock)
|
||||
{
|
||||
int AudioNumber=DecodeNumber((struct Decode *)&MD[UnpCurChannel]);
|
||||
int AudioNumber=DecodeNumber(Inp,&MD[UnpCurChannel]);
|
||||
|
||||
if (AudioNumber==256)
|
||||
{
|
||||
|
@ -102,7 +62,7 @@ void Unpack::Unpack20(bool Solid)
|
|||
continue;
|
||||
}
|
||||
|
||||
int Number=DecodeNumber((struct Decode *)&LD);
|
||||
int Number=DecodeNumber(Inp,&BlockTables.LD);
|
||||
if (Number<256)
|
||||
{
|
||||
Window[UnpPtr++]=(byte)Number;
|
||||
|
@ -114,16 +74,16 @@ void Unpack::Unpack20(bool Solid)
|
|||
int Length=LDecode[Number-=270]+3;
|
||||
if ((Bits=LBits[Number])>0)
|
||||
{
|
||||
Length+=getbits()>>(16-Bits);
|
||||
addbits(Bits);
|
||||
Length+=Inp.getbits()>>(16-Bits);
|
||||
Inp.addbits(Bits);
|
||||
}
|
||||
|
||||
int DistNumber=DecodeNumber((struct Decode *)&DD);
|
||||
int DistNumber=DecodeNumber(Inp,&BlockTables.DD);
|
||||
unsigned int Distance=DDecode[DistNumber]+1;
|
||||
if ((Bits=DBits[DistNumber])>0)
|
||||
{
|
||||
Distance+=getbits()>>(16-Bits);
|
||||
addbits(Bits);
|
||||
Distance+=Inp.getbits()>>(16-Bits);
|
||||
Inp.addbits(Bits);
|
||||
}
|
||||
|
||||
if (Distance>=0x2000)
|
||||
|
@ -150,12 +110,12 @@ void Unpack::Unpack20(bool Solid)
|
|||
if (Number<261)
|
||||
{
|
||||
unsigned int Distance=OldDist[(OldDistPtr-(Number-256)) & 3];
|
||||
int LengthNumber=DecodeNumber((struct Decode *)&RD);
|
||||
int LengthNumber=DecodeNumber(Inp,&BlockTables.RD);
|
||||
int Length=LDecode[LengthNumber]+2;
|
||||
if ((Bits=LBits[LengthNumber])>0)
|
||||
{
|
||||
Length+=getbits()>>(16-Bits);
|
||||
addbits(Bits);
|
||||
Length+=Inp.getbits()>>(16-Bits);
|
||||
Inp.addbits(Bits);
|
||||
}
|
||||
if (Distance>=0x101)
|
||||
{
|
||||
|
@ -175,39 +135,55 @@ void Unpack::Unpack20(bool Solid)
|
|||
unsigned int Distance=SDDecode[Number-=261]+1;
|
||||
if ((Bits=SDBits[Number])>0)
|
||||
{
|
||||
Distance+=getbits()>>(16-Bits);
|
||||
addbits(Bits);
|
||||
Distance+=Inp.getbits()>>(16-Bits);
|
||||
Inp.addbits(Bits);
|
||||
}
|
||||
CopyString20(2,Distance);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
ReadLastTables();
|
||||
OldUnpWriteBuf();
|
||||
UnpWriteBuf20();
|
||||
}
|
||||
|
||||
|
||||
void Unpack::UnpWriteBuf20()
|
||||
{
|
||||
if (UnpPtr!=WrPtr)
|
||||
UnpSomeRead=true;
|
||||
if (UnpPtr<WrPtr)
|
||||
{
|
||||
UnpIO->UnpWrite(&Window[WrPtr],-(int)WrPtr & MaxWinMask);
|
||||
UnpIO->UnpWrite(Window,UnpPtr);
|
||||
UnpAllBuf=true;
|
||||
}
|
||||
else
|
||||
UnpIO->UnpWrite(&Window[WrPtr],UnpPtr-WrPtr);
|
||||
WrPtr=UnpPtr;
|
||||
}
|
||||
|
||||
|
||||
bool Unpack::ReadTables20()
|
||||
{
|
||||
byte BitLength[BC20];
|
||||
unsigned char Table[MC20*4];
|
||||
byte Table[MC20*4];
|
||||
int TableSize,N,I;
|
||||
if (InAddr>ReadTop-25)
|
||||
if (Inp.InAddr>ReadTop-25)
|
||||
if (!UnpReadBuf())
|
||||
return(false);
|
||||
unsigned int BitField=getbits();
|
||||
uint BitField=Inp.getbits();
|
||||
UnpAudioBlock=(BitField & 0x8000);
|
||||
|
||||
if (!(BitField & 0x4000))
|
||||
memset(UnpOldTable20,0,sizeof(UnpOldTable20));
|
||||
addbits(2);
|
||||
Inp.addbits(2);
|
||||
|
||||
if (UnpAudioBlock)
|
||||
{
|
||||
UnpChannels=((BitField>>12) & 3)+1;
|
||||
if (UnpCurChannel>=UnpChannels)
|
||||
UnpCurChannel=0;
|
||||
addbits(2);
|
||||
Inp.addbits(2);
|
||||
TableSize=MC20*UnpChannels;
|
||||
}
|
||||
else
|
||||
|
@ -215,17 +191,17 @@ bool Unpack::ReadTables20()
|
|||
|
||||
for (I=0;I<BC20;I++)
|
||||
{
|
||||
BitLength[I]=(byte)(getbits() >> 12);
|
||||
addbits(4);
|
||||
BitLength[I]=(byte)(Inp.getbits() >> 12);
|
||||
Inp.addbits(4);
|
||||
}
|
||||
MakeDecodeTables(BitLength,(struct Decode *)&BD,BC20);
|
||||
MakeDecodeTables(BitLength,&BlockTables.BD,BC20);
|
||||
I=0;
|
||||
while (I<TableSize)
|
||||
{
|
||||
if (InAddr>ReadTop-5)
|
||||
if (Inp.InAddr>ReadTop-5)
|
||||
if (!UnpReadBuf())
|
||||
return(false);
|
||||
int Number=DecodeNumber((struct Decode *)&BD);
|
||||
return false;
|
||||
int Number=DecodeNumber(Inp,&BlockTables.BD);
|
||||
if (Number<16)
|
||||
{
|
||||
Table[I]=(Number+UnpOldTable20[I]) & 0xf;
|
||||
|
@ -234,8 +210,9 @@ bool Unpack::ReadTables20()
|
|||
else
|
||||
if (Number==16)
|
||||
{
|
||||
N=(getbits() >> 14)+3;
|
||||
addbits(2);
|
||||
N=(Inp.getbits() >> 14)+3;
|
||||
Inp.addbits(2);
|
||||
if (I>0)
|
||||
while (N-- > 0 && I<TableSize)
|
||||
{
|
||||
Table[I]=Table[I-1];
|
||||
|
@ -246,28 +223,28 @@ bool Unpack::ReadTables20()
|
|||
{
|
||||
if (Number==17)
|
||||
{
|
||||
N=(getbits() >> 13)+3;
|
||||
addbits(3);
|
||||
N=(Inp.getbits() >> 13)+3;
|
||||
Inp.addbits(3);
|
||||
}
|
||||
else
|
||||
{
|
||||
N=(getbits() >> 9)+11;
|
||||
addbits(7);
|
||||
N=(Inp.getbits() >> 9)+11;
|
||||
Inp.addbits(7);
|
||||
}
|
||||
while (N-- > 0 && I<TableSize)
|
||||
Table[I++]=0;
|
||||
}
|
||||
}
|
||||
if (InAddr>ReadTop)
|
||||
if (Inp.InAddr>ReadTop)
|
||||
return(true);
|
||||
if (UnpAudioBlock)
|
||||
for (I=0;I<UnpChannels;I++)
|
||||
MakeDecodeTables(&Table[I*MC20],(struct Decode *)&MD[I],MC20);
|
||||
MakeDecodeTables(&Table[I*MC20],&MD[I],MC20);
|
||||
else
|
||||
{
|
||||
MakeDecodeTables(&Table[0],(struct Decode *)&LD,NC20);
|
||||
MakeDecodeTables(&Table[NC20],(struct Decode *)&DD,DC20);
|
||||
MakeDecodeTables(&Table[NC20+DC20],(struct Decode *)&RD,RC20);
|
||||
MakeDecodeTables(&Table[0],&BlockTables.LD,NC20);
|
||||
MakeDecodeTables(&Table[NC20],&BlockTables.DD,DC20);
|
||||
MakeDecodeTables(&Table[NC20+DC20],&BlockTables.RD,RC20);
|
||||
}
|
||||
memcpy(UnpOldTable20,Table,sizeof(UnpOldTable20));
|
||||
return(true);
|
||||
|
@ -276,18 +253,16 @@ bool Unpack::ReadTables20()
|
|||
|
||||
void Unpack::ReadLastTables()
|
||||
{
|
||||
if (ReadTop>=InAddr+5)
|
||||
{
|
||||
if (ReadTop>=Inp.InAddr+5)
|
||||
if (UnpAudioBlock)
|
||||
{
|
||||
if (DecodeNumber((struct Decode *)&MD[UnpCurChannel])==256)
|
||||
if (DecodeNumber(Inp,&MD[UnpCurChannel])==256)
|
||||
ReadTables20();
|
||||
}
|
||||
else
|
||||
if (DecodeNumber((struct Decode *)&LD)==269)
|
||||
if (DecodeNumber(Inp,&BlockTables.LD)==269)
|
||||
ReadTables20();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Unpack::UnpInitData20(int Solid)
|
||||
|
@ -393,4 +368,3 @@ byte Unpack::DecodeAudio(int Delta)
|
|||
}
|
||||
return((byte)Ch);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,836 @@
|
|||
// We use it instead of direct PPM.DecodeChar call to be sure that
|
||||
// we reset PPM structures in case of corrupt data. It is important,
|
||||
// because these structures can be invalid after PPM.DecodeChar returned -1.
|
||||
inline int Unpack::SafePPMDecodeChar()
|
||||
{
|
||||
int Ch=PPM.DecodeChar();
|
||||
if (Ch==-1) // Corrupt PPM data found.
|
||||
{
|
||||
PPM.CleanUp(); // Reset possibly corrupt PPM data structures.
|
||||
UnpBlockType=BLOCK_LZ; // Set faster and more fail proof LZ mode.
|
||||
}
|
||||
return(Ch);
|
||||
}
|
||||
|
||||
|
||||
void Unpack::Unpack29(bool Solid)
|
||||
{
|
||||
static unsigned char LDecode[]={0,1,2,3,4,5,6,7,8,10,12,14,16,20,24,28,32,40,48,56,64,80,96,112,128,160,192,224};
|
||||
static unsigned char LBits[]= {0,0,0,0,0,0,0,0,1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5};
|
||||
static int DDecode[DC];
|
||||
static byte DBits[DC];
|
||||
static int DBitLengthCounts[]= {4,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,14,0,12};
|
||||
static unsigned char SDDecode[]={0,4,8,16,32,64,128,192};
|
||||
static unsigned char SDBits[]= {2,2,3, 4, 5, 6, 6, 6};
|
||||
unsigned int Bits;
|
||||
|
||||
if (DDecode[1]==0)
|
||||
{
|
||||
int Dist=0,BitLength=0,Slot=0;
|
||||
for (int I=0;I<ASIZE(DBitLengthCounts);I++,BitLength++)
|
||||
for (int J=0;J<DBitLengthCounts[I];J++,Slot++,Dist+=(1<<BitLength))
|
||||
{
|
||||
DDecode[Slot]=Dist;
|
||||
DBits[Slot]=BitLength;
|
||||
}
|
||||
}
|
||||
|
||||
FileExtracted=true;
|
||||
|
||||
if (!Suspended)
|
||||
{
|
||||
UnpInitData(Solid);
|
||||
if (!UnpReadBuf30())
|
||||
return;
|
||||
if ((!Solid || !TablesRead) && !ReadTables30())
|
||||
return;
|
||||
}
|
||||
|
||||
while (true)
|
||||
{
|
||||
UnpPtr&=MaxWinMask;
|
||||
|
||||
if (Inp.InAddr>ReadBorder)
|
||||
{
|
||||
if (!UnpReadBuf30())
|
||||
break;
|
||||
}
|
||||
if (((WrPtr-UnpPtr) & MaxWinMask)<260 && WrPtr!=UnpPtr)
|
||||
{
|
||||
UnpWriteBuf30();
|
||||
if (WrittenFileSize>DestUnpSize)
|
||||
return;
|
||||
if (Suspended)
|
||||
{
|
||||
FileExtracted=false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (UnpBlockType==BLOCK_PPM)
|
||||
{
|
||||
// Here speed is critical, so we do not use SafePPMDecodeChar,
|
||||
// because sometimes even the inline function can introduce
|
||||
// some additional penalty.
|
||||
int Ch=PPM.DecodeChar();
|
||||
if (Ch==-1) // Corrupt PPM data found.
|
||||
{
|
||||
PPM.CleanUp(); // Reset possibly corrupt PPM data structures.
|
||||
UnpBlockType=BLOCK_LZ; // Set faster and more fail proof LZ mode.
|
||||
break;
|
||||
}
|
||||
if (Ch==PPMEscChar)
|
||||
{
|
||||
int NextCh=SafePPMDecodeChar();
|
||||
if (NextCh==0) // End of PPM encoding.
|
||||
{
|
||||
if (!ReadTables30())
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
if (NextCh==-1) // Corrupt PPM data found.
|
||||
break;
|
||||
if (NextCh==2) // End of file in PPM mode.
|
||||
break;
|
||||
if (NextCh==3) // Read VM code.
|
||||
{
|
||||
if (!ReadVMCodePPM())
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
if (NextCh==4) // LZ inside of PPM.
|
||||
{
|
||||
unsigned int Distance=0,Length;
|
||||
bool Failed=false;
|
||||
for (int I=0;I<4 && !Failed;I++)
|
||||
{
|
||||
int Ch=SafePPMDecodeChar();
|
||||
if (Ch==-1)
|
||||
Failed=true;
|
||||
else
|
||||
if (I==3)
|
||||
Length=(byte)Ch;
|
||||
else
|
||||
Distance=(Distance<<8)+(byte)Ch;
|
||||
}
|
||||
if (Failed)
|
||||
break;
|
||||
|
||||
CopyString(Length+32,Distance+2);
|
||||
continue;
|
||||
}
|
||||
if (NextCh==5) // One byte distance match (RLE) inside of PPM.
|
||||
{
|
||||
int Length=SafePPMDecodeChar();
|
||||
if (Length==-1)
|
||||
break;
|
||||
CopyString(Length+4,1);
|
||||
continue;
|
||||
}
|
||||
// If we are here, NextCh must be 1, what means that current byte
|
||||
// is equal to our 'escape' byte, so we just store it to Window.
|
||||
}
|
||||
Window[UnpPtr++]=Ch;
|
||||
continue;
|
||||
}
|
||||
|
||||
int Number=DecodeNumber(Inp,&BlockTables.LD);
|
||||
if (Number<256)
|
||||
{
|
||||
Window[UnpPtr++]=(byte)Number;
|
||||
continue;
|
||||
}
|
||||
if (Number>=271)
|
||||
{
|
||||
int Length=LDecode[Number-=271]+3;
|
||||
if ((Bits=LBits[Number])>0)
|
||||
{
|
||||
Length+=Inp.getbits()>>(16-Bits);
|
||||
Inp.addbits(Bits);
|
||||
}
|
||||
|
||||
int DistNumber=DecodeNumber(Inp,&BlockTables.DD);
|
||||
unsigned int Distance=DDecode[DistNumber]+1;
|
||||
if ((Bits=DBits[DistNumber])>0)
|
||||
{
|
||||
if (DistNumber>9)
|
||||
{
|
||||
if (Bits>4)
|
||||
{
|
||||
Distance+=((Inp.getbits()>>(20-Bits))<<4);
|
||||
Inp.addbits(Bits-4);
|
||||
}
|
||||
if (LowDistRepCount>0)
|
||||
{
|
||||
LowDistRepCount--;
|
||||
Distance+=PrevLowDist;
|
||||
}
|
||||
else
|
||||
{
|
||||
int LowDist=DecodeNumber(Inp,&BlockTables.LDD);
|
||||
if (LowDist==16)
|
||||
{
|
||||
LowDistRepCount=LOW_DIST_REP_COUNT-1;
|
||||
Distance+=PrevLowDist;
|
||||
}
|
||||
else
|
||||
{
|
||||
Distance+=LowDist;
|
||||
PrevLowDist=LowDist;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Distance+=Inp.getbits()>>(16-Bits);
|
||||
Inp.addbits(Bits);
|
||||
}
|
||||
}
|
||||
|
||||
if (Distance>=0x2000)
|
||||
{
|
||||
Length++;
|
||||
if (Distance>=0x40000L)
|
||||
Length++;
|
||||
}
|
||||
|
||||
InsertOldDist(Distance);
|
||||
LastLength=Length;
|
||||
CopyString(Length,Distance);
|
||||
continue;
|
||||
}
|
||||
if (Number==256)
|
||||
{
|
||||
if (!ReadEndOfBlock())
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
if (Number==257)
|
||||
{
|
||||
if (!ReadVMCode())
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
if (Number==258)
|
||||
{
|
||||
if (LastLength!=0)
|
||||
CopyString(LastLength,OldDist[0]);
|
||||
continue;
|
||||
}
|
||||
if (Number<263)
|
||||
{
|
||||
int DistNum=Number-259;
|
||||
unsigned int Distance=OldDist[DistNum];
|
||||
for (int I=DistNum;I>0;I--)
|
||||
OldDist[I]=OldDist[I-1];
|
||||
OldDist[0]=Distance;
|
||||
|
||||
int LengthNumber=DecodeNumber(Inp,&BlockTables.RD);
|
||||
int Length=LDecode[LengthNumber]+2;
|
||||
if ((Bits=LBits[LengthNumber])>0)
|
||||
{
|
||||
Length+=Inp.getbits()>>(16-Bits);
|
||||
Inp.addbits(Bits);
|
||||
}
|
||||
LastLength=Length;
|
||||
CopyString(Length,Distance);
|
||||
continue;
|
||||
}
|
||||
if (Number<272)
|
||||
{
|
||||
unsigned int Distance=SDDecode[Number-=263]+1;
|
||||
if ((Bits=SDBits[Number])>0)
|
||||
{
|
||||
Distance+=Inp.getbits()>>(16-Bits);
|
||||
Inp.addbits(Bits);
|
||||
}
|
||||
InsertOldDist(Distance);
|
||||
LastLength=2;
|
||||
CopyString(2,Distance);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
UnpWriteBuf30();
|
||||
}
|
||||
|
||||
|
||||
// Return 'false' to quit unpacking the current file or 'true' to continue.
|
||||
bool Unpack::ReadEndOfBlock()
|
||||
{
|
||||
uint BitField=Inp.getbits();
|
||||
bool NewTable,NewFile=false;
|
||||
|
||||
// "1" - no new file, new table just here.
|
||||
// "00" - new file, no new table.
|
||||
// "01" - new file, new table (in beginning of next file).
|
||||
|
||||
if ((BitField & 0x8000)!=0)
|
||||
{
|
||||
NewTable=true;
|
||||
Inp.addbits(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
NewFile=true;
|
||||
NewTable=(BitField & 0x4000)!=0;
|
||||
Inp.addbits(2);
|
||||
}
|
||||
TablesRead=!NewTable;
|
||||
|
||||
// Quit immediately if "new file" flag is set. If "new table" flag
|
||||
// is present, we'll read the table in beginning of next file
|
||||
// based on 'TablesRead' 'false' value.
|
||||
if (NewFile)
|
||||
return false;
|
||||
return ReadTables30(); // Quit only if we failed to read tables.
|
||||
}
|
||||
|
||||
|
||||
bool Unpack::ReadVMCode()
|
||||
{
|
||||
// Entire VM code is guaranteed to fully present in block defined
|
||||
// by current Huffman table. Compressor checks that VM code does not cross
|
||||
// Huffman block boundaries.
|
||||
unsigned int FirstByte=Inp.getbits()>>8;
|
||||
Inp.addbits(8);
|
||||
int Length=(FirstByte & 7)+1;
|
||||
if (Length==7)
|
||||
{
|
||||
Length=(Inp.getbits()>>8)+7;
|
||||
Inp.addbits(8);
|
||||
}
|
||||
else
|
||||
if (Length==8)
|
||||
{
|
||||
Length=Inp.getbits();
|
||||
Inp.addbits(16);
|
||||
}
|
||||
Array<byte> VMCode(Length);
|
||||
for (int I=0;I<Length;I++)
|
||||
{
|
||||
// Try to read the new buffer if only one byte is left.
|
||||
// But if we read all bytes except the last, one byte is enough.
|
||||
if (Inp.InAddr>=ReadTop-1 && !UnpReadBuf30() && I<Length-1)
|
||||
return(false);
|
||||
VMCode[I]=Inp.getbits()>>8;
|
||||
Inp.addbits(8);
|
||||
}
|
||||
return(AddVMCode(FirstByte,&VMCode[0],Length));
|
||||
}
|
||||
|
||||
|
||||
bool Unpack::ReadVMCodePPM()
|
||||
{
|
||||
unsigned int FirstByte=SafePPMDecodeChar();
|
||||
if ((int)FirstByte==-1)
|
||||
return(false);
|
||||
int Length=(FirstByte & 7)+1;
|
||||
if (Length==7)
|
||||
{
|
||||
int B1=SafePPMDecodeChar();
|
||||
if (B1==-1)
|
||||
return(false);
|
||||
Length=B1+7;
|
||||
}
|
||||
else
|
||||
if (Length==8)
|
||||
{
|
||||
int B1=SafePPMDecodeChar();
|
||||
if (B1==-1)
|
||||
return(false);
|
||||
int B2=SafePPMDecodeChar();
|
||||
if (B2==-1)
|
||||
return(false);
|
||||
Length=B1*256+B2;
|
||||
}
|
||||
Array<byte> VMCode(Length);
|
||||
for (int I=0;I<Length;I++)
|
||||
{
|
||||
int Ch=SafePPMDecodeChar();
|
||||
if (Ch==-1)
|
||||
return(false);
|
||||
VMCode[I]=Ch;
|
||||
}
|
||||
return(AddVMCode(FirstByte,&VMCode[0],Length));
|
||||
}
|
||||
|
||||
|
||||
bool Unpack::AddVMCode(uint FirstByte,byte *Code,int CodeSize)
|
||||
{
|
||||
VMCodeInp.InitBitInput();
|
||||
memcpy(VMCodeInp.InBuf,Code,Min(BitInput::MAX_SIZE,CodeSize));
|
||||
VM.Init();
|
||||
|
||||
uint FiltPos;
|
||||
if (FirstByte & 0x80)
|
||||
{
|
||||
FiltPos=RarVM::ReadData(VMCodeInp);
|
||||
if (FiltPos==0)
|
||||
InitFilters30();
|
||||
else
|
||||
FiltPos--;
|
||||
}
|
||||
else
|
||||
FiltPos=LastFilter; // Use the same filter as last time.
|
||||
|
||||
if (FiltPos>Filters30.Size() || FiltPos>OldFilterLengths.Size())
|
||||
return(false);
|
||||
LastFilter=FiltPos;
|
||||
bool NewFilter=(FiltPos==Filters30.Size());
|
||||
|
||||
UnpackFilter30 *StackFilter=new UnpackFilter30; // New filter for PrgStack.
|
||||
|
||||
UnpackFilter30 *Filter;
|
||||
if (NewFilter) // New filter code, never used before since VM reset.
|
||||
{
|
||||
if (FiltPos>MAX3_FILTERS)
|
||||
{
|
||||
// Too many different filters, corrupt archive.
|
||||
delete StackFilter;
|
||||
return false;
|
||||
}
|
||||
|
||||
Filters30.Add(1);
|
||||
Filters30[Filters30.Size()-1]=Filter=new UnpackFilter30;
|
||||
StackFilter->ParentFilter=(uint)(Filters30.Size()-1);
|
||||
|
||||
// Reserve one item, where we store the data block length of our new
|
||||
// filter entry. We'll set it to real block length below, after reading
|
||||
// it. But we need to initialize it now, because when processing corrupt
|
||||
// data, we can access this item even before we set it to real value.
|
||||
OldFilterLengths.Push(0);
|
||||
Filter->ExecCount=0;
|
||||
}
|
||||
else // Filter was used in the past.
|
||||
{
|
||||
Filter=Filters30[FiltPos];
|
||||
StackFilter->ParentFilter=FiltPos;
|
||||
Filter->ExecCount++;
|
||||
}
|
||||
|
||||
int EmptyCount=0;
|
||||
for (uint I=0;I<PrgStack.Size();I++)
|
||||
{
|
||||
PrgStack[I-EmptyCount]=PrgStack[I];
|
||||
if (PrgStack[I]==NULL)
|
||||
EmptyCount++;
|
||||
if (EmptyCount>0)
|
||||
PrgStack[I]=NULL;
|
||||
}
|
||||
if (EmptyCount==0)
|
||||
{
|
||||
PrgStack.Add(1);
|
||||
EmptyCount=1;
|
||||
}
|
||||
int StackPos=(int)(PrgStack.Size()-EmptyCount);
|
||||
PrgStack[StackPos]=StackFilter;
|
||||
StackFilter->ExecCount=Filter->ExecCount;
|
||||
|
||||
uint BlockStart=RarVM::ReadData(VMCodeInp);
|
||||
if (FirstByte & 0x40)
|
||||
BlockStart+=258;
|
||||
StackFilter->BlockStart=(uint)((BlockStart+UnpPtr)&MaxWinMask);
|
||||
if (FirstByte & 0x20)
|
||||
{
|
||||
StackFilter->BlockLength=RarVM::ReadData(VMCodeInp);
|
||||
|
||||
// Store the last data block length for current filter.
|
||||
OldFilterLengths[FiltPos]=StackFilter->BlockLength;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Set the data block size to same value as the previous block size
|
||||
// for same filter. It is possible on corrupt data to access here a new
|
||||
// and not filled yet item of OldFilterLengths array. This is why above
|
||||
// we set new OldFilterLengths items to zero.
|
||||
StackFilter->BlockLength=FiltPos<OldFilterLengths.Size() ? OldFilterLengths[FiltPos]:0;
|
||||
}
|
||||
|
||||
StackFilter->NextWindow=WrPtr!=UnpPtr && ((WrPtr-UnpPtr)&MaxWinMask)<=BlockStart;
|
||||
|
||||
// DebugLog("\nNextWindow: UnpPtr=%08x WrPtr=%08x BlockStart=%08x",UnpPtr,WrPtr,BlockStart);
|
||||
|
||||
memset(StackFilter->Prg.InitR,0,sizeof(StackFilter->Prg.InitR));
|
||||
StackFilter->Prg.InitR[3]=VM_GLOBALMEMADDR;
|
||||
StackFilter->Prg.InitR[4]=StackFilter->BlockLength;
|
||||
StackFilter->Prg.InitR[5]=StackFilter->ExecCount;
|
||||
|
||||
if (FirstByte & 0x10) // set registers to optional parameters if any
|
||||
{
|
||||
unsigned int InitMask=VMCodeInp.fgetbits()>>9;
|
||||
VMCodeInp.faddbits(7);
|
||||
for (int I=0;I<7;I++)
|
||||
if (InitMask & (1<<I))
|
||||
StackFilter->Prg.InitR[I]=RarVM::ReadData(VMCodeInp);
|
||||
}
|
||||
|
||||
if (NewFilter)
|
||||
{
|
||||
uint VMCodeSize=RarVM::ReadData(VMCodeInp);
|
||||
if (VMCodeSize>=0x10000 || VMCodeSize==0)
|
||||
return(false);
|
||||
Array<byte> VMCode(VMCodeSize);
|
||||
for (uint I=0;I<VMCodeSize;I++)
|
||||
{
|
||||
if (VMCodeInp.Overflow(3))
|
||||
return(false);
|
||||
VMCode[I]=VMCodeInp.fgetbits()>>8;
|
||||
VMCodeInp.faddbits(8);
|
||||
}
|
||||
VM.Prepare(&VMCode[0],VMCodeSize,&Filter->Prg);
|
||||
}
|
||||
StackFilter->Prg.AltCmd=&Filter->Prg.Cmd[0];
|
||||
StackFilter->Prg.CmdCount=Filter->Prg.CmdCount;
|
||||
|
||||
size_t StaticDataSize=Filter->Prg.StaticData.Size();
|
||||
if (StaticDataSize>0 && StaticDataSize<VM_GLOBALMEMSIZE)
|
||||
{
|
||||
// read statically defined data contained in DB commands
|
||||
StackFilter->Prg.StaticData.Add(StaticDataSize);
|
||||
memcpy(&StackFilter->Prg.StaticData[0],&Filter->Prg.StaticData[0],StaticDataSize);
|
||||
}
|
||||
|
||||
if (StackFilter->Prg.GlobalData.Size()<VM_FIXEDGLOBALSIZE)
|
||||
{
|
||||
StackFilter->Prg.GlobalData.Reset();
|
||||
StackFilter->Prg.GlobalData.Add(VM_FIXEDGLOBALSIZE);
|
||||
}
|
||||
byte *GlobalData=&StackFilter->Prg.GlobalData[0];
|
||||
for (int I=0;I<7;I++)
|
||||
VM.SetLowEndianValue((uint *)&GlobalData[I*4],StackFilter->Prg.InitR[I]);
|
||||
VM.SetLowEndianValue((uint *)&GlobalData[0x1c],StackFilter->BlockLength);
|
||||
VM.SetLowEndianValue((uint *)&GlobalData[0x20],0);
|
||||
VM.SetLowEndianValue((uint *)&GlobalData[0x2c],StackFilter->ExecCount);
|
||||
memset(&GlobalData[0x30],0,16);
|
||||
|
||||
if (FirstByte & 8) // Put the data block passed as parameter if any.
|
||||
{
|
||||
if (VMCodeInp.Overflow(3))
|
||||
return(false);
|
||||
uint DataSize=RarVM::ReadData(VMCodeInp);
|
||||
if (DataSize>VM_GLOBALMEMSIZE-VM_FIXEDGLOBALSIZE)
|
||||
return(false);
|
||||
size_t CurSize=StackFilter->Prg.GlobalData.Size();
|
||||
if (CurSize<DataSize+VM_FIXEDGLOBALSIZE)
|
||||
StackFilter->Prg.GlobalData.Add(DataSize+VM_FIXEDGLOBALSIZE-CurSize);
|
||||
byte *GlobalData=&StackFilter->Prg.GlobalData[VM_FIXEDGLOBALSIZE];
|
||||
for (uint I=0;I<DataSize;I++)
|
||||
{
|
||||
if (VMCodeInp.Overflow(3))
|
||||
return(false);
|
||||
GlobalData[I]=VMCodeInp.fgetbits()>>8;
|
||||
VMCodeInp.faddbits(8);
|
||||
}
|
||||
}
|
||||
return(true);
|
||||
}
|
||||
|
||||
|
||||
bool Unpack::UnpReadBuf30()
|
||||
{
|
||||
int DataSize=ReadTop-Inp.InAddr; // Data left to process.
|
||||
if (DataSize<0)
|
||||
return(false);
|
||||
if (Inp.InAddr>BitInput::MAX_SIZE/2)
|
||||
{
|
||||
// If we already processed more than half of buffer, let's move
|
||||
// remaining data into beginning to free more space for new data
|
||||
// and ensure that calling function does not cross the buffer border
|
||||
// even if we did not read anything here. Also it ensures that read size
|
||||
// is not less than CRYPT_BLOCK_SIZE, so we can align it without risk
|
||||
// to make it zero.
|
||||
if (DataSize>0)
|
||||
memmove(Inp.InBuf,Inp.InBuf+Inp.InAddr,DataSize);
|
||||
Inp.InAddr=0;
|
||||
ReadTop=DataSize;
|
||||
}
|
||||
else
|
||||
DataSize=ReadTop;
|
||||
int ReadCode=UnpIO->UnpRead(Inp.InBuf+DataSize,BitInput::MAX_SIZE-DataSize);
|
||||
if (ReadCode>0)
|
||||
ReadTop+=ReadCode;
|
||||
ReadBorder=ReadTop-30;
|
||||
return(ReadCode!=-1);
|
||||
}
|
||||
|
||||
|
||||
void Unpack::UnpWriteBuf30()
|
||||
{
|
||||
uint WrittenBorder=(uint)WrPtr;
|
||||
uint WriteSize=(uint)((UnpPtr-WrittenBorder)&MaxWinMask);
|
||||
for (size_t I=0;I<PrgStack.Size();I++)
|
||||
{
|
||||
// Here we apply filters to data which we need to write.
|
||||
// We always copy data to virtual machine memory before processing.
|
||||
// We cannot process them just in place in Window buffer, because
|
||||
// these data can be used for future string matches, so we must
|
||||
// preserve them in original form.
|
||||
|
||||
UnpackFilter30 *flt=PrgStack[I];
|
||||
if (flt==NULL)
|
||||
continue;
|
||||
if (flt->NextWindow)
|
||||
{
|
||||
flt->NextWindow=false;
|
||||
continue;
|
||||
}
|
||||
unsigned int BlockStart=flt->BlockStart;
|
||||
unsigned int BlockLength=flt->BlockLength;
|
||||
if (((BlockStart-WrittenBorder)&MaxWinMask)<WriteSize)
|
||||
{
|
||||
if (WrittenBorder!=BlockStart)
|
||||
{
|
||||
UnpWriteArea(WrittenBorder,BlockStart);
|
||||
WrittenBorder=BlockStart;
|
||||
WriteSize=(uint)((UnpPtr-WrittenBorder)&MaxWinMask);
|
||||
}
|
||||
if (BlockLength<=WriteSize)
|
||||
{
|
||||
uint BlockEnd=(BlockStart+BlockLength)&MaxWinMask;
|
||||
if (BlockStart<BlockEnd || BlockEnd==0)
|
||||
VM.SetMemory(0,Window+BlockStart,BlockLength);
|
||||
else
|
||||
{
|
||||
uint FirstPartLength=uint(MaxWinSize-BlockStart);
|
||||
VM.SetMemory(0,Window+BlockStart,FirstPartLength);
|
||||
VM.SetMemory(FirstPartLength,Window,BlockEnd);
|
||||
}
|
||||
|
||||
VM_PreparedProgram *ParentPrg=&Filters30[flt->ParentFilter]->Prg;
|
||||
VM_PreparedProgram *Prg=&flt->Prg;
|
||||
|
||||
if (ParentPrg->GlobalData.Size()>VM_FIXEDGLOBALSIZE)
|
||||
{
|
||||
// Copy global data from previous script execution if any.
|
||||
Prg->GlobalData.Alloc(ParentPrg->GlobalData.Size());
|
||||
memcpy(&Prg->GlobalData[VM_FIXEDGLOBALSIZE],&ParentPrg->GlobalData[VM_FIXEDGLOBALSIZE],ParentPrg->GlobalData.Size()-VM_FIXEDGLOBALSIZE);
|
||||
}
|
||||
|
||||
ExecuteCode(Prg);
|
||||
|
||||
if (Prg->GlobalData.Size()>VM_FIXEDGLOBALSIZE)
|
||||
{
|
||||
// Save global data for next script execution.
|
||||
if (ParentPrg->GlobalData.Size()<Prg->GlobalData.Size())
|
||||
ParentPrg->GlobalData.Alloc(Prg->GlobalData.Size());
|
||||
memcpy(&ParentPrg->GlobalData[VM_FIXEDGLOBALSIZE],&Prg->GlobalData[VM_FIXEDGLOBALSIZE],Prg->GlobalData.Size()-VM_FIXEDGLOBALSIZE);
|
||||
}
|
||||
else
|
||||
ParentPrg->GlobalData.Reset();
|
||||
|
||||
byte *FilteredData=Prg->FilteredData;
|
||||
unsigned int FilteredDataSize=Prg->FilteredDataSize;
|
||||
|
||||
delete PrgStack[I];
|
||||
PrgStack[I]=NULL;
|
||||
while (I+1<PrgStack.Size())
|
||||
{
|
||||
UnpackFilter30 *NextFilter=PrgStack[I+1];
|
||||
if (NextFilter==NULL || NextFilter->BlockStart!=BlockStart ||
|
||||
NextFilter->BlockLength!=FilteredDataSize || NextFilter->NextWindow)
|
||||
break;
|
||||
|
||||
// Apply several filters to same data block.
|
||||
|
||||
VM.SetMemory(0,FilteredData,FilteredDataSize);
|
||||
|
||||
VM_PreparedProgram *ParentPrg=&Filters30[NextFilter->ParentFilter]->Prg;
|
||||
VM_PreparedProgram *NextPrg=&NextFilter->Prg;
|
||||
|
||||
if (ParentPrg->GlobalData.Size()>VM_FIXEDGLOBALSIZE)
|
||||
{
|
||||
// Copy global data from previous script execution if any.
|
||||
NextPrg->GlobalData.Alloc(ParentPrg->GlobalData.Size());
|
||||
memcpy(&NextPrg->GlobalData[VM_FIXEDGLOBALSIZE],&ParentPrg->GlobalData[VM_FIXEDGLOBALSIZE],ParentPrg->GlobalData.Size()-VM_FIXEDGLOBALSIZE);
|
||||
}
|
||||
|
||||
ExecuteCode(NextPrg);
|
||||
|
||||
if (NextPrg->GlobalData.Size()>VM_FIXEDGLOBALSIZE)
|
||||
{
|
||||
// Save global data for next script execution.
|
||||
if (ParentPrg->GlobalData.Size()<NextPrg->GlobalData.Size())
|
||||
ParentPrg->GlobalData.Alloc(NextPrg->GlobalData.Size());
|
||||
memcpy(&ParentPrg->GlobalData[VM_FIXEDGLOBALSIZE],&NextPrg->GlobalData[VM_FIXEDGLOBALSIZE],NextPrg->GlobalData.Size()-VM_FIXEDGLOBALSIZE);
|
||||
}
|
||||
else
|
||||
ParentPrg->GlobalData.Reset();
|
||||
|
||||
FilteredData=NextPrg->FilteredData;
|
||||
FilteredDataSize=NextPrg->FilteredDataSize;
|
||||
I++;
|
||||
delete PrgStack[I];
|
||||
PrgStack[I]=NULL;
|
||||
}
|
||||
UnpIO->UnpWrite(FilteredData,FilteredDataSize);
|
||||
UnpSomeRead=true;
|
||||
WrittenFileSize+=FilteredDataSize;
|
||||
WrittenBorder=BlockEnd;
|
||||
WriteSize=uint((UnpPtr-WrittenBorder)&MaxWinMask);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Current filter intersects the window write border, so we adjust
|
||||
// the window border to process this filter next time, not now.
|
||||
for (size_t J=I;J<PrgStack.Size();J++)
|
||||
{
|
||||
UnpackFilter30 *flt=PrgStack[J];
|
||||
if (flt!=NULL && flt->NextWindow)
|
||||
flt->NextWindow=false;
|
||||
}
|
||||
WrPtr=WrittenBorder;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UnpWriteArea(WrittenBorder,UnpPtr);
|
||||
WrPtr=UnpPtr;
|
||||
}
|
||||
|
||||
|
||||
void Unpack::ExecuteCode(VM_PreparedProgram *Prg)
|
||||
{
|
||||
if (Prg->GlobalData.Size()>0)
|
||||
{
|
||||
Prg->InitR[6]=(uint)WrittenFileSize;
|
||||
VM.SetLowEndianValue((uint *)&Prg->GlobalData[0x24],(uint)WrittenFileSize);
|
||||
VM.SetLowEndianValue((uint *)&Prg->GlobalData[0x28],(uint)(WrittenFileSize>>32));
|
||||
VM.Execute(Prg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool Unpack::ReadTables30()
|
||||
{
|
||||
byte BitLength[BC];
|
||||
byte Table[HUFF_TABLE_SIZE30];
|
||||
if (Inp.InAddr>ReadTop-25)
|
||||
if (!UnpReadBuf30())
|
||||
return(false);
|
||||
Inp.faddbits((8-Inp.InBit)&7);
|
||||
uint BitField=Inp.fgetbits();
|
||||
if (BitField & 0x8000)
|
||||
{
|
||||
UnpBlockType=BLOCK_PPM;
|
||||
return(PPM.DecodeInit(this,PPMEscChar));
|
||||
}
|
||||
UnpBlockType=BLOCK_LZ;
|
||||
|
||||
PrevLowDist=0;
|
||||
LowDistRepCount=0;
|
||||
|
||||
if (!(BitField & 0x4000))
|
||||
memset(UnpOldTable,0,sizeof(UnpOldTable));
|
||||
Inp.faddbits(2);
|
||||
|
||||
for (int I=0;I<BC;I++)
|
||||
{
|
||||
int Length=(byte)(Inp.fgetbits() >> 12);
|
||||
Inp.faddbits(4);
|
||||
if (Length==15)
|
||||
{
|
||||
int ZeroCount=(byte)(Inp.fgetbits() >> 12);
|
||||
Inp.faddbits(4);
|
||||
if (ZeroCount==0)
|
||||
BitLength[I]=15;
|
||||
else
|
||||
{
|
||||
ZeroCount+=2;
|
||||
while (ZeroCount-- > 0 && I<ASIZE(BitLength))
|
||||
BitLength[I++]=0;
|
||||
I--;
|
||||
}
|
||||
}
|
||||
else
|
||||
BitLength[I]=Length;
|
||||
}
|
||||
MakeDecodeTables(BitLength,&BlockTables.BD,BC30);
|
||||
|
||||
const int TableSize=HUFF_TABLE_SIZE30;
|
||||
for (int I=0;I<TableSize;)
|
||||
{
|
||||
if (Inp.InAddr>ReadTop-5)
|
||||
if (!UnpReadBuf30())
|
||||
return(false);
|
||||
int Number=DecodeNumber(Inp,&BlockTables.BD);
|
||||
if (Number<16)
|
||||
{
|
||||
Table[I]=(Number+UnpOldTable[I]) & 0xf;
|
||||
I++;
|
||||
}
|
||||
else
|
||||
if (Number<18)
|
||||
{
|
||||
int N;
|
||||
if (Number==16)
|
||||
{
|
||||
N=(Inp.fgetbits() >> 13)+3;
|
||||
Inp.faddbits(3);
|
||||
}
|
||||
else
|
||||
{
|
||||
N=(Inp.fgetbits() >> 9)+11;
|
||||
Inp.faddbits(7);
|
||||
}
|
||||
if (I>0)
|
||||
while (N-- > 0 && I<TableSize)
|
||||
{
|
||||
Table[I]=Table[I-1];
|
||||
I++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int N;
|
||||
if (Number==18)
|
||||
{
|
||||
N=(Inp.fgetbits() >> 13)+3;
|
||||
Inp.faddbits(3);
|
||||
}
|
||||
else
|
||||
{
|
||||
N=(Inp.fgetbits() >> 9)+11;
|
||||
Inp.faddbits(7);
|
||||
}
|
||||
while (N-- > 0 && I<TableSize)
|
||||
Table[I++]=0;
|
||||
}
|
||||
}
|
||||
TablesRead=true;
|
||||
if (Inp.InAddr>ReadTop)
|
||||
return false;
|
||||
MakeDecodeTables(&Table[0],&BlockTables.LD,NC30);
|
||||
MakeDecodeTables(&Table[NC30],&BlockTables.DD,DC30);
|
||||
MakeDecodeTables(&Table[NC30+DC30],&BlockTables.LDD,LDC30);
|
||||
MakeDecodeTables(&Table[NC30+DC30+LDC30],&BlockTables.RD,RC30);
|
||||
memcpy(UnpOldTable,Table,sizeof(UnpOldTable));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void Unpack::UnpInitData30(bool Solid)
|
||||
{
|
||||
if (!Solid)
|
||||
{
|
||||
TablesRead=false;
|
||||
memset(UnpOldTable,0,sizeof(UnpOldTable));
|
||||
PPMEscChar=2;
|
||||
UnpBlockType=BLOCK_LZ;
|
||||
|
||||
InitFilters30();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Unpack::InitFilters30()
|
||||
{
|
||||
OldFilterLengths.Reset();
|
||||
LastFilter=0;
|
||||
|
||||
for (size_t I=0;I<Filters30.Size();I++)
|
||||
delete Filters30[I];
|
||||
Filters30.Reset();
|
||||
for (size_t I=0;I<PrgStack.Size();I++)
|
||||
delete PrgStack[I];
|
||||
PrgStack.Reset();
|
||||
}
|
|
@ -0,0 +1,648 @@
|
|||
void Unpack::Unpack5(bool Solid)
|
||||
{
|
||||
FileExtracted=true;
|
||||
|
||||
if (!Suspended)
|
||||
{
|
||||
UnpInitData(Solid);
|
||||
if (!UnpReadBuf())
|
||||
return;
|
||||
if (!ReadBlockHeader(Inp,BlockHeader) || !ReadTables(Inp,BlockHeader,BlockTables))
|
||||
return;
|
||||
}
|
||||
|
||||
while (true)
|
||||
{
|
||||
UnpPtr&=MaxWinMask;
|
||||
|
||||
if (Inp.InAddr>=ReadBorder)
|
||||
{
|
||||
bool FileDone=false;
|
||||
|
||||
// We use 'while', because for empty block containing only Huffman table,
|
||||
// we'll be on the block border once again just after reading the table.
|
||||
while (Inp.InAddr>BlockHeader.BlockStart+BlockHeader.BlockSize-1 ||
|
||||
Inp.InAddr==BlockHeader.BlockStart+BlockHeader.BlockSize-1 &&
|
||||
Inp.InBit>=BlockHeader.BlockBitSize)
|
||||
{
|
||||
if (BlockHeader.LastBlockInFile)
|
||||
{
|
||||
FileDone=true;
|
||||
break;
|
||||
}
|
||||
if (!ReadBlockHeader(Inp,BlockHeader) || !ReadTables(Inp,BlockHeader,BlockTables))
|
||||
return;
|
||||
}
|
||||
if (FileDone || !UnpReadBuf())
|
||||
break;
|
||||
}
|
||||
|
||||
if (((WriteBorder-UnpPtr) & MaxWinMask)<MAX_LZ_MATCH+3 && WriteBorder!=UnpPtr)
|
||||
{
|
||||
UnpWriteBuf();
|
||||
if (WrittenFileSize>DestUnpSize)
|
||||
return;
|
||||
if (Suspended)
|
||||
{
|
||||
FileExtracted=false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
uint MainSlot=DecodeNumber(Inp,&BlockTables.LD);
|
||||
if (MainSlot<256)
|
||||
{
|
||||
if (Fragmented)
|
||||
FragWindow[UnpPtr++]=(byte)MainSlot;
|
||||
else
|
||||
Window[UnpPtr++]=(byte)MainSlot;
|
||||
continue;
|
||||
}
|
||||
if (MainSlot>=262)
|
||||
{
|
||||
uint Length=SlotToLength(Inp,MainSlot-262);
|
||||
|
||||
uint DBits,Distance=1,DistSlot=DecodeNumber(Inp,&BlockTables.DD);
|
||||
if (DistSlot<4)
|
||||
{
|
||||
DBits=0;
|
||||
Distance+=DistSlot;
|
||||
}
|
||||
else
|
||||
{
|
||||
DBits=DistSlot/2 - 1;
|
||||
Distance+=(2 | (DistSlot & 1)) << DBits;
|
||||
}
|
||||
|
||||
if (DBits>0)
|
||||
{
|
||||
if (DBits>=4)
|
||||
{
|
||||
if (DBits>4)
|
||||
{
|
||||
Distance+=((Inp.getbits32()>>(36-DBits))<<4);
|
||||
Inp.addbits(DBits-4);
|
||||
}
|
||||
uint LowDist=DecodeNumber(Inp,&BlockTables.LDD);
|
||||
Distance+=LowDist;
|
||||
}
|
||||
else
|
||||
{
|
||||
Distance+=Inp.getbits32()>>(32-DBits);
|
||||
Inp.addbits(DBits);
|
||||
}
|
||||
}
|
||||
|
||||
if (Distance>0x100)
|
||||
{
|
||||
Length++;
|
||||
if (Distance>0x2000)
|
||||
{
|
||||
Length++;
|
||||
if (Distance>0x40000)
|
||||
Length++;
|
||||
}
|
||||
}
|
||||
|
||||
InsertOldDist(Distance);
|
||||
LastLength=Length;
|
||||
if (Fragmented)
|
||||
FragWindow.CopyString(Length,Distance,UnpPtr,MaxWinMask);
|
||||
else
|
||||
CopyString(Length,Distance);
|
||||
continue;
|
||||
}
|
||||
if (MainSlot==256)
|
||||
{
|
||||
UnpackFilter Filter;
|
||||
if (!ReadFilter(Inp,Filter) || !AddFilter(Filter))
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
if (MainSlot==257)
|
||||
{
|
||||
if (LastLength!=0)
|
||||
if (Fragmented)
|
||||
FragWindow.CopyString(LastLength,OldDist[0],UnpPtr,MaxWinMask);
|
||||
else
|
||||
CopyString(LastLength,OldDist[0]);
|
||||
continue;
|
||||
}
|
||||
if (MainSlot<262)
|
||||
{
|
||||
uint DistNum=MainSlot-258;
|
||||
uint Distance=OldDist[DistNum];
|
||||
for (uint I=DistNum;I>0;I--)
|
||||
OldDist[I]=OldDist[I-1];
|
||||
OldDist[0]=Distance;
|
||||
|
||||
uint LengthSlot=DecodeNumber(Inp,&BlockTables.RD);
|
||||
uint Length=SlotToLength(Inp,LengthSlot);
|
||||
LastLength=Length;
|
||||
if (Fragmented)
|
||||
FragWindow.CopyString(Length,Distance,UnpPtr,MaxWinMask);
|
||||
else
|
||||
CopyString(Length,Distance);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
UnpWriteBuf();
|
||||
}
|
||||
|
||||
|
||||
uint Unpack::ReadFilterData(BitInput &Inp)
|
||||
{
|
||||
uint ByteCount=(Inp.fgetbits()>>14)+1;
|
||||
Inp.addbits(2);
|
||||
|
||||
uint Data=0;
|
||||
for (uint I=0;I<ByteCount;I++)
|
||||
{
|
||||
Data+=(Inp.fgetbits()>>8)<<(I*8);
|
||||
Inp.addbits(8);
|
||||
}
|
||||
return Data;
|
||||
}
|
||||
|
||||
|
||||
bool Unpack::ReadFilter(BitInput &Inp,UnpackFilter &Filter)
|
||||
{
|
||||
if (!Inp.ExternalBuffer && Inp.InAddr>ReadTop-16)
|
||||
if (!UnpReadBuf())
|
||||
return false;
|
||||
|
||||
Filter.BlockStart=ReadFilterData(Inp);
|
||||
Filter.BlockLength=ReadFilterData(Inp);
|
||||
|
||||
Filter.Type=Inp.fgetbits()>>13;
|
||||
Inp.faddbits(3);
|
||||
|
||||
if (Filter.Type==FILTER_DELTA)
|
||||
{
|
||||
Filter.Channels=(Inp.fgetbits()>>11)+1;
|
||||
Inp.faddbits(5);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Unpack::AddFilter(UnpackFilter &Filter)
|
||||
{
|
||||
if (Filters.Size()>=MAX_UNPACK_FILTERS-1)
|
||||
UnpWriteBuf(); // Write data, apply and flush filters.
|
||||
|
||||
// If distance to filter start is that large that due to circular dictionary
|
||||
// mode it points to old not written yet data, then we set 'NextWindow'
|
||||
// flag and process this filter only after processing that older data.
|
||||
Filter.NextWindow=WrPtr!=UnpPtr && ((WrPtr-UnpPtr)&MaxWinMask)<=Filter.BlockStart;
|
||||
|
||||
Filter.BlockStart=uint((Filter.BlockStart+UnpPtr)&MaxWinMask);
|
||||
Filters.Push(Filter);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Unpack::UnpReadBuf()
|
||||
{
|
||||
int DataSize=ReadTop-Inp.InAddr; // Data left to process.
|
||||
if (DataSize<0)
|
||||
return false;
|
||||
BlockHeader.BlockSize-=Inp.InAddr-BlockHeader.BlockStart;
|
||||
if (Inp.InAddr>BitInput::MAX_SIZE/2)
|
||||
{
|
||||
// If we already processed more than half of buffer, let's move
|
||||
// remaining data into beginning to free more space for new data
|
||||
// and ensure that calling function does not cross the buffer border
|
||||
// even if we did not read anything here. Also it ensures that read size
|
||||
// is not less than CRYPT_BLOCK_SIZE, so we can align it without risk
|
||||
// to make it zero.
|
||||
if (DataSize>0)
|
||||
memmove(Inp.InBuf,Inp.InBuf+Inp.InAddr,DataSize);
|
||||
Inp.InAddr=0;
|
||||
ReadTop=DataSize;
|
||||
}
|
||||
else
|
||||
DataSize=ReadTop;
|
||||
int ReadCode=0;
|
||||
if (BitInput::MAX_SIZE!=DataSize)
|
||||
ReadCode=UnpIO->UnpRead(Inp.InBuf+DataSize,BitInput::MAX_SIZE-DataSize);
|
||||
if (ReadCode>0) // Can be also -1.
|
||||
ReadTop+=ReadCode;
|
||||
ReadBorder=ReadTop-30;
|
||||
BlockHeader.BlockStart=Inp.InAddr;
|
||||
if (BlockHeader.BlockSize!=-1) // '-1' means not defined yet.
|
||||
{
|
||||
// We may need to quit from main extraction loop and read new block header
|
||||
// and trees earlier than data in input buffer ends.
|
||||
ReadBorder=Min(ReadBorder,BlockHeader.BlockStart+BlockHeader.BlockSize-1);
|
||||
}
|
||||
return ReadCode!=-1;
|
||||
}
|
||||
|
||||
|
||||
void Unpack::UnpWriteBuf()
|
||||
{
|
||||
size_t WrittenBorder=WrPtr;
|
||||
size_t FullWriteSize=(UnpPtr-WrittenBorder)&MaxWinMask;
|
||||
size_t WriteSizeLeft=FullWriteSize;
|
||||
bool NotAllFiltersProcessed=false;
|
||||
for (size_t I=0;I<Filters.Size();I++)
|
||||
{
|
||||
// Here we apply filters to data which we need to write.
|
||||
// We always copy data to virtual machine memory before processing.
|
||||
// We cannot process them just in place in Window buffer, because
|
||||
// these data can be used for future string matches, so we must
|
||||
// preserve them in original form.
|
||||
|
||||
UnpackFilter *flt=&Filters[I];
|
||||
if (flt->Type==FILTER_NONE)
|
||||
continue;
|
||||
if (flt->NextWindow)
|
||||
{
|
||||
// Here we skip filters which have block start in current data range
|
||||
// due to address warp around in circular dictionary, but actually
|
||||
// belong to next dictionary block. If such filter start position
|
||||
// is included to current write range, then we reset 'NextWindow' flag.
|
||||
// In fact we can reset it even without such check, because current
|
||||
// implementation seems to guarantee 'NextWindow' flag reset after
|
||||
// buffer writing for all existing filters. But let's keep this check
|
||||
// just in case. Compressor guarantees that distance between
|
||||
// filter block start and filter storing position cannot exceed
|
||||
// the dictionary size. So if we covered the filter block start with
|
||||
// our write here, we can safely assume that filter is applicable
|
||||
// to next block on no further wrap arounds is possible.
|
||||
if (((flt->BlockStart-WrPtr)&MaxWinMask)<=FullWriteSize)
|
||||
flt->NextWindow=false;
|
||||
continue;
|
||||
}
|
||||
uint BlockStart=flt->BlockStart;
|
||||
uint BlockLength=flt->BlockLength;
|
||||
if (((BlockStart-WrittenBorder)&MaxWinMask)<WriteSizeLeft)
|
||||
{
|
||||
if (WrittenBorder!=BlockStart)
|
||||
{
|
||||
UnpWriteArea(WrittenBorder,BlockStart);
|
||||
WrittenBorder=BlockStart;
|
||||
WriteSizeLeft=(UnpPtr-WrittenBorder)&MaxWinMask;
|
||||
}
|
||||
if (BlockLength<=WriteSizeLeft)
|
||||
{
|
||||
if (BlockLength>0)
|
||||
{
|
||||
uint BlockEnd=(BlockStart+BlockLength)&MaxWinMask;
|
||||
|
||||
FilterSrcMemory.Alloc(BlockLength);
|
||||
byte *Mem=&FilterSrcMemory[0];
|
||||
if (BlockStart<BlockEnd || BlockEnd==0)
|
||||
{
|
||||
if (Fragmented)
|
||||
FragWindow.CopyData(Mem,BlockStart,BlockLength);
|
||||
else
|
||||
memcpy(Mem,Window+BlockStart,BlockLength);
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t FirstPartLength=size_t(MaxWinSize-BlockStart);
|
||||
if (Fragmented)
|
||||
{
|
||||
FragWindow.CopyData(Mem,BlockStart,FirstPartLength);
|
||||
FragWindow.CopyData(Mem+FirstPartLength,0,BlockEnd);
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(Mem,Window+BlockStart,FirstPartLength);
|
||||
memcpy(Mem+FirstPartLength,Window,BlockEnd);
|
||||
}
|
||||
}
|
||||
|
||||
byte *OutMem=ApplyFilter(Mem,BlockLength,flt);
|
||||
|
||||
Filters[I].Type=FILTER_NONE;
|
||||
|
||||
if (OutMem!=NULL)
|
||||
UnpIO->UnpWrite(OutMem,BlockLength);
|
||||
|
||||
UnpSomeRead=true;
|
||||
WrittenFileSize+=BlockLength;
|
||||
WrittenBorder=BlockEnd;
|
||||
WriteSizeLeft=(UnpPtr-WrittenBorder)&MaxWinMask;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Current filter intersects the window write border, so we adjust
|
||||
// the window border to process this filter next time, not now.
|
||||
WrPtr=WrittenBorder;
|
||||
|
||||
// Since Filter start position can only increase, we quit processing
|
||||
// all following filters for this data block and reset 'NextWindow'
|
||||
// flag for them.
|
||||
for (size_t J=I;J<Filters.Size();J++)
|
||||
{
|
||||
UnpackFilter *flt=&Filters[J];
|
||||
if (flt->Type!=FILTER_NONE)
|
||||
flt->NextWindow=false;
|
||||
}
|
||||
|
||||
// Do not write data left after current filter now.
|
||||
NotAllFiltersProcessed=true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Remove processed filters from queue.
|
||||
size_t EmptyCount=0;
|
||||
for (size_t I=0;I<Filters.Size();I++)
|
||||
{
|
||||
if (EmptyCount>0)
|
||||
Filters[I-EmptyCount]=Filters[I];
|
||||
if (Filters[I].Type==FILTER_NONE)
|
||||
EmptyCount++;
|
||||
}
|
||||
if (EmptyCount>0)
|
||||
Filters.Alloc(Filters.Size()-EmptyCount);
|
||||
|
||||
if (!NotAllFiltersProcessed) // Only if all filters are processed.
|
||||
{
|
||||
// Write data left after last filter.
|
||||
UnpWriteArea(WrittenBorder,UnpPtr);
|
||||
WrPtr=UnpPtr;
|
||||
}
|
||||
|
||||
// We prefer to write data in blocks not exceeding UNPACK_MAX_WRITE
|
||||
// instead of potentially huge MaxWinSize blocks.
|
||||
WriteBorder=(UnpPtr+Min(MaxWinSize,UNPACK_MAX_WRITE))&MaxWinMask;
|
||||
|
||||
// Choose the nearest among WriteBorder and WrPtr actual written border.
|
||||
// If border is equal to UnpPtr, it means that we have MaxWinSize data ahead.
|
||||
if (WriteBorder==UnpPtr ||
|
||||
WrPtr!=UnpPtr && ((WrPtr-UnpPtr)&MaxWinMask)<((WriteBorder-UnpPtr)&MaxWinMask))
|
||||
WriteBorder=WrPtr;
|
||||
}
|
||||
|
||||
|
||||
byte* Unpack::ApplyFilter(byte *Data,uint DataSize,UnpackFilter *Flt)
|
||||
{
|
||||
byte *SrcData=Data;
|
||||
switch(Flt->Type)
|
||||
{
|
||||
case FILTER_E8:
|
||||
case FILTER_E8E9:
|
||||
{
|
||||
uint FileOffset=(uint)WrittenFileSize;
|
||||
|
||||
const int FileSize=0x1000000;
|
||||
byte CmpByte2=Flt->Type==FILTER_E8E9 ? 0xe9:0xe8;
|
||||
for (uint CurPos=0;(int)CurPos<(int)DataSize-4;)
|
||||
{
|
||||
byte CurByte=*(Data++);
|
||||
CurPos++;
|
||||
if (CurByte==0xe8 || CurByte==CmpByte2)
|
||||
{
|
||||
uint Offset=(CurPos+FileOffset)%FileSize;
|
||||
uint Addr=RawGet4(Data);
|
||||
|
||||
// We check 0x80000000 bit instead of '< 0' comparison
|
||||
// not assuming int32 presence or uint size and endianness.
|
||||
if ((Addr & 0x80000000)!=0) // Addr<0
|
||||
{
|
||||
if (((Addr+Offset) & 0x80000000)==0) // Addr+Offset>=0
|
||||
RawPut4(Addr+FileSize,Data);
|
||||
}
|
||||
else
|
||||
if (((Addr-FileSize) & 0x80000000)!=0) // Addr<FileSize
|
||||
RawPut4(Addr-Offset,Data);
|
||||
|
||||
Data+=4;
|
||||
CurPos+=4;
|
||||
}
|
||||
}
|
||||
}
|
||||
return SrcData;
|
||||
case FILTER_ARM:
|
||||
{
|
||||
uint FileOffset=(uint)WrittenFileSize;
|
||||
for (uint CurPos=0;(int)CurPos<(int)DataSize-3;CurPos+=4)
|
||||
{
|
||||
byte *D=Data+CurPos;
|
||||
if (D[3]==0xeb) // BL command with '1110' (Always) condition.
|
||||
{
|
||||
uint Offset=D[0]+uint(D[1])*0x100+uint(D[2])*0x10000;
|
||||
Offset-=(FileOffset+CurPos)/4;
|
||||
D[0]=(byte)Offset;
|
||||
D[1]=(byte)(Offset>>8);
|
||||
D[2]=(byte)(Offset>>16);
|
||||
}
|
||||
}
|
||||
}
|
||||
return SrcData;
|
||||
case FILTER_DELTA:
|
||||
{
|
||||
uint Channels=Flt->Channels,SrcPos=0;
|
||||
|
||||
FilterDstMemory.Alloc(DataSize);
|
||||
byte *DstData=&FilterDstMemory[0];
|
||||
|
||||
// Bytes from same channels are grouped to continual data blocks,
|
||||
// so we need to place them back to their interleaving positions.
|
||||
for (uint CurChannel=0;CurChannel<Channels;CurChannel++)
|
||||
{
|
||||
byte PrevByte=0;
|
||||
for (uint DestPos=CurChannel;DestPos<DataSize;DestPos+=Channels)
|
||||
DstData[DestPos]=(PrevByte-=Data[SrcPos++]);
|
||||
}
|
||||
return DstData;
|
||||
}
|
||||
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void Unpack::UnpWriteArea(size_t StartPtr,size_t EndPtr)
|
||||
{
|
||||
if (EndPtr!=StartPtr)
|
||||
UnpSomeRead=true;
|
||||
if (EndPtr<StartPtr)
|
||||
UnpAllBuf=true;
|
||||
|
||||
if (Fragmented)
|
||||
{
|
||||
size_t SizeToWrite=(EndPtr-StartPtr) & MaxWinMask;
|
||||
while (SizeToWrite>0)
|
||||
{
|
||||
size_t BlockSize=FragWindow.GetBlockSize(StartPtr,SizeToWrite);
|
||||
UnpWriteData(&FragWindow[StartPtr],BlockSize);
|
||||
SizeToWrite-=BlockSize;
|
||||
StartPtr=(StartPtr+BlockSize) & MaxWinMask;
|
||||
}
|
||||
}
|
||||
else
|
||||
if (EndPtr<StartPtr)
|
||||
{
|
||||
UnpWriteData(Window+StartPtr,MaxWinSize-StartPtr);
|
||||
UnpWriteData(Window,EndPtr);
|
||||
}
|
||||
else
|
||||
UnpWriteData(Window+StartPtr,EndPtr-StartPtr);
|
||||
}
|
||||
|
||||
|
||||
void Unpack::UnpWriteData(byte *Data,size_t Size)
|
||||
{
|
||||
if (WrittenFileSize>=DestUnpSize)
|
||||
return;
|
||||
size_t WriteSize=Size;
|
||||
int64 LeftToWrite=DestUnpSize-WrittenFileSize;
|
||||
if ((int64)WriteSize>LeftToWrite)
|
||||
WriteSize=(size_t)LeftToWrite;
|
||||
UnpIO->UnpWrite(Data,WriteSize);
|
||||
WrittenFileSize+=Size;
|
||||
}
|
||||
|
||||
|
||||
bool Unpack::ReadBlockHeader(BitInput &Inp,UnpackBlockHeader &Header)
|
||||
{
|
||||
Header.HeaderSize=0;
|
||||
|
||||
if (!Inp.ExternalBuffer && Inp.InAddr>ReadTop-7)
|
||||
if (!UnpReadBuf())
|
||||
return false;
|
||||
Inp.faddbits((8-Inp.InBit)&7);
|
||||
|
||||
byte BlockFlags=Inp.fgetbits()>>8;
|
||||
Inp.faddbits(8);
|
||||
uint ByteCount=((BlockFlags>>3)&3)+1; // Block size byte count.
|
||||
|
||||
if (ByteCount==4)
|
||||
return false;
|
||||
|
||||
Header.HeaderSize=2+ByteCount;
|
||||
|
||||
Header.BlockBitSize=(BlockFlags&7)+1;
|
||||
|
||||
byte SavedCheckSum=Inp.fgetbits()>>8;
|
||||
Inp.faddbits(8);
|
||||
|
||||
int BlockSize=0;
|
||||
for (uint I=0;I<ByteCount;I++)
|
||||
{
|
||||
BlockSize+=(Inp.fgetbits()>>8)<<(I*8);
|
||||
Inp.addbits(8);
|
||||
}
|
||||
|
||||
Header.BlockSize=BlockSize;
|
||||
byte CheckSum=byte(0x5a^BlockFlags^BlockSize^(BlockSize>>8)^(BlockSize>>16));
|
||||
if (CheckSum!=SavedCheckSum)
|
||||
return false;
|
||||
|
||||
Header.BlockStart=Inp.InAddr;
|
||||
ReadBorder=Min(ReadBorder,Header.BlockStart+Header.BlockSize-1);
|
||||
|
||||
Header.LastBlockInFile=(BlockFlags & 0x40)!=0;
|
||||
Header.TablePresent=(BlockFlags & 0x80)!=0;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Unpack::ReadTables(BitInput &Inp,UnpackBlockHeader &Header,UnpackBlockTables &Tables)
|
||||
{
|
||||
if (!Header.TablePresent)
|
||||
return true;
|
||||
|
||||
if (!Inp.ExternalBuffer && Inp.InAddr>ReadTop-25)
|
||||
if (!UnpReadBuf())
|
||||
return false;
|
||||
|
||||
byte BitLength[BC];
|
||||
for (int I=0;I<BC;I++)
|
||||
{
|
||||
int Length=(byte)(Inp.fgetbits() >> 12);
|
||||
Inp.faddbits(4);
|
||||
if (Length==15)
|
||||
{
|
||||
int ZeroCount=(byte)(Inp.fgetbits() >> 12);
|
||||
Inp.faddbits(4);
|
||||
if (ZeroCount==0)
|
||||
BitLength[I]=15;
|
||||
else
|
||||
{
|
||||
ZeroCount+=2;
|
||||
while (ZeroCount-- > 0 && I<sizeof(BitLength)/sizeof(BitLength[0]))
|
||||
BitLength[I++]=0;
|
||||
I--;
|
||||
}
|
||||
}
|
||||
else
|
||||
BitLength[I]=Length;
|
||||
}
|
||||
|
||||
MakeDecodeTables(BitLength,&Tables.BD,BC);
|
||||
|
||||
byte Table[HUFF_TABLE_SIZE];
|
||||
const int TableSize=HUFF_TABLE_SIZE;
|
||||
for (int I=0;I<TableSize;)
|
||||
{
|
||||
if (!Inp.ExternalBuffer && Inp.InAddr>ReadTop-5)
|
||||
if (!UnpReadBuf())
|
||||
return(false);
|
||||
int Number=DecodeNumber(Inp,&Tables.BD);
|
||||
if (Number<16)
|
||||
{
|
||||
Table[I]=Number;
|
||||
I++;
|
||||
}
|
||||
else
|
||||
if (Number<18)
|
||||
{
|
||||
int N;
|
||||
if (Number==16)
|
||||
{
|
||||
N=(Inp.fgetbits() >> 13)+3;
|
||||
Inp.faddbits(3);
|
||||
}
|
||||
else
|
||||
{
|
||||
N=(Inp.fgetbits() >> 9)+11;
|
||||
Inp.faddbits(7);
|
||||
}
|
||||
if (I>0)
|
||||
while (N-- > 0 && I<TableSize)
|
||||
{
|
||||
Table[I]=Table[I-1];
|
||||
I++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int N;
|
||||
if (Number==18)
|
||||
{
|
||||
N=(Inp.fgetbits() >> 13)+3;
|
||||
Inp.faddbits(3);
|
||||
}
|
||||
else
|
||||
{
|
||||
N=(Inp.fgetbits() >> 9)+11;
|
||||
Inp.faddbits(7);
|
||||
}
|
||||
while (N-- > 0 && I<TableSize)
|
||||
Table[I++]=0;
|
||||
}
|
||||
}
|
||||
if (!Inp.ExternalBuffer && Inp.InAddr>ReadTop)
|
||||
return(false);
|
||||
MakeDecodeTables(&Table[0],&Tables.LD,NC);
|
||||
MakeDecodeTables(&Table[NC],&Tables.DD,DC);
|
||||
MakeDecodeTables(&Table[NC+DC],&Tables.LDD,LDC);
|
||||
MakeDecodeTables(&Table[NC+DC+LDC],&Tables.RD,RC);
|
||||
return(true);
|
||||
}
|
||||
|
||||
|
||||
void Unpack::InitFilters()
|
||||
{
|
||||
Filters.Reset();
|
||||
}
|
|
@ -0,0 +1,103 @@
|
|||
FragmentedWindow::FragmentedWindow()
|
||||
{
|
||||
memset(Mem,0,sizeof(Mem));
|
||||
memset(MemSize,0,sizeof(MemSize));
|
||||
}
|
||||
|
||||
|
||||
FragmentedWindow::~FragmentedWindow()
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
|
||||
void FragmentedWindow::Reset()
|
||||
{
|
||||
for (uint I=0;I<ASIZE(Mem);I++)
|
||||
if (Mem[I]!=NULL)
|
||||
{
|
||||
free(Mem[I]);
|
||||
Mem[I]=NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FragmentedWindow::Init(size_t WinSize)
|
||||
{
|
||||
Reset();
|
||||
|
||||
uint BlockNum=0;
|
||||
size_t TotalSize=0; // Already allocated.
|
||||
while (TotalSize<WinSize && BlockNum<ASIZE(Mem))
|
||||
{
|
||||
size_t Size=WinSize-TotalSize; // Size needed to allocate.
|
||||
|
||||
// Minimum still acceptable block size. Next allocations cannot be larger
|
||||
// than current, so we do not need blocks if they are smaller than
|
||||
// "size left / attempts left". Also we do not waste time to blocks
|
||||
// smaller than some arbitrary constant.
|
||||
size_t MinSize=Max(Size/(ASIZE(Mem)-BlockNum), 0x400000);
|
||||
|
||||
byte *NewMem=NULL;
|
||||
while (Size>=MinSize)
|
||||
{
|
||||
NewMem=(byte *)malloc(Size);
|
||||
if (NewMem!=NULL)
|
||||
break;
|
||||
Size-=Size/32;
|
||||
}
|
||||
if (NewMem==NULL)
|
||||
throw std::bad_alloc();
|
||||
|
||||
// Clean the window to generate the same output when unpacking corrupt
|
||||
// RAR files, which may access to unused areas of sliding dictionary.
|
||||
memset(NewMem,0,Size);
|
||||
|
||||
Mem[BlockNum]=NewMem;
|
||||
TotalSize+=Size;
|
||||
MemSize[BlockNum]=TotalSize;
|
||||
BlockNum++;
|
||||
}
|
||||
if (TotalSize<WinSize) // Not found enough free blocks.
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
|
||||
|
||||
byte& FragmentedWindow::operator [](size_t Item)
|
||||
{
|
||||
if (Item<MemSize[0])
|
||||
return Mem[0][Item];
|
||||
for (uint I=1;I<ASIZE(MemSize);I++)
|
||||
if (Item<MemSize[I])
|
||||
return Mem[I][Item-MemSize[I-1]];
|
||||
return Mem[0][0]; // Must never happen;
|
||||
}
|
||||
|
||||
|
||||
void FragmentedWindow::CopyString(uint Length,uint Distance,size_t &UnpPtr,size_t MaxWinMask)
|
||||
{
|
||||
size_t SrcPtr=UnpPtr-Distance;
|
||||
while (Length-- > 0)
|
||||
{
|
||||
(*this)[UnpPtr]=(*this)[SrcPtr++ & MaxWinMask];
|
||||
// We need to have masked UnpPtr after quit from loop, so it must not
|
||||
// be replaced with '(*this)[UnpPtr++ & MaxWinMask]'
|
||||
UnpPtr=(UnpPtr+1) & MaxWinMask;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FragmentedWindow::CopyData(byte *Dest,size_t WinPos,size_t Size)
|
||||
{
|
||||
for (size_t I=0;I<Size;I++)
|
||||
Dest[I]=(*this)[WinPos+I];
|
||||
}
|
||||
|
||||
|
||||
size_t FragmentedWindow::GetBlockSize(size_t StartPos,size_t RequiredSize)
|
||||
{
|
||||
for (uint I=0;I<ASIZE(MemSize);I++)
|
||||
if (StartPos<MemSize[I])
|
||||
return Min(MemSize[I]-StartPos,RequiredSize);
|
||||
return 0; // Must never be here.
|
||||
}
|
|
@ -0,0 +1,142 @@
|
|||
inline void Unpack::InsertOldDist(uint Distance)
|
||||
{
|
||||
OldDist[3]=OldDist[2];
|
||||
OldDist[2]=OldDist[1];
|
||||
OldDist[1]=OldDist[0];
|
||||
OldDist[0]=Distance;
|
||||
}
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define FAST_MEMCPY
|
||||
#endif
|
||||
|
||||
inline void Unpack::CopyString(uint Length,uint Distance)
|
||||
{
|
||||
size_t SrcPtr=UnpPtr-Distance;
|
||||
if (SrcPtr<MaxWinSize-MAX_LZ_MATCH && UnpPtr<MaxWinSize-MAX_LZ_MATCH)
|
||||
{
|
||||
// If we are not close to end of window, we do not need to waste time
|
||||
// to "& MaxWinMask" pointer protection.
|
||||
|
||||
byte *Src=Window+SrcPtr;
|
||||
byte *Dest=Window+UnpPtr;
|
||||
UnpPtr+=Length;
|
||||
|
||||
#ifdef FAST_MEMCPY
|
||||
if (Distance<Length) // Overlapping strings
|
||||
#endif
|
||||
while (Length>=8)
|
||||
{
|
||||
Dest[0]=Src[0];
|
||||
Dest[1]=Src[1];
|
||||
Dest[2]=Src[2];
|
||||
Dest[3]=Src[3];
|
||||
Dest[4]=Src[4];
|
||||
Dest[5]=Src[5];
|
||||
Dest[6]=Src[6];
|
||||
Dest[7]=Src[7];
|
||||
|
||||
Src+=8;
|
||||
Dest+=8;
|
||||
Length-=8;
|
||||
}
|
||||
#ifdef FAST_MEMCPY
|
||||
else
|
||||
while (Length>=8)
|
||||
{
|
||||
// This memcpy expanded inline by MSVC. We could also use uint64
|
||||
// assignment, which seems to provide about the same speed.
|
||||
memcpy(Dest,Src,8);
|
||||
|
||||
Src+=8;
|
||||
Dest+=8;
|
||||
Length-=8;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Unroll the loop for 0 - 7 bytes left. Note that we use nested "if"s.
|
||||
if (Length>0) { Dest[0]=Src[0];
|
||||
if (Length>1) { Dest[1]=Src[1];
|
||||
if (Length>2) { Dest[2]=Src[2];
|
||||
if (Length>3) { Dest[3]=Src[3];
|
||||
if (Length>4) { Dest[4]=Src[4];
|
||||
if (Length>5) { Dest[5]=Src[5];
|
||||
if (Length>6) { Dest[6]=Src[6]; } } } } } } } // Close all nested "if"s.
|
||||
}
|
||||
else
|
||||
while (Length-- > 0) // Slow copying with all possible precautions.
|
||||
{
|
||||
Window[UnpPtr]=Window[SrcPtr++ & MaxWinMask];
|
||||
// We need to have masked UnpPtr after quit from loop, so it must not
|
||||
// be replaced with 'Window[UnpPtr++ & MaxWinMask]'
|
||||
UnpPtr=(UnpPtr+1) & MaxWinMask;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
inline uint Unpack::DecodeNumber(BitInput &Inp,DecodeTable *Dec)
|
||||
{
|
||||
// Left aligned 15 bit length raw bit field.
|
||||
uint BitField=Inp.getbits() & 0xfffe;
|
||||
|
||||
if (BitField<Dec->DecodeLen[Dec->QuickBits])
|
||||
{
|
||||
uint Code=BitField>>(16-Dec->QuickBits);
|
||||
Inp.addbits(Dec->QuickLen[Code]);
|
||||
return Dec->QuickNum[Code];
|
||||
}
|
||||
|
||||
// Detect the real bit length for current code.
|
||||
uint Bits=15;
|
||||
for (uint I=Dec->QuickBits+1;I<15;I++)
|
||||
if (BitField<Dec->DecodeLen[I])
|
||||
{
|
||||
Bits=I;
|
||||
break;
|
||||
}
|
||||
|
||||
Inp.addbits(Bits);
|
||||
|
||||
// Calculate the distance from the start code for current bit length.
|
||||
uint Dist=BitField-Dec->DecodeLen[Bits-1];
|
||||
|
||||
// Start codes are left aligned, but we need the normal right aligned
|
||||
// number. So we shift the distance to the right.
|
||||
Dist>>=(16-Bits);
|
||||
|
||||
// Now we can calculate the position in the code list. It is the sum
|
||||
// of first position for current bit length and right aligned distance
|
||||
// between our bit field and start code for current bit length.
|
||||
uint Pos=Dec->DecodePos[Bits]+Dist;
|
||||
|
||||
// Out of bounds safety check required for damaged archives.
|
||||
if (Pos>=Dec->MaxNum)
|
||||
Pos=0;
|
||||
|
||||
// Convert the position in the code list to position in alphabet
|
||||
// and return it.
|
||||
return(Dec->DecodeNum[Pos]);
|
||||
}
|
||||
|
||||
|
||||
inline uint Unpack::SlotToLength(BitInput &Inp,uint Slot)
|
||||
{
|
||||
uint LBits,Length=2;
|
||||
if (Slot<8)
|
||||
{
|
||||
LBits=0;
|
||||
Length+=Slot;
|
||||
}
|
||||
else
|
||||
{
|
||||
LBits=Slot/4-1;
|
||||
Length+=(4 | (Slot & 3)) << LBits;
|
||||
}
|
||||
|
||||
if (LBits>0)
|
||||
{
|
||||
Length+=Inp.getbits()>>(16-LBits);
|
||||
Inp.addbits(LBits);
|
||||
}
|
||||
return Length;
|
||||
}
|
|
@ -42,8 +42,7 @@ void Rar_Error_Handler::MemoryError()
|
|||
|
||||
//// Internal
|
||||
|
||||
unrar_t::unrar_t() :
|
||||
Buffer( &Arc )
|
||||
unrar_t::unrar_t()
|
||||
{
|
||||
Arc.user_read = NULL;
|
||||
Arc.user_write = NULL;
|
||||
|
@ -74,8 +73,8 @@ unrar_t::~unrar_t()
|
|||
static inline bool solid_file( const unrar_t* p )
|
||||
{
|
||||
return p->Arc.Solid &&
|
||||
p->Arc.NewLhd.Method != 0x30 &&
|
||||
p->Arc.NewLhd.FullPackSize != 0;
|
||||
p->Arc.FileHead.Method != 0 &&
|
||||
p->Arc.FileHead.PackSize != 0;
|
||||
}
|
||||
|
||||
static void update_solid_pos( unrar_t* p )
|
||||
|
@ -129,8 +128,9 @@ static unrar_err_t next_( unrar_t* p, bool skipping_solid )
|
|||
|
||||
for (;;)
|
||||
{
|
||||
size_t ReadSize;
|
||||
p->Arc.SeekToNext();
|
||||
unrar_err_t const err = p->Arc.ReadHeader();
|
||||
unrar_err_t const err = p->Arc.ReadHeader(&ReadSize);
|
||||
if ( err != unrar_err_arc_eof )
|
||||
RETURN_ERR( err );
|
||||
//else
|
||||
|
@ -138,17 +138,17 @@ static unrar_err_t next_( unrar_t* p, bool skipping_solid )
|
|||
|
||||
HEADER_TYPE const type = (HEADER_TYPE) p->Arc.GetHeaderType();
|
||||
|
||||
if ( err != unrar_ok || type == ENDARC_HEAD )
|
||||
if ( err != unrar_ok || type == HEAD_ENDARC )
|
||||
{
|
||||
p->done = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if ( type != FILE_HEAD )
|
||||
if ( type != HEAD_FILE )
|
||||
{
|
||||
// Skip non-files
|
||||
/*if ( type != NEWSUB_HEAD && type != PROTECT_HEAD && type != SIGN_HEAD && type != SUB_HEAD )
|
||||
debug_printf( "unrar: Skipping unknown block type: %X\n", (unsigned) type );*/
|
||||
if ( type != HEAD_SERVICE && type != HEAD_CRYPT && type != HEAD_MARK )
|
||||
debug_printf( "unrar: Skipping unknown block type: %X\n", (unsigned) type );
|
||||
|
||||
update_solid_pos( p );
|
||||
}
|
||||
|
@ -162,7 +162,7 @@ static unrar_err_t next_( unrar_t* p, bool skipping_solid )
|
|||
{
|
||||
// Ignore labels
|
||||
}
|
||||
else if ( IsLink( p->Arc.NewLhd.FileAttr ) )
|
||||
else if ( IsLink( p->Arc.FileHead.FileAttr ) )
|
||||
{
|
||||
// Ignore links
|
||||
|
||||
|
@ -175,12 +175,12 @@ static unrar_err_t next_( unrar_t* p, bool skipping_solid )
|
|||
}
|
||||
else
|
||||
{
|
||||
p->info.size = p->Arc.NewLhd.UnpSize;
|
||||
p->info.name = p->Arc.NewLhd.FileName;
|
||||
p->info.name_w = p->Arc.NewLhd.FileNameW;
|
||||
p->info.is_unicode = (p->Arc.NewLhd.Flags & LHD_UNICODE) != 0;
|
||||
p->info.dos_date = p->Arc.NewLhd.mtime.time;
|
||||
p->info.crc = p->Arc.NewLhd.FileCRC;
|
||||
p->info.size = p->Arc.FileHead.UnpSize;
|
||||
p->info.name_w = p->Arc.FileHead.FileName;
|
||||
WideToChar(p->info.name_w, p->info.name);
|
||||
p->info.is_unicode = (p->Arc.FileHead.Flags & LHD_UNICODE) != 0;
|
||||
p->info.dos_date = p->Arc.FileHead.mtime.GetDos();
|
||||
p->info.crc = p->Arc.FileHead.FileHash.CRC32;
|
||||
p->info.is_crc32 = !p->Arc.OldFormat;
|
||||
|
||||
// Stop for files
|
||||
|
|
|
@ -11,8 +11,10 @@
|
|||
|
||||
#if !defined (UNRAR_NO_LONG_LONG) && defined (LLONG_MAX)
|
||||
typedef long long unrar_long_long;
|
||||
typedef unsigned long long unrar_ulong_long;
|
||||
#else
|
||||
typedef long unrar_long_long;
|
||||
typedef unsigned long unrar_ulong_long;
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -91,7 +93,7 @@ unrar_err_t unrar_seek( unrar_t*, unrar_pos_t );
|
|||
typedef struct unrar_info_t
|
||||
{
|
||||
unrar_pos_t size; /**< Uncompressed size */
|
||||
const char* name; /**< Name, in Unicode if is_unicode is true */
|
||||
char name[32767]; /**< Name, in Unicode if is_unicode is true */
|
||||
const blargg_wchar_t* name_w; /**< Name in Unicode, "" if unavailable */
|
||||
unrar_bool is_unicode; /**< True if name is Unicode (UTF-8) */
|
||||
unsigned int dos_date; /**< Date in DOS-style format, 0 if unavailable */
|
||||
|
|
|
@ -11,8 +11,8 @@
|
|||
|
||||
void unrar_init()
|
||||
{
|
||||
if (CRCTab[1]==0)
|
||||
InitCRC();
|
||||
if (crc_tables[0][1]==0)
|
||||
InitCRCTables();
|
||||
|
||||
Unpack::init_tables();
|
||||
}
|
||||
|
@ -55,7 +55,7 @@ unrar_err_t unrar_extract( unrar_t* p, void* out, unrar_pos_t size )
|
|||
inline
|
||||
static bool is_entire_file( const unrar_t* p, const void* in, int count )
|
||||
{
|
||||
return (count == p->Arc.NewLhd.UnpSize && p->Unp && in == p->Unp->window_wrptr());
|
||||
return (count == p->Arc.SubHead.UnpSize && p->Unp && in == p->Unp->window_wrptr());
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
|
@ -149,10 +149,7 @@ void ComprDataIO::UnpWrite( byte* out, uint count )
|
|||
if ( write_error == unrar_ok )
|
||||
write_error = user_write( user_write_data, out, count );
|
||||
|
||||
if ( OldFormat )
|
||||
UnpFileCRC = OldCRC( (ushort) UnpFileCRC, out, count );
|
||||
else
|
||||
UnpFileCRC = CRC( UnpFileCRC, out, count );
|
||||
UnpHash.Update(out,count);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -162,7 +159,7 @@ int ComprDataIO::UnpRead( byte* out, uint count )
|
|||
return 0;
|
||||
|
||||
if ( count > (uint) UnpPackedSize )
|
||||
count = (uint) UnpPackedSize;
|
||||
count = UnpPackedSize;
|
||||
|
||||
int result = Read( out, count );
|
||||
UnpPackedSize -= result;
|
||||
|
|
Loading…
Reference in New Issue