Unpack.cs 43 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270
  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using SharpCompress.Common;
  5. using SharpCompress.Common.Rar.Headers;
  6. using SharpCompress.Compressors.PPMd.H;
  7. using SharpCompress.Compressors.Rar.UnpackV1.Decode;
  8. using SharpCompress.Compressors.Rar.UnpackV1.PPM;
  9. using SharpCompress.Compressors.Rar.VM;
  10. namespace SharpCompress.Compressors.Rar.UnpackV1
  11. {
  12. internal sealed partial class Unpack : BitInput, IRarUnpack
  13. {
  14. private readonly BitInput Inp;
  15. public Unpack() {
  16. // to ease in porting Unpack50.cs
  17. Inp = this;
  18. }
  19. public bool FileExtracted { get; private set; }
  20. public long DestSize
  21. {
  22. get => destUnpSize;
  23. set
  24. {
  25. destUnpSize = value;
  26. FileExtracted = false;
  27. }
  28. }
  29. public bool Suspended {
  30. get => suspended;
  31. set => suspended = value;
  32. }
  33. public int Char
  34. {
  35. get
  36. {
  37. if (inAddr > MAX_SIZE - 30)
  38. {
  39. unpReadBuf();
  40. }
  41. return (InBuf[inAddr++] & 0xff);
  42. }
  43. }
  44. public int PpmEscChar { get; set; }
  45. private readonly ModelPpm ppm = new ModelPpm();
  46. private readonly RarVM rarVM = new RarVM();
  47. // Filters code, one entry per filter
  48. private readonly List<UnpackFilter> filters = new List<UnpackFilter>();
  49. // Filters stack, several entrances of same filter are possible
  50. private readonly List<UnpackFilter> prgStack = new List<UnpackFilter>();
  51. // lengths of preceding blocks, one length per filter. Used to reduce size
  52. // required to write block length if lengths are repeating
  53. private readonly List<int> oldFilterLengths = new List<int>();
  54. private int lastFilter;
  55. private bool tablesRead;
  56. private readonly byte[] unpOldTable = new byte[PackDef.HUFF_TABLE_SIZE];
  57. private BlockTypes unpBlockType;
  58. //private bool externalWindow;
  59. private long writtenFileSize;
  60. private bool ppmError;
  61. private int prevLowDist;
  62. private int lowDistRepCount;
  63. private static readonly int[] DBitLengthCounts = {4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 14, 0, 12};
  64. private FileHeader fileHeader;
  65. private void Init(byte[] window)
  66. {
  67. if (window == null)
  68. {
  69. this.window = new byte[PackDef.MAXWINSIZE];
  70. }
  71. else
  72. {
  73. this.window = window;
  74. //externalWindow = true;
  75. }
  76. inAddr = 0;
  77. UnpInitData(false);
  78. }
  79. public void DoUnpack(FileHeader fileHeader, Stream readStream, Stream writeStream)
  80. {
  81. destUnpSize = fileHeader.UncompressedSize;
  82. this.fileHeader = fileHeader;
  83. this.readStream = readStream;
  84. this.writeStream = writeStream;
  85. if (!fileHeader.IsSolid)
  86. {
  87. Init(null);
  88. }
  89. suspended = false;
  90. DoUnpack();
  91. }
  92. public void DoUnpack()
  93. {
  94. if (fileHeader.CompressionMethod == 0)
  95. {
  96. UnstoreFile();
  97. return;
  98. }
  99. switch (fileHeader.CompressionAlgorithm)
  100. {
  101. case 15: // rar 1.5 compression
  102. unpack15(fileHeader.IsSolid);
  103. break;
  104. case 20: // rar 2.x compression
  105. case 26: // files larger than 2GB
  106. unpack20(fileHeader.IsSolid);
  107. break;
  108. case 29: // rar 3.x compression
  109. case 36: // alternative hash
  110. Unpack29(fileHeader.IsSolid);
  111. break;
  112. case 50: // rar 5.x compression
  113. Unpack5(fileHeader.IsSolid);
  114. break;
  115. default:
  116. throw new InvalidFormatException("unknown rar compression version " + fileHeader.CompressionAlgorithm);
  117. }
  118. }
  119. private void UnstoreFile()
  120. {
  121. byte[] buffer = new byte[0x10000];
  122. while (true)
  123. {
  124. int code = readStream.Read(buffer, 0, (int)Math.Min(buffer.Length, destUnpSize));
  125. if (code == 0 || code == -1)
  126. {
  127. break;
  128. }
  129. code = code < destUnpSize ? code : (int)destUnpSize;
  130. writeStream.Write(buffer, 0, code);
  131. if (destUnpSize >= 0)
  132. {
  133. destUnpSize -= code;
  134. }
  135. if (suspended)
  136. {
  137. return;
  138. }
  139. }
  140. }
  141. private void Unpack29(bool solid)
  142. {
  143. int[] DDecode = new int[PackDef.DC];
  144. byte[] DBits = new byte[PackDef.DC];
  145. int Bits;
  146. if (DDecode[1] == 0)
  147. {
  148. int Dist = 0, BitLength = 0, Slot = 0;
  149. for (int I = 0; I < DBitLengthCounts.Length; I++, BitLength++)
  150. {
  151. int count = DBitLengthCounts[I];
  152. for (int J = 0; J < count; J++, Slot++, Dist += (1 << BitLength))
  153. {
  154. DDecode[Slot] = Dist;
  155. DBits[Slot] = (byte)BitLength;
  156. }
  157. }
  158. }
  159. FileExtracted = true;
  160. if (!suspended)
  161. {
  162. UnpInitData(solid);
  163. if (!unpReadBuf())
  164. {
  165. return;
  166. }
  167. if ((!solid || !tablesRead) && !ReadTables())
  168. {
  169. return;
  170. }
  171. }
  172. if (ppmError)
  173. {
  174. return;
  175. }
  176. while (true)
  177. {
  178. unpPtr &= PackDef.MAXWINMASK;
  179. if (inAddr > readBorder)
  180. {
  181. if (!unpReadBuf())
  182. {
  183. break;
  184. }
  185. }
  186. // System.out.println(((wrPtr - unpPtr) &
  187. // Compress.MAXWINMASK)+":"+wrPtr+":"+unpPtr);
  188. if (((wrPtr - unpPtr) & PackDef.MAXWINMASK) < 260 && wrPtr != unpPtr)
  189. {
  190. UnpWriteBuf();
  191. if (destUnpSize <= 0)
  192. {
  193. return;
  194. }
  195. if (suspended)
  196. {
  197. FileExtracted = false;
  198. return;
  199. }
  200. }
  201. if (unpBlockType == BlockTypes.BLOCK_PPM)
  202. {
  203. int Ch = ppm.DecodeChar();
  204. if (Ch == -1)
  205. {
  206. ppmError = true;
  207. break;
  208. }
  209. if (Ch == PpmEscChar)
  210. {
  211. int NextCh = ppm.DecodeChar();
  212. if (NextCh == 0)
  213. {
  214. if (!ReadTables())
  215. {
  216. break;
  217. }
  218. continue;
  219. }
  220. if (NextCh == 2 || NextCh == -1)
  221. {
  222. break;
  223. }
  224. if (NextCh == 3)
  225. {
  226. if (!ReadVMCodePPM())
  227. {
  228. break;
  229. }
  230. continue;
  231. }
  232. if (NextCh == 4)
  233. {
  234. int Distance = 0, Length = 0;
  235. bool failed = false;
  236. for (int I = 0; I < 4 && !failed; I++)
  237. {
  238. int ch = ppm.DecodeChar();
  239. if (ch == -1)
  240. {
  241. failed = true;
  242. }
  243. else
  244. {
  245. if (I == 3)
  246. {
  247. // Bug fixed
  248. Length = ch & 0xff;
  249. }
  250. else
  251. {
  252. // Bug fixed
  253. Distance = (Distance << 8) + (ch & 0xff);
  254. }
  255. }
  256. }
  257. if (failed)
  258. {
  259. break;
  260. }
  261. CopyString(Length + 32, Distance + 2);
  262. continue;
  263. }
  264. if (NextCh == 5)
  265. {
  266. int Length = ppm.DecodeChar();
  267. if (Length == -1)
  268. {
  269. break;
  270. }
  271. CopyString(Length + 4, 1);
  272. continue;
  273. }
  274. }
  275. window[unpPtr++] = (byte)Ch;
  276. continue;
  277. }
  278. int Number = this.decodeNumber(LD);
  279. if (Number < 256)
  280. {
  281. window[unpPtr++] = (byte)Number;
  282. continue;
  283. }
  284. if (Number >= 271)
  285. {
  286. int Length = LDecode[Number -= 271] + 3;
  287. if ((Bits = LBits[Number]) > 0)
  288. {
  289. Length += Utility.URShift(GetBits(), (16 - Bits));
  290. AddBits(Bits);
  291. }
  292. int DistNumber = this.decodeNumber(DD);
  293. int Distance = DDecode[DistNumber] + 1;
  294. if ((Bits = DBits[DistNumber]) > 0)
  295. {
  296. if (DistNumber > 9)
  297. {
  298. if (Bits > 4)
  299. {
  300. Distance += ((Utility.URShift(GetBits(), (20 - Bits))) << 4);
  301. AddBits(Bits - 4);
  302. }
  303. if (lowDistRepCount > 0)
  304. {
  305. lowDistRepCount--;
  306. Distance += prevLowDist;
  307. }
  308. else
  309. {
  310. int LowDist = this.decodeNumber(LDD);
  311. if (LowDist == 16)
  312. {
  313. lowDistRepCount = PackDef.LOW_DIST_REP_COUNT - 1;
  314. Distance += prevLowDist;
  315. }
  316. else
  317. {
  318. Distance += LowDist;
  319. prevLowDist = LowDist;
  320. }
  321. }
  322. }
  323. else
  324. {
  325. Distance += Utility.URShift(GetBits(), (16 - Bits));
  326. AddBits(Bits);
  327. }
  328. }
  329. if (Distance >= 0x2000)
  330. {
  331. Length++;
  332. if (Distance >= 0x40000L)
  333. {
  334. Length++;
  335. }
  336. }
  337. InsertOldDist(Distance);
  338. InsertLastMatch(Length, Distance);
  339. CopyString(Length, Distance);
  340. continue;
  341. }
  342. if (Number == 256)
  343. {
  344. if (!ReadEndOfBlock())
  345. {
  346. break;
  347. }
  348. continue;
  349. }
  350. if (Number == 257)
  351. {
  352. if (!ReadVMCode())
  353. {
  354. break;
  355. }
  356. continue;
  357. }
  358. if (Number == 258)
  359. {
  360. if (lastLength != 0)
  361. {
  362. CopyString(lastLength, lastDist);
  363. }
  364. continue;
  365. }
  366. if (Number < 263)
  367. {
  368. int DistNum = Number - 259;
  369. int Distance = oldDist[DistNum];
  370. for (int I = DistNum; I > 0; I--)
  371. {
  372. oldDist[I] = oldDist[I - 1];
  373. }
  374. oldDist[0] = Distance;
  375. int LengthNumber = this.decodeNumber(RD);
  376. int Length = LDecode[LengthNumber] + 2;
  377. if ((Bits = LBits[LengthNumber]) > 0)
  378. {
  379. Length += Utility.URShift(GetBits(), (16 - Bits));
  380. AddBits(Bits);
  381. }
  382. InsertLastMatch(Length, Distance);
  383. CopyString(Length, Distance);
  384. continue;
  385. }
  386. if (Number < 272)
  387. {
  388. int Distance = SDDecode[Number -= 263] + 1;
  389. if ((Bits = SDBits[Number]) > 0)
  390. {
  391. Distance += Utility.URShift(GetBits(), (16 - Bits));
  392. AddBits(Bits);
  393. }
  394. InsertOldDist(Distance);
  395. InsertLastMatch(2, Distance);
  396. CopyString(2, Distance);
  397. }
  398. }
  399. UnpWriteBuf();
  400. }
  401. private void UnpWriteBuf()
  402. {
  403. int WrittenBorder = wrPtr;
  404. int WriteSize = (unpPtr - WrittenBorder) & PackDef.MAXWINMASK;
  405. for (int I = 0; I < prgStack.Count; I++)
  406. {
  407. UnpackFilter flt = prgStack[I];
  408. if (flt == null)
  409. {
  410. continue;
  411. }
  412. if (flt.NextWindow)
  413. {
  414. flt.NextWindow = false; // ->NextWindow=false;
  415. continue;
  416. }
  417. int BlockStart = flt.BlockStart; // ->BlockStart;
  418. int BlockLength = flt.BlockLength; // ->BlockLength;
  419. if (((BlockStart - WrittenBorder) & PackDef.MAXWINMASK) < WriteSize)
  420. {
  421. if (WrittenBorder != BlockStart)
  422. {
  423. UnpWriteArea(WrittenBorder, BlockStart);
  424. WrittenBorder = BlockStart;
  425. WriteSize = (unpPtr - WrittenBorder) & PackDef.MAXWINMASK;
  426. }
  427. if (BlockLength <= WriteSize)
  428. {
  429. int BlockEnd = (BlockStart + BlockLength) & PackDef.MAXWINMASK;
  430. if (BlockStart < BlockEnd || BlockEnd == 0)
  431. {
  432. // VM.SetMemory(0,Window+BlockStart,BlockLength);
  433. rarVM.setMemory(0, window, BlockStart, BlockLength);
  434. }
  435. else
  436. {
  437. int FirstPartLength = PackDef.MAXWINSIZE - BlockStart;
  438. // VM.SetMemory(0,Window+BlockStart,FirstPartLength);
  439. rarVM.setMemory(0, window, BlockStart, FirstPartLength);
  440. // VM.SetMemory(FirstPartLength,Window,BlockEnd);
  441. rarVM.setMemory(FirstPartLength, window, 0, BlockEnd);
  442. }
  443. VMPreparedProgram ParentPrg = filters[flt.ParentFilter].Program;
  444. VMPreparedProgram Prg = flt.Program;
  445. if (ParentPrg.GlobalData.Count > RarVM.VM_FIXEDGLOBALSIZE)
  446. {
  447. // copy global data from previous script execution if
  448. // any
  449. // Prg->GlobalData.Alloc(ParentPrg->GlobalData.Size());
  450. // memcpy(&Prg->GlobalData[VM_FIXEDGLOBALSIZE],&ParentPrg->GlobalData[VM_FIXEDGLOBALSIZE],ParentPrg->GlobalData.Size()-VM_FIXEDGLOBALSIZE);
  451. Prg.GlobalData.Clear();
  452. for (int i = 0; i < ParentPrg.GlobalData.Count - RarVM.VM_FIXEDGLOBALSIZE; i++)
  453. {
  454. Prg.GlobalData[RarVM.VM_FIXEDGLOBALSIZE + i] =
  455. ParentPrg.GlobalData[RarVM.VM_FIXEDGLOBALSIZE + i];
  456. }
  457. }
  458. ExecuteCode(Prg);
  459. if (Prg.GlobalData.Count > RarVM.VM_FIXEDGLOBALSIZE)
  460. {
  461. // save global data for next script execution
  462. if (ParentPrg.GlobalData.Count < Prg.GlobalData.Count)
  463. {
  464. //ParentPrg.GlobalData.Clear(); // ->GlobalData.Alloc(Prg->GlobalData.Size());
  465. ParentPrg.GlobalData.SetSize(Prg.GlobalData.Count);
  466. }
  467. // memcpy(&ParentPrg->GlobalData[VM_FIXEDGLOBALSIZE],&Prg->GlobalData[VM_FIXEDGLOBALSIZE],Prg->GlobalData.Size()-VM_FIXEDGLOBALSIZE);
  468. for (int i = 0; i < Prg.GlobalData.Count - RarVM.VM_FIXEDGLOBALSIZE; i++)
  469. {
  470. ParentPrg.GlobalData[RarVM.VM_FIXEDGLOBALSIZE + i] =
  471. Prg.GlobalData[RarVM.VM_FIXEDGLOBALSIZE + i];
  472. }
  473. }
  474. else
  475. {
  476. ParentPrg.GlobalData.Clear();
  477. }
  478. int FilteredDataOffset = Prg.FilteredDataOffset;
  479. int FilteredDataSize = Prg.FilteredDataSize;
  480. byte[] FilteredData = new byte[FilteredDataSize];
  481. for (int i = 0; i < FilteredDataSize; i++)
  482. {
  483. FilteredData[i] = rarVM.Mem[FilteredDataOffset + i];
  484. // Prg.GlobalData.get(FilteredDataOffset
  485. // +
  486. // i);
  487. }
  488. prgStack[I] = null;
  489. while (I + 1 < prgStack.Count)
  490. {
  491. UnpackFilter NextFilter = prgStack[I + 1];
  492. if (NextFilter == null || NextFilter.BlockStart != BlockStart ||
  493. NextFilter.BlockLength != FilteredDataSize || NextFilter.NextWindow)
  494. {
  495. break;
  496. }
  497. // apply several filters to same data block
  498. rarVM.setMemory(0, FilteredData, 0, FilteredDataSize);
  499. // .SetMemory(0,FilteredData,FilteredDataSize);
  500. VMPreparedProgram pPrg = filters[NextFilter.ParentFilter].Program;
  501. VMPreparedProgram NextPrg = NextFilter.Program;
  502. if (pPrg.GlobalData.Count > RarVM.VM_FIXEDGLOBALSIZE)
  503. {
  504. // copy global data from previous script execution
  505. // if any
  506. // NextPrg->GlobalData.Alloc(ParentPrg->GlobalData.Size());
  507. NextPrg.GlobalData.SetSize(pPrg.GlobalData.Count);
  508. // memcpy(&NextPrg->GlobalData[VM_FIXEDGLOBALSIZE],&ParentPrg->GlobalData[VM_FIXEDGLOBALSIZE],ParentPrg->GlobalData.Size()-VM_FIXEDGLOBALSIZE);
  509. for (int i = 0; i < pPrg.GlobalData.Count - RarVM.VM_FIXEDGLOBALSIZE; i++)
  510. {
  511. NextPrg.GlobalData[RarVM.VM_FIXEDGLOBALSIZE + i] =
  512. pPrg.GlobalData[RarVM.VM_FIXEDGLOBALSIZE + i];
  513. }
  514. }
  515. ExecuteCode(NextPrg);
  516. if (NextPrg.GlobalData.Count > RarVM.VM_FIXEDGLOBALSIZE)
  517. {
  518. // save global data for next script execution
  519. if (pPrg.GlobalData.Count < NextPrg.GlobalData.Count)
  520. {
  521. pPrg.GlobalData.SetSize(NextPrg.GlobalData.Count);
  522. }
  523. // memcpy(&ParentPrg->GlobalData[VM_FIXEDGLOBALSIZE],&NextPrg->GlobalData[VM_FIXEDGLOBALSIZE],NextPrg->GlobalData.Size()-VM_FIXEDGLOBALSIZE);
  524. for (int i = 0; i < NextPrg.GlobalData.Count - RarVM.VM_FIXEDGLOBALSIZE; i++)
  525. {
  526. pPrg.GlobalData[RarVM.VM_FIXEDGLOBALSIZE + i] =
  527. NextPrg.GlobalData[RarVM.VM_FIXEDGLOBALSIZE + i];
  528. }
  529. }
  530. else
  531. {
  532. pPrg.GlobalData.Clear();
  533. }
  534. FilteredDataOffset = NextPrg.FilteredDataOffset;
  535. FilteredDataSize = NextPrg.FilteredDataSize;
  536. FilteredData = new byte[FilteredDataSize];
  537. for (int i = 0; i < FilteredDataSize; i++)
  538. {
  539. FilteredData[i] = NextPrg.GlobalData[FilteredDataOffset + i];
  540. }
  541. I++;
  542. prgStack[I] = null;
  543. }
  544. writeStream.Write(FilteredData, 0, FilteredDataSize);
  545. unpSomeRead = true;
  546. writtenFileSize += FilteredDataSize;
  547. destUnpSize -= FilteredDataSize;
  548. WrittenBorder = BlockEnd;
  549. WriteSize = (unpPtr - WrittenBorder) & PackDef.MAXWINMASK;
  550. }
  551. else
  552. {
  553. for (int J = I; J < prgStack.Count; J++)
  554. {
  555. UnpackFilter filt = prgStack[J];
  556. if (filt != null && filt.NextWindow)
  557. {
  558. filt.NextWindow = false;
  559. }
  560. }
  561. wrPtr = WrittenBorder;
  562. return;
  563. }
  564. }
  565. }
  566. UnpWriteArea(WrittenBorder, unpPtr);
  567. wrPtr = unpPtr;
  568. }
  569. private void UnpWriteArea(int startPtr, int endPtr)
  570. {
  571. if (endPtr != startPtr)
  572. {
  573. unpSomeRead = true;
  574. }
  575. if (endPtr < startPtr)
  576. {
  577. UnpWriteData(window, startPtr, -startPtr & PackDef.MAXWINMASK);
  578. UnpWriteData(window, 0, endPtr);
  579. unpAllBuf = true;
  580. }
  581. else
  582. {
  583. UnpWriteData(window, startPtr, endPtr - startPtr);
  584. }
  585. }
  586. private void UnpWriteData(byte[] data, int offset, int size)
  587. {
  588. if (destUnpSize <= 0)
  589. {
  590. return;
  591. }
  592. int writeSize = size;
  593. if (writeSize > destUnpSize)
  594. {
  595. writeSize = (int)destUnpSize;
  596. }
  597. writeStream.Write(data, offset, writeSize);
  598. writtenFileSize += size;
  599. destUnpSize -= size;
  600. }
  601. private void InsertOldDist(uint distance) {
  602. // TODO uint
  603. InsertOldDist((int)distance);
  604. }
  605. private void InsertOldDist(int distance)
  606. {
  607. oldDist[3] = oldDist[2];
  608. oldDist[2] = oldDist[1];
  609. oldDist[1] = oldDist[0];
  610. oldDist[0] = distance;
  611. }
  612. private void InsertLastMatch(int length, int distance)
  613. {
  614. lastDist = distance;
  615. lastLength = length;
  616. }
  617. private void CopyString(uint length, uint distance) {
  618. // TODO uint
  619. CopyString((int)length, (int)distance) ;
  620. }
  621. private void CopyString(int length, int distance)
  622. {
  623. // System.out.println("copyString(" + length + ", " + distance + ")");
  624. int destPtr = unpPtr - distance;
  625. // System.out.println(unpPtr+":"+distance);
  626. if (destPtr >= 0 && destPtr < PackDef.MAXWINSIZE - 260 && unpPtr < PackDef.MAXWINSIZE - 260)
  627. {
  628. window[unpPtr++] = window[destPtr++];
  629. while (--length > 0)
  630. {
  631. window[unpPtr++] = window[destPtr++];
  632. }
  633. }
  634. else
  635. {
  636. while (length-- != 0)
  637. {
  638. window[unpPtr] = window[destPtr++ & PackDef.MAXWINMASK];
  639. unpPtr = (unpPtr + 1) & PackDef.MAXWINMASK;
  640. }
  641. }
  642. }
  643. private void UnpInitData(bool solid)
  644. {
  645. if (!solid)
  646. {
  647. tablesRead = false;
  648. Utility.Fill(oldDist, 0); // memset(oldDist,0,sizeof(OldDist));
  649. oldDistPtr = 0;
  650. lastDist = 0;
  651. lastLength = 0;
  652. Utility.Fill(unpOldTable, (byte)0); // memset(UnpOldTable,0,sizeof(UnpOldTable));
  653. unpPtr = 0;
  654. wrPtr = 0;
  655. PpmEscChar = 2;
  656. WriteBorder=Math.Min(MaxWinSize,UNPACK_MAX_WRITE)&MaxWinMask;
  657. InitFilters();
  658. }
  659. InitBitInput();
  660. ppmError = false;
  661. writtenFileSize = 0;
  662. readTop = 0;
  663. readBorder = 0;
  664. unpInitData20(solid);
  665. }
  666. //void Unpack::UnpInitData(bool Solid)
  667. //{
  668. // if (!Solid)
  669. // {
  670. // memset(OldDist,0,sizeof(OldDist));
  671. // OldDistPtr=0;
  672. // LastDist=LastLength=0;
  673. //// memset(Window,0,MaxWinSize);
  674. // memset(&BlockTables,0,sizeof(BlockTables));
  675. // UnpPtr=WrPtr=0;
  676. // WriteBorder=Min(MaxWinSize,UNPACK_MAX_WRITE)&MaxWinMask;
  677. // }
  678. // // Filters never share several solid files, so we can safely reset them
  679. // // even in solid archive.
  680. // InitFilters();
  681. //
  682. // Inp.InitBitInput();
  683. // WrittenFileSize=0;
  684. // ReadTop=0;
  685. // ReadBorder=0;
  686. //
  687. // memset(&BlockHeader,0,sizeof(BlockHeader));
  688. // BlockHeader.BlockSize=-1; // '-1' means not defined yet.
  689. //#ifndef SFX_MODULE
  690. // UnpInitData20(Solid);
  691. //#endif
  692. // UnpInitData30(Solid);
  693. // UnpInitData50(Solid);
  694. //}
  695. private void InitFilters()
  696. {
  697. oldFilterLengths.Clear();
  698. lastFilter = 0;
  699. filters.Clear();
  700. prgStack.Clear();
  701. }
  702. private bool ReadEndOfBlock()
  703. {
  704. int BitField = GetBits();
  705. bool NewTable, NewFile = false;
  706. if ((BitField & 0x8000) != 0)
  707. {
  708. NewTable = true;
  709. AddBits(1);
  710. }
  711. else
  712. {
  713. NewFile = true;
  714. NewTable = (BitField & 0x4000) != 0;
  715. AddBits(2);
  716. }
  717. tablesRead = !NewTable;
  718. return !(NewFile || NewTable && !ReadTables());
  719. }
  720. private bool ReadTables()
  721. {
  722. byte[] bitLength = new byte[PackDef.BC];
  723. byte[] table = new byte[PackDef.HUFF_TABLE_SIZE];
  724. if (inAddr > readTop - 25)
  725. {
  726. if (!unpReadBuf())
  727. {
  728. return (false);
  729. }
  730. }
  731. AddBits((8 - inBit) & 7);
  732. long bitField = GetBits() & unchecked((int)0xffFFffFF);
  733. if ((bitField & 0x8000) != 0)
  734. {
  735. unpBlockType = BlockTypes.BLOCK_PPM;
  736. return (ppm.DecodeInit(this, PpmEscChar));
  737. }
  738. unpBlockType = BlockTypes.BLOCK_LZ;
  739. prevLowDist = 0;
  740. lowDistRepCount = 0;
  741. if ((bitField & 0x4000) == 0)
  742. {
  743. Utility.Fill(unpOldTable, (byte)0); // memset(UnpOldTable,0,sizeof(UnpOldTable));
  744. }
  745. AddBits(2);
  746. for (int i = 0; i < PackDef.BC; i++)
  747. {
  748. int length = (Utility.URShift(GetBits(), 12)) & 0xFF;
  749. AddBits(4);
  750. if (length == 15)
  751. {
  752. int zeroCount = (Utility.URShift(GetBits(), 12)) & 0xFF;
  753. AddBits(4);
  754. if (zeroCount == 0)
  755. {
  756. bitLength[i] = 15;
  757. }
  758. else
  759. {
  760. zeroCount += 2;
  761. while (zeroCount-- > 0 && i < bitLength.Length)
  762. {
  763. bitLength[i++] = 0;
  764. }
  765. i--;
  766. }
  767. }
  768. else
  769. {
  770. bitLength[i] = (byte)length;
  771. }
  772. }
  773. UnpackUtility.makeDecodeTables(bitLength, 0, BD, PackDef.BC);
  774. int TableSize = PackDef.HUFF_TABLE_SIZE;
  775. for (int i = 0; i < TableSize;)
  776. {
  777. if (inAddr > readTop - 5)
  778. {
  779. if (!unpReadBuf())
  780. {
  781. return (false);
  782. }
  783. }
  784. int Number = this.decodeNumber(BD);
  785. if (Number < 16)
  786. {
  787. table[i] = (byte)((Number + unpOldTable[i]) & 0xf);
  788. i++;
  789. }
  790. else if (Number < 18)
  791. {
  792. int N;
  793. if (Number == 16)
  794. {
  795. N = (Utility.URShift(GetBits(), 13)) + 3;
  796. AddBits(3);
  797. }
  798. else
  799. {
  800. N = (Utility.URShift(GetBits(), 9)) + 11;
  801. AddBits(7);
  802. }
  803. while (N-- > 0 && i < TableSize)
  804. {
  805. table[i] = table[i - 1];
  806. i++;
  807. }
  808. }
  809. else
  810. {
  811. int N;
  812. if (Number == 18)
  813. {
  814. N = (Utility.URShift(GetBits(), 13)) + 3;
  815. AddBits(3);
  816. }
  817. else
  818. {
  819. N = (Utility.URShift(GetBits(), 9)) + 11;
  820. AddBits(7);
  821. }
  822. while (N-- > 0 && i < TableSize)
  823. {
  824. table[i++] = 0;
  825. }
  826. }
  827. }
  828. tablesRead = true;
  829. if (inAddr > readTop)
  830. {
  831. return (false);
  832. }
  833. UnpackUtility.makeDecodeTables(table, 0, LD, PackDef.NC);
  834. UnpackUtility.makeDecodeTables(table, PackDef.NC, DD, PackDef.DC);
  835. UnpackUtility.makeDecodeTables(table, PackDef.NC + PackDef.DC, LDD, PackDef.LDC);
  836. UnpackUtility.makeDecodeTables(table, PackDef.NC + PackDef.DC + PackDef.LDC, RD, PackDef.RC);
  837. // memcpy(unpOldTable,table,sizeof(unpOldTable));
  838. Buffer.BlockCopy(table, 0, unpOldTable, 0, unpOldTable.Length);
  839. return (true);
  840. }
  841. private bool ReadVMCode()
  842. {
  843. int FirstByte = GetBits() >> 8;
  844. AddBits(8);
  845. int Length = (FirstByte & 7) + 1;
  846. if (Length == 7)
  847. {
  848. Length = (GetBits() >> 8) + 7;
  849. AddBits(8);
  850. }
  851. else if (Length == 8)
  852. {
  853. Length = GetBits();
  854. AddBits(16);
  855. }
  856. List<Byte> vmCode = new List<Byte>();
  857. for (int I = 0; I < Length; I++)
  858. {
  859. if (inAddr >= readTop - 1 && !unpReadBuf() && I < Length - 1)
  860. {
  861. return (false);
  862. }
  863. vmCode.Add((byte)(GetBits() >> 8));
  864. AddBits(8);
  865. }
  866. return (AddVMCode(FirstByte, vmCode, Length));
  867. }
  868. private bool ReadVMCodePPM()
  869. {
  870. int FirstByte = ppm.DecodeChar();
  871. if (FirstByte == -1)
  872. {
  873. return (false);
  874. }
  875. int Length = (FirstByte & 7) + 1;
  876. if (Length == 7)
  877. {
  878. int B1 = ppm.DecodeChar();
  879. if (B1 == -1)
  880. {
  881. return (false);
  882. }
  883. Length = B1 + 7;
  884. }
  885. else if (Length == 8)
  886. {
  887. int B1 = ppm.DecodeChar();
  888. if (B1 == -1)
  889. {
  890. return (false);
  891. }
  892. int B2 = ppm.DecodeChar();
  893. if (B2 == -1)
  894. {
  895. return (false);
  896. }
  897. Length = B1 * 256 + B2;
  898. }
  899. List<Byte> vmCode = new List<Byte>();
  900. for (int I = 0; I < Length; I++)
  901. {
  902. int Ch = ppm.DecodeChar();
  903. if (Ch == -1)
  904. {
  905. return (false);
  906. }
  907. vmCode.Add((byte)Ch); // VMCode[I]=Ch;
  908. }
  909. return (AddVMCode(FirstByte, vmCode, Length));
  910. }
  911. private bool AddVMCode(int firstByte, List<byte> vmCode, int length)
  912. {
  913. BitInput Inp = new BitInput();
  914. Inp.InitBitInput();
  915. // memcpy(Inp.InBuf,Code,Min(BitInput::MAX_SIZE,CodeSize));
  916. for (int i = 0; i < Math.Min(MAX_SIZE, vmCode.Count); i++)
  917. {
  918. Inp.InBuf[i] = vmCode[i];
  919. }
  920. rarVM.init();
  921. int FiltPos;
  922. if ((firstByte & 0x80) != 0)
  923. {
  924. FiltPos = RarVM.ReadData(Inp);
  925. if (FiltPos == 0)
  926. {
  927. InitFilters();
  928. }
  929. else
  930. {
  931. FiltPos--;
  932. }
  933. }
  934. else
  935. {
  936. FiltPos = lastFilter; // use the same filter as last time
  937. }
  938. if (FiltPos > filters.Count || FiltPos > oldFilterLengths.Count)
  939. {
  940. return (false);
  941. }
  942. lastFilter = FiltPos;
  943. bool NewFilter = (FiltPos == filters.Count);
  944. UnpackFilter StackFilter = new UnpackFilter(); // new filter for
  945. // PrgStack
  946. UnpackFilter Filter;
  947. if (NewFilter)
  948. // new filter code, never used before since VM reset
  949. {
  950. // too many different filters, corrupt archive
  951. if (FiltPos > 1024)
  952. {
  953. return (false);
  954. }
  955. // Filters[Filters.Size()-1]=Filter=new UnpackFilter;
  956. Filter = new UnpackFilter();
  957. filters.Add(Filter);
  958. StackFilter.ParentFilter = filters.Count - 1;
  959. oldFilterLengths.Add(0);
  960. Filter.ExecCount = 0;
  961. }
  962. // filter was used in the past
  963. else
  964. {
  965. Filter = filters[FiltPos];
  966. StackFilter.ParentFilter = FiltPos;
  967. Filter.ExecCount = Filter.ExecCount + 1; // ->ExecCount++;
  968. }
  969. prgStack.Add(StackFilter);
  970. StackFilter.ExecCount = Filter.ExecCount; // ->ExecCount;
  971. int BlockStart = RarVM.ReadData(Inp);
  972. if ((firstByte & 0x40) != 0)
  973. {
  974. BlockStart += 258;
  975. }
  976. StackFilter.BlockStart = ((BlockStart + unpPtr) & PackDef.MAXWINMASK);
  977. if ((firstByte & 0x20) != 0)
  978. {
  979. StackFilter.BlockLength = RarVM.ReadData(Inp);
  980. }
  981. else
  982. {
  983. StackFilter.BlockLength = FiltPos < oldFilterLengths.Count ? oldFilterLengths[FiltPos] : 0;
  984. }
  985. StackFilter.NextWindow = (wrPtr != unpPtr) && ((wrPtr - unpPtr) & PackDef.MAXWINMASK) <= BlockStart;
  986. // DebugLog("\nNextWindow: UnpPtr=%08x WrPtr=%08x
  987. // BlockStart=%08x",UnpPtr,WrPtr,BlockStart);
  988. oldFilterLengths[FiltPos] = StackFilter.BlockLength;
  989. // memset(StackFilter->Prg.InitR,0,sizeof(StackFilter->Prg.InitR));
  990. Utility.Fill(StackFilter.Program.InitR, 0);
  991. StackFilter.Program.InitR[3] = RarVM.VM_GLOBALMEMADDR; // StackFilter->Prg.InitR[3]=VM_GLOBALMEMADDR;
  992. StackFilter.Program.InitR[4] = StackFilter.BlockLength;
  993. // StackFilter->Prg.InitR[4]=StackFilter->BlockLength;
  994. StackFilter.Program.InitR[5] = StackFilter.ExecCount; // StackFilter->Prg.InitR[5]=StackFilter->ExecCount;
  995. if ((firstByte & 0x10) != 0)
  996. // set registers to optional parameters
  997. // if any
  998. {
  999. int InitMask = Utility.URShift(Inp.GetBits(), 9);
  1000. Inp.AddBits(7);
  1001. for (int I = 0; I < 7; I++)
  1002. {
  1003. if ((InitMask & (1 << I)) != 0)
  1004. {
  1005. // StackFilter->Prg.InitR[I]=RarVM::ReadData(Inp);
  1006. StackFilter.Program.InitR[I] = RarVM.ReadData(Inp);
  1007. }
  1008. }
  1009. }
  1010. if (NewFilter)
  1011. {
  1012. int VMCodeSize = RarVM.ReadData(Inp);
  1013. if (VMCodeSize >= 0x10000 || VMCodeSize == 0)
  1014. {
  1015. return (false);
  1016. }
  1017. byte[] VMCode = new byte[VMCodeSize];
  1018. for (int I = 0; I < VMCodeSize; I++)
  1019. {
  1020. if (Inp.Overflow(3))
  1021. {
  1022. return (false);
  1023. }
  1024. VMCode[I] = (byte)(Inp.GetBits() >> 8);
  1025. Inp.AddBits(8);
  1026. }
  1027. // VM.Prepare(&VMCode[0],VMCodeSize,&Filter->Prg);
  1028. rarVM.prepare(VMCode, VMCodeSize, Filter.Program);
  1029. }
  1030. StackFilter.Program.AltCommands = Filter.Program.Commands; // StackFilter->Prg.AltCmd=&Filter->Prg.Cmd[0];
  1031. StackFilter.Program.CommandCount = Filter.Program.CommandCount;
  1032. // StackFilter->Prg.CmdCount=Filter->Prg.CmdCount;
  1033. int StaticDataSize = Filter.Program.StaticData.Count;
  1034. if (StaticDataSize > 0 && StaticDataSize < RarVM.VM_GLOBALMEMSIZE)
  1035. {
  1036. // read statically defined data contained in DB commands
  1037. // StackFilter->Prg.StaticData.Add(StaticDataSize);
  1038. StackFilter.Program.StaticData = Filter.Program.StaticData;
  1039. // memcpy(&StackFilter->Prg.StaticData[0],&Filter->Prg.StaticData[0],StaticDataSize);
  1040. }
  1041. if (StackFilter.Program.GlobalData.Count < RarVM.VM_FIXEDGLOBALSIZE)
  1042. {
  1043. // StackFilter->Prg.GlobalData.Reset();
  1044. // StackFilter->Prg.GlobalData.Add(VM_FIXEDGLOBALSIZE);
  1045. StackFilter.Program.GlobalData.Clear();
  1046. StackFilter.Program.GlobalData.SetSize(RarVM.VM_FIXEDGLOBALSIZE);
  1047. }
  1048. // byte *GlobalData=&StackFilter->Prg.GlobalData[0];
  1049. List<byte> globalData = StackFilter.Program.GlobalData;
  1050. for (int I = 0; I < 7; I++)
  1051. {
  1052. rarVM.SetLowEndianValue(globalData, I * 4, StackFilter.Program.InitR[I]);
  1053. }
  1054. // VM.SetLowEndianValue((uint
  1055. // *)&GlobalData[0x1c],StackFilter->BlockLength);
  1056. rarVM.SetLowEndianValue(globalData, 0x1c, StackFilter.BlockLength);
  1057. // VM.SetLowEndianValue((uint *)&GlobalData[0x20],0);
  1058. rarVM.SetLowEndianValue(globalData, 0x20, 0);
  1059. rarVM.SetLowEndianValue(globalData, 0x24, 0);
  1060. rarVM.SetLowEndianValue(globalData, 0x28, 0);
  1061. // VM.SetLowEndianValue((uint
  1062. // *)&GlobalData[0x2c],StackFilter->ExecCount);
  1063. rarVM.SetLowEndianValue(globalData, 0x2c, StackFilter.ExecCount);
  1064. // memset(&GlobalData[0x30],0,16);
  1065. for (int i = 0; i < 16; i++)
  1066. {
  1067. globalData[0x30 + i] = 0x0;
  1068. }
  1069. if ((firstByte & 8) != 0)
  1070. // put data block passed as parameter if any
  1071. {
  1072. if (Inp.Overflow(3))
  1073. {
  1074. return (false);
  1075. }
  1076. int DataSize = RarVM.ReadData(Inp);
  1077. if (DataSize > RarVM.VM_GLOBALMEMSIZE - RarVM.VM_FIXEDGLOBALSIZE)
  1078. {
  1079. return (false);
  1080. }
  1081. int CurSize = StackFilter.Program.GlobalData.Count;
  1082. if (CurSize < DataSize + RarVM.VM_FIXEDGLOBALSIZE)
  1083. {
  1084. // StackFilter->Prg.GlobalData.Add(DataSize+VM_FIXEDGLOBALSIZE-CurSize);
  1085. StackFilter.Program.GlobalData.SetSize(DataSize + RarVM.VM_FIXEDGLOBALSIZE - CurSize);
  1086. }
  1087. int offset = RarVM.VM_FIXEDGLOBALSIZE;
  1088. globalData = StackFilter.Program.GlobalData;
  1089. for (int I = 0; I < DataSize; I++)
  1090. {
  1091. if (Inp.Overflow(3))
  1092. {
  1093. return (false);
  1094. }
  1095. globalData[offset + I] = (byte)(Utility.URShift(Inp.GetBits(), 8));
  1096. Inp.AddBits(8);
  1097. }
  1098. }
  1099. return (true);
  1100. }
  1101. private void ExecuteCode(VMPreparedProgram Prg)
  1102. {
  1103. if (Prg.GlobalData.Count > 0)
  1104. {
  1105. // Prg->InitR[6]=int64to32(WrittenFileSize);
  1106. Prg.InitR[6] = (int)(writtenFileSize);
  1107. // rarVM.SetLowEndianValue((uint
  1108. // *)&Prg->GlobalData[0x24],int64to32(WrittenFileSize));
  1109. rarVM.SetLowEndianValue(Prg.GlobalData, 0x24, (int)writtenFileSize);
  1110. // rarVM.SetLowEndianValue((uint
  1111. // *)&Prg->GlobalData[0x28],int64to32(WrittenFileSize>>32));
  1112. rarVM.SetLowEndianValue(Prg.GlobalData, 0x28, (int)(Utility.URShift(writtenFileSize, 32)));
  1113. rarVM.execute(Prg);
  1114. }
  1115. }
  1116. private void CleanUp()
  1117. {
  1118. if (ppm != null)
  1119. {
  1120. SubAllocator allocator = ppm.SubAlloc;
  1121. if (allocator != null)
  1122. {
  1123. allocator.StopSubAllocator();
  1124. }
  1125. }
  1126. }
  1127. }
  1128. }