unrar_err_t Archive::IsArchive() { if (Read(MarkHead.Mark,SIZEOF_MARKHEAD)!=SIZEOF_MARKHEAD) return unrar_err_not_arc; if (IsSignature(MarkHead.Mark)) { if (OldFormat) Seek(0,SEEK_SET); } else { if (SFXSize==0) return unrar_err_not_arc; } unrar_err_t error = ReadHeader(); // (no need to seek to next) if ( error != unrar_ok ) return error; #ifndef SFX_MODULE if (OldFormat) { NewMhd.Flags=OldMhd.Flags & 0x3f; NewMhd.HeadSize=OldMhd.HeadSize; } else #endif { if (HeaderCRC!=NewMhd.HeadCRC) { return unrar_err_corrupt; } } bool Volume=(NewMhd.Flags & MHD_VOLUME); Solid=(NewMhd.Flags & MHD_SOLID)!=0; bool Encrypted=(NewMhd.Flags & MHD_PASSWORD)!=0; // (removed decryption and volume handling) if ( Encrypted ) return unrar_err_encrypted; if ( Volume ) return unrar_err_segmented; return unrar_ok; }
bool Archive::IsArchive(bool EnableBroken) { Encrypted=false; #ifdef USE_QOPEN QOpen.Unload(); #endif // Important if we reuse Archive object and it has virtual QOpen // file position not matching real. For example, for 'l -v volname'. Seek(0,SEEK_SET); #ifndef SFX_MODULE if (IsDevice()) { #ifndef SHELL_EXT Log(FileName,St(MInvalidName),FileName); #endif return false; } #endif if (Read(MarkHead.Mark,SIZEOF_MARKHEAD3)!=SIZEOF_MARKHEAD3) return(false); SFXSize=0; RARFORMAT Type; if ((Type=IsSignature(MarkHead.Mark,SIZEOF_MARKHEAD3))!=RARFMT_NONE) { Format=Type; if (Format==RARFMT14) Seek(0,SEEK_SET); } else { Array<char> Buffer(MAXSFXSIZE); long CurPos=(long)Tell(); int ReadSize=Read(&Buffer[0],Buffer.Size()-16); for (int I=0;I<ReadSize;I++) if (Buffer[I]==0x52 && (Type=IsSignature((byte *)&Buffer[I],ReadSize-I))!=RARFMT_NONE) { Format=Type; if (Format==RARFMT14 && I>0 && CurPos<28 && ReadSize>31) { char *D=&Buffer[28-CurPos]; if (D[0]!=0x52 || D[1]!=0x53 || D[2]!=0x46 || D[3]!=0x58) continue; } SFXSize=CurPos+I; Seek(SFXSize,SEEK_SET); if (Format==RARFMT15 || Format==RARFMT50) Read(MarkHead.Mark,SIZEOF_MARKHEAD3); break; } if (SFXSize==0) return false; } if (Format==RARFMT_FUTURE) { #if !defined(SHELL_EXT) && !defined(SFX_MODULE) Log(FileName,St(MNewRarFormat)); #endif return false; } if (Format==RARFMT50) // RAR 5.0 signature is by one byte longer. { Read(MarkHead.Mark+SIZEOF_MARKHEAD3,1); if (MarkHead.Mark[SIZEOF_MARKHEAD3]!=0) return false; MarkHead.HeadSize=SIZEOF_MARKHEAD5; } else MarkHead.HeadSize=SIZEOF_MARKHEAD3; // Skip the archive encryption header if any and read the main header. while (ReadHeader()!=0 && GetHeaderType()!=HEAD_MAIN) SeekToNext(); // This check allows to make RS based recovery even if password is incorrect. // But we should not do it for EnableBroken or we'll get 'not RAR archive' // messages when extracting encrypted archives with wrong password. if (FailedHeaderDecryption && !EnableBroken) return false; SeekToNext(); if (BrokenHeader) { #ifndef SHELL_EXT Log(FileName,St(MMainHeaderBroken)); #endif if (!EnableBroken) return false; } /* if (MainHead.EncryptVer>VER_UNPACK) { #ifdef RARDLL Cmd->DllError=ERAR_UNKNOWN_FORMAT; #else ErrHandler.SetErrorCode(RARX_WARNING); #if !defined(SILENT) && !defined(SFX_MODULE) Log(FileName,St(MUnknownMeth),FileName); Log(FileName,St(MVerRequired),MainHead.EncryptVer/10,MainHead.EncryptVer%10); #endif #endif return(false); } */ #ifdef RARDLL // If callback function is not set, we cannot get the password, // so we skip the initial header processing for encrypted header archive. // It leads to skipped archive comment, but the rest of archive data // is processed correctly. if (Cmd->Callback==NULL) SilentOpen=true; #endif MainComment=MainHead.CommentInHeader; #ifdef USE_QOPEN if (MainHead.Locator && MainHead.QOpenOffset>0 && Cmd->QOpenMode!=QOPEN_NONE) { QOpen.Init(this,false); QOpen.Load(MainHead.QOpenOffset); } #endif // If we process non-encrypted archive or can request a password, // we set 'first volume' flag based on file attributes below. // It is necessary for RAR 2.x archives, which did not have 'first volume' // flag in main header. if (!SilentOpen || !Encrypted) { SaveFilePos SavePos(*this); int64 SaveCurBlockPos=CurBlockPos,SaveNextBlockPos=NextBlockPos; while (ReadHeader()!=0) { HEADER_TYPE HeaderType=GetHeaderType(); if (HeaderType==HEAD_SERVICE) { if (SubHead.CmpName(SUBHEAD_TYPE_CMT)) MainComment=true; FirstVolume=!SubHead.SplitBefore; } else { FirstVolume=HeaderType==HEAD_FILE && !FileHead.SplitBefore; break; } SeekToNext(); } CurBlockPos=SaveCurBlockPos; NextBlockPos=SaveNextBlockPos; } if (!Volume || FirstVolume) wcscpy(FirstVolumeName,FileName); return true; }
bool Archive::IsArchive(bool EnableBroken) { Encrypted=false; #ifndef SFX_MODULE if (IsDevice()) { #ifndef SHELL_EXT Log(FileName,St(MInvalidName),FileName); #endif return(false); } #endif if (Read(MarkHead.Mark,SIZEOF_MARKHEAD)!=SIZEOF_MARKHEAD) return(false); SFXSize=0; if (IsSignature(MarkHead.Mark)) { if (OldFormat) Seek(0,SEEK_SET); } else { Array<char> Buffer(MAXSFXSIZE); long CurPos=(long)Tell(); int ReadSize=Read(&Buffer[0],Buffer.Size()-16); for (int I=0;I<ReadSize;I++) if (Buffer[I]==0x52 && IsSignature((byte *)&Buffer[I])) { if (OldFormat && I>0 && CurPos<28 && ReadSize>31) { char *D=&Buffer[28-CurPos]; if (D[0]!=0x52 || D[1]!=0x53 || D[2]!=0x46 || D[3]!=0x58) continue; } SFXSize=CurPos+I; Seek(SFXSize,SEEK_SET); if (!OldFormat) Read(MarkHead.Mark,SIZEOF_MARKHEAD); break; } if (SFXSize==0) return(false); } ReadHeader(); SeekToNext(); #ifndef SFX_MODULE if (OldFormat) { NewMhd.Flags=OldMhd.Flags & 0x3f; NewMhd.HeadSize=OldMhd.HeadSize; } else #endif { if (HeaderCRC!=NewMhd.HeadCRC) { #ifndef SHELL_EXT Log(FileName,St(MLogMainHead)); #endif Alarm(); if (!EnableBroken) return(false); } } Volume=(NewMhd.Flags & MHD_VOLUME); Solid=(NewMhd.Flags & MHD_SOLID)!=0; MainComment=(NewMhd.Flags & MHD_COMMENT)!=0; Locked=(NewMhd.Flags & MHD_LOCK)!=0; Signed=(NewMhd.PosAV!=0); Protected=(NewMhd.Flags & MHD_PROTECT)!=0; Encrypted=(NewMhd.Flags & MHD_PASSWORD)!=0; if (NewMhd.EncryptVer>UNP_VER) { #ifdef RARDLL Cmd->DllError=ERAR_UNKNOWN_FORMAT; #else ErrHandler.SetErrorCode(RARX_WARNING); #if !defined(SILENT) && !defined(SFX_MODULE) Log(FileName,St(MUnknownMeth),FileName); Log(FileName,St(MVerRequired),NewMhd.EncryptVer/10,NewMhd.EncryptVer%10); #endif #endif return(false); } #ifdef RARDLL // If callback function is not set, we cannot get the password, // so we skip the initial header processing for encrypted header archive. // It leads to skipped archive comment, but the rest of archive data // is processed correctly. if (Cmd->Callback==NULL) SilentOpen=true; #endif // If not encrypted, we'll check it below. NotFirstVolume=Encrypted && (NewMhd.Flags & MHD_FIRSTVOLUME)==0; if (!SilentOpen || !Encrypted) { SaveFilePos SavePos(*this); int64 SaveCurBlockPos=CurBlockPos,SaveNextBlockPos=NextBlockPos; NotFirstVolume=false; while (ReadHeader()!=0) { int HeaderType=GetHeaderType(); if (HeaderType==NEWSUB_HEAD) { if (SubHead.CmpName(SUBHEAD_TYPE_CMT)) MainComment=true; if ((SubHead.Flags & LHD_SPLIT_BEFORE) || Volume && (NewMhd.Flags & MHD_FIRSTVOLUME)==0) NotFirstVolume=true; } else { if (HeaderType==FILE_HEAD && ((NewLhd.Flags & LHD_SPLIT_BEFORE)!=0 || Volume && NewLhd.UnpVer>=29 && (NewMhd.Flags & MHD_FIRSTVOLUME)==0)) NotFirstVolume=true; break; } SeekToNext(); } CurBlockPos=SaveCurBlockPos; NextBlockPos=SaveNextBlockPos; } if (!Volume || !NotFirstVolume) { strcpy(FirstVolumeName,FileName); wcscpy(FirstVolumeNameW,FileNameW); } return(true); }
bool Archive::IsArchive(bool EnableBroken) { Encrypted=false; #ifndef SFX_MODULE if (IsDevice()) { #ifndef SHELL_EXT Log(FileName,St(MInvalidName),FileName); #endif return(false); } #endif if (Read(MarkHead.Mark,SIZEOF_MARKHEAD)!=SIZEOF_MARKHEAD) return(false); SFXSize=0; if (IsSignature(MarkHead.Mark)) { if (OldFormat) Seek(0,SEEK_SET); } else { Array<char> Buffer(0x40000); long CurPos=int64to32(Tell()); int ReadSize=Read(&Buffer[0],Buffer.Size()-16); for (int I=0;I<ReadSize;I++) if (Buffer[I]==0x52 && IsSignature((byte *)&Buffer[I])) { SFXSize=CurPos+I; Seek(SFXSize,SEEK_SET); if (!OldFormat) Read(MarkHead.Mark,SIZEOF_MARKHEAD); break; } if (SFXSize==0) return(false); } ReadHeader(); SeekToNext(); #ifndef SFX_MODULE if (OldFormat) { NewMhd.Flags=OldMhd.Flags & 0x3f; NewMhd.HeadSize=OldMhd.HeadSize; } else #endif { if (HeaderCRC!=NewMhd.HeadCRC) { #ifndef SHELL_EXT Log(FileName,St(MLogMainHead)); #endif Alarm(); if (!EnableBroken) return(false); } } Volume=(NewMhd.Flags & MHD_VOLUME); Solid=(NewMhd.Flags & MHD_SOLID)!=0; MainComment=(NewMhd.Flags & MHD_COMMENT)!=0; Locked=(NewMhd.Flags & MHD_LOCK)!=0; Signed=(NewMhd.PosAV!=0); Protected=(NewMhd.Flags & MHD_PROTECT)!=0; Encrypted=(NewMhd.Flags & MHD_PASSWORD)!=0; #ifdef RARDLL SilentOpen=true; #endif if (!SilentOpen || !Encrypted) { SaveFilePos SavePos(*this); Int64 SaveCurBlockPos=CurBlockPos,SaveNextBlockPos=NextBlockPos; NotFirstVolume=false; while (ReadHeader()) { int HeaderType=GetHeaderType(); if (HeaderType==NEWSUB_HEAD) { if (SubHead.CmpName(SUBHEAD_TYPE_CMT)) MainComment=true; if ((SubHead.Flags & LHD_SPLIT_BEFORE) || Volume && (NewMhd.Flags & MHD_FIRSTVOLUME)==0) NotFirstVolume=true; } else { if (HeaderType==FILE_HEAD && ((NewLhd.Flags & LHD_SPLIT_BEFORE)!=0 || Volume && NewLhd.UnpVer>=29 && (NewMhd.Flags & MHD_FIRSTVOLUME)==0)) NotFirstVolume=true; break; } SeekToNext(); } CurBlockPos=SaveCurBlockPos; NextBlockPos=SaveNextBlockPos; } return(true); }
/********************************************************************** * Function: TgtSelDlgProc * Info : dialog event handler for target file selection * Result : TRUE or FALSE **********************************************************************/ MRESULT EXPENTRY TgtSelDlgProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2) { static PFILEDLG pFileDlg2; CHAR Buffer[CCHMAXPATH+100]; CHAR FileBuffer[CCHMAXPATH]; CHAR PathBuffer3[CCHMAXPATH]; CHAR Title[TITLESTRN_MAXLEN+1]; BOOL SignedFile; MRESULT rc = FALSE; switch (msg) { case WM_INITDLG: CenterWindow(hwnd); pFileDlg2 = (PFILEDLG) WinQueryWindowULong(hwnd, QWL_USER); break; case WM_HELP: DisplayHelp(IDL_TGTFILE_HELP); break; case WM_COMMAND: switch(SHORT1FROMMP(mp1)) { case DID_OK: strcpy(PathBuffer3, pFileDlg2->szFullFile); WinQueryWindowText(WinWindowFromID(hwnd, DID_FILENAME_ED), sizeof(FileBuffer), FileBuffer); strcat(PathBuffer3, FileBuffer); SignedFile = IsSignature(JobDesc.SourceFile); if (!SignedFile || (SignedFile && !IsDetachedSignature) ) { if(FileExist(PathBuffer3)) { Len = WinLoadString(Hab, hRessourceModule, IDS_QUERY_TARGET_OVERWRITE, MSGSTRN_MAXLEN, Msg); Len = WinLoadString(Hab, hRessourceModule, IDS_BUBBLE_DECVERIFYDATA_HELP, TITLESTRN_MAXLEN, Title); sprintf(Buffer, Msg, PathBuffer3); if (MBID_YES == WinMessageBox(HWND_DESKTOP, hwnd, Buffer, "", 0, MB_ICONQUESTION | MB_YESNO)) { if (0 == remove(PathBuffer3)) { strcpy(pFileDlg2->szFullFile, PathBuffer3); pFileDlg2->lReturn = DID_OK; WinDismissDlg(hwnd, TRUE); return (MRESULT) TRUE; } pFileDlg2->lReturn = DID_CANCEL; } return (MRESULT) FALSE; } } else { /* * source file is a detached signature file that is to * be checked against the outfile, so there's no need to * query for outfile overwrite allowance */ strcpy(pFileDlg2->szFullFile, PathBuffer3); pFileDlg2->lReturn = DID_OK; WinDismissDlg(hwnd, TRUE); return (MRESULT) TRUE; } /* fall through! */ } default: rc = WinDefFileDlgProc (hwnd, msg, mp1, mp2); } return rc; }
bool Archive::IsArchive(bool EnableBroken) { Encrypted=false; BrokenHeader=false; // Might be left from previous volume. #ifndef SFX_MODULE if (IsDevice()) { uiMsg(UIERROR_INVALIDNAME,FileName,FileName); return false; } #endif if (Read(MarkHead.Mark,SIZEOF_MARKHEAD3)!=SIZEOF_MARKHEAD3) return false; SFXSize=0; RARFORMAT Type; if ((Type=IsSignature(MarkHead.Mark,SIZEOF_MARKHEAD3))!=RARFMT_NONE) { Format=Type; if (Format==RARFMT14) Seek(Tell()-SIZEOF_MARKHEAD3,SEEK_SET); } else { Array<char> Buffer(MAXSFXSIZE); long CurPos=(long)Tell(); int ReadSize=Read(&Buffer[0],Buffer.Size()-16); for (int I=0;I<ReadSize;I++) if (Buffer[I]==0x52 && (Type=IsSignature((byte *)&Buffer[I],ReadSize-I))!=RARFMT_NONE) { Format=Type; if (Format==RARFMT14 && I>0 && CurPos<28 && ReadSize>31) { char *D=&Buffer[28-CurPos]; if (D[0]!=0x52 || D[1]!=0x53 || D[2]!=0x46 || D[3]!=0x58) continue; } SFXSize=CurPos+I; Seek(SFXSize,SEEK_SET); if (Format==RARFMT15 || Format==RARFMT50) Read(MarkHead.Mark,SIZEOF_MARKHEAD3); break; } if (SFXSize==0) return false; } if (Format==RARFMT_FUTURE) { uiMsg(UIERROR_NEWRARFORMAT,FileName); return false; } if (Format==RARFMT50) // RAR 5.0 signature is by one byte longer. { Read(MarkHead.Mark+SIZEOF_MARKHEAD3,1); if (MarkHead.Mark[SIZEOF_MARKHEAD3]!=0) return false; MarkHead.HeadSize=SIZEOF_MARKHEAD5; } else MarkHead.HeadSize=SIZEOF_MARKHEAD3; #ifdef RARDLL // If callback function is not set, we cannot get the password, // so we skip the initial header processing for encrypted header archive. // It leads to skipped archive comment, but the rest of archive data // is processed correctly. if (Cmd->Callback==NULL) SilentOpen=true; #endif // Skip the archive encryption header if any and read the main header. while (ReadHeader()!=0) { HEADER_TYPE Type=GetHeaderType(); // In RAR 5.0 we need to quit after reading HEAD_CRYPT if we wish to // avoid the password prompt. if (Type==HEAD_MAIN || SilentOpen && Type==HEAD_CRYPT) break; SeekToNext(); } // This check allows to make RS based recovery even if password is incorrect. // But we should not do it for EnableBroken or we'll get 'not RAR archive' // messages when extracting encrypted archives with wrong password. if (FailedHeaderDecryption && !EnableBroken) return false; SeekToNext(); if (BrokenHeader) // Main archive header is corrupt. { uiMsg(UIERROR_MHEADERBROKEN,FileName); if (!EnableBroken) return false; } MainComment=MainHead.CommentInHeader; // If we process non-encrypted archive or can request a password, // we set 'first volume' flag based on file attributes below. // It is necessary for RAR 2.x archives, which did not have 'first volume' // flag in main header. Also for all RAR formats we need to scan until // first file header to set "comment" flag when reading service header. // Unless we are in silent mode, we need to know about presence of comment // immediately after IsArchive call. if (!SilentOpen || !Encrypted) { SaveFilePos SavePos(*this); int64 SaveCurBlockPos=CurBlockPos,SaveNextBlockPos=NextBlockPos; HEADER_TYPE SaveCurHeaderType=CurHeaderType; while (ReadHeader()!=0) { HEADER_TYPE HeaderType=GetHeaderType(); if (HeaderType==HEAD_SERVICE) FirstVolume=Volume && !SubHead.SplitBefore; else if (HeaderType==HEAD_FILE) { FirstVolume=Volume && !FileHead.SplitBefore; break; } SeekToNext(); } CurBlockPos=SaveCurBlockPos; NextBlockPos=SaveNextBlockPos; CurHeaderType=SaveCurHeaderType; } if (!Volume || FirstVolume) wcscpy(FirstVolumeName,FileName); return true; }