2013-04-07 10:58:58 +01:00
using System ;
using System.Collections.Generic ;
using System.IO ;
using SharpCompress.Common ;
using SharpCompress.Common.Rar.Headers ;
using SharpCompress.Compressor.PPMd.H ;
using SharpCompress.Compressor.Rar.decode ;
using SharpCompress.Compressor.Rar.PPM ;
using SharpCompress.Compressor.Rar.VM ;
namespace SharpCompress.Compressor.Rar
{
internal sealed class Unpack : Unpack20
{
public bool FileExtracted
{
// Duplicate method
// private boolean ReadEndOfBlock() throws IOException, RarException
// {
// int BitField = getbits();
// boolean NewTable, NewFile = false;
// if ((BitField & 0x8000) != 0) {
// NewTable = true;
// addbits(1);
// } else {
// NewFile = true;
// NewTable = (BitField & 0x4000) != 0;
// addbits(2);
// }
// tablesRead = !NewTable;
// return !(NewFile || NewTable && !readTables());
// }
2013-04-28 12:32:55 +01:00
get { return fileExtracted ; }
2013-04-07 10:58:58 +01:00
}
2013-04-28 12:32:55 +01:00
2013-04-07 10:58:58 +01:00
public long DestSize
{
2013-04-28 12:32:55 +01:00
get { return destUnpSize ; }
2013-04-07 10:58:58 +01:00
set
{
this . destUnpSize = value ;
this . fileExtracted = false ;
}
}
2013-04-28 12:32:55 +01:00
2013-04-07 10:58:58 +01:00
public bool Suspended
{
2013-04-28 12:32:55 +01:00
set { this . suspended = value ; }
2013-04-07 10:58:58 +01:00
}
2013-04-28 12:32:55 +01:00
2013-04-07 10:58:58 +01:00
public int Char
{
get
{
if ( inAddr > BitInput . MAX_SIZE - 30 )
{
unpReadBuf ( ) ;
}
return ( InBuf [ inAddr + + ] & 0xff ) ;
}
}
2013-04-28 12:32:55 +01:00
2013-04-07 10:58:58 +01:00
public int PpmEscChar
{
2013-04-28 12:32:55 +01:00
get { return ppmEscChar ; }
2013-04-07 10:58:58 +01:00
2013-04-28 12:32:55 +01:00
set { this . ppmEscChar = value ; }
2013-04-07 10:58:58 +01:00
}
//UPGRADE_NOTE: Final was removed from the declaration of 'ppm '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
private ModelPPM ppm = new ModelPPM ( ) ;
private int ppmEscChar ;
private RarVM rarVM = new RarVM ( ) ;
/* Filters code, one entry per filter */
//UPGRADE_ISSUE: The following fragment of code could not be parsed and was not converted. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1156'"
private List < UnpackFilter > filters = new List < UnpackFilter > ( ) ;
/* Filters stack, several entrances of same filter are possible */
//UPGRADE_ISSUE: The following fragment of code could not be parsed and was not converted. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1156'"
private List < UnpackFilter > prgStack = new List < UnpackFilter > ( ) ;
/ *
* lengths of preceding blocks , one length per filter . Used to reduce size
* required to write block length if lengths are repeating
* /
//UPGRADE_ISSUE: The following fragment of code could not be parsed and was not converted. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1156'"
private List < int > oldFilterLengths = new List < int > ( ) ;
private int lastFilter ;
private bool tablesRead ;
//UPGRADE_NOTE: The initialization of 'unpOldTable' was moved to method 'InitBlock'. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1005'"
private byte [ ] unpOldTable = new byte [ Compress . HUFF_TABLE_SIZE ] ;
private BlockTypes unpBlockType ;
//private bool externalWindow;
private long writtenFileSize ;
private bool fileExtracted ;
private bool ppmError ;
private int prevLowDist ;
private int lowDistRepCount ;
2013-04-28 12:32:55 +01:00
public static int [ ] DBitLengthCounts = new int [ ] { 4 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 14 , 0 , 12 } ;
2013-04-07 10:58:58 +01:00
private FileHeader fileHeader ;
public Unpack ( )
{
window = null ;
//externalWindow = false;
suspended = false ;
unpAllBuf = false ;
unpSomeRead = false ;
}
public void init ( byte [ ] window )
{
if ( window = = null )
{
this . window = new byte [ Compress . MAXWINSIZE ] ;
}
else
{
this . window = window ;
//externalWindow = true;
}
inAddr = 0 ;
unpInitData ( false ) ;
}
public void doUnpack ( FileHeader fileHeader , Stream readStream , Stream writeStream )
{
destUnpSize = fileHeader . UncompressedSize ;
this . fileHeader = fileHeader ;
base . writeStream = writeStream ;
base . readStream = readStream ;
bool solid = FlagUtility . HasFlag ( fileHeader . FileFlags , FileFlags . SOLID ) ;
if ( ! solid )
{
init ( null ) ;
}
suspended = false ;
doUnpack ( ) ;
}
public void doUnpack ( )
{
bool solid = FlagUtility . HasFlag ( fileHeader . FileFlags , FileFlags . SOLID ) ;
if ( fileHeader . PackingMethod = = 0x30 )
{
unstoreFile ( ) ;
return ;
}
switch ( fileHeader . RarVersion )
{
2013-04-28 12:32:55 +01:00
case 15 : // rar 1.5 compression
2013-04-07 10:58:58 +01:00
unpack15 ( solid ) ;
break ;
case 20 :
2013-04-28 12:32:55 +01:00
// rar 2.x compression
case 26 : // files larger than 2GB
2013-04-07 10:58:58 +01:00
unpack20 ( solid ) ;
break ;
case 29 :
2013-04-28 12:32:55 +01:00
// rar 3.x compression
case 36 : // alternative hash
2013-04-07 10:58:58 +01:00
unpack29 ( solid ) ;
break ;
}
}
private void unstoreFile ( )
{
byte [ ] buffer = new byte [ 0x10000 ] ;
while ( true )
{
2013-04-28 12:32:55 +01:00
int code = readStream . Read ( buffer , 0 , ( int ) System . Math . Min ( buffer . Length , destUnpSize ) ) ;
2013-04-07 10:58:58 +01:00
if ( code = = 0 | | code = = - 1 )
break ;
2013-04-28 12:32:55 +01:00
code = code < destUnpSize ? code : ( int ) destUnpSize ;
2013-04-07 10:58:58 +01:00
writeStream . Write ( buffer , 0 , code ) ;
if ( destUnpSize > = 0 )
destUnpSize - = code ;
if ( suspended )
return ;
}
}
private void unpack29 ( bool solid )
{
int [ ] DDecode = new int [ Compress . DC ] ;
byte [ ] DBits = new byte [ Compress . DC ] ;
int Bits ;
if ( DDecode [ 1 ] = = 0 )
{
int Dist = 0 , BitLength = 0 , Slot = 0 ;
for ( int I = 0 ; I < DBitLengthCounts . Length ; I + + , BitLength + + )
{
int count = DBitLengthCounts [ I ] ;
for ( int J = 0 ; J < count ; J + + , Slot + + , Dist + = ( 1 < < BitLength ) )
{
DDecode [ Slot ] = Dist ;
2013-04-28 12:32:55 +01:00
DBits [ Slot ] = ( byte ) BitLength ;
2013-04-07 10:58:58 +01:00
}
}
}
fileExtracted = true ;
if ( ! suspended )
{
unpInitData ( solid ) ;
if ( ! unpReadBuf ( ) )
{
return ;
}
if ( ( ! solid | | ! tablesRead ) & & ! readTables ( ) )
{
return ;
}
}
if ( ppmError )
{
return ;
}
while ( true )
{
unpPtr & = Compress . MAXWINMASK ;
if ( inAddr > readBorder )
{
if ( ! unpReadBuf ( ) )
{
break ;
}
}
// System.out.println(((wrPtr - unpPtr) &
// Compress.MAXWINMASK)+":"+wrPtr+":"+unpPtr);
if ( ( ( wrPtr - unpPtr ) & Compress . MAXWINMASK ) < 260 & & wrPtr ! = unpPtr )
{
UnpWriteBuf ( ) ;
if ( destUnpSize < = 0 )
{
return ;
}
if ( suspended )
{
fileExtracted = false ;
return ;
}
}
if ( unpBlockType = = BlockTypes . BLOCK_PPM )
{
int Ch = ppm . decodeChar ( ) ;
if ( Ch = = - 1 )
{
ppmError = true ;
break ;
}
if ( Ch = = ppmEscChar )
{
int NextCh = ppm . decodeChar ( ) ;
if ( NextCh = = 0 )
{
if ( ! readTables ( ) )
{
break ;
}
continue ;
}
if ( NextCh = = 2 | | NextCh = = - 1 )
{
break ;
}
if ( NextCh = = 3 )
{
if ( ! readVMCodePPM ( ) )
{
break ;
}
continue ;
}
if ( NextCh = = 4 )
{
int Distance = 0 , Length = 0 ;
bool failed = false ;
for ( int I = 0 ; I < 4 & & ! failed ; I + + )
{
int ch = ppm . decodeChar ( ) ;
if ( ch = = - 1 )
{
failed = true ;
}
else
{
if ( I = = 3 )
{
// Bug fixed
Length = ch & 0xff ;
}
else
{
// Bug fixed
Distance = ( Distance < < 8 ) + ( ch & 0xff ) ;
}
}
}
if ( failed )
{
break ;
}
copyString ( Length + 32 , Distance + 2 ) ;
continue ;
}
if ( NextCh = = 5 )
{
int Length = ppm . decodeChar ( ) ;
if ( Length = = - 1 )
{
break ;
}
copyString ( Length + 4 , 1 ) ;
continue ;
}
}
2013-04-28 12:32:55 +01:00
window [ unpPtr + + ] = ( byte ) Ch ;
2013-04-07 10:58:58 +01:00
continue ;
}
int Number = this . decodeNumber ( LD ) ;
if ( Number < 256 )
{
2013-04-28 12:32:55 +01:00
window [ unpPtr + + ] = ( byte ) Number ;
2013-04-07 10:58:58 +01:00
continue ;
}
if ( Number > = 271 )
{
int Length = LDecode [ Number - = 271 ] + 3 ;
if ( ( Bits = LBits [ Number ] ) > 0 )
{
Length + = Utility . URShift ( GetBits ( ) , ( 16 - Bits ) ) ;
AddBits ( Bits ) ;
}
int DistNumber = this . decodeNumber ( DD ) ;
int Distance = DDecode [ DistNumber ] + 1 ;
if ( ( Bits = DBits [ DistNumber ] ) > 0 )
{
if ( DistNumber > 9 )
{
if ( Bits > 4 )
{
Distance + = ( ( Utility . URShift ( GetBits ( ) , ( 20 - Bits ) ) ) < < 4 ) ;
AddBits ( Bits - 4 ) ;
}
if ( lowDistRepCount > 0 )
{
lowDistRepCount - - ;
Distance + = prevLowDist ;
}
else
{
int LowDist = this . decodeNumber ( LDD ) ;
if ( LowDist = = 16 )
{
lowDistRepCount = Compress . LOW_DIST_REP_COUNT - 1 ;
Distance + = prevLowDist ;
}
else
{
Distance + = LowDist ;
prevLowDist = LowDist ;
}
}
}
else
{
Distance + = Utility . URShift ( GetBits ( ) , ( 16 - Bits ) ) ;
AddBits ( Bits ) ;
}
}
if ( Distance > = 0x2000 )
{
Length + + ;
if ( Distance > = 0x40000L )
{
Length + + ;
}
}
insertOldDist ( Distance ) ;
insertLastMatch ( Length , Distance ) ;
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 , lastDist ) ;
}
continue ;
}
if ( Number < 263 )
{
int DistNum = Number - 259 ;
int Distance = oldDist [ DistNum ] ;
for ( int I = DistNum ; I > 0 ; I - - )
{
oldDist [ I ] = oldDist [ I - 1 ] ;
}
oldDist [ 0 ] = Distance ;
int LengthNumber = this . decodeNumber ( RD ) ;
int Length = LDecode [ LengthNumber ] + 2 ;
if ( ( Bits = LBits [ LengthNumber ] ) > 0 )
{
Length + = Utility . URShift ( GetBits ( ) , ( 16 - Bits ) ) ;
AddBits ( Bits ) ;
}
insertLastMatch ( Length , Distance ) ;
copyString ( Length , Distance ) ;
continue ;
}
if ( Number < 272 )
{
int Distance = SDDecode [ Number - = 263 ] + 1 ;
if ( ( Bits = SDBits [ Number ] ) > 0 )
{
Distance + = Utility . URShift ( GetBits ( ) , ( 16 - Bits ) ) ;
AddBits ( Bits ) ;
}
insertOldDist ( Distance ) ;
insertLastMatch ( 2 , Distance ) ;
copyString ( 2 , Distance ) ;
continue ;
}
}
UnpWriteBuf ( ) ;
}
private void UnpWriteBuf ( )
{
int WrittenBorder = wrPtr ;
int WriteSize = ( unpPtr - WrittenBorder ) & Compress . MAXWINMASK ;
for ( int I = 0 ; I < prgStack . Count ; I + + )
{
UnpackFilter flt = prgStack [ I ] ;
if ( flt = = null )
{
continue ;
}
if ( flt . NextWindow )
{
flt . NextWindow = false ; // ->NextWindow=false;
continue ;
}
int BlockStart = flt . BlockStart ; // ->BlockStart;
int BlockLength = flt . BlockLength ; // ->BlockLength;
if ( ( ( BlockStart - WrittenBorder ) & Compress . MAXWINMASK ) < WriteSize )
{
if ( WrittenBorder ! = BlockStart )
{
UnpWriteArea ( WrittenBorder , BlockStart ) ;
WrittenBorder = BlockStart ;
WriteSize = ( unpPtr - WrittenBorder ) & Compress . MAXWINMASK ;
}
if ( BlockLength < = WriteSize )
{
int BlockEnd = ( BlockStart + BlockLength ) & Compress . MAXWINMASK ;
if ( BlockStart < BlockEnd | | BlockEnd = = 0 )
{
// VM.SetMemory(0,Window+BlockStart,BlockLength);
rarVM . setMemory ( 0 , window , BlockStart , BlockLength ) ;
}
else
{
int FirstPartLength = Compress . MAXWINSIZE - BlockStart ;
// VM.SetMemory(0,Window+BlockStart,FirstPartLength);
rarVM . setMemory ( 0 , window , BlockStart , FirstPartLength ) ;
// VM.SetMemory(FirstPartLength,Window,BlockEnd);
rarVM . setMemory ( FirstPartLength , window , 0 , BlockEnd ) ;
}
VMPreparedProgram ParentPrg = filters [ flt . ParentFilter ] . Program ;
VMPreparedProgram Prg = flt . Program ;
if ( ParentPrg . GlobalData . Count > RarVM . 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);
Prg . GlobalData . Clear ( ) ;
for ( int i = 0 ; i < ParentPrg . GlobalData . Count - RarVM . VM_FIXEDGLOBALSIZE ; i + + )
{
2013-04-28 12:32:55 +01:00
Prg . GlobalData [ RarVM . VM_FIXEDGLOBALSIZE + i ] =
ParentPrg . GlobalData [ RarVM . VM_FIXEDGLOBALSIZE + i ] ;
2013-04-07 10:58:58 +01:00
}
}
ExecuteCode ( Prg ) ;
if ( Prg . GlobalData . Count > RarVM . VM_FIXEDGLOBALSIZE )
{
// save global data for next script execution
if ( ParentPrg . GlobalData . Count < Prg . GlobalData . Count )
{
//ParentPrg.GlobalData.Clear(); // ->GlobalData.Alloc(Prg->GlobalData.Size());
ParentPrg . GlobalData . SetSize ( Prg . GlobalData . Count ) ;
}
// memcpy(&ParentPrg->GlobalData[VM_FIXEDGLOBALSIZE],&Prg->GlobalData[VM_FIXEDGLOBALSIZE],Prg->GlobalData.Size()-VM_FIXEDGLOBALSIZE);
for ( int i = 0 ; i < Prg . GlobalData . Count - RarVM . VM_FIXEDGLOBALSIZE ; i + + )
{
2013-04-28 12:32:55 +01:00
ParentPrg . GlobalData [ RarVM . VM_FIXEDGLOBALSIZE + i ] =
Prg . GlobalData [ RarVM . VM_FIXEDGLOBALSIZE + i ] ;
2013-04-07 10:58:58 +01:00
}
}
else
{
ParentPrg . GlobalData . Clear ( ) ;
}
int FilteredDataOffset = Prg . FilteredDataOffset ;
int FilteredDataSize = Prg . FilteredDataSize ;
byte [ ] FilteredData = new byte [ FilteredDataSize ] ;
for ( int i = 0 ; i < FilteredDataSize ; i + + )
{
2013-04-28 12:32:55 +01:00
FilteredData [ i ] = rarVM . Mem [ FilteredDataOffset + i ] ;
// Prg.GlobalData.get(FilteredDataOffset
2013-04-07 10:58:58 +01:00
// +
// i);
}
prgStack [ I ] = null ;
while ( I + 1 < prgStack . Count )
{
UnpackFilter NextFilter = prgStack [ I + 1 ] ;
2013-04-28 12:32:55 +01:00
if ( NextFilter = = null | | NextFilter . BlockStart ! = BlockStart | |
NextFilter . BlockLength ! = FilteredDataSize | | NextFilter . NextWindow )
2013-04-07 10:58:58 +01:00
{
break ;
}
// apply several filters to same data block
2013-04-28 12:32:55 +01:00
rarVM . setMemory ( 0 , FilteredData , 0 , FilteredDataSize ) ;
// .SetMemory(0,FilteredData,FilteredDataSize);
2013-04-07 10:58:58 +01:00
VMPreparedProgram pPrg = filters [ NextFilter . ParentFilter ] . Program ;
VMPreparedProgram NextPrg = NextFilter . Program ;
if ( pPrg . GlobalData . Count > RarVM . VM_FIXEDGLOBALSIZE )
{
// copy global data from previous script execution
// if any
// NextPrg->GlobalData.Alloc(ParentPrg->GlobalData.Size());
NextPrg . GlobalData . SetSize ( pPrg . GlobalData . Count ) ;
// memcpy(&NextPrg->GlobalData[VM_FIXEDGLOBALSIZE],&ParentPrg->GlobalData[VM_FIXEDGLOBALSIZE],ParentPrg->GlobalData.Size()-VM_FIXEDGLOBALSIZE);
for ( int i = 0 ; i < pPrg . GlobalData . Count - RarVM . VM_FIXEDGLOBALSIZE ; i + + )
{
2013-04-28 12:32:55 +01:00
NextPrg . GlobalData [ RarVM . VM_FIXEDGLOBALSIZE + i ] =
pPrg . GlobalData [ RarVM . VM_FIXEDGLOBALSIZE + i ] ;
2013-04-07 10:58:58 +01:00
}
}
ExecuteCode ( NextPrg ) ;
if ( NextPrg . GlobalData . Count > RarVM . VM_FIXEDGLOBALSIZE )
{
// save global data for next script execution
if ( pPrg . GlobalData . Count < NextPrg . GlobalData . Count )
{
pPrg . GlobalData . SetSize ( NextPrg . GlobalData . Count ) ;
}
// memcpy(&ParentPrg->GlobalData[VM_FIXEDGLOBALSIZE],&NextPrg->GlobalData[VM_FIXEDGLOBALSIZE],NextPrg->GlobalData.Size()-VM_FIXEDGLOBALSIZE);
for ( int i = 0 ; i < NextPrg . GlobalData . Count - RarVM . VM_FIXEDGLOBALSIZE ; i + + )
{
2013-04-28 12:32:55 +01:00
pPrg . GlobalData [ RarVM . VM_FIXEDGLOBALSIZE + i ] =
NextPrg . GlobalData [ RarVM . VM_FIXEDGLOBALSIZE + i ] ;
2013-04-07 10:58:58 +01:00
}
}
else
{
pPrg . GlobalData . Clear ( ) ;
}
FilteredDataOffset = NextPrg . FilteredDataOffset ;
FilteredDataSize = NextPrg . FilteredDataSize ;
FilteredData = new byte [ FilteredDataSize ] ;
for ( int i = 0 ; i < FilteredDataSize ; i + + )
{
FilteredData [ i ] = NextPrg . GlobalData [ FilteredDataOffset + i ] ;
}
I + + ;
prgStack [ I ] = null ;
}
writeStream . Write ( FilteredData , 0 , FilteredDataSize ) ;
unpSomeRead = true ;
writtenFileSize + = FilteredDataSize ;
destUnpSize - = FilteredDataSize ;
WrittenBorder = BlockEnd ;
WriteSize = ( unpPtr - WrittenBorder ) & Compress . MAXWINMASK ;
}
else
{
for ( int J = I ; J < prgStack . Count ; J + + )
{
UnpackFilter filt = prgStack [ J ] ;
if ( filt ! = null & & filt . NextWindow )
{
filt . NextWindow = false ;
}
}
wrPtr = WrittenBorder ;
return ;
}
}
}
UnpWriteArea ( WrittenBorder , unpPtr ) ;
wrPtr = unpPtr ;
}
private void UnpWriteArea ( int startPtr , int endPtr )
{
if ( endPtr ! = startPtr )
{
unpSomeRead = true ;
}
if ( endPtr < startPtr )
{
UnpWriteData ( window , startPtr , - startPtr & Compress . MAXWINMASK ) ;
UnpWriteData ( window , 0 , endPtr ) ;
unpAllBuf = true ;
}
else
{
UnpWriteData ( window , startPtr , endPtr - startPtr ) ;
}
}
private void UnpWriteData ( byte [ ] data , int offset , int size )
{
if ( destUnpSize < = 0 )
{
return ;
}
int writeSize = size ;
if ( writeSize > destUnpSize )
{
2013-04-28 12:32:55 +01:00
writeSize = ( int ) destUnpSize ;
2013-04-07 10:58:58 +01:00
}
writeStream . Write ( data , offset , writeSize ) ;
writtenFileSize + = size ;
destUnpSize - = size ;
}
private void insertOldDist ( int distance )
{
oldDist [ 3 ] = oldDist [ 2 ] ;
oldDist [ 2 ] = oldDist [ 1 ] ;
oldDist [ 1 ] = oldDist [ 0 ] ;
oldDist [ 0 ] = distance ;
}
private void insertLastMatch ( int length , int distance )
{
lastDist = distance ;
lastLength = length ;
}
private void copyString ( int length , int distance )
{
// System.out.println("copyString(" + length + ", " + distance + ")");
int destPtr = unpPtr - distance ;
// System.out.println(unpPtr+":"+distance);
if ( destPtr > = 0 & & destPtr < Compress . MAXWINSIZE - 260 & & unpPtr < Compress . MAXWINSIZE - 260 )
{
window [ unpPtr + + ] = window [ destPtr + + ] ;
while ( - - length > 0 )
window [ unpPtr + + ] = window [ destPtr + + ] ;
}
else
while ( length - - ! = 0 )
{
window [ unpPtr ] = window [ destPtr + + & Compress . MAXWINMASK ] ;
unpPtr = ( unpPtr + 1 ) & Compress . MAXWINMASK ;
}
}
protected internal override void unpInitData ( bool solid )
{
if ( ! solid )
{
tablesRead = false ;
Utility . Fill ( oldDist , 0 ) ; // memset(oldDist,0,sizeof(OldDist));
oldDistPtr = 0 ;
lastDist = 0 ;
lastLength = 0 ;
2013-04-28 12:32:55 +01:00
Utility . Fill ( unpOldTable , ( byte ) 0 ) ; // memset(UnpOldTable,0,sizeof(UnpOldTable));
2013-04-07 10:58:58 +01:00
unpPtr = 0 ;
wrPtr = 0 ;
ppmEscChar = 2 ;
initFilters ( ) ;
}
InitBitInput ( ) ;
ppmError = false ;
writtenFileSize = 0 ;
readTop = 0 ;
readBorder = 0 ;
unpInitData20 ( solid ) ;
}
private void initFilters ( )
{
oldFilterLengths . Clear ( ) ;
lastFilter = 0 ;
filters . Clear ( ) ;
prgStack . Clear ( ) ;
}
private bool readEndOfBlock ( )
{
int BitField = GetBits ( ) ;
bool NewTable , NewFile = false ;
if ( ( BitField & 0x8000 ) ! = 0 )
{
NewTable = true ;
AddBits ( 1 ) ;
}
else
{
NewFile = true ;
NewTable = ( BitField & 0x4000 ) ! = 0 ? true : false ;
AddBits ( 2 ) ;
}
tablesRead = ! NewTable ;
return ! ( NewFile | | NewTable & & ! readTables ( ) ) ;
}
private bool readTables ( )
{
byte [ ] bitLength = new byte [ Compress . BC ] ;
byte [ ] table = new byte [ Compress . HUFF_TABLE_SIZE ] ;
if ( inAddr > readTop - 25 )
{
if ( ! unpReadBuf ( ) )
{
return ( false ) ;
}
}
AddBits ( ( 8 - inBit ) & 7 ) ;
2013-04-28 12:32:55 +01:00
long bitField = GetBits ( ) & unchecked ( ( int ) 0xffFFffFF ) ;
2013-04-07 10:58:58 +01:00
if ( ( bitField & 0x8000 ) ! = 0 )
{
unpBlockType = BlockTypes . BLOCK_PPM ;
return ( ppm . decodeInit ( this , ppmEscChar ) ) ;
}
unpBlockType = BlockTypes . BLOCK_LZ ;
prevLowDist = 0 ;
lowDistRepCount = 0 ;
if ( ( bitField & 0x4000 ) = = 0 )
{
2013-04-28 12:32:55 +01:00
Utility . Fill ( unpOldTable , ( byte ) 0 ) ; // memset(UnpOldTable,0,sizeof(UnpOldTable));
2013-04-07 10:58:58 +01:00
}
AddBits ( 2 ) ;
for ( int i = 0 ; i < Compress . BC ; i + + )
{
int length = ( Utility . URShift ( GetBits ( ) , 12 ) ) & 0xFF ;
AddBits ( 4 ) ;
if ( length = = 15 )
{
int zeroCount = ( Utility . URShift ( GetBits ( ) , 12 ) ) & 0xFF ;
AddBits ( 4 ) ;
if ( zeroCount = = 0 )
{
bitLength [ i ] = 15 ;
}
else
{
zeroCount + = 2 ;
while ( zeroCount - - > 0 & & i < bitLength . Length )
{
bitLength [ i + + ] = 0 ;
}
i - - ;
}
}
else
{
2013-04-28 12:32:55 +01:00
bitLength [ i ] = ( byte ) length ;
2013-04-07 10:58:58 +01:00
}
}
UnpackUtility . makeDecodeTables ( bitLength , 0 , BD , Compress . BC ) ;
int TableSize = Compress . HUFF_TABLE_SIZE ;
2013-04-28 12:32:55 +01:00
for ( int i = 0 ; i < TableSize ; )
2013-04-07 10:58:58 +01:00
{
if ( inAddr > readTop - 5 )
{
if ( ! unpReadBuf ( ) )
{
return ( false ) ;
}
}
int Number = this . decodeNumber ( BD ) ;
if ( Number < 16 )
{
2013-04-28 12:32:55 +01:00
table [ i ] = ( byte ) ( ( Number + unpOldTable [ i ] ) & 0xf ) ;
2013-04-07 10:58:58 +01:00
i + + ;
}
else if ( Number < 18 )
{
int N ;
if ( Number = = 16 )
{
N = ( Utility . URShift ( GetBits ( ) , 13 ) ) + 3 ;
AddBits ( 3 ) ;
}
else
{
N = ( Utility . URShift ( GetBits ( ) , 9 ) ) + 11 ;
AddBits ( 7 ) ;
}
while ( N - - > 0 & & i < TableSize )
{
table [ i ] = table [ i - 1 ] ;
i + + ;
}
}
else
{
int N ;
if ( Number = = 18 )
{
N = ( Utility . URShift ( GetBits ( ) , 13 ) ) + 3 ;
AddBits ( 3 ) ;
}
else
{
N = ( Utility . URShift ( GetBits ( ) , 9 ) ) + 11 ;
AddBits ( 7 ) ;
}
while ( N - - > 0 & & i < TableSize )
{
table [ i + + ] = 0 ;
}
}
}
tablesRead = true ;
if ( inAddr > readTop )
{
return ( false ) ;
}
UnpackUtility . makeDecodeTables ( table , 0 , LD , Compress . NC ) ;
UnpackUtility . makeDecodeTables ( table , Compress . NC , DD , Compress . DC ) ;
UnpackUtility . makeDecodeTables ( table , Compress . NC + Compress . DC , LDD , Compress . LDC ) ;
UnpackUtility . makeDecodeTables ( table , Compress . NC + Compress . DC + Compress . LDC , RD , Compress . RC ) ;
// memcpy(unpOldTable,table,sizeof(unpOldTable));
#if ! PORTABLE
Buffer . BlockCopy ( table , 0 , unpOldTable , 0 , unpOldTable . Length ) ;
#else
Array . Copy ( table , 0 , unpOldTable , 0 , unpOldTable . Length ) ;
#endif
return ( true ) ;
}
private bool readVMCode ( )
{
int FirstByte = GetBits ( ) > > 8 ;
AddBits ( 8 ) ;
int Length = ( FirstByte & 7 ) + 1 ;
if ( Length = = 7 )
{
Length = ( GetBits ( ) > > 8 ) + 7 ;
AddBits ( 8 ) ;
}
else if ( Length = = 8 )
{
Length = GetBits ( ) ;
AddBits ( 16 ) ;
}
//UPGRADE_ISSUE: The following fragment of code could not be parsed and was not converted. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1156'"
List < Byte > vmCode = new List < Byte > ( ) ;
for ( int I = 0 ; I < Length ; I + + )
{
if ( inAddr > = readTop - 1 & & ! unpReadBuf ( ) & & I < Length - 1 )
{
return ( false ) ;
}
2013-04-28 12:32:55 +01:00
vmCode . Add ( ( byte ) ( GetBits ( ) > > 8 ) ) ;
2013-04-07 10:58:58 +01:00
AddBits ( 8 ) ;
}
return ( addVMCode ( FirstByte , vmCode , Length ) ) ;
}
private bool readVMCodePPM ( )
{
int FirstByte = ppm . decodeChar ( ) ;
2013-04-28 12:32:55 +01:00
if ( ( int ) FirstByte = = - 1 )
2013-04-07 10:58:58 +01:00
{
return ( false ) ;
}
int Length = ( FirstByte & 7 ) + 1 ;
if ( Length = = 7 )
{
int B1 = ppm . decodeChar ( ) ;
if ( B1 = = - 1 )
{
return ( false ) ;
}
Length = B1 + 7 ;
}
else if ( Length = = 8 )
{
int B1 = ppm . decodeChar ( ) ;
if ( B1 = = - 1 )
{
return ( false ) ;
}
int B2 = ppm . decodeChar ( ) ;
if ( B2 = = - 1 )
{
return ( false ) ;
}
2013-04-28 12:32:55 +01:00
Length = B1 * 256 + B2 ;
2013-04-07 10:58:58 +01:00
}
//UPGRADE_ISSUE: The following fragment of code could not be parsed and was not converted. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1156'"
List < Byte > vmCode = new List < Byte > ( ) ;
for ( int I = 0 ; I < Length ; I + + )
{
int Ch = ppm . decodeChar ( ) ;
if ( Ch = = - 1 )
{
return ( false ) ;
}
2013-04-28 12:32:55 +01:00
vmCode . Add ( ( byte ) Ch ) ; // VMCode[I]=Ch;
2013-04-07 10:58:58 +01:00
}
return ( addVMCode ( FirstByte , vmCode , Length ) ) ;
}
private bool addVMCode ( int firstByte , List < byte > vmCode , int length )
{
BitInput Inp = new BitInput ( ) ;
Inp . InitBitInput ( ) ;
// memcpy(Inp.InBuf,Code,Min(BitInput::MAX_SIZE,CodeSize));
for ( int i = 0 ; i < Math . Min ( BitInput . MAX_SIZE , vmCode . Count ) ; i + + )
{
Inp . InBuf [ i ] = vmCode [ i ] ;
}
rarVM . init ( ) ;
int FiltPos ;
if ( ( firstByte & 0x80 ) ! = 0 )
{
FiltPos = RarVM . ReadData ( Inp ) ;
if ( FiltPos = = 0 )
{
initFilters ( ) ;
}
else
{
FiltPos - - ;
}
}
else
FiltPos = lastFilter ; // use the same filter as last time
if ( FiltPos > filters . Count | | FiltPos > oldFilterLengths . Count )
{
return ( false ) ;
}
lastFilter = FiltPos ;
bool NewFilter = ( FiltPos = = filters . Count ) ;
UnpackFilter StackFilter = new UnpackFilter ( ) ; // new filter for
// PrgStack
UnpackFilter Filter ;
if ( NewFilter )
2013-04-28 12:32:55 +01:00
// new filter code, never used before since VM reset
2013-04-07 10:58:58 +01:00
{
// too many different filters, corrupt archive
if ( FiltPos > 1024 )
{
return ( false ) ;
}
// Filters[Filters.Size()-1]=Filter=new UnpackFilter;
Filter = new UnpackFilter ( ) ;
filters . Add ( Filter ) ;
StackFilter . ParentFilter = filters . Count - 1 ;
oldFilterLengths . Add ( 0 ) ;
Filter . ExecCount = 0 ;
}
2013-04-28 12:32:55 +01:00
// filter was used in the past
2013-04-07 10:58:58 +01:00
else
{
Filter = filters [ FiltPos ] ;
StackFilter . ParentFilter = FiltPos ;
Filter . ExecCount = Filter . ExecCount + 1 ; // ->ExecCount++;
}
prgStack . Add ( StackFilter ) ;
StackFilter . ExecCount = Filter . ExecCount ; // ->ExecCount;
int BlockStart = RarVM . ReadData ( Inp ) ;
if ( ( firstByte & 0x40 ) ! = 0 )
{
BlockStart + = 258 ;
}
StackFilter . BlockStart = ( ( BlockStart + unpPtr ) & Compress . MAXWINMASK ) ;
if ( ( firstByte & 0x20 ) ! = 0 )
{
StackFilter . BlockLength = RarVM . ReadData ( Inp ) ;
}
else
{
StackFilter . BlockLength = FiltPos < oldFilterLengths . Count ? oldFilterLengths [ FiltPos ] : 0 ;
}
StackFilter . NextWindow = ( wrPtr ! = unpPtr ) & & ( ( wrPtr - unpPtr ) & Compress . MAXWINMASK ) < = BlockStart ;
// DebugLog("\nNextWindow: UnpPtr=%08x WrPtr=%08x
// BlockStart=%08x",UnpPtr,WrPtr,BlockStart);
oldFilterLengths [ FiltPos ] = StackFilter . BlockLength ;
// memset(StackFilter->Prg.InitR,0,sizeof(StackFilter->Prg.InitR));
Utility . Fill ( StackFilter . Program . InitR , 0 ) ;
StackFilter . Program . InitR [ 3 ] = RarVM . VM_GLOBALMEMADDR ; // StackFilter->Prg.InitR[3]=VM_GLOBALMEMADDR;
2013-04-28 12:32:55 +01:00
StackFilter . Program . InitR [ 4 ] = StackFilter . BlockLength ;
// StackFilter->Prg.InitR[4]=StackFilter->BlockLength;
2013-04-07 10:58:58 +01:00
StackFilter . Program . InitR [ 5 ] = StackFilter . ExecCount ; // StackFilter->Prg.InitR[5]=StackFilter->ExecCount;
if ( ( firstByte & 0x10 ) ! = 0 )
2013-04-28 12:32:55 +01:00
// set registers to optional parameters
// if any
2013-04-07 10:58:58 +01:00
{
int InitMask = Utility . URShift ( Inp . GetBits ( ) , 9 ) ;
Inp . AddBits ( 7 ) ;
for ( int I = 0 ; I < 7 ; I + + )
{
if ( ( InitMask & ( 1 < < I ) ) ! = 0 )
{
// StackFilter->Prg.InitR[I]=RarVM::ReadData(Inp);
StackFilter . Program . InitR [ I ] = RarVM . ReadData ( Inp ) ;
}
}
}
if ( NewFilter )
{
int VMCodeSize = RarVM . ReadData ( Inp ) ;
if ( VMCodeSize > = 0x10000 | | VMCodeSize = = 0 )
{
return ( false ) ;
}
byte [ ] VMCode = new byte [ VMCodeSize ] ;
for ( int I = 0 ; I < VMCodeSize ; I + + )
{
if ( Inp . Overflow ( 3 ) )
{
return ( false ) ;
}
2013-04-28 12:32:55 +01:00
VMCode [ I ] = ( byte ) ( Inp . GetBits ( ) > > 8 ) ;
2013-04-07 10:58:58 +01:00
Inp . AddBits ( 8 ) ;
}
// VM.Prepare(&VMCode[0],VMCodeSize,&Filter->Prg);
rarVM . prepare ( VMCode , VMCodeSize , Filter . Program ) ;
}
StackFilter . Program . AltCommands = Filter . Program . Commands ; // StackFilter->Prg.AltCmd=&Filter->Prg.Cmd[0];
2013-04-28 12:32:55 +01:00
StackFilter . Program . CommandCount = Filter . Program . CommandCount ;
// StackFilter->Prg.CmdCount=Filter->Prg.CmdCount;
2013-04-07 10:58:58 +01:00
int StaticDataSize = Filter . Program . StaticData . Count ;
if ( StaticDataSize > 0 & & StaticDataSize < RarVM . VM_GLOBALMEMSIZE )
{
// read statically defined data contained in DB commands
// StackFilter->Prg.StaticData.Add(StaticDataSize);
StackFilter . Program . StaticData = Filter . Program . StaticData ;
// memcpy(&StackFilter->Prg.StaticData[0],&Filter->Prg.StaticData[0],StaticDataSize);
}
if ( StackFilter . Program . GlobalData . Count < RarVM . VM_FIXEDGLOBALSIZE )
{
// StackFilter->Prg.GlobalData.Reset();
// StackFilter->Prg.GlobalData.Add(VM_FIXEDGLOBALSIZE);
StackFilter . Program . GlobalData . Clear ( ) ;
StackFilter . Program . GlobalData . SetSize ( RarVM . VM_FIXEDGLOBALSIZE ) ;
}
// byte *GlobalData=&StackFilter->Prg.GlobalData[0];
List < byte > globalData = StackFilter . Program . GlobalData ;
for ( int I = 0 ; I < 7 ; I + + )
{
2013-04-28 12:32:55 +01:00
rarVM . SetLowEndianValue ( globalData , I * 4 , StackFilter . Program . InitR [ I ] ) ;
2013-04-07 10:58:58 +01:00
}
// VM.SetLowEndianValue((uint
// *)&GlobalData[0x1c],StackFilter->BlockLength);
rarVM . SetLowEndianValue ( globalData , 0x1c , StackFilter . BlockLength ) ;
// VM.SetLowEndianValue((uint *)&GlobalData[0x20],0);
rarVM . SetLowEndianValue ( globalData , 0x20 , 0 ) ;
rarVM . SetLowEndianValue ( globalData , 0x24 , 0 ) ;
rarVM . SetLowEndianValue ( globalData , 0x28 , 0 ) ;
// VM.SetLowEndianValue((uint
// *)&GlobalData[0x2c],StackFilter->ExecCount);
rarVM . SetLowEndianValue ( globalData , 0x2c , StackFilter . ExecCount ) ;
// memset(&GlobalData[0x30],0,16);
for ( int i = 0 ; i < 16 ; i + + )
{
globalData [ 0x30 + i ] = 0x0 ;
}
if ( ( firstByte & 8 ) ! = 0 )
2013-04-28 12:32:55 +01:00
// put data block passed as parameter if any
2013-04-07 10:58:58 +01:00
{
if ( Inp . Overflow ( 3 ) )
{
return ( false ) ;
}
int DataSize = RarVM . ReadData ( Inp ) ;
if ( DataSize > RarVM . VM_GLOBALMEMSIZE - RarVM . VM_FIXEDGLOBALSIZE )
{
return ( false ) ;
}
int CurSize = StackFilter . Program . GlobalData . Count ;
if ( CurSize < DataSize + RarVM . VM_FIXEDGLOBALSIZE )
{
// StackFilter->Prg.GlobalData.Add(DataSize+VM_FIXEDGLOBALSIZE-CurSize);
StackFilter . Program . GlobalData . SetSize ( DataSize + RarVM . VM_FIXEDGLOBALSIZE - CurSize ) ;
}
int offset = RarVM . VM_FIXEDGLOBALSIZE ;
globalData = StackFilter . Program . GlobalData ;
for ( int I = 0 ; I < DataSize ; I + + )
{
if ( Inp . Overflow ( 3 ) )
{
return ( false ) ;
}
2013-04-28 12:32:55 +01:00
globalData [ offset + I ] = ( byte ) ( Utility . URShift ( Inp . GetBits ( ) , 8 ) ) ;
2013-04-07 10:58:58 +01:00
Inp . AddBits ( 8 ) ;
}
}
return ( true ) ;
}
private void ExecuteCode ( VMPreparedProgram Prg )
{
if ( Prg . GlobalData . Count > 0 )
{
// Prg->InitR[6]=int64to32(WrittenFileSize);
2013-04-28 12:32:55 +01:00
Prg . InitR [ 6 ] = ( int ) ( writtenFileSize ) ;
2013-04-07 10:58:58 +01:00
// rarVM.SetLowEndianValue((uint
// *)&Prg->GlobalData[0x24],int64to32(WrittenFileSize));
2013-04-28 12:32:55 +01:00
rarVM . SetLowEndianValue ( Prg . GlobalData , 0x24 , ( int ) writtenFileSize ) ;
2013-04-07 10:58:58 +01:00
// rarVM.SetLowEndianValue((uint
// *)&Prg->GlobalData[0x28],int64to32(WrittenFileSize>>32));
2013-04-28 12:32:55 +01:00
rarVM . SetLowEndianValue ( Prg . GlobalData , 0x28 , ( int ) ( Utility . URShift ( writtenFileSize , 32 ) ) ) ;
2013-04-07 10:58:58 +01:00
rarVM . execute ( Prg ) ;
}
}
public void cleanUp ( )
{
if ( ppm ! = null )
{
SubAllocator allocator = ppm . SubAlloc ;
if ( allocator ! = null )
{
allocator . stopSubAllocator ( ) ;
}
}
}
}
}