From 5bf3568f8865dc4d335def904f80c875dc45c4d1 Mon Sep 17 00:00:00 2001 From: Varun Khaneja Date: Tue, 26 Feb 2019 09:47:49 -0800 Subject: [PATCH] Integrate version 5.7.3 from https://www.rarlab.com/rar/unrarsrc-5.7.3.tar.gz --- arccmt.cpp | 21 +-- archive.hpp | 5 +- arcread.cpp | 61 +++++---- cmddata.cpp | 330 +++-------------------------------------------- cmddata.hpp | 11 +- cmdfilter.cpp | 299 ++++++++++++++++++++++++++++++++++++++++++ cmdmix.cpp | 118 +++++++++++++++++ crypt3.cpp | 8 +- dll.cpp | 43 ++++-- dll.def | 1 + dll.hpp | 10 +- dll.rc | 10 +- dll_nocrypt.def | 13 ++ errhnd.hpp | 2 +- extract.cpp | 17 ++- file.cpp | 2 +- file.hpp | 2 +- filefn.cpp | 2 +- find.cpp | 10 +- list.cpp | 12 +- loclang.hpp | 14 +- match.cpp | 10 +- match.hpp | 4 + options.hpp | 21 ++- os.hpp | 5 + pathfn.cpp | 102 +++++++++------ pathfn.hpp | 2 +- rar.cpp | 7 +- rdwrfn.cpp | 1 + recvol3.cpp | 12 +- recvol5.cpp | 8 +- rijndael.cpp | 5 +- rs16.cpp | 20 +-- scantree.cpp | 11 +- scantree.hpp | 2 +- strfn.cpp | 52 ++++---- strfn.hpp | 8 +- suballoc.hpp | 2 +- system.cpp | 22 ++++ system.hpp | 1 + timefn.cpp | 4 +- ui.hpp | 22 ++-- uicommon.cpp | 6 +- uiconsole.cpp | 13 +- unicode.cpp | 4 +- unpack50.cpp | 6 +- unpack50frag.cpp | 2 +- unpack50mt.cpp | 16 +-- version.hpp | 8 +- volume.cpp | 10 +- win32stm.cpp | 16 ++- 51 files changed, 832 insertions(+), 561 deletions(-) create mode 100644 cmdfilter.cpp create mode 100644 cmdmix.cpp create mode 100644 dll_nocrypt.def diff --git a/arccmt.cpp b/arccmt.cpp index ca98b10..92a3896 100644 --- a/arccmt.cpp +++ b/arccmt.cpp @@ -34,7 +34,7 @@ bool Archive::GetComment(Array *CmtData) #ifndef SFX_MODULE // Old style (RAR 2.9) comment header embedded into the main // archive header. - if (BrokenHeader) + if (BrokenHeader || CommHead.HeadSize *CmtData) #else UnpCmtLength=GetByte(); UnpCmtLength+=(GetByte()<<8); + if (CmtLength<2) + return false; CmtLength-=2; DataIO.SetCmt13Encryption(); CommHead.UnpVer=15; @@ -85,15 +87,18 @@ bool Archive::GetComment(Array *CmtData) byte *UnpData; size_t UnpDataSize; DataIO.GetUnpackedData(&UnpData,&UnpDataSize); + if (UnpDataSize>0) + { #ifdef _WIN_ALL - // If we ever decide to extend it to Android, we'll need to alloc - // 4x memory for OEM to UTF-8 output here. - OemToCharBuffA((char *)UnpData,(char *)UnpData,(DWORD)UnpDataSize); + // If we ever decide to extend it to Android, we'll need to alloc + // 4x memory for OEM to UTF-8 output here. + OemToCharBuffA((char *)UnpData,(char *)UnpData,(DWORD)UnpDataSize); #endif - CmtData->Alloc(UnpDataSize+1); - memset(CmtData->Addr(0),0,CmtData->Size()*sizeof(wchar)); - CharToWide((char *)UnpData,CmtData->Addr(0),CmtData->Size()); - CmtData->Alloc(wcslen(CmtData->Addr(0))); + CmtData->Alloc(UnpDataSize+1); + memset(CmtData->Addr(0),0,CmtData->Size()*sizeof(wchar)); + CharToWide((char *)UnpData,CmtData->Addr(0),CmtData->Size()); + CmtData->Alloc(wcslen(CmtData->Addr(0))); + } } } else diff --git a/archive.hpp b/archive.hpp index fd33ac3..4edb481 100644 --- a/archive.hpp +++ b/archive.hpp @@ -37,8 +37,7 @@ class Archive:public File void RequestArcPassword(); void UnexpEndArcMsg(); void BrokenHeaderMsg(); - void UnkEncVerMsg(const wchar *Name); - void UnkEncVerMsg(); + void UnkEncVerMsg(const wchar *Name,const wchar *Info); bool ReadCommentData(Array *CmtData); #if !defined(RAR_NOCRYPT) @@ -85,7 +84,7 @@ class Archive:public File void AddSubData(byte *SrcData,uint64 DataSize,File *SrcFile, const wchar *Name,uint Flags); bool ReadSubData(Array *UnpData,File *DestFile); - HEADER_TYPE GetHeaderType() {return CurHeaderType;}; + HEADER_TYPE GetHeaderType() {return CurHeaderType;} RAROptions* GetRAROptions() {return Cmd;} void SetSilentOpen(bool Mode) {SilentOpen=Mode;} #if 0 diff --git a/arcread.cpp b/arcread.cpp index c8cb1ee..c299d3d 100644 --- a/arcread.cpp +++ b/arcread.cpp @@ -10,7 +10,10 @@ size_t Archive::ReadHeader() CurBlockPos=Tell(); - size_t ReadSize; + // Other developers asked us to initialize it to suppress "may be used + // uninitialized" warning in code below in some compilers. + size_t ReadSize=0; + switch(Format) { #ifndef SFX_MODULE @@ -113,9 +116,9 @@ void Archive::BrokenHeaderMsg() } -void Archive::UnkEncVerMsg(const wchar *Name) +void Archive::UnkEncVerMsg(const wchar *Name,const wchar *Info) { - uiMsg(UIERROR_UNKNOWNENCMETHOD,FileName,Name); + uiMsg(UIERROR_UNKNOWNENCMETHOD,FileName,Name,Info); ErrHandler.SetErrorCode(RARX_WARNING); } @@ -201,7 +204,7 @@ size_t Archive::ReadHeader15() 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 + // 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. @@ -227,7 +230,7 @@ size_t Archive::ReadHeader15() 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. @@ -254,7 +257,7 @@ size_t Archive::ReadHeader15() 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(); @@ -279,7 +282,7 @@ size_t Archive::ReadHeader15() { case 13: hd->CryptMethod=CRYPT_RAR13; break; case 15: hd->CryptMethod=CRYPT_RAR15; break; - case 20: + case 20: case 26: hd->CryptMethod=CRYPT_RAR20; break; default: hd->CryptMethod=CRYPT_RAR30; break; } @@ -301,7 +304,7 @@ size_t Archive::ReadHeader15() } hd->Inherited=!FileBlock && (hd->SubFlags & SUBHEAD_FLAGS_INHERITED)!=0; - + hd->LargeFile=(hd->Flags & LHD_LARGE)!=0; uint HighPackSize,HighUnpSize; @@ -311,7 +314,7 @@ size_t Archive::ReadHeader15() HighUnpSize=Raw.Get4(); hd->UnknownUnpSize=(LowUnpSize==0xffffffff && HighUnpSize==0xffffffff); } - else + else { HighPackSize=HighUnpSize=0; // UnpSize equal to 0xffffffff without LHD_LARGE flag indicates @@ -506,7 +509,7 @@ size_t Archive::ReadHeader15() NextBlockPos+=Raw.Get4(); break; } - + ushort HeaderCRC=Raw.GetCRC15(false); // Old AV header does not have header CRC properly set. @@ -641,7 +644,7 @@ size_t Archive::ReadHeader50() BrokenHeaderMsg(); return 0; } - + Raw.Read(SizeToRead); if (Raw.Size()CRYPT_VERSION) { - UnkEncVerMsg(FileName); + wchar Info[20]; + swprintf(Info,ASIZE(Info),L"h%u",CryptVersion); + UnkEncVerMsg(FileName,Info); return 0; } uint EncFlags=(uint)Raw.GetV(); @@ -710,7 +715,9 @@ size_t Archive::ReadHeader50() CryptHead.Lg2Count=Raw.Get1(); if (CryptHead.Lg2Count>CRYPT5_KDF_LG2_COUNT_MAX) { - UnkEncVerMsg(FileName); + wchar Info[20]; + swprintf(Info,ASIZE(Info),L"hc%u",CryptHead.Lg2Count); + UnkEncVerMsg(FileName,Info); return 0; } Raw.GetB(CryptHead.Salt,SIZE_SALT50); @@ -763,7 +770,7 @@ size_t Archive::ReadHeader50() // to not break normal archive processing by calling function. int64 SaveCurBlockPos=CurBlockPos,SaveNextBlockPos=NextBlockPos; HEADER_TYPE SaveCurHeaderType=CurHeaderType; - + QOpen.Init(this,false); QOpen.Load(MainHead.QOpenOffset); @@ -788,7 +795,7 @@ size_t Archive::ReadHeader50() hd->PackSize=DataSize; hd->FileFlags=(uint)Raw.GetV(); hd->UnpSize=Raw.GetV(); - + hd->UnknownUnpSize=(hd->FileFlags & FHFL_UNPUNKNOWN)!=0; if (hd->UnknownUnpSize) hd->UnpSize=INT64NDF; @@ -875,7 +882,7 @@ size_t Archive::ReadHeader50() RecoverySize=Header.RecSectionSize*Header.RecCount; } #endif - + if (BadCRC) // Add the file name to broken header message displayed above. uiMsg(UIERROR_FHEADERBROKEN,Archive::FileName,hd->FileName); } @@ -991,8 +998,12 @@ void Archive::ProcessExtra50(RawRead *Raw,size_t ExtraSize,BaseBlock *bb) { FileHeader *hd=(FileHeader *)bb; uint EncVersion=(uint)Raw->GetV(); - if (EncVersion > CRYPT_VERSION) - UnkEncVerMsg(hd->FileName); + if (EncVersion>CRYPT_VERSION) + { + wchar Info[20]; + swprintf(Info,ASIZE(Info),L"x%u",EncVersion); + UnkEncVerMsg(hd->FileName,Info); + } else { uint Flags=(uint)Raw->GetV(); @@ -1000,7 +1011,11 @@ void Archive::ProcessExtra50(RawRead *Raw,size_t ExtraSize,BaseBlock *bb) hd->UseHashKey=(Flags & FHEXTRA_CRYPT_HASHMAC)!=0; hd->Lg2Count=Raw->Get1(); if (hd->Lg2Count>CRYPT5_KDF_LG2_COUNT_MAX) - UnkEncVerMsg(hd->FileName); + { + wchar Info[20]; + swprintf(Info,ASIZE(Info),L"xc%u",hd->Lg2Count); + UnkEncVerMsg(hd->FileName,Info); + } Raw->GetB(hd->Salt,SIZE_SALT50); Raw->GetB(hd->InitV,SIZE_INITV); if (hd->UsePswCheck) @@ -1292,7 +1307,7 @@ void Archive::ConvertAttributes() if (mask == (mode_t) -1) { - // umask call returns the current umask value. Argument (022) is not + // umask call returns the current umask value. Argument (022) is not // really important here. mask = umask(022); @@ -1369,8 +1384,8 @@ void Archive::ConvertFileHeader(FileHeader *hd) // ':' in file names is allowed in Unix, but not in Windows. // Even worse, file data will be written to NTFS stream on NTFS, - // so automatic name correction on file create error in extraction - // routine does not work. In Windows and DOS versions we better + // so automatic name correction on file create error in extraction + // routine does not work. In Windows and DOS versions we better // replace ':' now. if (*s==':') *s='_'; diff --git a/cmddata.cpp b/cmddata.cpp index 32b8412..7b92686 100644 --- a/cmddata.cpp +++ b/cmddata.cpp @@ -1,5 +1,8 @@ #include "rar.hpp" +#include "cmdfilter.cpp" +#include "cmdmix.cpp" + CommandData::CommandData() { Init(); @@ -130,7 +133,7 @@ void CommandData::ParseArg(wchar *Arg) FindData FileData; bool Found=FindFile::FastFind(Arg,&FileData); if ((!Found || ListMode==RCLM_ACCEPT_LISTS) && - ListMode!=RCLM_REJECT_LISTS && *Arg=='@' && !IsWildcard(Arg)) + ListMode!=RCLM_REJECT_LISTS && *Arg=='@' && !IsWildcard(Arg+1)) { FileLists=true; @@ -280,7 +283,11 @@ void CommandData::ProcessSwitch(const wchar *Switch) ClearArc=true; break; case 'D': - AppendArcNameToPath=true; + if (Switch[2]==0) + AppendArcNameToPath=APPENDARCNAME_DESTPATH; + else + if (Switch[2]=='1') + AppendArcNameToPath=APPENDARCNAME_OWNDIR; break; #ifndef SFX_MODULE case 'G': @@ -302,7 +309,7 @@ void CommandData::ProcessSwitch(const wchar *Switch) AddArcOnly=true; break; case 'P': - wcscpy(ArcPath,Switch+2); + wcsncpyz(ArcPath,Switch+2,ASIZE(ArcPath)); break; case 'S': SyncFiles=true; @@ -407,9 +414,9 @@ void CommandData::ProcessSwitch(const wchar *Switch) wcsncpyz(LogName,Switch[4]!=0 ? Switch+4:DefLogName,ASIZE(LogName)); break; } - if (wcsicomp(Switch+1,L"SND")==0) + if (wcsnicomp(Switch+1,L"SND",3)==0) { - Sound=true; + Sound=Switch[4]=='-' ? SOUND_NOTIFY_OFF : SOUND_NOTIFY_ON; break; } if (wcsicomp(Switch+1,L"ERR")==0) @@ -805,16 +812,16 @@ void CommandData::ProcessSwitch(const wchar *Switch) ArcTime=ARCTIME_LATEST; break; case 'O': - FileTimeBefore.SetAgeText(Switch+2); + SetTimeFilters(Switch+2,true,true); break; case 'N': - FileTimeAfter.SetAgeText(Switch+2); + SetTimeFilters(Switch+2,false,true); break; case 'B': - FileTimeBefore.SetIsoText(Switch+2); + SetTimeFilters(Switch+2,true,false); break; case 'A': - FileTimeAfter.SetIsoText(Switch+2); + SetTimeFilters(Switch+2,false,false); break; case 'S': { @@ -897,7 +904,7 @@ void CommandData::ProcessSwitch(const wchar *Switch) if (Switch[1]==0) { // If comment file is not specified, we read data from stdin. - wcscpy(CommentFile,L"stdin"); + wcsncpyz(CommentFile,L"stdin",ASIZE(CommentFile)); } else wcsncpyz(CommentFile,Switch+1,ASIZE(CommentFile)); @@ -922,309 +929,6 @@ void CommandData::BadSwitch(const wchar *Switch) #endif -void CommandData::OutTitle() -{ - if (BareOutput || DisableCopyright) - return; -#if defined(__GNUC__) && defined(SFX_MODULE) - mprintf(St(MCopyrightS)); -#else -#ifndef SILENT - static bool TitleShown=false; - if (TitleShown) - return; - TitleShown=true; - - wchar Version[80]; - if (RARVER_BETA!=0) - swprintf(Version,ASIZE(Version),L"%d.%02d %ls %d",RARVER_MAJOR,RARVER_MINOR,St(MBeta),RARVER_BETA); - else - swprintf(Version,ASIZE(Version),L"%d.%02d",RARVER_MAJOR,RARVER_MINOR); -#if defined(_WIN_32) || defined(_WIN_64) - wcsncatz(Version,L" ",ASIZE(Version)); -#endif -#ifdef _WIN_32 - wcsncatz(Version,St(Mx86),ASIZE(Version)); -#endif -#ifdef _WIN_64 - wcsncatz(Version,St(Mx64),ASIZE(Version)); -#endif - if (PrintVersion) - { - mprintf(L"%s",Version); - exit(0); - } - mprintf(St(MUCopyright),Version,RARVER_YEAR); -#endif -#endif -} - - -inline bool CmpMSGID(MSGID i1,MSGID i2) -{ -#ifdef MSGID_INT - return i1==i2; -#else - // If MSGID is const char*, we cannot compare pointers only. - // Pointers to different instances of same string can differ, - // so we need to compare complete strings. - return wcscmp(i1,i2)==0; -#endif -} - -void CommandData::OutHelp(RAR_EXIT ExitCode) -{ -#if !defined(SILENT) - OutTitle(); - static MSGID Help[]={ -#ifdef SFX_MODULE - // Console SFX switches definition. - MCHelpCmd,MSHelpCmdE,MSHelpCmdT,MSHelpCmdV -#else - // UnRAR switches definition. - MUNRARTitle1,MRARTitle2,MCHelpCmd,MCHelpCmdE,MCHelpCmdL, - MCHelpCmdP,MCHelpCmdT,MCHelpCmdV,MCHelpCmdX,MCHelpSw,MCHelpSwm, - MCHelpSwAT,MCHelpSwAC,MCHelpSwAD,MCHelpSwAG,MCHelpSwAI,MCHelpSwAP, - MCHelpSwCm,MCHelpSwCFGm,MCHelpSwCL,MCHelpSwCU, - MCHelpSwDH,MCHelpSwEP,MCHelpSwEP3,MCHelpSwF,MCHelpSwIDP,MCHelpSwIERR, - MCHelpSwINUL,MCHelpSwIOFF,MCHelpSwKB,MCHelpSwN,MCHelpSwNa,MCHelpSwNal, - MCHelpSwO,MCHelpSwOC,MCHelpSwOL,MCHelpSwOR,MCHelpSwOW,MCHelpSwP, - MCHelpSwPm,MCHelpSwR,MCHelpSwRI,MCHelpSwSC,MCHelpSwSL,MCHelpSwSM, - MCHelpSwTA,MCHelpSwTB,MCHelpSwTN,MCHelpSwTO,MCHelpSwTS,MCHelpSwU, - MCHelpSwVUnr,MCHelpSwVER,MCHelpSwVP,MCHelpSwX,MCHelpSwXa,MCHelpSwXal, - MCHelpSwY -#endif - }; - - for (uint I=0;IRewind(); - while (Args->GetString(CurMask,ASIZE(CurMask))) - { - wchar *LastMaskChar=PointToLastChar(CurMask); - bool DirMask=IsPathDiv(*LastMaskChar); // Mask for directories only. - - if (Dir) - { - // CheckName is a directory. - if (DirMask) - { - // We process the directory and have the directory exclusion mask. - // So let's convert "mask\" to "mask" and process it normally. - - *LastMaskChar=0; - } - else - { - // REMOVED, we want -npath\* to match empty folders too. - // If mask has wildcards in name part and does not have the trailing - // '\' character, we cannot use it for directories. - - // if (IsWildcard(PointToName(CurMask))) - // continue; - } - } - else - { - // If we process a file inside of directory excluded by "dirmask\". - // we want to exclude such file too. So we convert "dirmask\" to - // "dirmask\*". It is important for operations other than archiving - // with -x. When archiving with -x, directory matched by "dirmask\" - // is excluded from further scanning. - - if (DirMask) - wcsncatz(CurMask,L"*",ASIZE(CurMask)); - } - -#ifndef SFX_MODULE - if (CheckFullPath && IsFullPath(CurMask)) - { - // We do not need to do the special "*\" processing here, because - // unlike the "else" part of this "if", now we convert names to full - // format, so they all include the path, which is matched by "*\" - // correctly. Moreover, removing "*\" from mask would break - // the comparison, because now all names have the path. - - if (*FullName==0) - ConvertNameToFull(CheckName,FullName,ASIZE(FullName)); - if (CmpName(CurMask,FullName,MatchMode)) - return true; - } - else -#endif - { - wchar NewName[NM+2],*CurName=Name; - - // Important to convert before "*\" check below, so masks like - // d:*\something are processed properly. - wchar *CmpMask=ConvertPath(CurMask,NULL); - - if (CmpMask[0]=='*' && IsPathDiv(CmpMask[1])) - { - // We want "*\name" to match 'name' not only in subdirectories, - // but also in the current directory. We convert the name - // from 'name' to '.\name' to be matched by "*\" part even if it is - // in current directory. - NewName[0]='.'; - NewName[1]=CPATHDIVIDER; - wcsncpyz(NewName+2,Name,ASIZE(NewName)-2); - CurName=NewName; - } - - if (CmpName(CmpMask,CurName,MatchMode)) - return true; - } - } - return false; -} - - -#ifndef SFX_MODULE -// Now this function performs only one task and only in Windows version: -// it skips symlinks to directories if -e1024 switch is specified. -// Symlinks are skipped in ScanTree class, so their entire contents -// is skipped too. Without this function we would check the attribute -// only directly before archiving, so we would skip the symlink record, -// but not the contents of symlinked directory. -bool CommandData::ExclDirByAttr(uint FileAttr) -{ -#ifdef _WIN_ALL - if ((FileAttr & FILE_ATTRIBUTE_REPARSE_POINT)!=0 && - (ExclFileAttr & FILE_ATTRIBUTE_REPARSE_POINT)!=0) - return true; -#endif - return false; -} -#endif - - - - -#ifndef SFX_MODULE -// Return 'true' if we need to exclude the file from processing. -bool CommandData::TimeCheck(RarTime &ft) -{ - if (FileTimeBefore.IsSet() && ft>=FileTimeBefore) - return true; - if (FileTimeAfter.IsSet() && ft<=FileTimeAfter) - return true; - return false; -} -#endif - - -#ifndef SFX_MODULE -// Return 'true' if we need to exclude the file from processing. -bool CommandData::SizeCheck(int64 Size) -{ - if (FileSizeLess!=INT64NDF && Size>=FileSizeLess) - return(true); - if (FileSizeMore!=INT64NDF && Size<=FileSizeMore) - return(true); - return(false); -} -#endif - - - - -int CommandData::IsProcessFile(FileHeader &FileHead,bool *ExactMatch,int MatchType, - wchar *MatchedArg,uint MatchedArgSize) -{ - if (MatchedArg!=NULL && MatchedArgSize>0) - *MatchedArg=0; -// if (wcslen(FileHead.FileName)>=NM) -// return 0; - bool Dir=FileHead.Dir; - if (ExclCheck(FileHead.FileName,Dir,false,true)) - return 0; -#ifndef SFX_MODULE - if (TimeCheck(FileHead.mtime)) - return 0; - if ((FileHead.FileAttr & ExclFileAttr)!=0 || InclAttrSet && (FileHead.FileAttr & InclFileAttr)==0) - return 0; - if (!Dir && SizeCheck(FileHead.UnpSize)) - return 0; -#endif - wchar *ArgName; - FileArgs.Rewind(); - for (int StringCount=1;(ArgName=FileArgs.GetString())!=NULL;StringCount++) - if (CmpName(ArgName,FileHead.FileName,MatchType)) - { - if (ExactMatch!=NULL) - *ExactMatch=wcsicompc(ArgName,FileHead.FileName)==0; - if (MatchedArg!=NULL) - wcsncpyz(MatchedArg,ArgName,MatchedArgSize); - return StringCount; - } - return 0; -} - - void CommandData::ProcessCommand() { #ifndef SFX_MODULE diff --git a/cmddata.hpp b/cmddata.hpp index e12d4fb..bf0efa6 100644 --- a/cmddata.hpp +++ b/cmddata.hpp @@ -6,6 +6,8 @@ enum RAR_CMD_LIST_MODE {RCLM_AUTO,RCLM_REJECT_LISTS,RCLM_ACCEPT_LISTS}; +enum IS_PROCESS_FILE_FLAGS {IPFF_EXCLUDE_PARENT=1}; + class CommandData:public RAROptions { private: @@ -13,6 +15,9 @@ class CommandData:public RAROptions void ProcessSwitch(const wchar *Switch); void BadSwitch(const wchar *Switch); uint GetExclAttr(const wchar *Str); +#if !defined(SFX_MODULE) + void SetTimeFilters(const wchar *Mod,bool Before,bool Age); +#endif bool FileLists; bool NoMoreSwitches; @@ -34,11 +39,11 @@ class CommandData:public RAROptions bool ExclCheck(const wchar *CheckName,bool Dir,bool CheckFullPath,bool CheckInclList); static bool CheckArgs(StringList *Args,bool Dir,const wchar *CheckName,bool CheckFullPath,int MatchMode); bool ExclDirByAttr(uint FileAttr); - bool TimeCheck(RarTime &ft); + bool TimeCheck(RarTime &ftm,RarTime &ftc,RarTime &fta); bool SizeCheck(int64 Size); bool AnyFiltersActive(); - int IsProcessFile(FileHeader &FileHead,bool *ExactMatch=NULL,int MatchType=MATCH_WILDSUBPATH, - wchar *MatchedArg=NULL,uint MatchedArgSize=0); + int IsProcessFile(FileHeader &FileHead,bool *ExactMatch,int MatchType, + bool Flags,wchar *MatchedArg,uint MatchedArgSize); void ProcessCommand(); void AddArcName(const wchar *Name); bool GetArcName(wchar *Name,int MaxSize); diff --git a/cmdfilter.cpp b/cmdfilter.cpp new file mode 100644 index 0000000..20660cb --- /dev/null +++ b/cmdfilter.cpp @@ -0,0 +1,299 @@ +// Return 'true' if we need to exclude the file from processing as result +// of -x switch. If CheckInclList is true, we also check the file against +// the include list created with -n switch. +bool CommandData::ExclCheck(const wchar *CheckName,bool Dir,bool CheckFullPath,bool CheckInclList) +{ + if (CheckArgs(&ExclArgs,Dir,CheckName,CheckFullPath,MATCH_WILDSUBPATH)) + return true; + if (!CheckInclList || InclArgs.ItemsCount()==0) + return false; + if (CheckArgs(&InclArgs,Dir,CheckName,CheckFullPath,MATCH_WILDSUBPATH)) + return false; + return true; +} + + +bool CommandData::CheckArgs(StringList *Args,bool Dir,const wchar *CheckName,bool CheckFullPath,int MatchMode) +{ + wchar *Name=ConvertPath(CheckName,NULL,0); + wchar FullName[NM]; + wchar CurMask[NM]; + *FullName=0; + Args->Rewind(); + while (Args->GetString(CurMask,ASIZE(CurMask))) + { + wchar *LastMaskChar=PointToLastChar(CurMask); + bool DirMask=IsPathDiv(*LastMaskChar); // Mask for directories only. + + if (Dir) + { + // CheckName is a directory. + if (DirMask) + { + // We process the directory and have the directory exclusion mask. + // So let's convert "mask\" to "mask" and process it normally. + + *LastMaskChar=0; + } + else + { + // REMOVED, we want -npath\* to match empty folders too. + // If mask has wildcards in name part and does not have the trailing + // '\' character, we cannot use it for directories. + + // if (IsWildcard(PointToName(CurMask))) + // continue; + } + } + else + { + // If we process a file inside of directory excluded by "dirmask\". + // we want to exclude such file too. So we convert "dirmask\" to + // "dirmask\*". It is important for operations other than archiving + // with -x. When archiving with -x, directory matched by "dirmask\" + // is excluded from further scanning. + + if (DirMask) + wcsncatz(CurMask,L"*",ASIZE(CurMask)); + } + +#ifndef SFX_MODULE + if (CheckFullPath && IsFullPath(CurMask)) + { + // We do not need to do the special "*\" processing here, because + // unlike the "else" part of this "if", now we convert names to full + // format, so they all include the path, which is matched by "*\" + // correctly. Moreover, removing "*\" from mask would break + // the comparison, because now all names have the path. + + if (*FullName==0) + ConvertNameToFull(CheckName,FullName,ASIZE(FullName)); + if (CmpName(CurMask,FullName,MatchMode)) + return true; + } + else +#endif + { + wchar NewName[NM+2],*CurName=Name; + + // Important to convert before "*\" check below, so masks like + // d:*\something are processed properly. + wchar *CmpMask=ConvertPath(CurMask,NULL,0); + + if (CmpMask[0]=='*' && IsPathDiv(CmpMask[1])) + { + // We want "*\name" to match 'name' not only in subdirectories, + // but also in the current directory. We convert the name + // from 'name' to '.\name' to be matched by "*\" part even if it is + // in current directory. + NewName[0]='.'; + NewName[1]=CPATHDIVIDER; + wcsncpyz(NewName+2,Name,ASIZE(NewName)-2); + CurName=NewName; + } + + if (CmpName(CmpMask,CurName,MatchMode)) + return true; + } + } + return false; +} + + + + +#ifndef SFX_MODULE +// Now this function performs only one task and only in Windows version: +// it skips symlinks to directories if -e1024 switch is specified. +// Symlinks are skipped in ScanTree class, so their entire contents +// is skipped too. Without this function we would check the attribute +// only directly before archiving, so we would skip the symlink record, +// but not the contents of symlinked directory. +bool CommandData::ExclDirByAttr(uint FileAttr) +{ +#ifdef _WIN_ALL + if ((FileAttr & FILE_ATTRIBUTE_REPARSE_POINT)!=0 && + (ExclFileAttr & FILE_ATTRIBUTE_REPARSE_POINT)!=0) + return true; +#endif + return false; +} +#endif + + + + +#if !defined(SFX_MODULE) +void CommandData::SetTimeFilters(const wchar *Mod,bool Before,bool Age) +{ + bool ModeOR=false,TimeMods=false; + const wchar *S=Mod; + for (;wcschr(L"MCAOmcao",*S)!=NULL;S++) + if (*S=='o' || *S=='O') + ModeOR=true; + else + TimeMods=true; + + if (!TimeMods) + Mod=L"m"; + + for (;wcschr(L"MCAOmcao",*Mod)!=NULL;Mod++) + switch(toupperw(*Mod)) + { + case 'M': + if (Before) + { + Age ? FileMtimeBefore.SetAgeText(S):FileMtimeBefore.SetIsoText(S); + FileMtimeBeforeOR=ModeOR; + } + else + { + Age ? FileMtimeAfter.SetAgeText(S):FileMtimeAfter.SetIsoText(S); + FileMtimeAfterOR=ModeOR; + } + break; + case 'C': + if (Before) + { + Age ? FileCtimeBefore.SetAgeText(S):FileCtimeBefore.SetIsoText(S); + FileCtimeBeforeOR=ModeOR; + } + else + { + Age ? FileCtimeAfter.SetAgeText(S):FileCtimeAfter.SetIsoText(S); + FileCtimeAfterOR=ModeOR; + } + break; + case 'A': + if (Before) + { + Age ? FileAtimeBefore.SetAgeText(S):FileAtimeBefore.SetIsoText(S); + FileAtimeBeforeOR=ModeOR; + } + else + { + Age ? FileAtimeAfter.SetAgeText(S):FileAtimeAfter.SetIsoText(S); + FileAtimeAfterOR=ModeOR; + } + break; + } +} +#endif + + +#ifndef SFX_MODULE +// Return 'true' if we need to exclude the file from processing. +bool CommandData::TimeCheck(RarTime &ftm,RarTime &ftc,RarTime &fta) +{ + bool FilterOR=false; + + if (FileMtimeBefore.IsSet()) // Filter present. + if (ftm>=FileMtimeBefore) // Condition not matched. + if (FileMtimeBeforeOR) + FilterOR=true; // Not matched OR filter is present. + else + return true; // Exclude file in AND mode. + else // Condition matched. + if (FileMtimeBeforeOR) + return false; // Include file in OR mode. + + if (FileMtimeAfter.IsSet()) // Filter present. + if (ftm=FileCtimeBefore) // Condition not matched. + if (FileCtimeBeforeOR) + FilterOR=true; // Not matched OR filter is present. + else + return true; // Exclude file in AND mode. + else // Condition matched. + if (FileCtimeBeforeOR) + return false; // Include file in OR mode. + + if (FileCtimeAfter.IsSet()) // Filter present. + if (ftc=FileAtimeBefore) // Condition not matched. + if (FileAtimeBeforeOR) + FilterOR=true; // Not matched OR filter is present. + else + return true; // Exclude file in AND mode. + else // Condition matched. + if (FileAtimeBeforeOR) + return false; // Include file in OR mode. + + if (FileAtimeAfter.IsSet()) // Filter present. + if (fta=FileSizeLess) + return true; + if (FileSizeMore!=INT64NDF && Size<=FileSizeMore) + return true; + return false; +} +#endif + + + + +// Return 0 if file must not be processed or a number of matched parameter otherwise. +int CommandData::IsProcessFile(FileHeader &FileHead,bool *ExactMatch,int MatchType, + bool Flags,wchar *MatchedArg,uint MatchedArgSize) +{ + if (MatchedArg!=NULL && MatchedArgSize>0) + *MatchedArg=0; + bool Dir=FileHead.Dir; + if (ExclCheck(FileHead.FileName,Dir,false,true)) + return 0; +#ifndef SFX_MODULE + if (TimeCheck(FileHead.mtime,FileHead.ctime,FileHead.atime)) + return 0; + if ((FileHead.FileAttr & ExclFileAttr)!=0 || InclAttrSet && (FileHead.FileAttr & InclFileAttr)==0) + return 0; + if (!Dir && SizeCheck(FileHead.UnpSize)) + return 0; +#endif + wchar *ArgName; + FileArgs.Rewind(); + for (int StringCount=1;(ArgName=FileArgs.GetString())!=NULL;StringCount++) + if (CmpName(ArgName,FileHead.FileName,MatchType)) + { + if (ExactMatch!=NULL) + *ExactMatch=wcsicompc(ArgName,FileHead.FileName)==0; + if (MatchedArg!=NULL) + wcsncpyz(MatchedArg,ArgName,MatchedArgSize); + return StringCount; + } + return 0; +} diff --git a/cmdmix.cpp b/cmdmix.cpp new file mode 100644 index 0000000..3990cc1 --- /dev/null +++ b/cmdmix.cpp @@ -0,0 +1,118 @@ +void CommandData::OutTitle() +{ + if (BareOutput || DisableCopyright) + return; +#if defined(__GNUC__) && defined(SFX_MODULE) + mprintf(St(MCopyrightS)); +#else +#ifndef SILENT + static bool TitleShown=false; + if (TitleShown) + return; + TitleShown=true; + + wchar Version[80]; + if (RARVER_BETA!=0) + swprintf(Version,ASIZE(Version),L"%d.%02d %ls %d",RARVER_MAJOR,RARVER_MINOR,St(MBeta),RARVER_BETA); + else + swprintf(Version,ASIZE(Version),L"%d.%02d",RARVER_MAJOR,RARVER_MINOR); +#if defined(_WIN_32) || defined(_WIN_64) + wcsncatz(Version,L" ",ASIZE(Version)); +#endif +#ifdef _WIN_32 + wcsncatz(Version,St(Mx86),ASIZE(Version)); +#endif +#ifdef _WIN_64 + wcsncatz(Version,St(Mx64),ASIZE(Version)); +#endif + if (PrintVersion) + { + mprintf(L"%s",Version); + exit(0); + } + mprintf(St(MUCopyright),Version,RARVER_YEAR); +#endif +#endif +} + + +inline bool CmpMSGID(MSGID i1,MSGID i2) +{ +#ifdef MSGID_INT + return i1==i2; +#else + // If MSGID is const char*, we cannot compare pointers only. + // Pointers to different instances of same string can differ, + // so we need to compare complete strings. + return wcscmp(i1,i2)==0; +#endif +} + +void CommandData::OutHelp(RAR_EXIT ExitCode) +{ +#if !defined(SILENT) + OutTitle(); + static MSGID Help[]={ +#ifdef SFX_MODULE + // Console SFX switches definition. + MCHelpCmd,MSHelpCmdE,MSHelpCmdT,MSHelpCmdV +#else + // UnRAR switches definition. + MUNRARTitle1,MRARTitle2,MCHelpCmd,MCHelpCmdE,MCHelpCmdL, + MCHelpCmdP,MCHelpCmdT,MCHelpCmdV,MCHelpCmdX,MCHelpSw,MCHelpSwm, + MCHelpSwAT,MCHelpSwAC,MCHelpSwAD,MCHelpSwAG,MCHelpSwAI,MCHelpSwAP, + MCHelpSwCm,MCHelpSwCFGm,MCHelpSwCL,MCHelpSwCU, + MCHelpSwDH,MCHelpSwEP,MCHelpSwEP3,MCHelpSwF,MCHelpSwIDP,MCHelpSwIERR, + MCHelpSwINUL,MCHelpSwIOFF,MCHelpSwKB,MCHelpSwN,MCHelpSwNa,MCHelpSwNal, + MCHelpSwO,MCHelpSwOC,MCHelpSwOL,MCHelpSwOR,MCHelpSwOW,MCHelpSwP, + MCHelpSwPm,MCHelpSwR,MCHelpSwRI,MCHelpSwSC,MCHelpSwSL,MCHelpSwSM, + MCHelpSwTA,MCHelpSwTB,MCHelpSwTN,MCHelpSwTO,MCHelpSwTS,MCHelpSwU, + MCHelpSwVUnr,MCHelpSwVER,MCHelpSwVP,MCHelpSwX,MCHelpSwXa,MCHelpSwXal, + MCHelpSwY +#endif + }; + + for (uint I=0;I>(J*8)); KDF3Cache[KDF3CachePos].Pwd=*Password; diff --git a/dll.cpp b/dll.cpp index 4b60aa4..5f4d00e 100644 --- a/dll.cpp +++ b/dll.cpp @@ -42,6 +42,7 @@ HANDLE PASCAL RAROpenArchiveEx(struct RAROpenArchiveDataEx *r) Data->Cmd.DllError=0; Data->OpenMode=r->OpenMode; Data->Cmd.FileArgs.AddString(L"*"); + Data->Cmd.KeepBroken=(r->OpFlags&ROADOF_KEEPBROKEN)!=0; char AnsiArcName[NM]; *AnsiArcName=0; @@ -95,6 +96,8 @@ HANDLE PASCAL RAROpenArchiveEx(struct RAROpenArchiveDataEx *r) if (Data->Arc.Volume) r->Flags|=0x01; + if (Data->Arc.MainComment) + r->Flags|=0x02; if (Data->Arc.Locked) r->Flags|=0x04; if (Data->Arc.Solid) @@ -113,17 +116,29 @@ HANDLE PASCAL RAROpenArchiveEx(struct RAROpenArchiveDataEx *r) Array CmtDataW; if (r->CmtBufSize!=0 && Data->Arc.GetComment(&CmtDataW)) { - Array CmtData(CmtDataW.Size()*4+1); - memset(&CmtData[0],0,CmtData.Size()); - WideToChar(&CmtDataW[0],&CmtData[0],CmtData.Size()-1); - size_t Size=strlen(&CmtData[0])+1; - - r->Flags|=2; - r->CmtState=Size>r->CmtBufSize ? ERAR_SMALL_BUF:1; - r->CmtSize=(uint)Min(Size,r->CmtBufSize); - memcpy(r->CmtBuf,&CmtData[0],r->CmtSize-1); - if (Size<=r->CmtBufSize) - r->CmtBuf[r->CmtSize-1]=0; + if (r->CmtBufW!=NULL) + { + CmtDataW.Push(0); + size_t Size=wcslen(&CmtDataW[0])+1; + + r->CmtState=Size>r->CmtBufSize ? ERAR_SMALL_BUF:1; + r->CmtSize=(uint)Min(Size,r->CmtBufSize); + memcpy(r->CmtBufW,&CmtDataW[0],(r->CmtSize-1)*sizeof(*r->CmtBufW)); + r->CmtBufW[r->CmtSize-1]=0; + } + else + if (r->CmtBuf!=NULL) + { + Array CmtData(CmtDataW.Size()*4+1); + memset(&CmtData[0],0,CmtData.Size()); + WideToChar(&CmtDataW[0],&CmtData[0],CmtData.Size()-1); + size_t Size=strlen(&CmtData[0])+1; + + r->CmtState=Size>r->CmtBufSize ? ERAR_SMALL_BUF:1; + r->CmtSize=(uint)Min(Size,r->CmtBufSize); + memcpy(r->CmtBuf,&CmtData[0],r->CmtSize-1); + r->CmtBuf[r->CmtSize-1]=0; + } } else r->CmtState=r->CmtSize=0; @@ -369,7 +384,7 @@ int PASCAL ProcessFile(HANDLE hArcData,int Operation,char *DestPath,char *DestNa if (DestNameW!=NULL) wcsncpyz(Data->Cmd.DllDestName,DestNameW,ASIZE(Data->Cmd.DllDestName)); - wcscpy(Data->Cmd.Command,Operation==RAR_EXTRACT ? L"X":L"T"); + wcsncpyz(Data->Cmd.Command,Operation==RAR_EXTRACT ? L"X":L"T",ASIZE(Data->Cmd.Command)); Data->Cmd.Test=Operation!=RAR_EXTRACT; bool Repeat=false; Data->Extract.ExtractCurrentFile(Data->Arc,Data->HeaderSize,Repeat); @@ -436,16 +451,16 @@ void PASCAL RARSetProcessDataProc(HANDLE hArcData,PROCESSDATAPROC ProcessDataPro } -#ifndef RAR_NOCRYPT void PASCAL RARSetPassword(HANDLE hArcData,char *Password) { +#ifndef RAR_NOCRYPT DataSet *Data=(DataSet *)hArcData; wchar PasswordW[MAXPASSWORD]; GetWideName(Password,NULL,PasswordW,ASIZE(PasswordW)); Data->Cmd.Password.Set(PasswordW); cleandata(PasswordW,sizeof(PasswordW)); -} #endif +} int PASCAL RARGetDllVersion() diff --git a/dll.def b/dll.def index 660f69b..3c9a2c8 100644 --- a/dll.def +++ b/dll.def @@ -5,6 +5,7 @@ EXPORTS RARReadHeader RARReadHeaderEx RARProcessFile + RARProcessFileW RARSetCallback RARSetChangeVolProc RARSetProcessDataProc diff --git a/dll.hpp b/dll.hpp index 7f82906..c785ff1 100644 --- a/dll.hpp +++ b/dll.hpp @@ -1,7 +1,7 @@ #ifndef _UNRAR_DLL_ #define _UNRAR_DLL_ -#pragma pack(1) +#pragma pack(push, 1) #define ERAR_SUCCESS 0 #define ERAR_END_ARCHIVE 10 @@ -135,6 +135,8 @@ typedef int (CALLBACK *UNRARCALLBACK)(UINT msg,LPARAM UserData,LPARAM P1,LPARAM #define ROADF_ENCHEADERS 0x0080 #define ROADF_FIRSTVOLUME 0x0100 +#define ROADOF_KEEPBROKEN 0x0001 + struct RAROpenArchiveDataEx { char *ArcName; @@ -148,7 +150,9 @@ struct RAROpenArchiveDataEx unsigned int Flags; UNRARCALLBACK Callback; LPARAM UserData; - unsigned int Reserved[28]; + unsigned int OpFlags; + wchar_t *CmtBufW; + unsigned int Reserved[25]; }; enum UNRARCALLBACK_MESSAGES { @@ -180,6 +184,6 @@ int PASCAL RARGetDllVersion(); } #endif -#pragma pack() +#pragma pack(pop) #endif diff --git a/dll.rc b/dll.rc index 30a0166..4564d92 100644 --- a/dll.rc +++ b/dll.rc @@ -2,8 +2,8 @@ #include VS_VERSION_INFO VERSIONINFO -FILEVERSION 5, 61, 100, 2835 -PRODUCTVERSION 5, 61, 100, 2835 +FILEVERSION 5, 70, 100, 2983 +PRODUCTVERSION 5, 70, 100, 2983 FILEOS VOS__WINDOWS32 FILETYPE VFT_APP { @@ -14,9 +14,9 @@ FILETYPE VFT_APP VALUE "CompanyName", "Alexander Roshal\0" VALUE "ProductName", "RAR decompression library\0" VALUE "FileDescription", "RAR decompression library\0" - VALUE "FileVersion", "5.61.0\0" - VALUE "ProductVersion", "5.61.0\0" - VALUE "LegalCopyright", "Copyright © Alexander Roshal 1993-2018\0" + VALUE "FileVersion", "5.70.0\0" + VALUE "ProductVersion", "5.70.0\0" + VALUE "LegalCopyright", "Copyright © Alexander Roshal 1993-2019\0" VALUE "OriginalFilename", "Unrar.dll\0" } } diff --git a/dll_nocrypt.def b/dll_nocrypt.def new file mode 100644 index 0000000..d473e97 --- /dev/null +++ b/dll_nocrypt.def @@ -0,0 +1,13 @@ +EXPORTS + RAROpenArchive + RAROpenArchiveEx + RARCloseArchive + RARReadHeader + RARReadHeaderEx + RARProcessFile + RARProcessFileW + RARSetCallback + RARSetChangeVolProc + RARSetProcessDataProc +; RARSetPassword + RARGetDllVersion diff --git a/errhnd.hpp b/errhnd.hpp index eae5914..3455dac 100644 --- a/errhnd.hpp +++ b/errhnd.hpp @@ -56,7 +56,7 @@ class ErrorHandler uint GetErrorCount() {return ErrCount;} void SetSignalHandlers(bool Enable); void Throw(RAR_EXIT Code); - void SetSilent(bool Mode) {Silent=Mode;}; + void SetSilent(bool Mode) {Silent=Mode;} bool GetSysErrMsg(wchar *Msg,size_t Size); void SysErrMsg(); int GetSystemErrorCode(); diff --git a/extract.cpp b/extract.cpp index 4540bd3..fe11d7f 100644 --- a/extract.cpp +++ b/extract.cpp @@ -87,7 +87,7 @@ void CmdExtract::ExtractArchiveInit(Archive &Arc) FirstFile=true; #endif - GlobalPassword=Cmd->Password.IsSet(); + GlobalPassword=Cmd->Password.IsSet() || uiIsGlobalPasswordSet(); DataIO.UnpVolume=false; @@ -298,7 +298,7 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat) bool EqualNames=false; wchar MatchedArg[NM]; - int MatchNumber=Cmd->IsProcessFile(Arc.FileHead,&EqualNames,MatchType,MatchedArg,ASIZE(MatchedArg)); + int MatchNumber=Cmd->IsProcessFile(Arc.FileHead,&EqualNames,MatchType,0,MatchedArg,ASIZE(MatchedArg)); bool MatchFound=MatchNumber!=0; #ifndef SFX_MODULE if (Cmd->ExclPath==EXCL_BASEPATH) @@ -345,7 +345,7 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat) #endif wchar ArcFileName[NM]; - ConvertPath(Arc.FileHead.FileName,ArcFileName); + ConvertPath(Arc.FileHead.FileName,ArcFileName,ASIZE(ArcFileName)); if (Arc.FileHead.Version) { @@ -473,7 +473,7 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat) memcmp(Arc.FileHead.PswCheck,PswCheck,SIZE_PSWCHECK)!=0 && !Arc.BrokenHeader) { - if (GlobalPassword) // For -p or Ctrl+P. + if (GlobalPassword) // For -p or Ctrl+P to avoid the infinite loop. { // This message is used by Android GUI to reset cached passwords. // Update appropriate code if changed. @@ -851,9 +851,12 @@ void CmdExtract::ExtrPrepareName(Archive &Arc,const wchar *ArcFileName,wchar *De } #ifndef SFX_MODULE - if (Cmd->AppendArcNameToPath) + if (Cmd->AppendArcNameToPath!=APPENDARCNAME_NONE) { - wcsncatz(DestName,PointToName(Arc.FirstVolumeName),DestSize); + if (Cmd->AppendArcNameToPath==APPENDARCNAME_DESTPATH) + wcsncatz(DestName,PointToName(Arc.FirstVolumeName),DestSize); + else + wcsncpyz(DestName,Arc.FirstVolumeName,DestSize); // To archive own dir. SetExt(DestName,NULL,DestSize); AddEndSlash(DestName,DestSize); } @@ -1082,7 +1085,7 @@ void CmdExtract::ExtrCreateDir(Archive &Arc,const wchar *ArcFileName) { #if defined(_WIN_ALL) && !defined(SFX_MODULE) if (Cmd->SetCompressedAttr && - (Arc.FileHead.FileAttr & FILE_ATTRIBUTE_COMPRESSED)!=0 && WinNT()) + (Arc.FileHead.FileAttr & FILE_ATTRIBUTE_COMPRESSED)!=0 && WinNT()!=WNT_NONE) SetFileCompression(DestFileName,true); #endif SetFileHeaderExtra(Cmd,Arc,DestFileName); diff --git a/file.cpp b/file.cpp index e2bb42a..fb9594d 100644 --- a/file.cpp +++ b/file.cpp @@ -271,7 +271,7 @@ bool File::Rename(const wchar *NewName) Success=RenameFile(FileName,NewName); if (Success) - wcscpy(FileName,NewName); + wcsncpyz(FileName,NewName,ASIZE(FileName)); return Success; } diff --git a/file.hpp b/file.hpp index f99336a..794023a 100644 --- a/file.hpp +++ b/file.hpp @@ -99,7 +99,7 @@ class File void SetCloseFileTime(RarTime *ftm,RarTime *fta=NULL); static void SetCloseFileTimeByName(const wchar *Name,RarTime *ftm,RarTime *fta); void GetOpenFileTime(RarTime *ft); - virtual bool IsOpened() {return hFile!=FILE_BAD_HANDLE;}; // 'virtual' for MultiFile class. + virtual bool IsOpened() {return hFile!=FILE_BAD_HANDLE;} // 'virtual' for MultiFile class. int64 FileLength(); void SetHandleType(FILE_HANDLETYPE Type) {HandleType=Type;} FILE_HANDLETYPE GetHandleType() {return HandleType;} diff --git a/filefn.cpp b/filefn.cpp index 4eb7b9b..cae7598 100644 --- a/filefn.cpp +++ b/filefn.cpp @@ -348,7 +348,7 @@ wchar *MkTemp(wchar *Name,size_t MaxSize) swprintf(RndText,ASIZE(RndText),L"%u.%03u",PID,Ext); if (Length+wcslen(RndText)>=MaxSize || Attempt==1000) return NULL; - wcscpy(Name+Length,RndText); + wcsncpyz(Name+Length,RndText,MaxSize-Length); if (!FileExist(Name)) break; } diff --git a/find.cpp b/find.cpp index 812af6b..98cf771 100644 --- a/find.cpp +++ b/find.cpp @@ -26,7 +26,7 @@ FindFile::~FindFile() void FindFile::SetMask(const wchar *Mask) { - wcscpy(FindMask,Mask); + wcsncpyz(FindMask,Mask,ASIZE(FindMask)); FirstCall=true; } @@ -52,7 +52,7 @@ bool FindFile::Next(FindData *fd,bool GetSymLink) wcsncpyz(DirName,FindMask,ASIZE(DirName)); RemoveNameFromPath(DirName); if (*DirName==0) - wcscpy(DirName,L"."); + wcsncpyz(DirName,L".",ASIZE(DirName)); char DirNameA[NM]; WideToChar(DirName,DirNameA,ASIZE(DirNameA)); if ((dirp=opendir(DirNameA))==NULL) @@ -75,20 +75,20 @@ bool FindFile::Next(FindData *fd,bool GetSymLink) if (CmpName(FindMask,Name,MATCH_NAMES)) { wchar FullName[NM]; - wcscpy(FullName,FindMask); + wcsncpyz(FullName,FindMask,ASIZE(FullName)); *PointToName(FullName)=0; if (wcslen(FullName)+wcslen(Name)>=ASIZE(FullName)-1) { uiMsg(UIERROR_PATHTOOLONG,FullName,L"",Name); return false; } - wcscat(FullName,Name); + wcsncatz(FullName,Name,ASIZE(FullName)); if (!FastFind(FullName,fd,GetSymLink)) { ErrHandler.OpenErrorMsg(FullName); continue; } - wcscpy(fd->Name,FullName); + wcsncpyz(fd->Name,FullName,ASIZE(fd->Name)); break; } } diff --git a/list.cpp b/list.cpp index b957f16..11c404e 100644 --- a/list.cpp +++ b/list.cpp @@ -91,7 +91,7 @@ void ListArchive(CommandData *Cmd) switch(HeaderType) { case HEAD_FILE: - FileMatched=Cmd->IsProcessFile(Arc.FileHead)!=0; + FileMatched=Cmd->IsProcessFile(Arc.FileHead,NULL,MATCH_WILDSUBPATH,0,NULL,0)!=0; if (FileMatched) { ListFileHeader(Arc,Arc.FileHead,TitleShown,Verbose,Technical,Bare); @@ -215,7 +215,7 @@ void ListFileHeader(Archive &Arc,FileHeader &hd,bool &TitleShown,bool Verbose,bo wchar UnpSizeText[30],PackSizeText[30]; if (hd.UnpSize==INT64NDF) - wcscpy(UnpSizeText,L"?"); + wcsncpyz(UnpSizeText,L"?",ASIZE(UnpSizeText)); else itoa(hd.UnpSize,UnpSizeText,ASIZE(UnpSizeText)); itoa(hd.PackSize,PackSizeText,ASIZE(PackSizeText)); @@ -229,13 +229,13 @@ void ListFileHeader(Archive &Arc,FileHeader &hd,bool &TitleShown,bool Verbose,bo wchar RatioStr[10]; if (hd.SplitBefore && hd.SplitAfter) - wcscpy(RatioStr,L"<->"); + wcsncpyz(RatioStr,L"<->",ASIZE(RatioStr)); else if (hd.SplitBefore) - wcscpy(RatioStr,L"<--"); + wcsncpyz(RatioStr,L"<--",ASIZE(RatioStr)); else if (hd.SplitAfter) - wcscpy(RatioStr,L"-->"); + wcsncpyz(RatioStr,L"-->",ASIZE(RatioStr)); else swprintf(RatioStr,ASIZE(RatioStr),L"%d%%",ToPercentUnlim(hd.PackSize,hd.UnpSize)); @@ -467,7 +467,7 @@ void ListFileAttr(uint A,HOST_SYSTEM_TYPE HostType,wchar *AttrStr,size_t AttrSiz (A & 0x0001) ? ((A & 0x200)!=0 ? 't' : 'x') : '-'); break; case HSYS_UNKNOWN: - wcscpy(AttrStr,L"?"); + wcsncpyz(AttrStr,L"?",AttrSize); break; } } diff --git a/loclang.hpp b/loclang.hpp index ebc9654..181fcb4 100644 --- a/loclang.hpp +++ b/loclang.hpp @@ -85,7 +85,7 @@ #define MCHelpSwILOG L"\n ilog[name] Log errors to file" #define MCHelpSwINUL L"\n inul Disable all messages" #define MCHelpSwIOFF L"\n ioff[n] Turn PC off after completing an operation" -#define MCHelpSwISND L"\n isnd Enable sound" +#define MCHelpSwISND L"\n isnd Control notification sounds" #define MCHelpSwIVER L"\n iver Display the version number" #define MCHelpSwK L"\n k Lock archive" #define MCHelpSwKB L"\n kb Keep broken extracted files" @@ -127,11 +127,11 @@ #define MCHelpSwT L"\n t Test files after archiving" #define MCHelpSwTK L"\n tk Keep original archive time" #define MCHelpSwTL L"\n tl Set archive time to latest file" -#define MCHelpSwTN L"\n tn