1 #include "rar.hpp"
2 
3 #include "coder.cpp"
4 #include "suballoc.cpp"
5 #include "model.cpp"
6 #ifndef SFX_MODULE
7 #include "unpack15.cpp"
8 #include "unpack20.cpp"
9 #endif
10 
Unpack(ComprDataIO * DataIO)11 Unpack::Unpack(ComprDataIO *DataIO)
12 {
13   UnpIO=DataIO;
14   Window=NULL;
15   ExternalWindow=false;
16   Suspended=false;
17   UnpAllBuf=false;
18   UnpSomeRead=false;
19 }
20 
21 
~Unpack()22 Unpack::~Unpack()
23 {
24   if (Window!=NULL && !ExternalWindow)
25     delete[] Window;
26   InitFilters();
27 }
28 
29 
Init(byte * Window)30 void Unpack::Init(byte *Window)
31 {
32   if (Window==NULL)
33   {
34     Unpack::Window=new byte[MAXWINSIZE];
35 #ifndef ALLOW_EXCEPTIONS
36     if (Unpack::Window==NULL)
37       ErrHandler.MemoryError();
38 #endif
39   }
40   else
41   {
42     Unpack::Window=Window;
43     ExternalWindow=true;
44   }
45   UnpInitData(false);
46 }
47 
48 
DoUnpack(int Method,bool Solid)49 void Unpack::DoUnpack(int Method,bool Solid)
50 {
51   switch(Method)
52   {
53 #ifndef SFX_MODULE
54     case 15:
55       Unpack15(Solid);
56       break;
57     case 20:
58     case 26:
59       Unpack20(Solid);
60       break;
61 #endif
62     case 29:
63       Unpack29(Solid);
64       break;
65   }
66 }
67 
68 
InsertOldDist(unsigned int Distance)69 inline void Unpack::InsertOldDist(unsigned int Distance)
70 {
71   OldDist[3]=OldDist[2];
72   OldDist[2]=OldDist[1];
73   OldDist[1]=OldDist[0];
74   OldDist[0]=Distance;
75 }
76 
77 
InsertLastMatch(unsigned int Length,unsigned int Distance)78 inline void Unpack::InsertLastMatch(unsigned int Length,unsigned int Distance)
79 {
80   LastDist=Distance;
81   LastLength=Length;
82 }
83 
84 
CopyString(unsigned int Length,unsigned int Distance)85 void Unpack::CopyString(unsigned int Length,unsigned int Distance)
86 {
87   unsigned int DestPtr=UnpPtr-Distance;
88   if (DestPtr<MAXWINSIZE-260 && UnpPtr<MAXWINSIZE-260)
89   {
90     Window[UnpPtr++]=Window[DestPtr++];
91     while (--Length>0)
92       Window[UnpPtr++]=Window[DestPtr++];
93   }
94   else
95     while (Length--)
96     {
97       Window[UnpPtr]=Window[DestPtr++ & MAXWINMASK];
98       UnpPtr=(UnpPtr+1) & MAXWINMASK;
99     }
100 }
101 
102 
DecodeNumber(struct Decode * Dec)103 int Unpack::DecodeNumber(struct Decode *Dec)
104 {
105   unsigned int Bits;
106   unsigned int BitField=getbits() & 0xfffe;
107   if (BitField<Dec->DecodeLen[8])
108     if (BitField<Dec->DecodeLen[4])
109       if (BitField<Dec->DecodeLen[2])
110         if (BitField<Dec->DecodeLen[1])
111           Bits=1;
112         else
113           Bits=2;
114       else
115         if (BitField<Dec->DecodeLen[3])
116           Bits=3;
117         else
118           Bits=4;
119     else
120       if (BitField<Dec->DecodeLen[6])
121         if (BitField<Dec->DecodeLen[5])
122           Bits=5;
123         else
124           Bits=6;
125       else
126         if (BitField<Dec->DecodeLen[7])
127           Bits=7;
128         else
129           Bits=8;
130   else
131     if (BitField<Dec->DecodeLen[12])
132       if (BitField<Dec->DecodeLen[10])
133         if (BitField<Dec->DecodeLen[9])
134           Bits=9;
135         else
136           Bits=10;
137       else
138         if (BitField<Dec->DecodeLen[11])
139           Bits=11;
140         else
141           Bits=12;
142     else
143       if (BitField<Dec->DecodeLen[14])
144         if (BitField<Dec->DecodeLen[13])
145           Bits=13;
146         else
147           Bits=14;
148       else
149         Bits=15;
150 
151   addbits(Bits);
152   unsigned int N=Dec->DecodePos[Bits]+((BitField-Dec->DecodeLen[Bits-1])>>(16-Bits));
153   if (N>=Dec->MaxNum)
154     N=0;
155   return(Dec->DecodeNum[N]);
156 }
157 
158 
Unpack29(bool Solid)159 void Unpack::Unpack29(bool Solid)
160 {
161   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};
162   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};
163   static int DDecode[DC];
164   static byte DBits[DC];
165   static int DBitLengthCounts[]= {4,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,14,0,12};
166   static unsigned char SDDecode[]={0,4,8,16,32,64,128,192};
167   static unsigned char SDBits[]=  {2,2,3, 4, 5, 6,  6,  6};
168   unsigned int Bits;
169 
170   if (DDecode[1]==0)
171   {
172     int Dist=0,BitLength=0,Slot=0;
173     for (int I=0;I<sizeof(DBitLengthCounts)/sizeof(DBitLengthCounts[0]);I++,BitLength++)
174       for (int J=0;J<DBitLengthCounts[I];J++,Slot++,Dist+=(1<<BitLength))
175       {
176         DDecode[Slot]=Dist;
177         DBits[Slot]=BitLength;
178       }
179   }
180 
181   FileExtracted=true;
182 
183   if (!Suspended)
184   {
185     UnpInitData(Solid);
186     if (!UnpReadBuf())
187       return;
188     if ((!Solid || !TablesRead) && !ReadTables())
189       return;
190   }
191 
192   if (PPMError)
193     return;
194 
195   while (true)
196   {
197     UnpPtr&=MAXWINMASK;
198 
199     if (InAddr>ReadBorder)
200     {
201       if (!UnpReadBuf())
202         break;
203     }
204     if (((WrPtr-UnpPtr) & MAXWINMASK)<260 && WrPtr!=UnpPtr)
205     {
206       UnpWriteBuf();
207       if (WrittenFileSize>DestUnpSize)
208         return;
209       if (Suspended)
210       {
211         FileExtracted=false;
212         return;
213       }
214     }
215     if (UnpBlockType==BLOCK_PPM)
216     {
217       int Ch=PPM.DecodeChar();
218       if (Ch==-1)
219       {
220         PPMError=true;
221         break;
222       }
223       if (Ch==PPMEscChar)
224       {
225         int NextCh=PPM.DecodeChar();
226         if (NextCh==0)
227         {
228           if (!ReadTables())
229             break;
230           continue;
231         }
232         if (NextCh==2 || NextCh==-1)
233           break;
234         if (NextCh==3)
235         {
236           if (!ReadVMCodePPM())
237             break;
238           continue;
239         }
240         if (NextCh==4)
241         {
242           unsigned int Distance=0,Length;
243           bool Failed=false;
244           for (int I=0;I<4 && !Failed;I++)
245           {
246             int Ch=PPM.DecodeChar();
247             if (Ch==-1)
248               Failed=true;
249             else
250               if (I==3)
251                 Length=(byte)Ch;
252               else
253                 Distance=(Distance<<8)+(byte)Ch;
254           }
255           if (Failed)
256             break;
257           CopyString(Length+32,Distance+2);
258           continue;
259         }
260         if (NextCh==5)
261         {
262           int Length=PPM.DecodeChar();
263           if (Length==-1)
264             break;
265           CopyString(Length+4,1);
266           continue;
267         }
268       }
269       Window[UnpPtr++]=Ch;
270       continue;
271     }
272 
273     int Number=DecodeNumber((struct Decode *)&LD);
274     if (Number<256)
275     {
276       Window[UnpPtr++]=(byte)Number;
277       continue;
278     }
279     if (Number>=271)
280     {
281       int Length=LDecode[Number-=271]+3;
282       if ((Bits=LBits[Number])>0)
283       {
284         Length+=getbits()>>(16-Bits);
285         addbits(Bits);
286       }
287 
288       int DistNumber=DecodeNumber((struct Decode *)&DD);
289       unsigned int Distance=DDecode[DistNumber]+1;
290       if ((Bits=DBits[DistNumber])>0)
291       {
292         if (DistNumber>9)
293         {
294           if (Bits>4)
295           {
296             Distance+=((getbits()>>(20-Bits))<<4);
297             addbits(Bits-4);
298           }
299           if (LowDistRepCount>0)
300           {
301             LowDistRepCount--;
302             Distance+=PrevLowDist;
303           }
304           else
305           {
306             int LowDist=DecodeNumber((struct Decode *)&LDD);
307             if (LowDist==16)
308             {
309               LowDistRepCount=LOW_DIST_REP_COUNT-1;
310               Distance+=PrevLowDist;
311             }
312             else
313             {
314               Distance+=LowDist;
315               PrevLowDist=LowDist;
316             }
317           }
318         }
319         else
320         {
321           Distance+=getbits()>>(16-Bits);
322           addbits(Bits);
323         }
324       }
325 
326       if (Distance>=0x2000)
327       {
328         Length++;
329         if (Distance>=0x40000L)
330           Length++;
331       }
332 
333       InsertOldDist(Distance);
334       InsertLastMatch(Length,Distance);
335       CopyString(Length,Distance);
336       continue;
337     }
338     if (Number==256)
339     {
340       if (!ReadEndOfBlock())
341         break;
342       continue;
343     }
344     if (Number==257)
345     {
346       if (!ReadVMCode())
347         break;
348       continue;
349     }
350     if (Number==258)
351     {
352       if (LastLength!=0)
353         CopyString(LastLength,LastDist);
354       continue;
355     }
356     if (Number<263)
357     {
358       int DistNum=Number-259;
359       unsigned int Distance=OldDist[DistNum];
360       for (int I=DistNum;I>0;I--)
361         OldDist[I]=OldDist[I-1];
362       OldDist[0]=Distance;
363 
364       int LengthNumber=DecodeNumber((struct Decode *)&RD);
365       int Length=LDecode[LengthNumber]+2;
366       if ((Bits=LBits[LengthNumber])>0)
367       {
368         Length+=getbits()>>(16-Bits);
369         addbits(Bits);
370       }
371       InsertLastMatch(Length,Distance);
372       CopyString(Length,Distance);
373       continue;
374     }
375     if (Number<272)
376     {
377       unsigned int Distance=SDDecode[Number-=263]+1;
378       if ((Bits=SDBits[Number])>0)
379       {
380         Distance+=getbits()>>(16-Bits);
381         addbits(Bits);
382       }
383       InsertOldDist(Distance);
384       InsertLastMatch(2,Distance);
385       CopyString(2,Distance);
386       continue;
387     }
388   }
389   UnpWriteBuf();
390 }
391 
392 
ReadEndOfBlock()393 bool Unpack::ReadEndOfBlock()
394 {
395   unsigned int BitField=getbits();
396   bool NewTable,NewFile=false;
397   if (BitField & 0x8000)
398   {
399     NewTable=true;
400     addbits(1);
401   }
402   else
403   {
404     NewFile=true;
405     NewTable=(BitField & 0x4000);
406     addbits(2);
407   }
408   TablesRead=!NewTable;
409   return !(NewFile || NewTable && !ReadTables());
410 }
411 
412 
ReadVMCode()413 bool Unpack::ReadVMCode()
414 {
415   unsigned int FirstByte=getbits()>>8;
416   addbits(8);
417   int Length=(FirstByte & 7)+1;
418   if (Length==7)
419   {
420     Length=(getbits()>>8)+7;
421     addbits(8);
422   }
423   else
424     if (Length==8)
425     {
426       Length=getbits();
427       addbits(16);
428     }
429   Array<byte> VMCode(Length);
430   for (int I=0;I<Length;I++)
431   {
432     if (InAddr>=ReadTop-1 && !UnpReadBuf() && I<Length-1)
433       return(false);
434     VMCode[I]=getbits()>>8;
435     addbits(8);
436   }
437   return(AddVMCode(FirstByte,&VMCode[0],Length));
438 }
439 
440 
ReadVMCodePPM()441 bool Unpack::ReadVMCodePPM()
442 {
443   unsigned int FirstByte=PPM.DecodeChar();
444   if ((int)FirstByte==-1)
445     return(false);
446   int Length=(FirstByte & 7)+1;
447   if (Length==7)
448   {
449     int B1=PPM.DecodeChar();
450     if (B1==-1)
451       return(false);
452     Length=B1+7;
453   }
454   else
455     if (Length==8)
456     {
457       int B1=PPM.DecodeChar();
458       if (B1==-1)
459         return(false);
460       int B2=PPM.DecodeChar();
461       if (B2==-1)
462         return(false);
463       Length=B1*256+B2;
464     }
465   Array<byte> VMCode(Length);
466   for (int I=0;I<Length;I++)
467   {
468     int Ch=PPM.DecodeChar();
469     if (Ch==-1)
470       return(false);
471     VMCode[I]=Ch;
472   }
473   return(AddVMCode(FirstByte,&VMCode[0],Length));
474 }
475 
476 
AddVMCode(unsigned int FirstByte,byte * Code,int CodeSize)477 bool Unpack::AddVMCode(unsigned int FirstByte,byte *Code,int CodeSize)
478 {
479   BitInput Inp;
480   Inp.InitBitInput();
481   memcpy(Inp.InBuf,Code,Min(BitInput::MAX_SIZE,CodeSize));
482   VM.Init();
483 
484   uint FiltPos;
485   if (FirstByte & 0x80)
486   {
487     FiltPos=RarVM::ReadData(Inp);
488     if (FiltPos==0)
489       InitFilters();
490     else
491       FiltPos--;
492   }
493   else
494     FiltPos=LastFilter;
495   if (FiltPos>Filters.Size() || FiltPos>OldFilterLengths.Size())
496     return(false);
497   LastFilter=FiltPos;
498   bool NewFilter=(FiltPos==Filters.Size());
499 
500   UnpackFilter *Filter;
501   if (NewFilter)
502   {
503     Filters.Add(1);
504     Filters[Filters.Size()-1]=Filter=new UnpackFilter;
505     OldFilterLengths.Add(1);
506     Filter->ExecCount=0;
507   }
508   else
509   {
510     Filter=Filters[FiltPos];
511     Filter->ExecCount++;
512   }
513 
514   UnpackFilter *StackFilter=new UnpackFilter;
515 
516   int EmptyCount=0;
517   for (int I=0;I<PrgStack.Size();I++)
518   {
519     PrgStack[I-EmptyCount]=PrgStack[I];
520     if (PrgStack[I]==NULL)
521       EmptyCount++;
522     if (EmptyCount>0)
523       PrgStack[I]=NULL;
524   }
525   if (EmptyCount==0)
526   {
527     PrgStack.Add(1);
528     EmptyCount=1;
529   }
530   int StackPos=PrgStack.Size()-EmptyCount;
531   PrgStack[StackPos]=StackFilter;
532   StackFilter->ExecCount=Filter->ExecCount;
533 
534   uint BlockStart=RarVM::ReadData(Inp);
535   if (FirstByte & 0x40)
536     BlockStart+=258;
537   StackFilter->BlockStart=(BlockStart+UnpPtr)&MAXWINMASK;
538   if (FirstByte & 0x20)
539     StackFilter->BlockLength=RarVM::ReadData(Inp);
540   else
541     StackFilter->BlockLength=FiltPos<OldFilterLengths.Size() ? OldFilterLengths[FiltPos]:0;
542   StackFilter->NextWindow=WrPtr!=UnpPtr && ((WrPtr-UnpPtr)&MAXWINMASK)<=BlockStart;
543 
544 //  DebugLog("\nNextWindow: UnpPtr=%08x WrPtr=%08x BlockStart=%08x",UnpPtr,WrPtr,BlockStart);
545 
546   OldFilterLengths[FiltPos]=StackFilter->BlockLength;
547 
548   memset(StackFilter->Prg.InitR,0,sizeof(StackFilter->Prg.InitR));
549   StackFilter->Prg.InitR[3]=VM_GLOBALMEMADDR;
550   StackFilter->Prg.InitR[4]=StackFilter->BlockLength;
551   StackFilter->Prg.InitR[5]=StackFilter->ExecCount;
552   if (FirstByte & 0x10)
553   {
554     unsigned int InitMask=Inp.fgetbits()>>9;
555     Inp.faddbits(7);
556     for (int I=0;I<7;I++)
557       if (InitMask & (1<<I))
558         StackFilter->Prg.InitR[I]=RarVM::ReadData(Inp);
559   }
560   if (NewFilter)
561   {
562     uint VMCodeSize=RarVM::ReadData(Inp);
563     if (VMCodeSize>=0x10000 || VMCodeSize==0)
564       return(false);
565     Array<byte> VMCode(VMCodeSize);
566     for (int I=0;I<VMCodeSize;I++)
567     {
568       VMCode[I]=Inp.fgetbits()>>8;
569       Inp.faddbits(8);
570     }
571     VM.Prepare(&VMCode[0],VMCodeSize,&Filter->Prg);
572   }
573   StackFilter->Prg.AltCmd=&Filter->Prg.Cmd[0];
574   StackFilter->Prg.CmdCount=Filter->Prg.CmdCount;
575 
576   int StaticDataSize=Filter->Prg.StaticData.Size();
577   if (StaticDataSize>0 && StaticDataSize<VM_GLOBALMEMSIZE)
578   {
579     StackFilter->Prg.StaticData.Add(StaticDataSize);
580     memcpy(&StackFilter->Prg.StaticData[0],&Filter->Prg.StaticData[0],StaticDataSize);
581   }
582 
583   if (StackFilter->Prg.GlobalData.Size()<VM_FIXEDGLOBALSIZE)
584   {
585     StackFilter->Prg.GlobalData.Reset();
586     StackFilter->Prg.GlobalData.Add(VM_FIXEDGLOBALSIZE);
587   }
588   byte *GlobalData=&StackFilter->Prg.GlobalData[0];
589   for (int I=0;I<7;I++)
590     VM.SetValue((uint *)&GlobalData[I*4],StackFilter->Prg.InitR[I]);
591   VM.SetValue((uint *)&GlobalData[0x1c],StackFilter->BlockLength);
592   VM.SetValue((uint *)&GlobalData[0x20],0);
593   VM.SetValue((uint *)&GlobalData[0x2c],StackFilter->ExecCount);
594   memset(&GlobalData[0x30],0,16);
595 
596   if (FirstByte & 8)
597   {
598     uint DataSize=RarVM::ReadData(Inp);
599     if (DataSize>=0x10000)
600       return(false);
601     unsigned int CurSize=StackFilter->Prg.GlobalData.Size();
602     if (CurSize<DataSize+VM_FIXEDGLOBALSIZE)
603       StackFilter->Prg.GlobalData.Add(DataSize+VM_FIXEDGLOBALSIZE-CurSize);
604     byte *GlobalData=&StackFilter->Prg.GlobalData[VM_FIXEDGLOBALSIZE];
605     for (int I=0;I<DataSize;I++)
606     {
607       GlobalData[I]=Inp.fgetbits()>>8;
608       Inp.faddbits(8);
609     }
610   }
611   return(true);
612 }
613 
614 
UnpReadBuf()615 bool Unpack::UnpReadBuf()
616 {
617   int DataSize=ReadTop-InAddr;
618   if (DataSize<0)
619     return(false);
620   if (InAddr>BitInput::MAX_SIZE/2)
621   {
622     if (DataSize>0)
623       memmove(InBuf,InBuf+InAddr,DataSize);
624     InAddr=0;
625     ReadTop=DataSize;
626   }
627   else
628     DataSize=ReadTop;
629   int ReadCode=UnpIO->UnpRead(InBuf+DataSize,(BitInput::MAX_SIZE-DataSize)&~0xf);
630   if (ReadCode>0)
631     ReadTop+=ReadCode;
632   ReadBorder=ReadTop-30;
633   return(ReadCode!=-1);
634 }
635 
636 
UnpWriteBuf()637 void Unpack::UnpWriteBuf()
638 {
639   unsigned int WrittenBorder=WrPtr;
640   unsigned int WriteSize=(UnpPtr-WrittenBorder)&MAXWINMASK;
641   for (int I=0;I<PrgStack.Size();I++)
642   {
643     UnpackFilter *flt=PrgStack[I];
644     if (flt==NULL)
645       continue;
646     if (flt->NextWindow)
647     {
648       flt->NextWindow=false;
649       continue;
650     }
651     unsigned int BlockStart=flt->BlockStart;
652     unsigned int BlockLength=flt->BlockLength;
653     if (((BlockStart-WrittenBorder)&MAXWINMASK)<WriteSize)
654     {
655       if (WrittenBorder!=BlockStart)
656       {
657         UnpWriteArea(WrittenBorder,BlockStart);
658         WrittenBorder=BlockStart;
659         WriteSize=(UnpPtr-WrittenBorder)&MAXWINMASK;
660       }
661       if (BlockLength<=WriteSize)
662       {
663         unsigned int BlockEnd=(BlockStart+BlockLength)&MAXWINMASK;
664         if (BlockStart<BlockEnd || BlockEnd==0)
665           VM.SetMemory(0,Window+BlockStart,BlockLength);
666         else
667         {
668           unsigned int FirstPartLength=MAXWINSIZE-BlockStart;
669           VM.SetMemory(0,Window+BlockStart,FirstPartLength);
670           VM.SetMemory(FirstPartLength,Window,BlockEnd);
671         }
672         VM_PreparedProgram *Prg=&flt->Prg;
673         ExecuteCode(Prg);
674 
675         byte *FilteredData=Prg->FilteredData;
676         unsigned int FilteredDataSize=Prg->FilteredDataSize;
677 
678         delete PrgStack[I];
679         PrgStack[I]=NULL;
680         while (I+1<PrgStack.Size())
681         {
682           UnpackFilter *NextFilter=PrgStack[I+1];
683           if (NextFilter==NULL || NextFilter->BlockStart!=BlockStart ||
684               NextFilter->BlockLength!=FilteredDataSize || NextFilter->NextWindow)
685             break;
686           VM.SetMemory(0,FilteredData,FilteredDataSize);
687           VM_PreparedProgram *NextPrg=&PrgStack[I+1]->Prg;
688           ExecuteCode(NextPrg);
689           FilteredData=NextPrg->FilteredData;
690           FilteredDataSize=NextPrg->FilteredDataSize;
691           I++;
692           delete PrgStack[I];
693           PrgStack[I]=NULL;
694         }
695         UnpIO->UnpWrite(FilteredData,FilteredDataSize);
696         UnpSomeRead=true;
697         WrittenFileSize+=FilteredDataSize;
698         WrittenBorder=BlockEnd;
699         WriteSize=(UnpPtr-WrittenBorder)&MAXWINMASK;
700       }
701       else
702       {
703         for (int J=I;J<PrgStack.Size();J++)
704         {
705           UnpackFilter *flt=PrgStack[J];
706           if (flt!=NULL && flt->NextWindow)
707             flt->NextWindow=false;
708         }
709         WrPtr=WrittenBorder;
710         return;
711       }
712     }
713   }
714 
715   UnpWriteArea(WrittenBorder,UnpPtr);
716   WrPtr=UnpPtr;
717 }
718 
719 
ExecuteCode(VM_PreparedProgram * Prg)720 void Unpack::ExecuteCode(VM_PreparedProgram *Prg)
721 {
722   if (Prg->GlobalData.Size()>0)
723   {
724     Prg->InitR[6]=int64to32(WrittenFileSize);
725     VM.SetValue((uint *)&Prg->GlobalData[0x24],int64to32(WrittenFileSize));
726     VM.SetValue((uint *)&Prg->GlobalData[0x28],int64to32(WrittenFileSize>>32));
727     VM.Execute(Prg);
728   }
729 }
730 
731 
UnpWriteArea(unsigned int StartPtr,unsigned int EndPtr)732 void Unpack::UnpWriteArea(unsigned int StartPtr,unsigned int EndPtr)
733 {
734   if (EndPtr!=StartPtr)
735     UnpSomeRead=true;
736   if (EndPtr<StartPtr)
737   {
738     UnpWriteData(&Window[StartPtr],-StartPtr & MAXWINMASK);
739     UnpWriteData(Window,EndPtr);
740     UnpAllBuf=true;
741   }
742   else
743     UnpWriteData(&Window[StartPtr],EndPtr-StartPtr);
744 }
745 
746 
UnpWriteData(byte * Data,int Size)747 void Unpack::UnpWriteData(byte *Data,int Size)
748 {
749   if (WrittenFileSize>=DestUnpSize)
750     return;
751   int WriteSize=Size;
752   Int64 LeftToWrite=DestUnpSize-WrittenFileSize;
753   if (WriteSize>LeftToWrite)
754     WriteSize=int64to32(LeftToWrite);
755   UnpIO->UnpWrite(Data,WriteSize);
756   WrittenFileSize+=Size;
757 }
758 
759 
ReadTables()760 bool Unpack::ReadTables()
761 {
762   byte BitLength[BC];
763   unsigned char Table[HUFF_TABLE_SIZE];
764   if (InAddr>ReadTop-25)
765     if (!UnpReadBuf())
766       return(false);
767   faddbits((8-InBit)&7);
768   unsigned int BitField=fgetbits();
769   if (BitField & 0x8000)
770   {
771     UnpBlockType=BLOCK_PPM;
772     return(PPM.DecodeInit(this,PPMEscChar));
773   }
774   UnpBlockType=BLOCK_LZ;
775 
776   PrevLowDist=0;
777   LowDistRepCount=0;
778 
779   if (!(BitField & 0x4000))
780     memset(UnpOldTable,0,sizeof(UnpOldTable));
781   faddbits(2);
782 
783   for (int I=0;I<BC;I++)
784   {
785     int Length=(byte)(fgetbits() >> 12);
786     faddbits(4);
787     if (Length==15)
788     {
789       int ZeroCount=(byte)(fgetbits() >> 12);
790       faddbits(4);
791       if (ZeroCount==0)
792         BitLength[I]=15;
793       else
794       {
795         ZeroCount+=2;
796         while (ZeroCount-- > 0 && I<sizeof(BitLength)/sizeof(BitLength[0]))
797           BitLength[I++]=0;
798         I--;
799       }
800     }
801     else
802       BitLength[I]=Length;
803   }
804   MakeDecodeTables(BitLength,(struct Decode *)&BD,BC);
805 
806   const int TableSize=HUFF_TABLE_SIZE;
807   for (int I=0;I<TableSize;)
808   {
809     if (InAddr>ReadTop-5)
810       if (!UnpReadBuf())
811         return(false);
812     int Number=DecodeNumber((struct Decode *)&BD);
813     if (Number<16)
814     {
815       Table[I]=(Number+UnpOldTable[I]) & 0xf;
816       I++;
817     }
818     else
819       if (Number<18)
820       {
821         int N;
822         if (Number==16)
823         {
824           N=(fgetbits() >> 13)+3;
825           faddbits(3);
826         }
827         else
828         {
829           N=(fgetbits() >> 9)+11;
830           faddbits(7);
831         }
832         while (N-- > 0 && I<TableSize)
833         {
834           Table[I]=Table[I-1];
835           I++;
836         }
837       }
838       else
839       {
840         int N;
841         if (Number==18)
842         {
843           N=(fgetbits() >> 13)+3;
844           faddbits(3);
845         }
846         else
847         {
848           N=(fgetbits() >> 9)+11;
849           faddbits(7);
850         }
851         while (N-- > 0 && I<TableSize)
852           Table[I++]=0;
853       }
854   }
855   TablesRead=true;
856   if (InAddr>ReadTop)
857     return(false);
858   MakeDecodeTables(&Table[0],(struct Decode *)&LD,NC);
859   MakeDecodeTables(&Table[NC],(struct Decode *)&DD,DC);
860   MakeDecodeTables(&Table[NC+DC],(struct Decode *)&LDD,LDC);
861   MakeDecodeTables(&Table[NC+DC+LDC],(struct Decode *)&RD,RC);
862   memcpy(UnpOldTable,Table,sizeof(UnpOldTable));
863   return(true);
864 }
865 
866 
UnpInitData(int Solid)867 void Unpack::UnpInitData(int Solid)
868 {
869   if (!Solid)
870   {
871     TablesRead=false;
872     memset(OldDist,0,sizeof(OldDist));
873     OldDistPtr=0;
874     LastDist=LastLength=0;
875 //    memset(Window,0,MAXWINSIZE);
876     memset(UnpOldTable,0,sizeof(UnpOldTable));
877     UnpPtr=WrPtr=0;
878     PPMEscChar=2;
879 
880     InitFilters();
881   }
882   InitBitInput();
883   PPMError=false;
884   WrittenFileSize=0;
885   ReadTop=0;
886   ReadBorder=0;
887 #ifndef SFX_MODULE
888   UnpInitData20(Solid);
889 #endif
890 }
891 
892 
InitFilters()893 void Unpack::InitFilters()
894 {
895   OldFilterLengths.Reset();
896   LastFilter=0;
897 
898   for (int I=0;I<Filters.Size();I++)
899     delete Filters[I];
900   Filters.Reset();
901   for (int I=0;I<PrgStack.Size();I++)
902     delete PrgStack[I];
903   PrgStack.Reset();
904 }
905 
906 
MakeDecodeTables(unsigned char * LenTab,struct Decode * Dec,int Size)907 void Unpack::MakeDecodeTables(unsigned char *LenTab,struct Decode *Dec,int Size)
908 {
909   int LenCount[16],TmpPos[16],I;
910   long M,N;
911   memset(LenCount,0,sizeof(LenCount));
912   memset(Dec->DecodeNum,0,Size*sizeof(*Dec->DecodeNum));
913   for (I=0;I<Size;I++)
914     LenCount[LenTab[I] & 0xF]++;
915 
916   LenCount[0]=0;
917   for (TmpPos[0]=Dec->DecodePos[0]=Dec->DecodeLen[0]=0,N=0,I=1;I<16;I++)
918   {
919     N=2*(N+LenCount[I]);
920     M=N<<(15-I);
921     if (M>0xFFFF)
922       M=0xFFFF;
923     Dec->DecodeLen[I]=(unsigned int)M;
924     TmpPos[I]=Dec->DecodePos[I]=Dec->DecodePos[I-1]+LenCount[I-1];
925   }
926 
927   for (I=0;I<Size;I++)
928     if (LenTab[I]!=0)
929       Dec->DecodeNum[TmpPos[LenTab[I] & 0xF]++]=I;
930   Dec->MaxNum=Size;
931 }
932