private bool ReadFilter(UnpackFilter Filter) { if (!Inp.ExternalBuffer && Inp.InAddr > ReadTop - 16) { if (!UnpReadBuf()) { return(false); } } Filter.uBlockStart = ReadFilterData(); Filter.uBlockLength = ReadFilterData(); if (Filter.BlockLength > MAX_FILTER_BLOCK_SIZE) { Filter.BlockLength = 0; } //Filter.Type=Inp.fgetbits()>>13; Filter.Type = (byte)(Inp.fgetbits() >> 13); Inp.faddbits(3); if (Filter.Type == (byte)FilterType.FILTER_DELTA) { //Filter.Channels=(Inp.fgetbits()>>11)+1; Filter.Channels = (byte)((Inp.fgetbits() >> 11) + 1); Inp.faddbits(5); } return(true); }
private bool AddFilter(UnpackFilter Filter) { if (Filters.Count >= MAX_UNPACK_FILTERS) { UnpWriteBuf(); // Write data, apply and flush filters. if (Filters.Count >= MAX_UNPACK_FILTERS) { InitFilters(); // Still too many filters, prevent excessive memory use. } } // If distance to filter start is that large that due to circular dictionary // mode now 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.uBlockStart = (uint)((Filter.BlockStart + UnpPtr) & MaxWinMask); Filters.Add(Filter); return(true); }
private void UnpWriteBuf() { int WrittenBorder = wrPtr; int WriteSize = (unpPtr - WrittenBorder) & PackDef.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) & PackDef.MAXWINMASK) < WriteSize) { if (WrittenBorder != BlockStart) { UnpWriteArea(WrittenBorder, BlockStart); WrittenBorder = BlockStart; WriteSize = (unpPtr - WrittenBorder) & PackDef.MAXWINMASK; } if (BlockLength <= WriteSize) { int BlockEnd = (BlockStart + BlockLength) & PackDef.MAXWINMASK; if (BlockStart < BlockEnd || BlockEnd == 0) { // VM.SetMemory(0,Window+BlockStart,BlockLength); rarVM.setMemory(0, window, BlockStart, BlockLength); } else { int FirstPartLength = PackDef.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++) { Prg.GlobalData[RarVM.VM_FIXEDGLOBALSIZE + i] = ParentPrg.GlobalData[RarVM.VM_FIXEDGLOBALSIZE + i]; } } 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++) { ParentPrg.GlobalData[RarVM.VM_FIXEDGLOBALSIZE + i] = Prg.GlobalData[RarVM.VM_FIXEDGLOBALSIZE + i]; } } else { ParentPrg.GlobalData.Clear(); } int FilteredDataOffset = Prg.FilteredDataOffset; int FilteredDataSize = Prg.FilteredDataSize; byte[] FilteredData = new byte[FilteredDataSize]; for (int i = 0; i < FilteredDataSize; i++) { FilteredData[i] = rarVM.Mem[FilteredDataOffset + i]; // Prg.GlobalData.get(FilteredDataOffset // + // i); } prgStack[I] = null; while (I + 1 < prgStack.Count) { UnpackFilter NextFilter = prgStack[I + 1]; if (NextFilter == null || NextFilter.BlockStart != BlockStart || NextFilter.BlockLength != FilteredDataSize || NextFilter.NextWindow) { break; } // apply several filters to same data block rarVM.setMemory(0, FilteredData, 0, FilteredDataSize); // .SetMemory(0,FilteredData,FilteredDataSize); 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++) { NextPrg.GlobalData[RarVM.VM_FIXEDGLOBALSIZE + i] = pPrg.GlobalData[RarVM.VM_FIXEDGLOBALSIZE + i]; } } 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++) { pPrg.GlobalData[RarVM.VM_FIXEDGLOBALSIZE + i] = NextPrg.GlobalData[RarVM.VM_FIXEDGLOBALSIZE + i]; } } 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) & PackDef.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; }
public void Unpack5(bool Solid) { FileExtracted = true; if (!Suspended) { UnpInitData(Solid); if (!UnpReadBuf()) { return; } // Check TablesRead5 to be sure that we read tables at least once // regardless of current block header TablePresent flag. // So we can safefly use these tables below. if (!ReadBlockHeader() || !ReadTables() || !TablesRead5) { 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() || !ReadTables()) { return; } } if (FileDone || !UnpReadBuf()) { break; } } if (((WriteBorder - UnpPtr) & MaxWinMask) < PackDef.MAX_LZ_MATCH + 3 && WriteBorder != UnpPtr) { UnpWriteBuf(); if (WrittenFileSize > DestUnpSize) { return; } if (Suspended) { FileExtracted = false; return; } } //uint MainSlot=DecodeNumber(Inp,LD); uint MainSlot = this.DecodeNumber(LD); if (MainSlot < 256) { // if (Fragmented) // FragWindow[UnpPtr++]=(byte)MainSlot; // else Window[UnpPtr++] = (byte)MainSlot; continue; } if (MainSlot >= 262) { uint Length = SlotToLength(MainSlot - 262); //uint DBits,Distance=1,DistSlot=DecodeNumber(Inp,&BlockTables.DD); int DBits; uint Distance = 1, DistSlot = this.DecodeNumber(DD); if (DistSlot < 4) { DBits = 0; Distance += DistSlot; } else { //DBits=DistSlot/2 - 1; DBits = (int)(DistSlot / 2 - 1); Distance += (2 | (DistSlot & 1)) << DBits; } if (DBits > 0) { if (DBits >= 4) { if (DBits > 4) { Distance += ((Inp.getbits() >> (36 - DBits)) << 4); Inp.AddBits(DBits - 4); } //uint LowDist=DecodeNumber(Inp,&BlockTables.LDD); uint LowDist = this.DecodeNumber(LDD); Distance += LowDist; } else { Distance += Inp.getbits() >> (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 = new UnpackFilter(); if (!ReadFilter(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]); { CopyString(LastLength, OldDistN(0)); } continue; } if (MainSlot < 262) { //uint DistNum=MainSlot-258; int DistNum = (int)(MainSlot - 258); //uint Distance=OldDist[DistNum]; uint Distance = OldDistN(DistNum); //for (uint I=DistNum;I>0;I--) for (int I = DistNum; I > 0; I--) //OldDistN[I]=OldDistN(I-1); { SetOldDistN(I, OldDistN(I - 1)); } //OldDistN[0]=Distance; SetOldDistN(0, Distance); uint LengthSlot = this.DecodeNumber(RD); uint Length = SlotToLength(LengthSlot); LastLength = Length; // if (Fragmented) // FragWindow.CopyString(Length,Distance,UnpPtr,MaxWinMask); // else CopyString(Length, Distance); continue; } } UnpWriteBuf(); }
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(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) // new filter code, never used before since VM reset { // 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; } // filter was used in the past 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) & PackDef.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) & PackDef.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; StackFilter.Program.InitR[4] = StackFilter.BlockLength; // StackFilter->Prg.InitR[4]=StackFilter->BlockLength; StackFilter.Program.InitR[5] = StackFilter.ExecCount; // StackFilter->Prg.InitR[5]=StackFilter->ExecCount; if ((firstByte & 0x10) != 0) // set registers to optional parameters // if any { 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); } VMCode[I] = (byte)(Inp.GetBits() >> 8); 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]; StackFilter.Program.CommandCount = Filter.Program.CommandCount; // StackFilter->Prg.CmdCount=Filter->Prg.CmdCount; 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++) { rarVM.SetLowEndianValue(globalData, I * 4, StackFilter.Program.InitR[I]); } // 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) // put data block passed as parameter if any { 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); } globalData[offset + I] = (byte)(Utility.URShift(Inp.GetBits(), 8)); Inp.AddBits(8); } } return(true); }