Exemple #1
0
        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);
        }
Exemple #2
0
        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);
        }
Exemple #3
0
        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;
        }
Exemple #4
0
        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();
        }
Exemple #5
0
        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);
        }