uint CalcFileCRC(File *SrcFile,int64 Size,CALCCRC_SHOWMODE ShowMode) { SaveFilePos SavePos(*SrcFile); const size_t BufSize=0x10000; Array<byte> Data(BufSize); int64 BlockCount=0; uint DataCRC=0xffffffff; #if !defined(SILENT) && !defined(_WIN_CE) int64 FileLength=SrcFile->FileLength(); if (ShowMode!=CALCCRC_SHOWNONE) { mprintf(St(MCalcCRC)); mprintf(" "); } #endif SrcFile->Seek(0,SEEK_SET); while (true) { size_t SizeToRead; if (Size==INT64NDF) // If we process the entire file. SizeToRead=BufSize; // Then always attempt to read the entire buffer. else SizeToRead=(size_t)Min((int64)BufSize,Size); int ReadSize=SrcFile->Read(&Data[0],SizeToRead); if (ReadSize==0) break; ++BlockCount; if ((BlockCount & 15)==0) { #if !defined(SILENT) && !defined(_WIN_CE) if (ShowMode==CALCCRC_SHOWALL) mprintf("\b\b\b\b%3d%%",ToPercent(BlockCount*int64(BufSize),FileLength)); #endif Wait(); } DataCRC=CRC(DataCRC,&Data[0],ReadSize); if (Size!=INT64NDF) Size-=ReadSize; } #if !defined(SILENT) && !defined(_WIN_CE) if (ShowMode==CALCCRC_SHOWALL) mprintf("\b\b\b\b "); #endif return(DataCRC^0xffffffff); }
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::ShowUnpRead(int64 ArcPos,int64 ArcSize) { if (ShowProgress && SrcFile!=NULL) { if (TotalArcSize!=0) { // important when processing several archives or multivolume archive ArcSize=TotalArcSize; ArcPos+=ProcessedArcSize; } Archive *SrcArc=(Archive *)SrcFile; RAROptions *Cmd=SrcArc->GetRAROptions(); int CurPercent=ToPercent(ArcPos,ArcSize); if (!Cmd->DisablePercentage && CurPercent!=LastPercent) { LastPercent=CurPercent; } } }
void ComprDataIO::ShowUnpRead(int64 ArcPos,int64 ArcSize) { return; // OPENMPT ADDITION if (ShowProgress && SrcFile!=NULL) { if (TotalArcSize!=0) { // important when processing several archives or multivolume archive ArcSize=TotalArcSize; ArcPos+=ProcessedArcSize; } Archive *SrcArc=(Archive *)SrcFile; RAROptions *Cmd=SrcArc->GetRAROptions(); int CurPercent=ToPercent(ArcPos,ArcSize); if (!Cmd->DisablePercentage && CurPercent!=LastPercent) { uiExtractProgress(CurUnpWrite,SrcArc->FileHead.UnpSize,ArcPos,ArcSize); LastPercent=CurPercent; } } }
void CalcFileSum(File *SrcFile,uint *CRC32,byte *Blake2,uint Threads,int64 Size,uint Flags) { SaveFilePos SavePos(*SrcFile); #ifndef SILENT int64 FileLength=SrcFile->FileLength(); if ((Flags & (CALCFSUM_SHOWTEXT|CALCFSUM_SHOWALL))!=0) { mprintf(St(MCalcCRC)); mprintf(L" "); } #endif if ((Flags & CALCFSUM_CURPOS)==0) SrcFile->Seek(0,SEEK_SET); const size_t BufSize=0x100000; Array<byte> Data(BufSize); DataHash HashCRC,HashBlake2; HashCRC.Init(HASH_CRC32,Threads); HashBlake2.Init(HASH_BLAKE2,Threads); int64 BlockCount=0; while (true) { size_t SizeToRead; if (Size==INT64NDF) // If we process the entire file. SizeToRead=BufSize; // Then always attempt to read the entire buffer. else SizeToRead=(size_t)Min((int64)BufSize,Size); int ReadSize=SrcFile->Read(&Data[0],SizeToRead); if (ReadSize==0) break; if ((++BlockCount & 0xf)==0) { #ifndef SILENT if ((Flags & CALCFSUM_SHOWALL)!=0) mprintf(L"\b\b\b\b%3d%%",ToPercent(BlockCount*int64(BufSize),FileLength)); #endif Wait(); } if (CRC32!=NULL) HashCRC.Update(&Data[0],ReadSize); if (Blake2!=NULL) HashBlake2.Update(&Data[0],ReadSize); if (Size!=INT64NDF) Size-=ReadSize; } #ifndef SILENT if ((Flags & CALCFSUM_SHOWALL)!=0) mprintf(L"\b\b\b\b "); #endif if (CRC32!=NULL) *CRC32=HashCRC.GetCRC32(); if (Blake2!=NULL) { HashValue Result; HashBlake2.Result(&Result); memcpy(Blake2,Result.Digest,sizeof(Result.Digest)); } }
size_t Archive::ReadHeader15() { RawRead Raw(this); bool Decrypt=Encrypted && CurBlockPos>(int64)SFXSize+SIZEOF_MARKHEAD3; if (Decrypt) { #ifdef RAR_NOCRYPT // For rarext.dll and unrar_nocrypt.dll. return 0; #else RequestArcPassword(); byte Salt[SIZE_SALT30]; if (Read(Salt,SIZE_SALT30)!=SIZE_SALT30) { UnexpEndArcMsg(); return 0; } HeadersCrypt.SetCryptKeys(false,CRYPT_RAR30,&Cmd->Password,Salt,NULL,0,NULL,NULL); Raw.SetCrypt(&HeadersCrypt); #endif } Raw.Read(SIZEOF_SHORTBLOCKHEAD); if (Raw.Size()==0) { UnexpEndArcMsg(); return 0; } ShortBlock.HeadCRC=Raw.Get2(); ShortBlock.Reset(); uint HeaderType=Raw.Get1(); ShortBlock.Flags=Raw.Get2(); ShortBlock.SkipIfUnknown=(ShortBlock.Flags & SKIP_IF_UNKNOWN)!=0; ShortBlock.HeadSize=Raw.Get2(); ShortBlock.HeaderType=(HEADER_TYPE)HeaderType; if (ShortBlock.HeadSize<SIZEOF_SHORTBLOCKHEAD) { BrokenHeaderMsg(); return 0; } // For simpler further processing we map header types common // for RAR 1.5 and 5.0 formats to RAR 5.0 values. It does not include // header types specific for RAR 1.5 - 4.x only. switch(ShortBlock.HeaderType) { case HEAD3_MAIN: ShortBlock.HeaderType=HEAD_MAIN; break; case HEAD3_FILE: ShortBlock.HeaderType=HEAD_FILE; break; case HEAD3_SERVICE: ShortBlock.HeaderType=HEAD_SERVICE; break; case HEAD3_ENDARC: ShortBlock.HeaderType=HEAD_ENDARC; break; } CurHeaderType=ShortBlock.HeaderType; if (ShortBlock.HeaderType==HEAD3_CMT) { // Old style (up to RAR 2.9) comment header embedded into main // or file header. We must not read the entire ShortBlock.HeadSize here // to not break the comment processing logic later. Raw.Read(SIZEOF_COMMHEAD-SIZEOF_SHORTBLOCKHEAD); } else if (ShortBlock.HeaderType==HEAD_MAIN && (ShortBlock.Flags & MHD_COMMENT)!=0) { // Old style (up to RAR 2.9) main archive comment embedded into // the main archive header found. While we can read the entire // ShortBlock.HeadSize here and remove this part of "if", it would be // waste of memory, because we'll read and process this comment data // in other function anyway and we do not need them here now. Raw.Read(SIZEOF_MAINHEAD3-SIZEOF_SHORTBLOCKHEAD); } else Raw.Read(ShortBlock.HeadSize-SIZEOF_SHORTBLOCKHEAD); NextBlockPos=CurBlockPos+FullHeaderSize(ShortBlock.HeadSize); switch(ShortBlock.HeaderType) { case HEAD_MAIN: MainHead.Reset(); *(BaseBlock *)&MainHead=ShortBlock; MainHead.HighPosAV=Raw.Get2(); MainHead.PosAV=Raw.Get4(); Volume=(MainHead.Flags & MHD_VOLUME)!=0; Solid=(MainHead.Flags & MHD_SOLID)!=0; Locked=(MainHead.Flags & MHD_LOCK)!=0; Protected=(MainHead.Flags & MHD_PROTECT)!=0; Encrypted=(MainHead.Flags & MHD_PASSWORD)!=0; Signed=MainHead.PosAV!=0 || MainHead.HighPosAV!=0; MainHead.CommentInHeader=(MainHead.Flags & MHD_COMMENT)!=0; // Only for encrypted 3.0+ archives. 2.x archives did not have this // flag, so for non-encrypted archives, we'll set it later based on // file attributes. FirstVolume=(MainHead.Flags & MHD_FIRSTVOLUME)!=0; NewNumbering=(MainHead.Flags & MHD_NEWNUMBERING)!=0; break; case HEAD_FILE: case HEAD_SERVICE: { bool FileBlock=ShortBlock.HeaderType==HEAD_FILE; FileHeader *hd=FileBlock ? &FileHead:&SubHead; hd->Reset(); *(BaseBlock *)hd=ShortBlock; hd->SplitBefore=(hd->Flags & LHD_SPLIT_BEFORE)!=0; hd->SplitAfter=(hd->Flags & LHD_SPLIT_AFTER)!=0; hd->Encrypted=(hd->Flags & LHD_PASSWORD)!=0; hd->SaltSet=(hd->Flags & LHD_SALT)!=0; hd->Solid=FileBlock && (hd->Flags & LHD_SOLID)!=0; hd->SubBlock=!FileBlock && (hd->Flags & LHD_SOLID)!=0; hd->Dir=(hd->Flags & LHD_WINDOWMASK)==LHD_DIRECTORY; hd->WinSize=hd->Dir ? 0:0x10000<<((hd->Flags & LHD_WINDOWMASK)>>5); hd->CommentInHeader=(hd->Flags & LHD_COMMENT)!=0; hd->Version=(hd->Flags & LHD_VERSION)!=0; hd->DataSize=Raw.Get4(); uint LowUnpSize=Raw.Get4(); hd->HostOS=Raw.Get1(); hd->FileHash.Type=HASH_CRC32; hd->FileHash.CRC32=Raw.Get4(); uint FileTime=Raw.Get4(); hd->UnpVer=Raw.Get1(); hd->Method=Raw.Get1()-0x30; size_t NameSize=Raw.Get2(); hd->FileAttr=Raw.Get4(); hd->CryptMethod=CRYPT_NONE; if (hd->Encrypted) switch(hd->UnpVer) { case 13: hd->CryptMethod=CRYPT_RAR13; break; case 15: hd->CryptMethod=CRYPT_RAR15; break; case 20: case 26: hd->CryptMethod=CRYPT_RAR20; break; default: hd->CryptMethod=CRYPT_RAR30; break; } hd->HSType=HSYS_UNKNOWN; if (hd->HostOS==HOST_UNIX || hd->HostOS==HOST_BEOS) hd->HSType=HSYS_UNIX; else if (hd->HostOS<HOST_MAX) hd->HSType=HSYS_WINDOWS; hd->RedirType=FSREDIR_NONE; // RAR 4.x Unix symlink. if (hd->HostOS==HOST_UNIX && (hd->FileAttr & 0xF000)==0xA000) { hd->RedirType=FSREDIR_UNIXSYMLINK; *hd->RedirName=0; } hd->Inherited=!FileBlock && (hd->SubFlags & SUBHEAD_FLAGS_INHERITED)!=0; hd->LargeFile=(hd->Flags & LHD_LARGE)!=0; uint HighPackSize,HighUnpSize; if (hd->LargeFile) { HighPackSize=Raw.Get4(); HighUnpSize=Raw.Get4(); hd->UnknownUnpSize=(LowUnpSize==0xffffffff && HighUnpSize==0xffffffff); } else { HighPackSize=HighUnpSize=0; // UnpSize equal to 0xffffffff without LHD_LARGE flag indicates // that we do not know the unpacked file size and must unpack it // until we find the end of file marker in compressed data. hd->UnknownUnpSize=(LowUnpSize==0xffffffff); } hd->PackSize=INT32TO64(HighPackSize,hd->DataSize); hd->UnpSize=INT32TO64(HighUnpSize,LowUnpSize); if (hd->UnknownUnpSize) hd->UnpSize=INT64NDF; char FileName[NM*4]; size_t ReadNameSize=Min(NameSize,ASIZE(FileName)-1); Raw.GetB((byte *)FileName,ReadNameSize); FileName[ReadNameSize]=0; if (FileBlock) { if ((hd->Flags & LHD_UNICODE)!=0) { EncodeFileName NameCoder; size_t Length=strlen(FileName); Length++; NameCoder.Decode(FileName,(byte *)FileName+Length, NameSize-Length,hd->FileName, ASIZE(hd->FileName)); } else *hd->FileName=0; char AnsiName[NM]; IntToExt(FileName,AnsiName,ASIZE(AnsiName)); GetWideName(AnsiName,hd->FileName,hd->FileName,ASIZE(hd->FileName)); #ifndef SFX_MODULE ConvertNameCase(hd->FileName); #endif ConvertFileHeader(hd); } else { CharToWide(FileName,hd->FileName,ASIZE(hd->FileName)); // Calculate the size of optional data. int DataSize=int(hd->HeadSize-NameSize-SIZEOF_FILEHEAD3); if ((hd->Flags & LHD_SALT)!=0) DataSize-=SIZE_SALT30; if (DataSize>0) { // Here we read optional additional fields for subheaders. // They are stored after the file name and before salt. hd->SubData.Alloc(DataSize); Raw.GetB(&hd->SubData[0],DataSize); if (hd->CmpName(SUBHEAD_TYPE_RR)) { byte *D=&hd->SubData[8]; RecoverySize=D[0]+((uint)D[1]<<8)+((uint)D[2]<<16)+((uint)D[3]<<24); RecoverySize*=512; // Sectors to size. int64 CurPos=Tell(); RecoveryPercent=ToPercent(RecoverySize,CurPos); // Round fractional percent exceeding .5 to upper value. if (ToPercent(RecoverySize+CurPos/200,CurPos)>RecoveryPercent) RecoveryPercent++; } } if (hd->CmpName(SUBHEAD_TYPE_CMT)) MainComment=true; } if ((hd->Flags & LHD_SALT)!=0) Raw.GetB(hd->Salt,SIZE_SALT30); hd->mtime.SetDos(FileTime); if ((hd->Flags & LHD_EXTTIME)!=0) { ushort Flags=Raw.Get2(); RarTime *tbl[4]; tbl[0]=&FileHead.mtime; tbl[1]=&FileHead.ctime; tbl[2]=&FileHead.atime; tbl[3]=NULL; // Archive time is not used now. for (int I=0;I<4;I++) { RarTime *CurTime=tbl[I]; uint rmode=Flags>>(3-I)*4; if ((rmode & 8)==0 || CurTime==NULL) continue; if (I!=0) { uint DosTime=Raw.Get4(); CurTime->SetDos(DosTime); } RarLocalTime rlt; CurTime->GetLocal(&rlt); if (rmode & 4) rlt.Second++; rlt.Reminder=0; int count=rmode&3; for (int J=0;J<count;J++) { byte CurByte=Raw.Get1(); rlt.Reminder|=(((uint)CurByte)<<((J+3-count)*8)); } CurTime->SetLocal(&rlt); } } NextBlockPos+=hd->PackSize; bool CRCProcessedOnly=hd->CommentInHeader; ushort HeaderCRC=Raw.GetCRC15(CRCProcessedOnly); if (hd->HeadCRC!=HeaderCRC) { BrokenHeader=true; ErrHandler.SetErrorCode(RARX_WARNING); // If we have a broken encrypted header, we do not need to display // the error message here, because it will be displayed for such // headers later in this function. Also such headers are unlikely // to have anything sensible in file name field, so it is useless // to display the file name. if (!Decrypt) uiMsg(UIERROR_FHEADERBROKEN,Archive::FileName,hd->FileName); } } break; case HEAD_ENDARC: *(BaseBlock *)&EndArcHead=ShortBlock; EndArcHead.NextVolume=(EndArcHead.Flags & EARC_NEXT_VOLUME)!=0; EndArcHead.DataCRC=(EndArcHead.Flags & EARC_DATACRC)!=0; EndArcHead.RevSpace=(EndArcHead.Flags & EARC_REVSPACE)!=0; EndArcHead.StoreVolNumber=(EndArcHead.Flags & EARC_VOLNUMBER)!=0; if (EndArcHead.DataCRC) EndArcHead.ArcDataCRC=Raw.Get4(); if (EndArcHead.StoreVolNumber) VolNumber=EndArcHead.VolNumber=Raw.Get2(); break; #ifndef SFX_MODULE case HEAD3_CMT: *(BaseBlock *)&CommHead=ShortBlock; CommHead.UnpSize=Raw.Get2(); CommHead.UnpVer=Raw.Get1(); CommHead.Method=Raw.Get1(); CommHead.CommCRC=Raw.Get2(); break; case HEAD3_SIGN: *(BaseBlock *)&SignHead=ShortBlock; SignHead.CreationTime=Raw.Get4(); SignHead.ArcNameSize=Raw.Get2(); SignHead.UserNameSize=Raw.Get2(); break; case HEAD3_AV: *(BaseBlock *)&AVHead=ShortBlock; AVHead.UnpVer=Raw.Get1(); AVHead.Method=Raw.Get1(); AVHead.AVVer=Raw.Get1(); AVHead.AVInfoCRC=Raw.Get4(); break; case HEAD3_PROTECT: *(BaseBlock *)&ProtectHead=ShortBlock; ProtectHead.DataSize=Raw.Get4(); ProtectHead.Version=Raw.Get1(); ProtectHead.RecSectors=Raw.Get2(); ProtectHead.TotalBlocks=Raw.Get4(); Raw.GetB(ProtectHead.Mark,8); NextBlockPos+=ProtectHead.DataSize; RecoverySize=ProtectHead.RecSectors*512; break; case HEAD3_OLDSERVICE: *(BaseBlock *)&SubBlockHead=ShortBlock; SubBlockHead.DataSize=Raw.Get4(); NextBlockPos+=SubBlockHead.DataSize; SubBlockHead.SubType=Raw.Get2(); SubBlockHead.Level=Raw.Get1(); switch(SubBlockHead.SubType) { case UO_HEAD: *(SubBlockHeader *)&UOHead=SubBlockHead; UOHead.OwnerNameSize=Raw.Get2(); UOHead.GroupNameSize=Raw.Get2(); if (UOHead.OwnerNameSize>=ASIZE(UOHead.OwnerName)) UOHead.OwnerNameSize=ASIZE(UOHead.OwnerName)-1; if (UOHead.GroupNameSize>=ASIZE(UOHead.GroupName)) UOHead.GroupNameSize=ASIZE(UOHead.GroupName)-1; Raw.GetB(UOHead.OwnerName,UOHead.OwnerNameSize); Raw.GetB(UOHead.GroupName,UOHead.GroupNameSize); UOHead.OwnerName[UOHead.OwnerNameSize]=0; UOHead.GroupName[UOHead.GroupNameSize]=0; break; case MAC_HEAD: *(SubBlockHeader *)&MACHead=SubBlockHead; MACHead.fileType=Raw.Get4(); MACHead.fileCreator=Raw.Get4(); break; case EA_HEAD: case BEEA_HEAD: case NTACL_HEAD: *(SubBlockHeader *)&EAHead=SubBlockHead; EAHead.UnpSize=Raw.Get4(); EAHead.UnpVer=Raw.Get1(); EAHead.Method=Raw.Get1(); EAHead.EACRC=Raw.Get4(); break; case STREAM_HEAD: *(SubBlockHeader *)&StreamHead=SubBlockHead; StreamHead.UnpSize=Raw.Get4(); StreamHead.UnpVer=Raw.Get1(); StreamHead.Method=Raw.Get1(); StreamHead.StreamCRC=Raw.Get4(); StreamHead.StreamNameSize=Raw.Get2(); if (StreamHead.StreamNameSize>=ASIZE(StreamHead.StreamName)) StreamHead.StreamNameSize=ASIZE(StreamHead.StreamName)-1; Raw.GetB(StreamHead.StreamName,StreamHead.StreamNameSize); StreamHead.StreamName[StreamHead.StreamNameSize]=0; break; } break; #endif default: if (ShortBlock.Flags & LONG_BLOCK) NextBlockPos+=Raw.Get4(); break; }
void QuickView::DisplayObject() { if (m_Flags.Check(FSCROBJ_ISREDRAWING)) return; m_Flags.Set(FSCROBJ_ISREDRAWING); if (!QView && !ProcessingPluginCommand) Parent()->GetAnotherPanel(this)->UpdateViewPanel(); if (this->Destroyed()) return; if (QView) QView->SetPosition(m_X1+1,m_Y1+1,m_X2-1,m_Y2-3); Box(m_X1,m_Y1,m_X2,m_Y2,colors::PaletteColorToFarColor(COL_PANELBOX),DOUBLE_BOX); SetScreen(m_X1+1,m_Y1+1,m_X2-1,m_Y2-1,L' ',colors::PaletteColorToFarColor(COL_PANELTEXT)); SetColor(m_Focus ? COL_PANELSELECTEDTITLE:COL_PANELTITLE); string strTitle = GetTitle(); if (!strTitle.empty()) { GotoXY(m_X1+(m_X2-m_X1+1-(int)strTitle.size())/2,m_Y1); Text(strTitle); } DrawSeparator(m_Y2-2); SetColor(COL_PANELTEXT); GotoXY(m_X1+1,m_Y2-1); Global->FS << fmt::LeftAlign()<<fmt::ExactWidth(m_X2-m_X1-1)<<PointToName(strCurFileName); if (!strCurFileType.empty()) { string strTypeText=L" "; strTypeText+=strCurFileType; strTypeText+=L" "; TruncStr(strTypeText,m_X2-m_X1-1); SetColor(COL_PANELSELECTEDINFO); GotoXY(m_X1+(m_X2-m_X1+1-(int)strTypeText.size())/2,m_Y2-2); Text(strTypeText); } if (Directory) { FormatString FString; string DisplayName(strCurFileName); TruncPathStr(DisplayName,std::max(0, m_X2-m_X1-1-StrLength(MSG(MQuickViewFolder))-5)); FString<<MSG(MQuickViewFolder)<<L" \""<<DisplayName<<L"\""; SetColor(COL_PANELTEXT); GotoXY(m_X1+2,m_Y1+2); PrintText(FString); DWORD currAttr=os::GetFileAttributes(strCurFileName); // обламывается, если нет доступа if (currAttr != INVALID_FILE_ATTRIBUTES && (currAttr&FILE_ATTRIBUTE_REPARSE_POINT)) { string Tmp, Target; DWORD ReparseTag=0; const wchar_t* PtrName; if (GetReparsePointInfo(strCurFileName, Target, &ReparseTag)) { NormalizeSymlinkName(Target); switch(ReparseTag) { // 0xA0000003L = Directory Junction or Volume Mount Point case IO_REPARSE_TAG_MOUNT_POINT: { LNGID ID_Msg = MQuickViewJunction; bool Root; if(ParsePath(Target, nullptr, &Root) == PATH_VOLUMEGUID && Root) { ID_Msg=MQuickViewVolMount; } PtrName = MSG(ID_Msg); } break; // 0xA000000CL = Directory or File Symbolic Link case IO_REPARSE_TAG_SYMLINK: PtrName = MSG(MQuickViewSymlink); break; // 0x8000000AL = Distributed File System case IO_REPARSE_TAG_DFS: PtrName = MSG(MQuickViewDFS); break; // 0x80000012L = Distributed File System Replication case IO_REPARSE_TAG_DFSR: PtrName = MSG(MQuickViewDFSR); break; // 0xC0000004L = Hierarchical Storage Management case IO_REPARSE_TAG_HSM: PtrName = MSG(MQuickViewHSM); break; // 0x80000006L = Hierarchical Storage Management2 case IO_REPARSE_TAG_HSM2: PtrName = MSG(MQuickViewHSM2); break; // 0x80000007L = Single Instance Storage case IO_REPARSE_TAG_SIS: PtrName = MSG(MQuickViewSIS); break; // 0x80000008L = Windows Imaging Format case IO_REPARSE_TAG_WIM: PtrName = MSG(MQuickViewWIM); break; // 0x80000009L = Cluster Shared Volumes case IO_REPARSE_TAG_CSV: PtrName = MSG(MQuickViewCSV); break; case IO_REPARSE_TAG_DEDUP: PtrName = MSG(MQuickViewDEDUP); break; case IO_REPARSE_TAG_NFS: PtrName = MSG(MQuickViewNFS); break; case IO_REPARSE_TAG_FILE_PLACEHOLDER: PtrName = MSG(MQuickViewPlaceholder); break; // 0x????????L = anything else default: if (Global->Opt->ShowUnknownReparsePoint) { Tmp = FormatString() << L":" << fmt::Radix(16) << fmt::ExactWidth(8) << fmt::FillChar(L'0') << ReparseTag; PtrName = Tmp.data(); } else { PtrName=MSG(MQuickViewUnknownReparsePoint); } } } else { PtrName = MSG(MQuickViewUnknownReparsePoint); Target = MSG(MQuickViewNoData); } TruncPathStr(Target,std::max(0, m_X2-m_X1-1-StrLength(PtrName)-5)); FString.clear(); FString<<PtrName<<L" \""<<Target<<L"\""; SetColor(COL_PANELTEXT); GotoXY(m_X1+2,m_Y1+3); PrintText(FString); } if (Directory==1 || Directory==4) { const auto iColor = uncomplete_dirscan? COL_PANELHIGHLIGHTTEXT : COL_PANELINFOTEXT; const wchar_t *prefix = uncomplete_dirscan ? L"~" : L""; GotoXY(m_X1+2,m_Y1+4); PrintText(MSG(MQuickViewContains)); GotoXY(m_X1+2,m_Y1+6); PrintText(MSG(MQuickViewFolders)); SetColor(iColor); FString.clear(); FString<<prefix<<Data.DirCount; PrintText(FString); SetColor(COL_PANELTEXT); GotoXY(m_X1+2,m_Y1+7); PrintText(MSG(MQuickViewFiles)); SetColor(iColor); FString.clear(); FString<<prefix<<Data.FileCount; PrintText(FString); SetColor(COL_PANELTEXT); GotoXY(m_X1+2,m_Y1+8); PrintText(MSG(MQuickViewBytes)); SetColor(iColor); string strSize; InsertCommas(Data.FileSize,strSize); PrintText(prefix+strSize); SetColor(COL_PANELTEXT); GotoXY(m_X1+2,m_Y1+9); PrintText(MSG(MQuickViewAllocated)); SetColor(iColor); InsertCommas(Data.AllocationSize,strSize); FString.clear(); FString << prefix << strSize << L" (" << ToPercent(Data.AllocationSize,Data.FileSize) << L"%)"; PrintText(FString); if (Directory!=4) { SetColor(COL_PANELTEXT); GotoXY(m_X1+2,m_Y1+11); PrintText(MSG(MQuickViewCluster)); SetColor(iColor); InsertCommas(Data.ClusterSize,strSize); PrintText(prefix+strSize); SetColor(COL_PANELTEXT); GotoXY(m_X1+2,m_Y1+12); PrintText(MSG(MQuickViewSlack)); SetColor(iColor); InsertCommas(Data.FilesSlack, strSize); FString.clear(); FString << prefix << strSize << L" (" << ToPercent(Data.FilesSlack, Data.AllocationSize) << L"%)"; PrintText(FString); SetColor(COL_PANELTEXT); GotoXY(m_X1+2,m_Y1+13); PrintText(MSG(MQuickViewMFTOverhead)); SetColor(iColor); InsertCommas(Data.MFTOverhead, strSize); FString.clear(); FString<<prefix<<strSize<<L" ("<<ToPercent(Data.MFTOverhead, Data.AllocationSize)<<L"%)"; PrintText(FString); } } } else if (QView) QView->Show(); m_Flags.Clear(FSCROBJ_ISREDRAWING); }
bool RecVolumes5::Restore(RAROptions *Cmd,const wchar *Name,bool Silent) { wchar ArcName[NM]; wcscpy(ArcName,Name); wchar *Num=GetVolNumPart(ArcName); while (Num>ArcName && IsDigit(*(Num-1))) Num--; wcsncpyz(Num,L"*.*",ASIZE(ArcName)-(Num-ArcName)); wchar FirstVolName[NM]; *FirstVolName=0; int64 RecFileSize=0; FindFile VolFind; VolFind.SetMask(ArcName); FindData fd; uint FoundRecVolumes=0; while (VolFind.Next(&fd)) { Wait(); Archive *Vol=new Archive(Cmd); int ItemPos=-1; if (Vol->WOpen(fd.Name)) { if (CmpExt(fd.Name,L"rev")) { uint RecNum=ReadHeader(Vol,FoundRecVolumes==0); if (RecNum!=0) { if (FoundRecVolumes==0) RecFileSize=Vol->FileLength(); ItemPos=RecNum; FoundRecVolumes++; } } else if (Vol->IsArchive(true) && (Vol->SFXSize>0 || CmpExt(fd.Name,L"rar"))) { if (!Vol->Volume && !Vol->BrokenHeader) { uiMsg(UIERROR_NOTVOLUME,ArcName); return false; } // We work with archive as with raw data file, so we do not want // to spend time to QOpen I/O redirection. Vol->QOpenUnload(); Vol->Seek(0,SEEK_SET); // RAR volume found. Get its number, store the handle in appropriate // array slot, clean slots in between if we had to grow the array. wchar *Num=GetVolNumPart(fd.Name); uint VolNum=0; for (uint K=1;Num>=fd.Name && IsDigit(*Num);K*=10,Num--) VolNum+=(*Num-'0')*K; if (VolNum==0 || VolNum>MaxVolumes) continue; size_t CurSize=RecItems.Size(); if (VolNum>CurSize) { RecItems.Alloc(VolNum); for (size_t I=CurSize;I<VolNum;I++) RecItems[I].f=NULL; } ItemPos=VolNum-1; if (*FirstVolName==0) VolNameToFirstName(fd.Name,FirstVolName,ASIZE(FirstVolName),true); } } if (ItemPos==-1) delete Vol; // Skip found file, it is not RAR or REV volume. else if ((uint)ItemPos<RecItems.Size()) // Check if found more REV than needed. { // Store found RAR or REV volume. RecVolItem *Item=RecItems+ItemPos; Item->f=Vol; Item->New=false; wcsncpyz(Item->Name,fd.Name,ASIZE(Item->Name)); } } if (!Silent || FoundRecVolumes!=0) uiMsg(UIMSG_RECVOLFOUND,FoundRecVolumes); if (FoundRecVolumes==0) return false; uiMsg(UIMSG_RECVOLCALCCHECKSUM); MissingVolumes=0; for (uint I=0;I<TotalCount;I++) { RecVolItem *Item=&RecItems[I]; if (Item->f!=NULL) { uiMsg(UIMSG_STRING,Item->Name); uint RevCRC; CalcFileSum(Item->f,&RevCRC,NULL,Cmd->Threads,INT64NDF,CALCFSUM_CURPOS); Item->Valid=RevCRC==Item->CRC; if (!Item->Valid) { uiMsg(UIMSG_CHECKSUM,Item->Name); // Close only corrupt REV volumes here. We'll close and rename corrupt // RAR volumes later, if we'll know that recovery is possible. if (I>=DataCount) { Item->f->Close(); Item->f=NULL; FoundRecVolumes--; } } } if (I<DataCount && (Item->f==NULL || !Item->Valid)) MissingVolumes++; } uiMsg(UIMSG_RECVOLMISSING,MissingVolumes); if (MissingVolumes==0) { uiMsg(UIERROR_RECVOLALLEXIST); return false; } if (MissingVolumes>FoundRecVolumes) { uiMsg(UIERROR_RECVOLFOUND,FoundRecVolumes); // Intentionally not displayed in console mode. uiMsg(UIERROR_RECVOLCANNOTFIX); return false; } uiMsg(UIMSG_RECONSTRUCTING); // Create missing and rename bad volumes. uint64 MaxVolSize=0; for (uint I=0;I<DataCount;I++) { RecVolItem *Item=&RecItems[I]; if (Item->FileSize>MaxVolSize) MaxVolSize=Item->FileSize; if (Item->f!=NULL && !Item->Valid) { Item->f->Close(); wchar NewName[NM]; wcscpy(NewName,Item->Name); wcscat(NewName,L".bad"); uiMsg(UIMSG_BADARCHIVE,Item->Name); uiMsg(UIMSG_RENAMING,Item->Name,NewName); RenameFile(Item->Name,NewName); delete Item->f; Item->f=NULL; } if (Item->New=(Item->f==NULL)) { wcsncpyz(Item->Name,FirstVolName,ASIZE(Item->Name)); uiMsg(UIMSG_CREATING,Item->Name); uiMsg(UIEVENT_NEWARCHIVE,Item->Name); File *NewVol=new File; bool UserReject; if (!FileCreate(Cmd,NewVol,Item->Name,ASIZE(Item->Name),&UserReject)) { if (!UserReject) ErrHandler.CreateErrorMsg(Item->Name); ErrHandler.Exit(UserReject ? RARX_USERBREAK:RARX_CREATE); } NewVol->Prealloc(Item->FileSize); Item->f=NewVol; Item->New=true; } NextVolumeName(FirstVolName,ASIZE(FirstVolName),false); } int64 ProcessedSize=0; #ifndef GUI int LastPercent=-1; mprintf(L" "); #endif // Even though we already preliminary calculated missing volume number, // let's do it again now, when we have the final and exact information. MissingVolumes=0; ValidFlags=new bool[TotalCount]; for (uint I=0;I<TotalCount;I++) { ValidFlags[I]=RecItems[I].f!=NULL && !RecItems[I].New; if (I<DataCount && !ValidFlags[I]) MissingVolumes++; } // Size of per file buffer. RecBufferSize=TotalBufferSize/MissingVolumes; if ((RecBufferSize&1)==1) // Must be even for our RS16 codec. RecBufferSize--; #ifdef USE_SSE RecBufferSize&=~(SSE_ALIGNMENT-1); // Align for SSE. #endif uint *Data=new uint[TotalCount]; RSCoder16 RS; if (!RS.Init(DataCount,RecCount,ValidFlags)) return false; // Should not happen, we check parameter validity above. RealReadBuffer=new byte[RecBufferSize+SSE_ALIGNMENT]; byte *ReadBuf=(byte *)ALIGN_VALUE(RealReadBuffer,SSE_ALIGNMENT); while (true) { Wait(); int MaxRead=0; for (uint I=0,J=DataCount;I<DataCount;I++) { uint VolNum=I; if (!ValidFlags[I]) // If next RAR volume is missing or invalid. { while (!ValidFlags[J]) // Find next valid REV volume. J++; VolNum=J++; // Use next valid REV volume data instead of RAR. } RecVolItem *Item=RecItems+VolNum; byte *B=&ReadBuf[0]; int ReadSize=0; if (Item->f!=NULL && !Item->New) ReadSize=Item->f->Read(B,RecBufferSize); if (ReadSize!=RecBufferSize) memset(B+ReadSize,0,RecBufferSize-ReadSize); if (ReadSize>MaxRead) MaxRead=ReadSize; // We can have volumes of different size. Let's use data chunk // for largest volume size. uint DataToProcess=(uint)Min(RecBufferSize,MaxVolSize-ProcessedSize); ProcessRS(Cmd,I,B,DataToProcess,false); } if (MaxRead==0) break; for (uint I=0,J=0;I<DataCount;I++) if (!ValidFlags[I]) { RecVolItem *Item=RecItems+I; size_t WriteSize=(size_t)Min(MaxRead,Item->FileSize); Item->f->Write(Buf+(J++)*RecBufferSize,WriteSize); Item->FileSize-=WriteSize; } int CurPercent=ToPercent(ProcessedSize,RecFileSize); if (!Cmd->DisablePercentage && CurPercent!=LastPercent) { uiProcessProgress("RV",ProcessedSize,RecFileSize); LastPercent=CurPercent; } ProcessedSize+=MaxRead; } for (uint I=0;I<TotalCount;I++) if (RecItems[I].f!=NULL) RecItems[I].f->Close(); delete[] ValidFlags; delete[] Data; #if !defined(GUI) && !defined(SILENT) if (!Cmd->DisablePercentage) mprintf(L"\b\b\b\b100%%"); if (!Silent && !Cmd->DisableDone) mprintf(St(MDone)); #endif return true; }
bool RecVolumes::Restore(RAROptions *Cmd,const char *Name,const wchar *NameW,bool Silent) { char ArcName[NM]; wchar ArcNameW[NM]; strcpy(ArcName,Name); wcscpy(ArcNameW,NameW); char *Ext=GetExt(ArcName); bool NewStyle=false; bool RevName=Ext!=NULL && stricomp(Ext,".rev")==0; if (RevName) { for (int DigitGroup=0;Ext>ArcName && DigitGroup<3;Ext--) if (!IsDigit(*Ext)) if (IsDigit(*(Ext-1)) && (*Ext=='_' || DigitGroup<2)) DigitGroup++; else if (DigitGroup<2) { NewStyle=true; break; } while (IsDigit(*Ext) && Ext>ArcName+1) Ext--; strcpy(Ext,"*.*"); if (*ArcNameW!=0) { wchar *ExtW=GetExt(ArcNameW); for (int DigitGroup=0;ExtW>ArcNameW && DigitGroup<3;ExtW--) if (!IsDigit(*ExtW)) if (IsDigit(*(ExtW-1)) && (*ExtW=='_' || DigitGroup<2)) DigitGroup++; else if (DigitGroup<2) { NewStyle=true; break; } while (IsDigit(*ExtW) && ExtW>ArcNameW+1) ExtW--; wcscpy(ExtW,L"*.*"); } FindFile Find; Find.SetMask(ArcName); Find.SetMaskW(ArcNameW); FindData fd; while (Find.Next(&fd)) { Archive Arc(Cmd); if (Arc.WOpen(fd.Name,fd.NameW) && Arc.IsArchive(true)) { strcpy(ArcName,fd.Name); wcscpy(ArcNameW,fd.NameW); break; } } } Archive Arc(Cmd); if (!Arc.WCheckOpen(ArcName,ArcNameW)) return(false); if (!Arc.Volume) { #ifndef SILENT Log(ArcName,St(MNotVolume),ArcName); #endif return(false); } bool NewNumbering=(Arc.NewMhd.Flags & MHD_NEWNUMBERING)!=0; Arc.Close(); char *VolNumStart=VolNameToFirstName(ArcName,ArcName,NewNumbering); char RecVolMask[NM]; strcpy(RecVolMask,ArcName); size_t BaseNamePartLength=VolNumStart-ArcName; strcpy(RecVolMask+BaseNamePartLength,"*.rev"); wchar RecVolMaskW[NM]; size_t BaseNamePartLengthW=0; *RecVolMaskW=0; if (*ArcNameW!=0) { wchar *VolNumStartW=VolNameToFirstName(ArcNameW,ArcNameW,NewNumbering); wcscpy(RecVolMaskW,ArcNameW); BaseNamePartLengthW=VolNumStartW-ArcNameW; wcscpy(RecVolMaskW+BaseNamePartLengthW,L"*.rev"); } #ifndef SILENT int64 RecFileSize=0; #endif // We cannot display "Calculating CRC..." message here, because we do not // know if we'll find any recovery volumes. We'll display it after finding // the first recovery volume. bool CalcCRCMessageDone=false; FindFile Find; Find.SetMask(RecVolMask); Find.SetMaskW(RecVolMaskW); FindData RecData; int FileNumber=0,RecVolNumber=0,FoundRecVolumes=0,MissingVolumes=0; char PrevName[NM]; wchar PrevNameW[NM]; while (Find.Next(&RecData)) { char *CurName=RecData.Name; wchar *CurNameW=RecData.NameW; int P[3]; if (!RevName && !NewStyle) { NewStyle=true; char *Dot=GetExt(CurName); if (Dot!=NULL) { int LineCount=0; Dot--; while (Dot>CurName && *Dot!='.') { if (*Dot=='_') LineCount++; Dot--; } if (LineCount==2) NewStyle=false; } wchar *DotW=GetExt(CurNameW); if (DotW!=NULL) { int LineCount=0; DotW--; while (DotW>CurNameW && *DotW!='.') { if (*DotW=='_') LineCount++; DotW--; } if (LineCount==2) NewStyle=false; } } if (NewStyle) { if (!CalcCRCMessageDone) { #ifndef SILENT mprintf(St(MCalcCRCAllVol)); #endif CalcCRCMessageDone=true; } #ifndef SILENT mprintf("\r\n%s",CurName); #endif File CurFile; CurFile.TOpen(CurName,CurNameW); CurFile.Seek(0,SEEK_END); int64 Length=CurFile.Tell(); CurFile.Seek(Length-7,SEEK_SET); for (int I=0;I<3;I++) P[2-I]=CurFile.GetByte()+1; uint FileCRC=0; for (int I=0;I<4;I++) FileCRC|=CurFile.GetByte()<<(I*8); if (FileCRC!=CalcFileCRC(&CurFile,Length-4)) { #ifndef SILENT mprintf(St(MCRCFailed),CurName); #endif continue; } } else { char *Dot=GetExt(CurName); if (Dot==NULL) continue; bool WrongParam=false; for (int I=0;I<ASIZE(P);I++) { do { Dot--; } while (IsDigit(*Dot) && Dot>=CurName+BaseNamePartLength); P[I]=atoi(Dot+1); if (P[I]==0 || P[I]>255) WrongParam=true; } if (WrongParam) continue; } if (P[1]+P[2]>255) continue; if (RecVolNumber!=0 && RecVolNumber!=P[1] || FileNumber!=0 && FileNumber!=P[2]) { #ifndef SILENT Log(NULL,St(MRecVolDiffSets),CurName,PrevName); #endif return(false); } RecVolNumber=P[1]; FileNumber=P[2]; strcpy(PrevName,CurName); wcscpy(PrevNameW,CurNameW); File *NewFile=new File; NewFile->TOpen(CurName,CurNameW); SrcFile[FileNumber+P[0]-1]=NewFile; FoundRecVolumes++; #ifndef SILENT if (RecFileSize==0) RecFileSize=NewFile->FileLength(); #endif } #ifndef SILENT if (!Silent || FoundRecVolumes!=0) { mprintf(St(MRecVolFound),FoundRecVolumes); } #endif if (FoundRecVolumes==0) return(false); bool WriteFlags[256]; memset(WriteFlags,0,sizeof(WriteFlags)); char LastVolName[NM]; *LastVolName=0; wchar LastVolNameW[NM]; *LastVolNameW=0; for (int CurArcNum=0;CurArcNum<FileNumber;CurArcNum++) { Archive *NewFile=new Archive; bool ValidVolume=FileExist(ArcName,ArcNameW); if (ValidVolume) { NewFile->TOpen(ArcName,ArcNameW); ValidVolume=NewFile->IsArchive(false); if (ValidVolume) { while (NewFile->ReadHeader()!=0) { if (NewFile->GetHeaderType()==ENDARC_HEAD) { #ifndef SILENT mprintf("\r\n%s",ArcName); #endif if ((NewFile->EndArcHead.Flags&EARC_DATACRC)!=0 && NewFile->EndArcHead.ArcDataCRC!=CalcFileCRC(NewFile,NewFile->CurBlockPos)) { ValidVolume=false; #ifndef SILENT mprintf(St(MCRCFailed),ArcName); #endif } break; } NewFile->SeekToNext(); } } if (!ValidVolume) { NewFile->Close(); char NewName[NM]; strcpy(NewName,ArcName); strcat(NewName,".bad"); wchar NewNameW[NM]; wcscpy(NewNameW,ArcNameW); if (*NewNameW!=0) wcscat(NewNameW,L".bad"); #ifndef SILENT mprintf(St(MBadArc),ArcName); mprintf(St(MRenaming),ArcName,NewName); #endif RenameFile(ArcName,ArcNameW,NewName,NewNameW); } NewFile->Seek(0,SEEK_SET); } if (!ValidVolume) { // It is important to return 'false' instead of aborting here, // so if we are called from extraction, we will be able to continue extracting. // It may happen if .rar and .rev are on read-only disks like CDs. if (!NewFile->Create(ArcName,ArcNameW)) { // We need to display the title of operation before the error message, // to make clear for user that create error is related to recovery // volumes. This is why we cannot use WCreate call here. Title must be // before create error, not after that. #ifndef SILENT mprintf(St(MReconstructing)); #endif ErrHandler.CreateErrorMsg(ArcName,ArcNameW); return false; } WriteFlags[CurArcNum]=true; MissingVolumes++; if (CurArcNum==FileNumber-1) { strcpy(LastVolName,ArcName); wcscpy(LastVolNameW,ArcNameW); } #ifndef SILENT mprintf(St(MAbsNextVol),ArcName); #endif } SrcFile[CurArcNum]=(File*)NewFile; NextVolumeName(ArcName,ArcNameW,ASIZE(ArcName),!NewNumbering); } #ifndef SILENT mprintf(St(MRecVolMissing),MissingVolumes); #endif if (MissingVolumes==0) { #ifndef SILENT mprintf(St(MRecVolAllExist)); #endif return(false); } if (MissingVolumes>FoundRecVolumes) { #ifndef SILENT mprintf(St(MRecVolCannotFix)); #endif return(false); } #ifndef SILENT mprintf(St(MReconstructing)); #endif int TotalFiles=FileNumber+RecVolNumber; int Erasures[256],EraSize=0; for (int I=0;I<TotalFiles;I++) if (WriteFlags[I] || SrcFile[I]==NULL) Erasures[EraSize++]=I; #ifndef SILENT int64 ProcessedSize=0; #ifndef GUI int LastPercent=-1; mprintf(" "); #endif #endif // Size of per file buffer. size_t RecBufferSize=TotalBufferSize/TotalFiles; #ifdef RAR_SMP uint ThreadNumber=Cmd->Threads; RSEncode rse[MaxPoolThreads]; uint WaitHandles[MaxPoolThreads]; #else uint ThreadNumber=1; RSEncode rse[1]; #endif for (uint I=0;I<ThreadNumber;I++) rse[I].Init(RecVolNumber); while (true) { Wait(); int MaxRead=0; for (int I=0;I<TotalFiles;I++) if (WriteFlags[I] || SrcFile[I]==NULL) memset(&Buf[I*RecBufferSize],0,RecBufferSize); else { int ReadSize=SrcFile[I]->Read(&Buf[I*RecBufferSize],RecBufferSize); if (ReadSize!=RecBufferSize) memset(&Buf[I*RecBufferSize+ReadSize],0,RecBufferSize-ReadSize); if (ReadSize>MaxRead) MaxRead=ReadSize; } if (MaxRead==0) break; #ifndef SILENT int CurPercent=ToPercent(ProcessedSize,RecFileSize); if (!Cmd->DisablePercentage && CurPercent!=LastPercent) { mprintf("\b\b\b\b%3d%%",CurPercent); LastPercent=CurPercent; } ProcessedSize+=MaxRead; #endif int BlockStart=0; int BlockSize=MaxRead/ThreadNumber; if (BlockSize<0x100) BlockSize=MaxRead; uint CurThread=0; while (BlockStart<MaxRead) { // Last thread processes all left data including increasement from rounding error. if (CurThread==ThreadNumber-1) BlockSize=MaxRead-BlockStart; RSEncode *curenc=rse+CurThread; curenc->Buf=&Buf[0]; curenc->BufStart=BlockStart; curenc->BufEnd=BlockStart+BlockSize; curenc->FileNumber=TotalFiles; curenc->RecBufferSize=RecBufferSize; curenc->Erasures=Erasures; curenc->EraSize=EraSize; #ifdef RAR_SMP if (ThreadNumber>1) { uint Handle=RSThreadPool.Start(RSDecodeThread,(void*)curenc); WaitHandles[CurThread++]=Handle; } else curenc->DecodeBuf(); #else curenc->DecodeBuf(); #endif BlockStart+=BlockSize; } #ifdef RAR_SMP if (CurThread>0) RSThreadPool.Wait(WaitHandles,CurThread); #endif // RAR_SMP for (int I=0;I<FileNumber;I++) if (WriteFlags[I]) SrcFile[I]->Write(&Buf[I*RecBufferSize],MaxRead); } for (int I=0;I<RecVolNumber+FileNumber;I++) if (SrcFile[I]!=NULL) { File *CurFile=SrcFile[I]; if (NewStyle && WriteFlags[I]) { int64 Length=CurFile->Tell(); CurFile->Seek(Length-7,SEEK_SET); for (int J=0;J<7;J++) CurFile->PutByte(0); } CurFile->Close(); SrcFile[I]=NULL; } if (*LastVolName!=0 || *LastVolNameW!=0) { // Truncate the last volume to its real size. Archive Arc(Cmd); if (Arc.Open(LastVolName,LastVolNameW,FMF_UPDATE) && Arc.IsArchive(true) && Arc.SearchBlock(ENDARC_HEAD)) { Arc.Seek(Arc.NextBlockPos,SEEK_SET); char Buf[8192]; int ReadSize=Arc.Read(Buf,sizeof(Buf)); int ZeroCount=0; while (ZeroCount<ReadSize && Buf[ZeroCount]==0) ZeroCount++; if (ZeroCount==ReadSize) { Arc.Seek(Arc.NextBlockPos,SEEK_SET); Arc.Truncate(); } } } #if !defined(GUI) && !defined(SILENT) if (!Cmd->DisablePercentage) mprintf("\b\b\b\b100%%"); if (!Silent && !Cmd->DisableDone) mprintf(St(MDone)); #endif return(true); }
void PluginClass::GetOpenPluginInfo(struct OpenPluginInfo *Info) { Info->StructSize=sizeof(*Info); Info->Flags=OPIF_USEFILTER|OPIF_USESORTGROUPS|OPIF_USEHIGHLIGHTING| OPIF_ADDDOTS|OPIF_COMPAREFATTIME; Info->HostFile=ArcName; Info->CurDir=CurDir; if (bGOPIFirstCall) ArcPlugin->GetFormatName(ArcPluginNumber,ArcPluginType,FormatName,DefExt); char NameTitle[NM]; lstrcpyn(NameTitle,FSF.PointToName(ArcName),sizeof(NameTitle)); { struct PanelInfo PInfo; if(::Info.Control((HANDLE)this,FCTL_GETPANELSHORTINFO,&PInfo)) { //TruncStr FSF.TruncPathStr(NameTitle,(PInfo.PanelRect.right-PInfo.PanelRect.left+1-(lstrlen(FormatName)+3+4))); } } FSF.sprintf(Title," %s:%s%s%s ",FormatName,NameTitle, *CurDir ? "\\" : "", *CurDir ? CurDir : ""); Info->PanelTitle=Title; if (bGOPIFirstCall || FarLangChanged()) { FSF.sprintf(Format,GetMsg(MArcFormat),FormatName); memset(InfoLines,0,sizeof(InfoLines)); FSF.sprintf(InfoLines[0].Text,GetMsg(MInfoTitle),FSF.PointToName(ArcName)); InfoLines[0].Separator=TRUE; FSF.sprintf(InfoLines[1].Text,GetMsg(MInfoArchive)); lstrcpy(InfoLines[1].Data,FormatName); if (ItemsInfo.UnpVer!=0) FSF.sprintf(InfoLines[1].Data+lstrlen(InfoLines[1].Data)," %d.%d", ItemsInfo.UnpVer/256,ItemsInfo.UnpVer%256); if (*ItemsInfo.HostOS) FSF.sprintf(InfoLines[1].Data+lstrlen(InfoLines[1].Data),"/%s",ItemsInfo.HostOS); lstrcpy(InfoLines[2].Text,GetMsg(MInfoArcType)); if (ItemsInfo.Solid) lstrcpy(InfoLines[2].Data,GetMsg(MInfoSolid)); if (CurArcInfo.SFXSize) { if (*InfoLines[2].Data) lstrcat(InfoLines[2].Data," "); lstrcat(InfoLines[2].Data,GetMsg(MInfoSFX)); } if (CurArcInfo.Flags & AF_HDRENCRYPTED) { if (*InfoLines[2].Data) lstrcat(InfoLines[2].Data," "); lstrcat(InfoLines[2].Data,GetMsg(MInfoHdrEncrypted)); } if (CurArcInfo.Volume) { if (*InfoLines[2].Data) lstrcat(InfoLines[2].Data," "); lstrcat(InfoLines[2].Data,GetMsg(MInfoVolume)); } if (*InfoLines[2].Data==0) lstrcpy(InfoLines[2].Data,GetMsg(MInfoNormal)); lstrcpy(InfoLines[3].Text,GetMsg(MInfoArcComment)); lstrcpy(InfoLines[3].Data,CurArcInfo.Comment ? GetMsg(MInfoPresent):GetMsg(MInfoAbsent)); lstrcpy(InfoLines[4].Text,GetMsg(MInfoFileComments)); lstrcpy(InfoLines[4].Data,ItemsInfo.Comment ? GetMsg(MInfoPresent):GetMsg(MInfoAbsent)); lstrcpy(InfoLines[5].Text,GetMsg(MInfoPasswords)); lstrcpy(InfoLines[5].Data,ItemsInfo.Encrypted ? GetMsg(MInfoPresent):GetMsg(MInfoAbsent)); lstrcpy(InfoLines[6].Text,GetMsg(MInfoRecovery)); lstrcpy(InfoLines[6].Data,CurArcInfo.Recovery ? GetMsg(MInfoPresent):GetMsg(MInfoAbsent)); lstrcpy(InfoLines[7].Text,GetMsg(MInfoLock)); lstrcpy(InfoLines[7].Data,CurArcInfo.Lock ? GetMsg(MInfoPresent):GetMsg(MInfoAbsent)); lstrcpy(InfoLines[8].Text,GetMsg(MInfoAuthVer)); lstrcpy(InfoLines[8].Data,(CurArcInfo.Flags & AF_AVPRESENT) ? GetMsg(MInfoPresent):GetMsg(MInfoAbsent)); lstrcpy(InfoLines[9].Text,GetMsg(MInfoDict)); if (ItemsInfo.DictSize==0) lstrcpy(InfoLines[9].Data,"???"); else FSF.sprintf(InfoLines[9].Data,"%d %s",ItemsInfo.DictSize,GetMsg(MInfoDictKb)); lstrcpy(InfoLines[10].Text,GetMsg(MInfoChapters)); if(CurArcInfo.Chapters) //FSF.sprintf(InfoLines[10].Data,"%d/%d",ItemsInfo.Chapter,CurArcInfo.Chapters); FSF.sprintf(InfoLines[10].Data,"%d",CurArcInfo.Chapters); else lstrcpy(InfoLines[10].Data,GetMsg(MInfoAbsent)); lstrcpy(InfoLines[11].Text,GetMsg(MInfoTotalFiles)); FSF.sprintf(InfoLines[11].Data,"%d",ArcDataCount); lstrcpy(InfoLines[12].Text,GetMsg(MInfoTotalSize)); InsertCommas(TotalSize,InfoLines[12].Data); lstrcpy(InfoLines[13].Text,GetMsg(MInfoPackedSize)); InsertCommas(PackedSize,InfoLines[13].Data); lstrcpy(InfoLines[14].Text,GetMsg(MInfoRatio)); FSF.sprintf(InfoLines[14].Data,"%d%%",ToPercent(PackedSize,TotalSize)); memset(&KeyBar,0,sizeof(KeyBar)); KeyBar.ShiftTitles[1-1]=(char*)""; KeyBar.AltTitles[6-1]=(char*)GetMsg(MAltF6); KeyBar.AltShiftTitles[9-1]=(char*)GetMsg(MAltShiftF9); } Info->Format=Format; Info->KeyBar=&KeyBar; Info->InfoLines=InfoLines; Info->InfoLinesNumber=ARRAYSIZE(InfoLines); lstrcpy(DescrFilesString,Opt.DescriptionNames); size_t DescrFilesNumber=0; char *NamePtr=DescrFilesString; while (DescrFilesNumber<ARRAYSIZE(DescrFiles)) { while (__isspace(*NamePtr)) NamePtr++; if (*NamePtr==0) break; DescrFiles[DescrFilesNumber++]=NamePtr; if ((NamePtr=strchr(NamePtr,','))==NULL) break; *(NamePtr++)=0; } Info->DescrFiles=DescrFiles; if (!Opt.ReadDescriptions || DizPresent) Info->DescrFilesNumber=0; else Info->DescrFilesNumber=(int)DescrFilesNumber; bGOPIFirstCall = false; }
void uiProcessProgress(const char *Command,int64 CurSize,int64 TotalSize) { int CurPercent=ToPercent(CurSize,TotalSize); mprintf(L"\b\b\b\b%3d%%",CurPercent); }
void uiExtractProgress(int64 CurFileSize,int64 TotalFileSize,int64 CurSize,int64 TotalSize) { int CurPercent=ToPercent(CurSize,TotalSize); mprintf(L"\b\b\b\b%3d%%",CurPercent); }
/**************************************** Callback called from GetFiles and PutFiles each time whole buffer sended or received to refresh state of copy progress Can be called in any plugin state (quite, not show, etc) ****************************************/ BOOL TrafficInformation::Callback(int Size) { double tmDiff; DWORD tm; time_t tmt; char str[MAX_PATH]; double TotalPercent,db; GET_TIME(tm); tmDiff = Abs(CMP_TIME(tm,LastTime)); tmt = time(NULL); FileSize += Size; FullFileSize = Max(FileSize,FullFileSize); if(Size && FTP_Info->CheckForEsc(FALSE,FALSE)) { Log(("User cancel")); return FALSE; } if(Size && tmDiff*1000 < FTP_Info->GetOpt()->IdleShowPeriod) return TRUE; memmove(&LastTime,&tm,sizeof(LastTime)); TotalPercent = ToPercent(TotalSz(),TotalFullSize); //Avg if(tmDiff > 0) { AvCps[0] = AvCps[1]; AvCps[1] = AvCps[2]; AvCps[2] = (FileSize - LastSize) / tmDiff; } LastSize = FileSize; //Cur db = ((double)tmt-FileStartTime-FileWaitTime); if(db > 0) Cps = FileSize / db; else Cps = 0; //Total db = ((double)tmt-TotalStartTime-TotalWaitTime); if(db > 0) TotalCps = (TotalSize+FileSize) / db; else TotalCps = 0; //Show QUIET progressing if(!ShowStatus) { _snprintf(str,ARRAYSIZE(str), "{%2.1lf%%} %s: %.26s", TotalPercent, FTP_Info->GetMsg(TitleMsg), FTP_Info->PointToName(SrcFileName)); FTP_Info->IdleMessage(str,FTP_Info->GetOpt()->ProcessColor); return TRUE; } //Window caption if(FTP_Info->FtpGetRetryCount()) _snprintf(str,ARRAYSIZE(str),"%d: {%2.1lf%%} %s - Far", FTP_Info->FtpGetRetryCount(), TotalPercent, FTP_Info->GetMsg(TitleMsg)); else _snprintf(str,ARRAYSIZE(str),"{%2.1lf%%} %s - Far", TotalPercent,FTP_Info->GetMsg(TitleMsg)); if(StrCmp(str,ConsoleTitle,-1,TRUE) != 0) { if(FTP_Info->WinVer->dwPlatformId != VER_PLATFORM_WIN32_NT) OemToChar(str,str); SetConsoleTitle(str); StrCpy(ConsoleTitle,str,ARRAYSIZE(ConsoleTitle)); } //Mark CMD window invisible FTP_Info->FtpCmdBlock(TRUE); //Show message LPCSTR MsgItems[MAX_TRAF_LINES+1]; DrawInfos(tmt); if(FTP_Info->FtpGetRetryCount()) _snprintf(str,ARRAYSIZE(str),"%d: %s",FTP_Info->FtpGetRetryCount(),FTP_Info->GetMsg(TitleMsg)); else StrCpy(str,FTP_Info->GetMsg(TitleMsg),ARRAYSIZE(str)); MsgItems[0] = str; int n; for(n = 0; n < LineCount; n++) MsgItems[n+1] = Lines[n]; FTP_Info->FMessage(FMSG_LEFTALIGN, NULL, (LPCSTR *)MsgItems, LineCount+1, 0); return TRUE; }
bool RecVolumes::Restore(RAROptions *Cmd,const char *Name, const wchar *NameW,bool Silent) { char ArcName[NM]; wchar ArcNameW[NM]; strcpy(ArcName,Name); strcpyw(ArcNameW,NameW); char *Ext=GetExt(ArcName); bool NewStyle=false; bool RevName=Ext!=NULL && stricomp(Ext,".rev")==0; if (RevName) { for (int DigitGroup=0;Ext>ArcName && DigitGroup<3;Ext--) if (!isdigit(*Ext)) { if (isdigit(*(Ext-1)) && (*Ext=='_' || DigitGroup<2)) DigitGroup++; else if (DigitGroup<2) { NewStyle=true; break; } } while (isdigit(*Ext) && Ext>ArcName+1) Ext--; strcpy(Ext,"*.*"); FindFile Find; Find.SetMask(ArcName); struct FindData FD; while (Find.Next(&FD)) { Archive Arc(Cmd); if (Arc.WOpen(FD.Name,FD.NameW) && Arc.IsArchive(true)) { strcpy(ArcName,FD.Name); *ArcNameW=0; break; } } } Archive Arc(Cmd); if (!Arc.WCheckOpen(ArcName,ArcNameW)) return(false); if (!Arc.Volume) { #ifndef SILENT Log(ArcName,St(MNotVolume),ArcName); #endif return(false); } bool NewNumbering=(Arc.NewMhd.Flags & MHD_NEWNUMBERING); Arc.Close(); char *VolNumStart=VolNameToFirstName(ArcName,ArcName,NewNumbering); char RecVolMask[NM]; strcpy(RecVolMask,ArcName); int BaseNamePartLength=VolNumStart-ArcName; strcpy(RecVolMask+BaseNamePartLength,"*.rev"); #ifndef SILENT Int64 RecFileSize=0; #endif FindFile Find; Find.SetMask(RecVolMask); struct FindData RecData; int FileNumber=0,RecVolNumber=0,FoundRecVolumes=0,MissingVolumes=0; char PrevName[NM]; while (Find.Next(&RecData)) { char *Name=RecData.Name; int P[3]; if (!RevName && !NewStyle) { NewStyle=true; char *Dot=GetExt(Name); if (Dot!=NULL) { int LineCount=0; Dot--; while (Dot>Name && *Dot!='.') { if (*Dot=='_') LineCount++; Dot--; } if (LineCount==2) NewStyle=false; } } if (NewStyle) { File CurFile; CurFile.TOpen(Name); CurFile.Seek(0,SEEK_END); Int64 Length=CurFile.Tell(); CurFile.Seek(Length-7,SEEK_SET); for (int I=0;I<3;I++) P[2-I]=CurFile.GetByte()+1; uint FileCRC=0; for (int I=0;I<4;I++) FileCRC|=CurFile.GetByte()<<(I*8); if (FileCRC!=CalcFileCRC(&CurFile,Length-4)) { #ifndef SILENT mprintf(St(MCRCFailed),Name); #endif continue; } } else { char *Dot=GetExt(Name); if (Dot==NULL) continue; bool WrongParam=false; for (unsigned int I=0;I<sizeof(P)/sizeof(P[0]);I++) { do { Dot--; } while (isdigit(*Dot) && Dot>=Name+BaseNamePartLength); P[I]=atoi(Dot+1); if (P[I]==0 || P[I]>255) WrongParam=true; } if (WrongParam) continue; } if (P[1]+P[2]>255) continue; if ((RecVolNumber!=0 && RecVolNumber!=P[1]) || (FileNumber!=0 && FileNumber!=P[2])) { #ifndef SILENT Log(NULL,St(MRecVolDiffSets),Name,PrevName); #endif return(false); } RecVolNumber=P[1]; FileNumber=P[2]; strcpy(PrevName,Name); File *NewFile=new File; NewFile->TOpen(Name); SrcFile[FileNumber+P[0]-1]=NewFile; FoundRecVolumes++; #ifndef SILENT if (RecFileSize==0) RecFileSize=NewFile->FileLength(); #endif } #ifndef SILENT if (!Silent || FoundRecVolumes!=0) { mprintf(St(MRecVolFound),FoundRecVolumes); } #endif if (FoundRecVolumes==0) return(false); bool WriteFlags[256]; memset(WriteFlags,0,sizeof(WriteFlags)); char LastVolName[NM]; *LastVolName=0; for (int CurArcNum=0;CurArcNum<FileNumber;CurArcNum++) { Archive *NewFile=new Archive; bool ValidVolume=FileExist(ArcName); if (ValidVolume) { NewFile->TOpen(ArcName); ValidVolume=NewFile->IsArchive(false); if (ValidVolume) { bool EndFound=false,EndBlockRequired=false; while (!EndFound && NewFile->ReadHeader()!=0) { if (NewFile->GetHeaderType()==FILE_HEAD) { if (NewFile->NewLhd.UnpVer>=29) EndBlockRequired=true; if (!EndBlockRequired && (NewFile->NewLhd.Flags & LHD_SPLIT_AFTER)) EndFound=true; } if (NewFile->GetHeaderType()==ENDARC_HEAD) { if ((NewFile->EndArcHead.Flags&EARC_DATACRC)!=0 && NewFile->EndArcHead.ArcDataCRC!=CalcFileCRC(NewFile,NewFile->CurBlockPos)) { ValidVolume=false; #ifndef SILENT mprintf(St(MCRCFailed),ArcName); #endif } EndFound=true; } NewFile->SeekToNext(); } if (!EndFound) ValidVolume=false; } if (!ValidVolume) { NewFile->Close(); char NewName[NM]; strcpy(NewName,ArcName); strcat(NewName,".bad"); #ifndef SILENT mprintf(St(MBadArc),ArcName); mprintf(St(MRenaming),ArcName,NewName); #endif rename(ArcName,NewName); } NewFile->Seek(0,SEEK_SET); } if (!ValidVolume) { NewFile->TCreate(ArcName); WriteFlags[CurArcNum]=true; MissingVolumes++; if (CurArcNum==FileNumber-1) strcpy(LastVolName,ArcName); #ifndef SILENT mprintf(St(MAbsNextVol),ArcName); #endif } SrcFile[CurArcNum]=(File*)NewFile; NextVolumeName(ArcName,!NewNumbering); } #ifndef SILENT mprintf(St(MRecVolMissing),MissingVolumes); #endif if (MissingVolumes==0) { #ifndef SILENT mprintf(St(MRecVolAllExist)); #endif return(false); } if (MissingVolumes>FoundRecVolumes) { #ifndef SILENT mprintf(St(MRecVolCannotFix)); #endif return(false); } #ifndef SILENT mprintf(St(MReconstructing)); #endif RSCoder RSC(RecVolNumber); int TotalFiles=FileNumber+RecVolNumber; int Erasures[256],EraSize=0; for (int I=0;I<TotalFiles;I++) if (WriteFlags[I] || SrcFile[I]==NULL) Erasures[EraSize++]=I; #ifndef SILENT Int64 ProcessedSize=0; #ifndef GUI int LastPercent=-1; mprintf(" "); #endif #endif int RecCount=0; while (true) { if ((++RecCount & 15)==0) Wait(); int MaxRead=0; for (int I=0;I<TotalFiles;I++) if (WriteFlags[I] || SrcFile[I]==NULL) memset(&Buf[I*RECVOL_BUFSIZE],0,RECVOL_BUFSIZE); else { int ReadSize=SrcFile[I]->Read(&Buf[I*RECVOL_BUFSIZE],RECVOL_BUFSIZE); if (ReadSize!=RECVOL_BUFSIZE) memset(&Buf[I*RECVOL_BUFSIZE+ReadSize],0,RECVOL_BUFSIZE-ReadSize); if (ReadSize>MaxRead) MaxRead=ReadSize; } if (MaxRead==0) break; #ifndef SILENT int CurPercent=ToPercent(ProcessedSize,RecFileSize); if (!Cmd->DisablePercentage && CurPercent!=LastPercent) { mprintf("\b\b\b\b%3d%%",CurPercent); LastPercent=CurPercent; } ProcessedSize+=MaxRead; #endif for (int BufPos=0;BufPos<MaxRead;BufPos++) { byte Data[256]; for (int I=0;I<TotalFiles;I++) Data[I]=Buf[I*RECVOL_BUFSIZE+BufPos]; RSC.Decode(Data,TotalFiles,Erasures,EraSize); for (int I=0;I<EraSize;I++) Buf[Erasures[I]*RECVOL_BUFSIZE+BufPos]=Data[Erasures[I]]; /* for (int I=0;I<FileNumber;I++) Buf[I*RECVOL_BUFSIZE+BufPos]=Data[I]; */ } for (int I=0;I<FileNumber;I++) if (WriteFlags[I]) SrcFile[I]->Write(&Buf[I*RECVOL_BUFSIZE],MaxRead); } for (int I=0;I<RecVolNumber+FileNumber;I++) if (SrcFile[I]!=NULL) { File *CurFile=SrcFile[I]; if (NewStyle && WriteFlags[I]) { Int64 Length=CurFile->Tell(); CurFile->Seek(Length-7,SEEK_SET); for (int J=0;J<7;J++) CurFile->PutByte(0); } CurFile->Close(); SrcFile[I]=NULL; } if (*LastVolName) { Archive Arc(Cmd); if (Arc.Open(LastVolName,NULL,false,true) && Arc.IsArchive(true) && Arc.SearchBlock(ENDARC_HEAD)) { Arc.Seek(Arc.NextBlockPos,SEEK_SET); char Buf[8192]; int ReadSize=Arc.Read(Buf,sizeof(Buf)); int ZeroCount=0; while (ZeroCount<ReadSize && Buf[ZeroCount]==0) ZeroCount++; if (ZeroCount==ReadSize) { Arc.Seek(Arc.NextBlockPos,SEEK_SET); Arc.Truncate(); } } } #if !defined(GUI) && !defined(SILENT) if (!Cmd->DisablePercentage) mprintf("\b\b\b\b100%%"); if (!Silent && !Cmd->DisableDone) mprintf(St(MDone)); #endif return(true); }
/**************************************** TrafficInformation ****************************************/ void TrafficInformation::DrawInfo(InfoItem* it,time_t tm) { static char str[MAX_PATH+1]; double db; int cn; time_t tmp; struct tm *ltm; int len; switch(it->Type) { //00 " " ---- Space case 00: break; //01 "SrcPathname" ---- Source filename case 01: FTP_Info->StrCpy(str,SrcFileName,ARRAYSIZE(str)); break; //02 "SrcPath", case 02: FTP_Info->StrCpy(str,SrcFileName,ARRAYSIZE(str)); FTP_Info->PointToName(str)[0] = 0; break; //03 "SrcName", case 03: FTP_Info->StrCpy(str,FTP_Info->PointToName(SrcFileName),ARRAYSIZE(str)); break; //04 "DestPathname" ---- Target filename case 04: FTP_Info->StrCpy(str,DestFileName,ARRAYSIZE(str)); break; //05 "DestPath", case 05: FTP_Info->StrCpy(str,DestFileName,ARRAYSIZE(str)); FTP_Info->PointToName(str)[0] = 0; break; //06 "DestName", case 06: FTP_Info->StrCpy(str,FTP_Info->PointToName(DestFileName),ARRAYSIZE(str)); break; //07 "CurSize" ---- Current processed size case 07: FTP_Info->FDigit(str,CurrentSz(),-1); break; //08 "CurESize" ---- Full size of current file //09 "CurFSize", case 8: case 9: FTP_Info->FDigit(str,FullFileSize,-1); break; //10 "CurRSize" ---- Remain size of current file case 10: FTP_Info->FDigit(str,CurrentRemain(),-1); break; //11 "CurTime" ---- Time from start of current file case 11: cn = (int)(tm - FileStartTime); _snprintf(str,ARRAYSIZE(str), "%02d:%02d:%02d", cn/3600, (cn/60)%60, cn%60); break; //12 "CurFTime" ---- Full time to process current file case 12: db = Cps; if(db > 0) cn = (int)(CurrentDoRemain() / db); else cn = 0; cn = Max(cn,0); _snprintf(str,ARRAYSIZE(str), "%02d:%02d:%02d", cn/3600, (cn/60)%60, cn%60); break; //13 "CurRTime" ---- Remain time to process current file case 13: db = Cps; if(db > 0) cn = (int)(CurrentRemain() / db); else cn = 0; cn = Max(cn,0); _snprintf(str,ARRAYSIZE(str), "%02d:%02d:%02d", cn/3600, (cn/60)%60, cn%60); break; //14 "CurETime" ---- End time to process current file case 14: db = Cps; if(db > 0) tmp = tm + (time_t)(CurrentRemain() / db); else tmp = tm; tmp = Max(tmp,tm); ltm = Localtime(&tmp); StrTTime(str,ltm); break; //15 "CurEDate" ---- End date to process current file case 15: db = Cps; if(db > 0) tmp = tm + (time_t)(CurrentRemain() / db); else tmp = tm; tmp = Max(tmp,tm); ltm = Localtime(&tmp); StrYTime(str,ltm); break; //16 "TotSize" ---- Current processed size case 16: FTP_Info->FDigit(str,TotalSz(),-1); break; //17 "TotESize" ---- Full size of current file //18 "TotFSize", case 17: case 18: FTP_Info->FDigit(str,TotalFullSize,-1); break; //19 "TotRSize" ---- Remain size of current file case 19: FTP_Info->FDigit(str,TotalRemain(),-1); break; //20 "TotTime" ---- Time from start of current file case 20: cn = (int)(tm - TotalStartTime); _snprintf(str,ARRAYSIZE(str), "%02d:%02d:%02d", cn/3600, (cn/60)%60, cn%60); break; //21 "TotFTime" ---- Full time to process current file case 21: db = (AvCps[0] + AvCps[1] + AvCps[2])/3; if(db > 0) cn = (int)(TotalDoRemain() / db); else cn = 0; cn = Max(cn,0); _snprintf(str,ARRAYSIZE(str), "%02d:%02d:%02d", cn/3600, (cn/60)%60, cn%60); break; //22 "TotRTime" ----- Remain time to process current file case 22: db = (AvCps[0] + AvCps[1] + AvCps[2])/3; if(db > 0) cn = (int)(TotalRemain() / db); else cn = 0; cn = Max(cn,0); _snprintf(str,ARRAYSIZE(str), "%02d:%02d:%02d", cn/3600, (cn/60)%60, cn%60); break; //23 "TotETime" ---- End time to process all files case 23: db = TotalCps; if(db > 0) tmp = tm + (time_t)(TotalRemain() / db); else tmp = tm; ltm = Localtime(&tmp); StrTTime(str,ltm); break; //24 "TotEDate" ----- End date to process current file case 24: db = TotalCps; if(db > 0) tmp = tm + (time_t)(TotalRemain() / db); else tmp = tm; ltm = Localtime(&tmp); StrYTime(str,ltm); break; //25 "CurCPS" ----- CP of current file case 25: FTP_Info->FCps(str,Cps); break; //26 "CPS" ----- Summary CPS case 26: FTP_Info->FCps(str,(AvCps[0] + AvCps[1] + AvCps[2])/3); break; //27 "TotCPS" ----- Total CPS case 27: FTP_Info->FCps(str,TotalCps); break; //28 "Progress" ----- Current progress bar //42 "Pg" ----- ALIAS `Progress` case 42: case 28: PPercent(str,0,it->Size-1,(int)ToPercent(CurrentSz(),FullFileSize)); break; //29 "FProgress"----- Total progress bar //43 "FPg" ----- ALIAS `FProgress` case 43: case 29: PPercent(str,0,it->Size-1,(int)ToPercent(TotalSz(),TotalFullSize)); break; //40 "Pc" ----- ALIAS `Percent` //30 "PerCent" ----- Current "99.9%" percent case 40: case 30: db = ToPercent(CurrentSz(),FullFileSize); if(((int)db) == 100) FTP_Info->StrCpy(str,"100%",-1); else sprintf(str,"%2.1lf%%",db); break; //41 "FPc" ---- ALIAS `FPercent` //31 "FPerCent" ----- Total "99.9%" percent case 41: case 31: db = ToPercent(TotalSz(),TotalFullSize); if(((int)db) == 100) FTP_Info->StrCpy(str,"100%",-1); else sprintf(str,"%2.1lf%%",db); break; //32 "Cn" ---- Complete count case 32: FTP_Info->FDigit(str,TotalComplete,-1); break; //33 "CnSkip" ---- Skipped count case 33: FTP_Info->FDigit(str,TotalSkipped,-1); break; //34 "CnR" ---- Remain count case 34: FTP_Info->FDigit(str,TotalFiles-TotalComplete-TotalSkipped,-1); break; //35 "CnF" ---- Count case 35: FTP_Info->FDigit(str,TotalFiles,-1); break; //36 "CurPc" ---- Current percent case 36: db = ToPercent(TotalComplete,TotalFiles); if(((int)db) == 100) FTP_Info->StrCpy(str,"100%",-1); else sprintf(str,"%2.1lf%%",db); break; //37 "SkipPc" ---- Skipped percent case 37: db = ToPercent(TotalSkipped,TotalFiles); if(((int)db) == 100) FTP_Info->StrCpy(str,"100%",-1); else sprintf(str,"%2.1lf%%",db); break; //38 "CurPg" ---- Current percent progress case 38: PPercent(str,0,it->Size-1,(int)ToPercent(TotalComplete,TotalFiles)); break; //39 "SkipPg" ---- Skipped percent progress case 39: PPercent(str,0,it->Size-1,(int)ToPercent(TotalSkipped,TotalFiles)); break; //44 "CurCPS4" ----- CP of current file case 44: FCps4(str,Cps); break; //45 "CPS4" ----- Summary CPS case 45: FCps4(str,(AvCps[0] + AvCps[1] + AvCps[2])/3); break; //46 "TotCPS4" ----- Total CPS case 46: FCps4(str,TotalCps); break; //47 "IPc" ----- Current "99%" percent case 47: db = ToPercent(CurrentSz(),FullFileSize); if(((int)db) == 100) FTP_Info->StrCpy(str,"100%",-1); else sprintf(str,"%d%%",(int)db); break; //48 "IFPc" ----- Total "99%" percent case 48: db = ToPercent(TotalSz(),TotalFullSize); if(((int)db) == 100) FTP_Info->StrCpy(str,"100%",-1); else sprintf(str,"%d%%",(int)db); break; } if(it->Type) { len = static_cast<int>(strlen(str)); if(!it->Size && it->Align == tCenter) it->Pos -= len/2; if(!it->Size) it->Size = len; if(len > it->Size && it->Align == tCenter) it->Align = tLeft; if(it->Pos+it->Size > MAX_TRAF_WIDTH) return; if(len > it->Size) { if(it->Align == tLeft) { memmove(Lines[it->Line]+it->Pos,str+len-it->Size,it->Size); Lines[it->Line][it->Pos] = FAR_LEFT_CHAR; } else { memmove(Lines[it->Line]+it->Pos,str,it->Size); Lines[it->Line][it->Pos+it->Size] = FAR_RIGHT_CHAR; } } else { //Clear if(it->Align != tCenter) memset(Lines[it->Line]+it->Pos,it->Fill,it->Size); //Draw if(it->Align == tLeft) memmove(Lines[it->Line]+it->Pos, str, len); else if(it->Align == tRight) memmove(Lines[it->Line]+it->Pos + it->Size - len, str, len); else memmove(Lines[it->Line]+it->Pos + it->Size/2 - len/2, str, len); } } else { memset(Lines[it->Line]+it->Pos,it->Fill,it->Size); } }
void QuickView::DisplayObject() { if (Flags.Check(FSCROBJ_ISREDRAWING)) return; Flags.Set(FSCROBJ_ISREDRAWING); FARString strTitle; if (!QView && !ProcessingPluginCommand) CtrlObject->Cp()->GetAnotherPanel(this)->UpdateViewPanel(); if (QView) QView->SetPosition(X1+1,Y1+1,X2-1,Y2-3); Box(X1,Y1,X2,Y2,COL_PANELBOX,DOUBLE_BOX); SetScreen(X1+1,Y1+1,X2-1,Y2-1,L' ',COL_PANELTEXT); SetColor(Focus ? COL_PANELSELECTEDTITLE:COL_PANELTITLE); GetTitle(strTitle); if (!strTitle.IsEmpty()) { GotoXY(X1+(X2-X1+1-(int)strTitle.GetLength())/2,Y1); Text(strTitle); } DrawSeparator(Y2-2); SetColor(COL_PANELTEXT); GotoXY(X1+1,Y2-1); FS<<fmt::LeftAlign()<<fmt::Width(X2-X1-1)<<fmt::Precision(X2-X1-1)<<PointToName(strCurFileName); if (!strCurFileType.IsEmpty()) { FARString strTypeText=L" "; strTypeText+=strCurFileType; strTypeText+=L" "; TruncStr(strTypeText,X2-X1-1); SetColor(COL_PANELSELECTEDINFO); GotoXY(X1+(X2-X1+1-(int)strTypeText.GetLength())/2,Y2-2); Text(strTypeText); } if (Directory) { FormatString FString; FString<<MSG(MQuickViewFolder)<<L" \""<<strCurFileName<<L"\""; SetColor(COL_PANELTEXT); GotoXY(X1+2,Y1+2); PrintText(FString); /*if ((apiGetFileAttributes(strCurFileName)&FILE_ATTRIBUTE_REPARSE_POINT) == FILE_ATTRIBUTE_REPARSE_POINT) { FARString strJuncName; DWORD ReparseTag=0; if (GetReparsePointInfo(strCurFileName, strJuncName,&ReparseTag)) { int ID_Msg=MQuickViewJunction; if (ReparseTag==IO_REPARSE_TAG_MOUNT_POINT) { if (IsLocalVolumeRootPath(strJuncName)) { ID_Msg=MQuickViewVolMount; } } else if (ReparseTag==IO_REPARSE_TAG_SYMLINK) { ID_Msg=MQuickViewSymlink; } //"\??\D:\Junc\Src\" NormalizeSymlinkName(strJuncName); TruncPathStr(strJuncName,X2-X1-1-StrLength(MSG(ID_Msg))); FString.Clear(); FString<<MSG(ID_Msg)<<L" \""<<strJuncName<<L"\""; SetColor(COL_PANELTEXT); GotoXY(X1+2,Y1+3); PrintText(FString); } }*/ if (Directory==1 || Directory==4) { GotoXY(X1+2,Y1+4); PrintText(MSG(MQuickViewContains)); GotoXY(X1+2,Y1+6); PrintText(MSG(MQuickViewFolders)); SetColor(COL_PANELINFOTEXT); FString.Clear(); FString<<DirCount; PrintText(FString); SetColor(COL_PANELTEXT); GotoXY(X1+2,Y1+7); PrintText(MSG(MQuickViewFiles)); SetColor(COL_PANELINFOTEXT); FString.Clear(); FString<<FileCount; PrintText(FString); SetColor(COL_PANELTEXT); GotoXY(X1+2,Y1+8); PrintText(MSG(MQuickViewBytes)); SetColor(COL_PANELINFOTEXT); FARString strSize; InsertCommas(FileSize,strSize); PrintText(strSize); SetColor(COL_PANELTEXT); GotoXY(X1+2,Y1+9); PrintText(MSG(MQuickViewCompressed)); SetColor(COL_PANELINFOTEXT); InsertCommas(CompressedFileSize,strSize); PrintText(strSize); SetColor(COL_PANELTEXT); GotoXY(X1+2,Y1+10); PrintText(MSG(MQuickViewRatio)); SetColor(COL_PANELINFOTEXT); FString.Clear(); FString<<ToPercent64(CompressedFileSize,FileSize)<<L"%"; PrintText(FString); if (Directory!=4 && RealFileSize>=CompressedFileSize) { SetColor(COL_PANELTEXT); GotoXY(X1+2,Y1+12); PrintText(MSG(MQuickViewCluster)); SetColor(COL_PANELINFOTEXT); FARString strSize; InsertCommas(ClusterSize,strSize); PrintText(strSize); SetColor(COL_PANELTEXT); GotoXY(X1+2,Y1+13); PrintText(MSG(MQuickViewRealSize)); SetColor(COL_PANELINFOTEXT); InsertCommas(RealFileSize,strSize); PrintText(strSize); SetColor(COL_PANELTEXT); GotoXY(X1+2,Y1+14); PrintText(MSG(MQuickViewSlack)); SetColor(COL_PANELINFOTEXT); InsertCommas(RealFileSize-CompressedFileSize,strSize); uint64_t Size1=RealFileSize-CompressedFileSize; uint64_t Size2=RealFileSize; while ((Size2 >> 32) ) { Size1=Size1>>1; Size2=Size2>>1; } FString.Clear(); FString<<strSize<<L" ("<<ToPercent((DWORD)Size1, (DWORD)Size2)<<L"%)"; PrintText(FString); } }