#include "rar.hpp" #include "URL.h" #include "dialogs/GUIDialogProgress.h" ComprDataIO::ComprDataIO() { Init(); } void ComprDataIO::Init() { UnpackFromMemory=false; UnpackToMemory=false; UnpackToMemorySize=-1; UnpPackedSize=0; ShowProgress=true; TestMode=false; SkipUnpCRC=true; PackVolume=false; UnpVolume=false; NextVolumeMissing=false; SrcFile=NULL; DestFile=NULL; UnpWrSize=0; Command=NULL; Encryption=0; Decryption=0; TotalPackRead=0; CurPackRead=CurPackWrite=CurUnpRead=CurUnpWrite=CurUnpStart=0; PackFileCRC=UnpFileCRC=PackedCRC=0xffffffff; LastPercent=-1; SubHead=NULL; SubHeadPos=NULL; CurrentCommand=0; ProcessedArcSize=TotalArcSize=0; bQuit = false; m_pDlgProgress = NULL; } int ComprDataIO::UnpRead(byte *Addr,uint Count) { int RetCode=0,TotalRead=0; byte *ReadAddr; ReadAddr=Addr; while (Count > 0) { Archive *SrcArc=(Archive *)SrcFile; uint ReadSize=(Count>UnpPackedSize) ? int64to32(UnpPackedSize):Count; if (UnpackFromMemory) { memcpy(Addr,UnpackFromMemoryAddr,UnpackFromMemorySize); RetCode=UnpackFromMemorySize; UnpackFromMemorySize=0; } else { bool bRead = true; if (!SrcFile->IsOpened()) { NextVolumeMissing = true; return(-1); } if (UnpackToMemory) if (hSeek->WaitMSec(1)) // we are seeking { if (m_iSeekTo > CurUnpStart+SrcArc->NewLhd.FullPackSize) // need to seek outside this block { TotalRead += (int)(SrcArc->NextBlockPos-SrcFile->Tell()); CurUnpRead=CurUnpStart+SrcArc->NewLhd.FullPackSize; UnpPackedSize=0; RetCode = 0; bRead = false; } else { Int64 iStartOfFile = SrcArc->NextBlockPos-SrcArc->NewLhd.FullPackSize; m_iStartOfBuffer = CurUnpStart; Int64 iSeekTo=m_iSeekTo-CurUnpStartSrcArc->NewLhd.FullUnpSize) { m_iSeekTo=SrcArc->NewLhd.FullUnpSize-iSeekTo+iStartOfFile; // back UnpPackedSize = SrcArc->NewLhd.FullPackSize; } else { m_iSeekTo=MAXWINMEMSIZE-(m_iSeekTo-CurUnpStart); UnpPackedSize = SrcArc->NewLhd.FullPackSize - (m_iStartOfBuffer - CurUnpStart); } } else { m_iStartOfBuffer = m_iSeekTo-MAXWINMEMSIZE/2; // front if (m_iSeekTo+MAXWINMEMSIZE/2>SrcArc->NewLhd.FullUnpSize) { iSeekTo = iStartOfFile+SrcArc->NewLhd.FullPackSize-MAXWINMEMSIZE; m_iStartOfBuffer = CurUnpStart+SrcArc->NewLhd.FullPackSize-MAXWINMEMSIZE; m_iSeekTo = MAXWINMEMSIZE-(m_iSeekTo-m_iStartOfBuffer); UnpPackedSize = MAXWINMEMSIZE; } else { m_iSeekTo=MAXWINMEMSIZE/2; UnpPackedSize = SrcArc->NewLhd.FullPackSize - (m_iStartOfBuffer - CurUnpStart); } } SrcFile->Seek(iSeekTo,SEEK_SET); TotalRead = 0; CurUnpRead = CurUnpStart + iSeekTo - iStartOfFile; CurUnpWrite = SrcFile->Tell() - iStartOfFile + CurUnpStart; hSeek->Reset(); hSeekDone->Set(); } } if (bRead) { ReadSize=(Count>UnpPackedSize) ? int64to32(UnpPackedSize):Count; RetCode=SrcFile->Read(ReadAddr,ReadSize); FileHeader *hd=SubHead!=NULL ? SubHead:&SrcArc->NewLhd; if (hd->Flags & LHD_SPLIT_AFTER) { PackedCRC=CRC(PackedCRC,ReadAddr,ReadSize); } } } CurUnpRead+=RetCode; ReadAddr+=RetCode; TotalRead+=RetCode; Count-=RetCode; UnpPackedSize-=RetCode; if (UnpPackedSize == 0 && UnpVolume) { #ifndef NOVOLUME if (!MergeArchive(*SrcArc,this,true,CurrentCommand)) #endif { NextVolumeMissing=true; return(-1); } CurUnpStart = CurUnpRead; if (m_pDlgProgress) { CURL url(SrcArc->FileName); m_pDlgProgress->SetLine(0,url.GetWithoutUserDetails()); // update currently extracted rar file m_pDlgProgress->Progress(); } } else break; } Archive *SrcArc=(Archive *)SrcFile; if (SrcArc!=NULL) ShowUnpRead(SrcArc->CurBlockPos+CurUnpRead,UnpArcSize); if (RetCode!=-1) { RetCode=TotalRead; #ifndef NOCRYPT if (Decryption) { #ifndef SFX_MODULE if (Decryption<20) Decrypt.Crypt(Addr,RetCode,(Decryption==15) ? NEW_CRYPT : OLD_DECODE); else if (Decryption==20) for (int I=0;IGetRAROptions(); if (Cmd->DllOpMode!=RAR_SKIP) { if (Cmd->Callback!=NULL && Cmd->Callback(UCM_PROCESSDATA,Cmd->UserData,(LONG)Addr,Count)==-1) ErrHandler.Exit(USER_BREAK); if (Cmd->ProcessDataProc!=NULL) { #ifdef _WIN_32 _EBX=_ESP; #endif int RetCode=Cmd->ProcessDataProc(Addr,Count); #ifdef _WIN_32 _ESP=_EBX; #endif if (RetCode==0) ErrHandler.Exit(USER_BREAK); } } #endif UnpWrAddr=Addr; UnpWrSize=Count; if (UnpackToMemory) { while(UnpackToMemorySize < (int)Count) { hBufferEmpty->Set(); while(! hBufferFilled->WaitMSec(1)) if (hQuit->WaitMSec(1)) return; } if (! hSeek->WaitMSec(1)) // we are seeking { memcpy(UnpackToMemoryAddr,Addr,Count); UnpackToMemoryAddr+=Count; UnpackToMemorySize-=Count; } else return; } else if (!TestMode) DestFile->Write(Addr,Count); CurUnpWrite+=Count; if (!SkipUnpCRC) { #ifndef SFX_MODULE if (((Archive *)SrcFile)->OldFormat) UnpFileCRC=OldCRC((ushort)UnpFileCRC,Addr,Count); else #endif UnpFileCRC=CRC(UnpFileCRC,Addr,Count); } ShowUnpWrite(); Wait(); if (m_pDlgProgress) { m_pDlgProgress->ShowProgressBar(true); m_pDlgProgress->SetPercentage(int(float(CurUnpWrite)/float(((Archive*)SrcFile)->NewLhd.FullUnpSize)*100)); m_pDlgProgress->Progress(); if (m_pDlgProgress->IsCanceled()) bQuit = true; } } void ComprDataIO::ShowUnpRead(Int64 ArcPos,Int64 ArcSize) { if (ShowProgress && SrcFile!=NULL) { Archive *SrcArc=(Archive *)SrcFile; RAROptions *Cmd=SrcArc->GetRAROptions(); if (TotalArcSize!=0) ArcSize=TotalArcSize; ArcPos+=ProcessedArcSize; if (!SrcArc->Volume) { int CurPercent=ToPercent(ArcPos,ArcSize); if (!Cmd->DisablePercentage && CurPercent!=LastPercent) { mprintf("\b\b\b\b%3d%%",CurPercent); LastPercent=CurPercent; } } } } void ComprDataIO::ShowUnpWrite() { } void ComprDataIO::SetFiles(File *SrcFile,File *DestFile) { if (SrcFile!=NULL) ComprDataIO::SrcFile=SrcFile; if (DestFile!=NULL) ComprDataIO::DestFile=DestFile; LastPercent=-1; } void ComprDataIO::GetUnpackedData(byte **Data,uint *Size) { *Data=UnpWrAddr; *Size=UnpWrSize; } void ComprDataIO::SetEncryption(int Method,char *Password,byte *Salt,bool Encrypt) { if (Encrypt) { Encryption=*Password ? Method:0; #ifndef NOCRYPT Crypt.SetCryptKeys(Password,Salt,Encrypt); #endif } else { Decryption=*Password ? Method:0; #ifndef NOCRYPT Decrypt.SetCryptKeys(Password,Salt,Encrypt,Method<29); #endif } } #ifndef SFX_MODULE void ComprDataIO::SetAV15Encryption() { Decryption=15; Decrypt.SetAV15Encryption(); } #endif #ifndef SFX_MODULE void ComprDataIO::SetCmt13Encryption() { Decryption=13; Decrypt.SetCmt13Encryption(); } #endif void ComprDataIO::SetUnpackToMemory(byte *Addr,uint Size) { UnpackToMemory=true; UnpackToMemoryAddr=Addr; UnpackToMemorySize=Size; }