rdwrfn.cpp 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325
  1. #include "rar.hpp"
  2. ComprDataIO::ComprDataIO()
  3. {
  4. #ifndef RAR_NOCRYPT
  5. Crypt=new CryptData;
  6. Decrypt=new CryptData;
  7. #endif
  8. Init();
  9. }
  10. void ComprDataIO::Init()
  11. {
  12. UnpackFromMemory=false;
  13. UnpackToMemory=false;
  14. UnpPackedSize=0;
  15. UnpPackedLeft=0;
  16. ShowProgress=true;
  17. TestMode=false;
  18. SkipUnpCRC=false;
  19. NoFileHeader=false;
  20. PackVolume=false;
  21. UnpVolume=false;
  22. NextVolumeMissing=false;
  23. SrcFile=NULL;
  24. DestFile=NULL;
  25. UnpWrAddr=NULL;
  26. UnpWrSize=0;
  27. Command=NULL;
  28. Encryption=false;
  29. Decryption=false;
  30. CurPackRead=CurPackWrite=CurUnpRead=CurUnpWrite=0;
  31. LastPercent=-1;
  32. SubHead=NULL;
  33. SubHeadPos=NULL;
  34. CurrentCommand=0;
  35. ProcessedArcSize=0;
  36. LastArcSize=0;
  37. TotalArcSize=0;
  38. }
  39. ComprDataIO::~ComprDataIO()
  40. {
  41. #ifndef RAR_NOCRYPT
  42. delete Crypt;
  43. delete Decrypt;
  44. #endif
  45. }
  46. int ComprDataIO::UnpRead(byte *Addr,size_t Count)
  47. {
  48. #ifndef RAR_NOCRYPT
  49. // In case of encryption we need to align read size to encryption
  50. // block size. We can do it by simple masking, because unpack read code
  51. // always reads more than CRYPT_BLOCK_SIZE, so we do not risk to make it 0.
  52. if (Decryption)
  53. Count &= ~CRYPT_BLOCK_MASK;
  54. #endif
  55. int ReadSize=0,TotalRead=0;
  56. byte *ReadAddr;
  57. ReadAddr=Addr;
  58. while (Count > 0)
  59. {
  60. Archive *SrcArc=(Archive *)SrcFile;
  61. if (UnpackFromMemory)
  62. {
  63. memcpy(Addr,UnpackFromMemoryAddr,UnpackFromMemorySize);
  64. ReadSize=(int)UnpackFromMemorySize;
  65. UnpackFromMemorySize=0;
  66. }
  67. else
  68. {
  69. size_t SizeToRead=((int64)Count>UnpPackedLeft) ? (size_t)UnpPackedLeft:Count;
  70. if (SizeToRead > 0)
  71. {
  72. if (UnpVolume && Decryption && (int64)Count>UnpPackedLeft)
  73. {
  74. // We need aligned blocks for decryption and we want "Keep broken
  75. // files" to work efficiently with missing encrypted volumes.
  76. // So for last data block in volume we adjust the size to read to
  77. // next equal or smaller block producing aligned total block size.
  78. // So we'll ask for next volume only when processing few unaligned
  79. // bytes left in the end, when most of data is already extracted.
  80. size_t NewTotalRead = TotalRead + SizeToRead;
  81. size_t Adjust = NewTotalRead - (NewTotalRead & ~CRYPT_BLOCK_MASK);
  82. size_t NewSizeToRead = SizeToRead - Adjust;
  83. if ((int)NewSizeToRead > 0)
  84. SizeToRead = NewSizeToRead;
  85. }
  86. if (!SrcFile->IsOpened())
  87. return -1;
  88. ReadSize=SrcFile->Read(ReadAddr,SizeToRead);
  89. FileHeader *hd=SubHead!=NULL ? SubHead:&SrcArc->FileHead;
  90. if (!NoFileHeader && hd->SplitAfter)
  91. PackedDataHash.Update(ReadAddr,ReadSize);
  92. }
  93. }
  94. CurUnpRead+=ReadSize;
  95. TotalRead+=ReadSize;
  96. #ifndef NOVOLUME
  97. // These variable are not used in NOVOLUME mode, so it is better
  98. // to exclude commands below to avoid compiler warnings.
  99. ReadAddr+=ReadSize;
  100. Count-=ReadSize;
  101. #endif
  102. UnpPackedLeft-=ReadSize;
  103. // Do not ask for next volume if we read something from current volume.
  104. // If next volume is missing, we need to process all data from current
  105. // volume before aborting. It helps to recover all possible data
  106. // in "Keep broken files" mode. But if we process encrypted data,
  107. // we ask for next volume also if we have non-aligned encryption block.
  108. // Since we adjust data size for decryption earlier above,
  109. // it does not hurt "Keep broken files" mode efficiency.
  110. if (UnpVolume && UnpPackedLeft == 0 &&
  111. (ReadSize==0 || Decryption && (TotalRead & CRYPT_BLOCK_MASK) != 0) )
  112. {
  113. #ifndef NOVOLUME
  114. if (!MergeArchive(*SrcArc,this,true,CurrentCommand))
  115. #endif
  116. {
  117. NextVolumeMissing=true;
  118. return -1;
  119. }
  120. }
  121. else
  122. break;
  123. }
  124. Archive *SrcArc=(Archive *)SrcFile;
  125. if (SrcArc!=NULL)
  126. ShowUnpRead(SrcArc->NextBlockPos-UnpPackedSize+CurUnpRead,TotalArcSize);
  127. if (ReadSize!=-1)
  128. {
  129. ReadSize=TotalRead;
  130. #ifndef RAR_NOCRYPT
  131. if (Decryption)
  132. Decrypt->DecryptBlock(Addr,ReadSize);
  133. #endif
  134. }
  135. Wait();
  136. return ReadSize;
  137. }
  138. void ComprDataIO::UnpWrite(byte *Addr,size_t Count)
  139. {
  140. #ifdef RARDLL
  141. RAROptions *Cmd=((Archive *)SrcFile)->GetRAROptions();
  142. if (Cmd->DllOpMode!=RAR_SKIP)
  143. {
  144. if (Cmd->Callback!=NULL &&
  145. Cmd->Callback(UCM_PROCESSDATA,Cmd->UserData,(LPARAM)Addr,Count)==-1)
  146. ErrHandler.Exit(RARX_USERBREAK);
  147. /* // OPENMPT ADDITION
  148. if (Cmd->ProcessDataProc!=NULL)
  149. {
  150. int RetCode=Cmd->ProcessDataProc(Addr,(int)Count);
  151. if (RetCode==0)
  152. ErrHandler.Exit(RARX_USERBREAK);
  153. }
  154. */ // OPENMPT ADDITION
  155. }
  156. #endif // RARDLL
  157. UnpWrAddr=Addr;
  158. UnpWrSize=Count;
  159. if (UnpackToMemory)
  160. {
  161. if (Count <= UnpackToMemorySize)
  162. {
  163. memcpy(UnpackToMemoryAddr,Addr,Count);
  164. UnpackToMemoryAddr+=Count;
  165. UnpackToMemorySize-=Count;
  166. }
  167. }
  168. else
  169. if (!TestMode)
  170. DestFile->Write(Addr,Count);
  171. CurUnpWrite+=Count;
  172. if (!SkipUnpCRC)
  173. UnpHash.Update(Addr,Count);
  174. ShowUnpWrite();
  175. Wait();
  176. }
  177. void ComprDataIO::ShowUnpRead(int64 ArcPos,int64 ArcSize)
  178. {
  179. return; // OPENMPT ADDITION
  180. if (ShowProgress && SrcFile!=NULL)
  181. {
  182. // Important when processing several archives or multivolume archive.
  183. ArcPos+=ProcessedArcSize;
  184. Archive *SrcArc=(Archive *)SrcFile;
  185. RAROptions *Cmd=SrcArc->GetRAROptions();
  186. int CurPercent=ToPercent(ArcPos,ArcSize);
  187. if (!Cmd->DisablePercentage && CurPercent!=LastPercent)
  188. {
  189. uiExtractProgress(CurUnpWrite,SrcArc->FileHead.UnpSize,ArcPos,ArcSize);
  190. LastPercent=CurPercent;
  191. }
  192. }
  193. }
  194. void ComprDataIO::ShowUnpWrite()
  195. {
  196. }
  197. void ComprDataIO::SetFiles(File *SrcFile,File *DestFile)
  198. {
  199. if (SrcFile!=NULL)
  200. ComprDataIO::SrcFile=SrcFile;
  201. if (DestFile!=NULL)
  202. ComprDataIO::DestFile=DestFile;
  203. LastPercent=-1;
  204. }
  205. void ComprDataIO::GetUnpackedData(byte **Data,size_t *Size)
  206. {
  207. *Data=UnpWrAddr;
  208. *Size=UnpWrSize;
  209. }
  210. void ComprDataIO::SetEncryption(bool Encrypt,CRYPT_METHOD Method,
  211. SecPassword *Password,const byte *Salt,const byte *InitV,
  212. uint Lg2Cnt,byte *HashKey,byte *PswCheck)
  213. {
  214. #ifndef RAR_NOCRYPT
  215. if (Encrypt)
  216. Encryption=Crypt->SetCryptKeys(true,Method,Password,Salt,InitV,Lg2Cnt,HashKey,PswCheck);
  217. else
  218. Decryption=Decrypt->SetCryptKeys(false,Method,Password,Salt,InitV,Lg2Cnt,HashKey,PswCheck);
  219. #endif
  220. }
  221. #if !defined(SFX_MODULE) && !defined(RAR_NOCRYPT)
  222. void ComprDataIO::SetAV15Encryption()
  223. {
  224. Decryption=true;
  225. Decrypt->SetAV15Encryption();
  226. }
  227. #endif
  228. #if !defined(SFX_MODULE) && !defined(RAR_NOCRYPT)
  229. void ComprDataIO::SetCmt13Encryption()
  230. {
  231. Decryption=true;
  232. Decrypt->SetCmt13Encryption();
  233. }
  234. #endif
  235. void ComprDataIO::SetUnpackToMemory(byte *Addr,uint Size)
  236. {
  237. UnpackToMemory=true;
  238. UnpackToMemoryAddr=Addr;
  239. UnpackToMemorySize=Size;
  240. }
  241. // Extraction progress is based on the position in archive and we adjust
  242. // the total archives size here, so trailing blocks do not prevent progress
  243. // reaching 100% at the end of extraction. Alternatively we could print "100%"
  244. // after completing the entire archive extraction, but then we would need
  245. // to take into account possible messages like the checksum error after
  246. // last file percent progress.
  247. void ComprDataIO::AdjustTotalArcSize(Archive *Arc)
  248. {
  249. // If we know a position of QO or RR blocks, use them to adjust the total
  250. // packed size to beginning of these blocks. Earlier we already calculated
  251. // the total size based on entire archive sizes. We also set LastArcSize
  252. // to start of first trailing block, to add it later to ProcessedArcSize.
  253. int64 ArcLength=Arc->IsSeekable() ? Arc->FileLength() : 0;
  254. if (Arc->MainHead.QOpenOffset!=0) // QO is always preceding RR record.
  255. LastArcSize=Arc->MainHead.QOpenOffset;
  256. else
  257. if (Arc->MainHead.RROffset!=0)
  258. LastArcSize=Arc->MainHead.RROffset;
  259. else
  260. {
  261. // If neither QO nor RR are found, exclude the approximate size of
  262. // end of archive block.
  263. // We select EndBlock to be larger than typical 8 bytes HEAD_ENDARC,
  264. // but to not exceed the smallest 22 bytes HEAD_FILE with 1 byte file
  265. // name, so we do not have two files with 100% at the end of archive.
  266. const uint EndBlock=23;
  267. if (ArcLength>EndBlock)
  268. LastArcSize=ArcLength-EndBlock;
  269. }
  270. TotalArcSize-=ArcLength-LastArcSize;
  271. }