123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985 |
- #include "rar.hpp"
- CmdExtract::CmdExtract()
- {
- TotalFileCount=0;
- *Password=0;
- Unp=new Unpack(&DataIO);
- Unp->Init(NULL);
- }
- CmdExtract::~CmdExtract()
- {
- delete Unp;
- memset(Password,0,sizeof(Password));
- }
- void CmdExtract::DoExtract(CommandData *Cmd)
- {
- PasswordCancelled=false;
- DataIO.SetCurrentCommand(*Cmd->Command);
- FindData FD;
- while (Cmd->GetArcName(ArcName,ArcNameW,ASIZE(ArcName)))
- if (FindFile::FastFind(ArcName,ArcNameW,&FD))
- DataIO.TotalArcSize+=FD.Size;
- Cmd->ArcNames->Rewind();
- while (Cmd->GetArcName(ArcName,ArcNameW,ASIZE(ArcName)))
- {
- while (true)
- {
- wchar PrevCmdPassword[MAXPASSWORD];
- wcscpy(PrevCmdPassword,Cmd->Password);
- EXTRACT_ARC_CODE Code=ExtractArchive(Cmd);
- // Restore Cmd->Password, which could be changed in IsArchive() call
- // for next header encrypted archive.
- wcscpy(Cmd->Password,PrevCmdPassword);
- if (Code!=EXTRACT_ARC_REPEAT)
- break;
- }
- if (FindFile::FastFind(ArcName,ArcNameW,&FD))
- DataIO.ProcessedArcSize+=FD.Size;
- }
- if (TotalFileCount==0 && *Cmd->Command!='I')
- {
- if (!PasswordCancelled)
- {
- mprintf(St(MExtrNoFiles));
- }
- ErrHandler.SetErrorCode(NO_FILES_ERROR);
- }
- #ifndef GUI
- else
- if (!Cmd->DisableDone)
- if (*Cmd->Command=='I')
- mprintf(St(MDone));
- else
- if (ErrHandler.GetErrorCount()==0)
- mprintf(St(MExtrAllOk));
- else
- mprintf(St(MExtrTotalErr),ErrHandler.GetErrorCount());
- #endif
- }
- void CmdExtract::ExtractArchiveInit(CommandData *Cmd,Archive &Arc)
- {
- DataIO.UnpArcSize=Arc.FileLength();
- FileCount=0;
- MatchedArgs=0;
- #ifndef SFX_MODULE
- FirstFile=true;
- #endif
- if (*Cmd->Password!=0)
- wcscpy(Password,Cmd->Password);
- PasswordAll=(*Cmd->Password!=0);
- DataIO.UnpVolume=false;
- PrevExtracted=false;
- SignatureFound=false;
- AllMatchesExact=true;
- ReconstructDone=false;
- AnySolidDataUnpackedWell=false;
- StartTime.SetCurrentTime();
- }
- EXTRACT_ARC_CODE CmdExtract::ExtractArchive(CommandData *Cmd)
- {
- Archive Arc(Cmd);
- if (!Arc.WOpen(ArcName,ArcNameW))
- {
- ErrHandler.SetErrorCode(OPEN_ERROR);
- return(EXTRACT_ARC_NEXT);
- }
- if (!Arc.IsArchive(true))
- {
- #ifndef GUI
- mprintf(St(MNotRAR),ArcName);
- #endif
- if (CmpExt(ArcName,"rar"))
- ErrHandler.SetErrorCode(WARNING);
- return(EXTRACT_ARC_NEXT);
- }
- // Archive with corrupt encrypted header can be closed in IsArchive() call.
- // if (!Arc.IsOpened())
- // return(EXTRACT_ARC_NEXT);
- #ifndef SFX_MODULE
- if (Arc.Volume && Arc.NotFirstVolume)
- {
- char FirstVolName[NM];
- VolNameToFirstName(ArcName,FirstVolName,(Arc.NewMhd.Flags & MHD_NEWNUMBERING)!=0);
- // If several volume names from same volume set are specified
- // and current volume is not first in set and first volume is present
- // and specified too, let's skip the current volume.
- if (stricomp(ArcName,FirstVolName)!=0 && FileExist(FirstVolName) &&
- Cmd->ArcNames->Search(FirstVolName,NULL,false))
- return(EXTRACT_ARC_NEXT);
- }
- #endif
- int64 VolumeSetSize=0; // Total size of volumes after the current volume.
- if (Arc.Volume)
- {
- // Calculate the total size of all accessible volumes.
- // This size is necessary to display the correct total progress indicator.
- char NextName[NM];
- wchar NextNameW[NM];
- strcpy(NextName,Arc.FileName);
- wcscpy(NextNameW,Arc.FileNameW);
- while (true)
- {
- // First volume is already added to DataIO.TotalArcSize
- // in initial TotalArcSize calculation in DoExtract.
- // So we skip it and start from second volume.
- NextVolumeName(NextName,NextNameW,ASIZE(NextName),(Arc.NewMhd.Flags & MHD_NEWNUMBERING)==0 || Arc.OldFormat);
- struct FindData FD;
- if (FindFile::FastFind(NextName,NextNameW,&FD))
- VolumeSetSize+=FD.Size;
- else
- break;
- }
- DataIO.TotalArcSize+=VolumeSetSize;
- }
- ExtractArchiveInit(Cmd,Arc);
- if (*Cmd->Command=='T' || *Cmd->Command=='I')
- Cmd->Test=true;
- #ifndef GUI
- if (*Cmd->Command=='I')
- Cmd->DisablePercentage=true;
- else
- if (Cmd->Test)
- mprintf(St(MExtrTest),ArcName);
- else
- mprintf(St(MExtracting),ArcName);
- #endif
- Arc.ViewComment();
- // RAR can close a corrupt encrypted archive
- // if (!Arc.IsOpened())
- // return(EXTRACT_ARC_NEXT);
- while (1)
- {
- size_t Size=Arc.ReadHeader();
- bool Repeat=false;
- if (!ExtractCurrentFile(Cmd,Arc,Size,Repeat))
- if (Repeat)
- {
- // If we started extraction from not first volume and need to
- // restart it from first, we must correct DataIO.TotalArcSize
- // for correct total progress display. We subtract the size
- // of current volume and all volumes after it and add the size
- // of new (first) volume.
- FindData OldArc,NewArc;
- if (FindFile::FastFind(Arc.FileName,Arc.FileNameW,&OldArc) &&
- FindFile::FastFind(ArcName,ArcNameW,&NewArc))
- DataIO.TotalArcSize-=VolumeSetSize+OldArc.Size-NewArc.Size;
- return(EXTRACT_ARC_REPEAT);
- }
- else
- break;
- }
- return(EXTRACT_ARC_NEXT);
- }
- bool CmdExtract::ExtractCurrentFile(CommandData *Cmd,Archive &Arc,size_t HeaderSize,bool &Repeat)
- {
- char Command=*Cmd->Command;
- if (HeaderSize==0)
- if (DataIO.UnpVolume)
- {
- #ifdef NOVOLUME
- return(false);
- #else
- if (!MergeArchive(Arc,&DataIO,false,Command))
- {
- ErrHandler.SetErrorCode(WARNING);
- return(false);
- }
- SignatureFound=false;
- #endif
- }
- else
- return(false);
- int HeadType=Arc.GetHeaderType();
- if (HeadType!=FILE_HEAD)
- {
- if (HeadType==AV_HEAD || HeadType==SIGN_HEAD)
- SignatureFound=true;
- #if !defined(SFX_MODULE) && !defined(_WIN_CE)
- if (HeadType==SUB_HEAD && PrevExtracted)
- SetExtraInfo(Cmd,Arc,DestFileName,*DestFileNameW ? DestFileNameW:NULL);
- #endif
- if (HeadType==NEWSUB_HEAD)
- {
- if (Arc.SubHead.CmpName(SUBHEAD_TYPE_AV))
- SignatureFound=true;
- #if !defined(NOSUBBLOCKS) && !defined(_WIN_CE)
- if (PrevExtracted)
- SetExtraInfoNew(Cmd,Arc,DestFileName,*DestFileNameW ? DestFileNameW:NULL);
- #endif
- }
- if (HeadType==ENDARC_HEAD)
- if (Arc.EndArcHead.Flags & EARC_NEXT_VOLUME)
- {
- #ifndef NOVOLUME
- if (!MergeArchive(Arc,&DataIO,false,Command))
- {
- ErrHandler.SetErrorCode(WARNING);
- return(false);
- }
- SignatureFound=false;
- #endif
- Arc.Seek(Arc.CurBlockPos,SEEK_SET);
- return(true);
- }
- else
- return(false);
- Arc.SeekToNext();
- return(true);
- }
- PrevExtracted=false;
- if (SignatureFound ||
- !Cmd->Recurse && MatchedArgs>=Cmd->FileArgs->ItemsCount() &&
- AllMatchesExact)
- return(false);
- char ArcFileName[NM];
- IntToExt(Arc.NewLhd.FileName,Arc.NewLhd.FileName);
- strcpy(ArcFileName,Arc.NewLhd.FileName);
- wchar ArcFileNameW[NM];
- *ArcFileNameW=0;
- int MatchType=MATCH_WILDSUBPATH;
- bool EqualNames=false;
- int MatchNumber=Cmd->IsProcessFile(Arc.NewLhd,&EqualNames,MatchType);
- bool ExactMatch=MatchNumber!=0;
- #if !defined(SFX_MODULE) && !defined(_WIN_CE)
- if (Cmd->ExclPath==EXCL_BASEPATH)
- {
- *Cmd->ArcPath=0;
- if (ExactMatch)
- {
- Cmd->FileArgs->Rewind();
- if (Cmd->FileArgs->GetString(Cmd->ArcPath,NULL,sizeof(Cmd->ArcPath),MatchNumber-1))
- *PointToName(Cmd->ArcPath)=0;
- }
- }
- #endif
- if (ExactMatch && !EqualNames)
- AllMatchesExact=false;
- #ifdef UNICODE_SUPPORTED
- bool WideName=(Arc.NewLhd.Flags & LHD_UNICODE) && UnicodeEnabled();
- #else
- bool WideName=false;
- #endif
- #ifdef _APPLE
- if (WideName)
- {
- // Prepare UTF-8 name for OS X. Since we are sure that destination
- // is UTF-8, we can avoid calling the less reliable WideToChar function.
- WideToUtf(Arc.NewLhd.FileNameW,ArcFileName,ASIZE(ArcFileName));
- WideName=false;
- }
- #endif
- wchar *DestNameW=WideName ? DestFileNameW:NULL;
- #ifdef UNICODE_SUPPORTED
- if (WideName)
- {
- // Prepare the name in single byte native encoding (typically UTF-8
- // for Unix-based systems). Windows does not really need it,
- // but Unix system will use this name instead of Unicode.
- ConvertPath(Arc.NewLhd.FileNameW,ArcFileNameW);
- char Name[NM];
- if (WideToChar(ArcFileNameW,Name) && IsNameUsable(Name))
- strcpy(ArcFileName,Name);
- }
- #endif
- ConvertPath(ArcFileName,ArcFileName);
- if (Arc.IsArcLabel())
- return(true);
- if (Arc.NewLhd.Flags & LHD_VERSION)
- {
- if (Cmd->VersionControl!=1 && !EqualNames)
- {
- if (Cmd->VersionControl==0)
- ExactMatch=false;
- int Version=ParseVersionFileName(ArcFileName,ArcFileNameW,false);
- if (Cmd->VersionControl-1==Version)
- ParseVersionFileName(ArcFileName,ArcFileNameW,true);
- else
- ExactMatch=false;
- }
- }
- else
- if (!Arc.IsArcDir() && Cmd->VersionControl>1)
- ExactMatch=false;
- Arc.ConvertAttributes();
- #ifndef SFX_MODULE
- if ((Arc.NewLhd.Flags & LHD_SPLIT_BEFORE)!=0 && FirstFile)
- {
- char CurVolName[NM];
- strcpy(CurVolName,ArcName);
- bool NewNumbering=(Arc.NewMhd.Flags & MHD_NEWNUMBERING)!=0;
- VolNameToFirstName(ArcName,ArcName,NewNumbering);
- if (*ArcNameW!=0)
- VolNameToFirstName(ArcNameW,ArcNameW,NewNumbering);
- if (stricomp(ArcName,CurVolName)!=0 && FileExist(ArcName,ArcNameW))
- {
- // If first volume name does not match the current name and if
- // such volume name really exists, let's unpack from this first volume.
- Repeat=true;
- return(false);
- }
- #if !defined(RARDLL) && !defined(_WIN_CE)
- if (!ReconstructDone)
- {
- ReconstructDone=true;
- RecVolumes RecVol;
- if (RecVol.Restore(Cmd,Arc.FileName,Arc.FileNameW,true))
- {
- Repeat=true;
- return(false);
- }
- }
- #endif
- strcpy(ArcName,CurVolName);
- }
- #endif
- DataIO.UnpVolume=(Arc.NewLhd.Flags & LHD_SPLIT_AFTER)!=0;
- DataIO.NextVolumeMissing=false;
- Arc.Seek(Arc.NextBlockPos-Arc.NewLhd.FullPackSize,SEEK_SET);
- bool TestMode=false;
- bool ExtrFile=false;
- bool SkipSolid=false;
- #ifndef SFX_MODULE
- if (FirstFile && (ExactMatch || Arc.Solid) && (Arc.NewLhd.Flags & (LHD_SPLIT_BEFORE/*|LHD_SOLID*/))!=0)
- {
- if (ExactMatch)
- {
- Log(Arc.FileName,St(MUnpCannotMerge),ArcFileName);
- #ifdef RARDLL
- Cmd->DllError=ERAR_BAD_DATA;
- #endif
- ErrHandler.SetErrorCode(OPEN_ERROR);
- }
- ExactMatch=false;
- }
- FirstFile=false;
- #endif
- if (ExactMatch || (SkipSolid=Arc.Solid)!=0)
- {
- if ((Arc.NewLhd.Flags & LHD_PASSWORD)!=0)
- #ifndef RARDLL
- if (*Password==0)
- #endif
- {
- #ifdef RARDLL
- if (*Cmd->Password==0)
- {
- char PasswordA[MAXPASSWORD];
- if (Cmd->Callback==NULL ||
- Cmd->Callback(UCM_NEEDPASSWORD,Cmd->UserData,(LPARAM)PasswordA,ASIZE(PasswordA))==-1)
- return(false);
- GetWideName(PasswordA,NULL,Cmd->Password,ASIZE(Cmd->Password));
- }
- wcscpy(Password,Cmd->Password);
- #else
- if (!GetPassword(PASSWORD_FILE,ArcFileName,ArcFileNameW,Password,ASIZE(Password)))
- {
- PasswordCancelled=true;
- return(false);
- }
- #endif
- }
- #if !defined(GUI) && !defined(SILENT)
- else
- if (!PasswordAll && (!Arc.Solid || Arc.NewLhd.UnpVer>=20 && (Arc.NewLhd.Flags & LHD_SOLID)==0))
- {
- eprintf(St(MUseCurPsw),ArcFileName);
- switch(Cmd->AllYes ? 1:Ask(St(MYesNoAll)))
- {
- case -1:
- ErrHandler.Exit(USER_BREAK);
- case 2:
- if (!GetPassword(PASSWORD_FILE,ArcFileName,ArcFileNameW,Password,ASIZE(Password)))
- {
- return(false);
- }
- break;
- case 3:
- PasswordAll=true;
- break;
- }
- }
- #endif
- #ifndef SFX_MODULE
- if (*Cmd->ExtrPath==0 && *Cmd->ExtrPathW!=0)
- WideToChar(Cmd->ExtrPathW,DestFileName);
- else
- #endif
- strcpy(DestFileName,Cmd->ExtrPath);
- #ifndef SFX_MODULE
- if (Cmd->AppendArcNameToPath)
- {
- strcat(DestFileName,PointToName(Arc.FirstVolumeName));
- SetExt(DestFileName,NULL);
- AddEndSlash(DestFileName);
- }
- #endif
- char *ExtrName=ArcFileName;
- bool EmptyName=false;
- #ifndef SFX_MODULE
- size_t Length=strlen(Cmd->ArcPath);
- if (Length>1 && IsPathDiv(Cmd->ArcPath[Length-1]) &&
- strlen(ArcFileName)==Length-1)
- Length--;
- if (Length>0 && strnicomp(Cmd->ArcPath,ArcFileName,Length)==0)
- {
- ExtrName+=Length;
- while (*ExtrName==CPATHDIVIDER)
- ExtrName++;
- if (*ExtrName==0)
- EmptyName=true;
- }
- #endif
- // Use -ep3 only in systems, where disk letters are exist, not in Unix.
- bool AbsPaths=Cmd->ExclPath==EXCL_ABSPATH && Command=='X' && IsDriveDiv(':');
- // We do not use any user specified destination paths when extracting
- // absolute paths in -ep3 mode.
- if (AbsPaths)
- *DestFileName=0;
- if (Command=='E' || Cmd->ExclPath==EXCL_SKIPWHOLEPATH)
- strcat(DestFileName,PointToName(ExtrName));
- else
- strcat(DestFileName,ExtrName);
- char DiskLetter=etoupper(DestFileName[0]);
- if (AbsPaths)
- {
- if (DestFileName[1]=='_' && IsPathDiv(DestFileName[2]) &&
- DiskLetter>='A' && DiskLetter<='Z')
- DestFileName[1]=':';
- else
- if (DestFileName[0]=='_' && DestFileName[1]=='_')
- {
- // Convert __server\share to \\server\share.
- DestFileName[0]=CPATHDIVIDER;
- DestFileName[1]=CPATHDIVIDER;
- }
- }
- #ifndef SFX_MODULE
- if (!WideName && *Cmd->ExtrPathW!=0)
- {
- DestNameW=DestFileNameW;
- WideName=true;
- CharToWide(ArcFileName,ArcFileNameW);
- }
- #endif
- if (WideName)
- {
- if (*Cmd->ExtrPathW!=0)
- wcscpy(DestFileNameW,Cmd->ExtrPathW);
- else
- CharToWide(Cmd->ExtrPath,DestFileNameW);
- #ifndef SFX_MODULE
- if (Cmd->AppendArcNameToPath)
- {
- wchar FileNameW[NM];
- if (*Arc.FirstVolumeNameW!=0)
- wcscpy(FileNameW,Arc.FirstVolumeNameW);
- else
- CharToWide(Arc.FirstVolumeName,FileNameW);
- wcscat(DestFileNameW,PointToName(FileNameW));
- SetExt(DestFileNameW,NULL);
- AddEndSlash(DestFileNameW);
- }
- #endif
- wchar *ExtrNameW=ArcFileNameW;
- #ifndef SFX_MODULE
- if (Length>0)
- {
- wchar ArcPathW[NM];
- GetWideName(Cmd->ArcPath,Cmd->ArcPathW,ArcPathW,ASIZE(ArcPathW));
- Length=wcslen(ArcPathW);
- }
- ExtrNameW+=Length;
- while (*ExtrNameW==CPATHDIVIDER)
- ExtrNameW++;
- #endif
- if (AbsPaths)
- *DestFileNameW=0;
- if (Command=='E' || Cmd->ExclPath==EXCL_SKIPWHOLEPATH)
- wcscat(DestFileNameW,PointToName(ExtrNameW));
- else
- wcscat(DestFileNameW,ExtrNameW);
- if (AbsPaths && DestFileNameW[1]=='_' && IsPathDiv(DestFileNameW[2]))
- DestFileNameW[1]=':';
- }
- else
- *DestFileNameW=0;
- ExtrFile=!SkipSolid && !EmptyName && (Arc.NewLhd.Flags & LHD_SPLIT_BEFORE)==0;
- if ((Cmd->FreshFiles || Cmd->UpdateFiles) && (Command=='E' || Command=='X'))
- {
- struct FindData FD;
- if (FindFile::FastFind(DestFileName,DestNameW,&FD))
- {
- if (FD.mtime >= Arc.NewLhd.mtime)
- {
- // If directory already exists and its modification time is newer
- // than start of extraction, it is likely it was created
- // when creating a path to one of already extracted items.
- // In such case we'll better update its time even if archived
- // directory is older.
- if (!FD.IsDir || FD.mtime<StartTime)
- ExtrFile=false;
- }
- }
- else
- if (Cmd->FreshFiles)
- ExtrFile=false;
- }
- // Skip encrypted file if no password is specified.
- if ((Arc.NewLhd.Flags & LHD_PASSWORD)!=0 && *Password==0)
- {
- ErrHandler.SetErrorCode(WARNING);
- #ifdef RARDLL
- Cmd->DllError=ERAR_MISSING_PASSWORD;
- #endif
- ExtrFile=false;
- }
- #ifdef RARDLL
- if (*Cmd->DllDestName)
- {
- strncpyz(DestFileName,Cmd->DllDestName,ASIZE(DestFileName));
- *DestFileNameW=0;
- if (Cmd->DllOpMode!=RAR_EXTRACT)
- ExtrFile=false;
- }
- if (*Cmd->DllDestNameW)
- {
- wcsncpyz(DestFileNameW,Cmd->DllDestNameW,ASIZE(DestFileNameW));
- DestNameW=DestFileNameW;
- if (Cmd->DllOpMode!=RAR_EXTRACT)
- ExtrFile=false;
- }
- #endif
- #ifdef SFX_MODULE
- if ((Arc.NewLhd.UnpVer!=UNP_VER && Arc.NewLhd.UnpVer!=29) &&
- Arc.NewLhd.Method!=0x30)
- #else
- if (Arc.NewLhd.UnpVer<13 || Arc.NewLhd.UnpVer>UNP_VER)
- #endif
- {
- #ifndef SILENT
- Log(Arc.FileName,St(MUnknownMeth),ArcFileName);
- #ifndef SFX_MODULE
- Log(Arc.FileName,St(MVerRequired),Arc.NewLhd.UnpVer/10,Arc.NewLhd.UnpVer%10);
- #endif
- #endif
- ExtrFile=false;
- ErrHandler.SetErrorCode(WARNING);
- #ifdef RARDLL
- Cmd->DllError=ERAR_UNKNOWN_FORMAT;
- #endif
- }
- File CurFile;
- if (!IsLink(Arc.NewLhd.FileAttr))
- if (Arc.IsArcDir())
- {
- if (!ExtrFile || Command=='P' || Command=='E' || Cmd->ExclPath==EXCL_SKIPWHOLEPATH)
- return(true);
- if (SkipSolid)
- {
- #ifndef GUI
- mprintf(St(MExtrSkipFile),ArcFileName);
- #endif
- return(true);
- }
- TotalFileCount++;
- if (Cmd->Test)
- {
- #ifndef GUI
- mprintf(St(MExtrTestFile),ArcFileName);
- mprintf(" %s",St(MOk));
- #endif
- return(true);
- }
- MKDIR_CODE MDCode=MakeDir(DestFileName,DestNameW,!Cmd->IgnoreGeneralAttr,Arc.NewLhd.FileAttr);
- bool DirExist=false;
- if (MDCode!=MKDIR_SUCCESS)
- {
- DirExist=FileExist(DestFileName,DestNameW);
- if (DirExist && !IsDir(GetFileAttr(DestFileName,DestNameW)))
- {
- bool UserReject;
- FileCreate(Cmd,NULL,DestFileName,DestNameW,Cmd->Overwrite,&UserReject,Arc.NewLhd.FullUnpSize,Arc.NewLhd.FileTime);
- DirExist=false;
- }
- CreatePath(DestFileName,DestNameW,true);
- MDCode=MakeDir(DestFileName,DestNameW,!Cmd->IgnoreGeneralAttr,Arc.NewLhd.FileAttr);
- }
- if (MDCode==MKDIR_SUCCESS)
- {
- #ifndef GUI
- mprintf(St(MCreatDir),DestFileName);
- mprintf(" %s",St(MOk));
- #endif
- PrevExtracted=true;
- }
- else
- if (DirExist)
- {
- if (!Cmd->IgnoreGeneralAttr)
- SetFileAttr(DestFileName,DestNameW,Arc.NewLhd.FileAttr);
- PrevExtracted=true;
- }
- else
- {
- Log(Arc.FileName,St(MExtrErrMkDir),DestFileName);
- ErrHandler.CheckLongPathErrMsg(DestFileName,DestNameW);
- ErrHandler.SysErrMsg();
- #ifdef RARDLL
- Cmd->DllError=ERAR_ECREATE;
- #endif
- ErrHandler.SetErrorCode(CREATE_ERROR);
- }
- if (PrevExtracted)
- {
- #if defined(_WIN_ALL) && !defined(_WIN_CE) && !defined(SFX_MODULE)
- if (Cmd->SetCompressedAttr &&
- (Arc.NewLhd.FileAttr & FILE_ATTRIBUTE_COMPRESSED)!=0 && WinNT())
- SetFileCompression(DestFileName,DestNameW,true);
- #endif
- SetDirTime(DestFileName,DestNameW,
- Cmd->xmtime==EXTTIME_NONE ? NULL:&Arc.NewLhd.mtime,
- Cmd->xctime==EXTTIME_NONE ? NULL:&Arc.NewLhd.ctime,
- Cmd->xatime==EXTTIME_NONE ? NULL:&Arc.NewLhd.atime);
- }
- return(true);
- }
- else
- {
- if (Cmd->Test && ExtrFile)
- TestMode=true;
- #if !defined(GUI) && !defined(SFX_MODULE)
- if (Command=='P' && ExtrFile)
- CurFile.SetHandleType(FILE_HANDLESTD);
- #endif
- if ((Command=='E' || Command=='X') && ExtrFile && !Cmd->Test)
- {
- bool UserReject;
- if (!FileCreate(Cmd,&CurFile,DestFileName,DestNameW,Cmd->Overwrite,&UserReject,Arc.NewLhd.FullUnpSize,Arc.NewLhd.FileTime))
- {
- ExtrFile=false;
- if (!UserReject)
- {
- ErrHandler.CreateErrorMsg(Arc.FileName,Arc.FileNameW,DestFileName,DestFileNameW);
- ErrHandler.SetErrorCode(CREATE_ERROR);
- #ifdef RARDLL
- Cmd->DllError=ERAR_ECREATE;
- #endif
- if (!IsNameUsable(DestFileName))
- {
- Log(Arc.FileName,St(MCorrectingName));
- char OrigName[sizeof(DestFileName)];
- strncpyz(OrigName,DestFileName,ASIZE(OrigName));
- MakeNameUsable(DestFileName,true);
- CreatePath(DestFileName,NULL,true);
- if (FileCreate(Cmd,&CurFile,DestFileName,NULL,Cmd->Overwrite,&UserReject,Arc.NewLhd.FullUnpSize,Arc.NewLhd.FileTime))
- {
- #ifndef SFX_MODULE
- Log(Arc.FileName,St(MRenaming),OrigName,DestFileName);
- #endif
- ExtrFile=true;
- }
- else
- ErrHandler.CreateErrorMsg(Arc.FileName,Arc.FileNameW,DestFileName,DestFileNameW);
- }
- }
- }
- }
- }
- if (!ExtrFile && Arc.Solid)
- {
- SkipSolid=true;
- TestMode=true;
- ExtrFile=true;
- }
- if (ExtrFile)
- {
- if (!SkipSolid)
- {
- if (!TestMode && Command!='P' && CurFile.IsDevice())
- {
- Log(Arc.FileName,St(MInvalidName),DestFileName);
- ErrHandler.WriteError(Arc.FileName,Arc.FileNameW,DestFileName,DestFileNameW);
- }
- TotalFileCount++;
- }
- FileCount++;
- #ifndef GUI
- if (Command!='I')
- if (SkipSolid)
- mprintf(St(MExtrSkipFile),ArcFileName);
- else
- switch(Cmd->Test ? 'T':Command)
- {
- case 'T':
- mprintf(St(MExtrTestFile),ArcFileName);
- break;
- #ifndef SFX_MODULE
- case 'P':
- mprintf(St(MExtrPrinting),ArcFileName);
- break;
- #endif
- case 'X':
- case 'E':
- mprintf(St(MExtrFile),DestFileName);
- break;
- }
- if (!Cmd->DisablePercentage)
- mprintf(" ");
- #endif
- DataIO.CurUnpRead=0;
- DataIO.CurUnpWrite=0;
- DataIO.UnpFileCRC=Arc.OldFormat ? 0 : 0xffffffff;
- DataIO.PackedCRC=0xffffffff;
- wchar FilePassword[MAXPASSWORD];
- #ifdef _WIN_ALL
- if (Arc.NewLhd.HostOS==HOST_MSDOS/* && Arc.NewLhd.UnpVer<=25*/)
- {
- // We need the password in OEM encoding if file was encrypted by
- // native RAR/DOS (not extender based). Let's make the conversion.
- char PswA[MAXPASSWORD];
- CharToOemBuffW(Password,PswA,ASIZE(PswA));
- CharToWide(PswA,FilePassword,ASIZE(FilePassword));
- FilePassword[ASIZE(FilePassword)-1]=0;
- }
- else
- #endif
- wcscpy(FilePassword,Password);
-
- DataIO.SetEncryption(
- (Arc.NewLhd.Flags & LHD_PASSWORD)!=0 ? Arc.NewLhd.UnpVer:0,FilePassword,
- (Arc.NewLhd.Flags & LHD_SALT)!=0 ? Arc.NewLhd.Salt:NULL,false,
- Arc.NewLhd.UnpVer>=36);
- DataIO.SetPackedSizeToRead(Arc.NewLhd.FullPackSize);
- DataIO.SetFiles(&Arc,&CurFile);
- DataIO.SetTestMode(TestMode);
- DataIO.SetSkipUnpCRC(SkipSolid);
- #ifndef _WIN_CE
- if (!TestMode && !Arc.BrokenFileHeader &&
- (Arc.NewLhd.FullPackSize<<11)>Arc.NewLhd.FullUnpSize &&
- (Arc.NewLhd.FullUnpSize<100000000 || Arc.FileLength()>Arc.NewLhd.FullPackSize))
- CurFile.Prealloc(Arc.NewLhd.FullUnpSize);
- #endif
- CurFile.SetAllowDelete(!Cmd->KeepBroken);
- bool LinkCreateMode=!Cmd->Test && !SkipSolid;
- if (ExtractLink(DataIO,Arc,DestFileName,DataIO.UnpFileCRC,LinkCreateMode))
- PrevExtracted=LinkCreateMode;
- else
- if ((Arc.NewLhd.Flags & LHD_SPLIT_BEFORE)==0)
- if (Arc.NewLhd.Method==0x30)
- UnstoreFile(DataIO,Arc.NewLhd.FullUnpSize);
- else
- {
- Unp->SetDestSize(Arc.NewLhd.FullUnpSize);
- #ifndef SFX_MODULE
- if (Arc.NewLhd.UnpVer<=15)
- Unp->DoUnpack(15,FileCount>1 && Arc.Solid);
- else
- #endif
- Unp->DoUnpack(Arc.NewLhd.UnpVer,(Arc.NewLhd.Flags & LHD_SOLID)!=0);
- }
- // if (Arc.IsOpened())
- Arc.SeekToNext();
- bool ValidCRC=Arc.OldFormat && UINT32(DataIO.UnpFileCRC)==UINT32(Arc.NewLhd.FileCRC) ||
- !Arc.OldFormat && UINT32(DataIO.UnpFileCRC)==UINT32(Arc.NewLhd.FileCRC^0xffffffff);
- // We set AnySolidDataUnpackedWell to true if we found at least one
- // valid non-zero solid file in preceding solid stream. If it is true
- // and if current encrypted file is broken, we do not need to hint
- // about a wrong password and can report CRC error only.
- if ((Arc.NewLhd.Flags & LHD_SOLID)==0)
- AnySolidDataUnpackedWell=false; // Reset the flag, because non-solid file is found.
- else
- if (Arc.NewLhd.Method!=0x30 && Arc.NewLhd.FullUnpSize>0 && ValidCRC)
- AnySolidDataUnpackedWell=true;
-
- bool BrokenFile=false;
- if (!SkipSolid)
- {
- if (ValidCRC)
- {
- #ifndef GUI
- if (Command!='P' && Command!='I')
- mprintf("%s%s ",Cmd->DisablePercentage ? " ":"\b\b\b\b\b ",St(MOk));
- #endif
- }
- else
- {
- if ((Arc.NewLhd.Flags & LHD_PASSWORD)!=0 && !AnySolidDataUnpackedWell)
- {
- Log(Arc.FileName,St(MEncrBadCRC),ArcFileName);
- }
- else
- {
- Log(Arc.FileName,St(MCRCFailed),ArcFileName);
- }
- BrokenFile=true;
- ErrHandler.SetErrorCode(CRC_ERROR);
- #ifdef RARDLL
- Cmd->DllError=ERAR_BAD_DATA;
- #endif
- Alarm();
- }
- }
- #ifndef GUI
- else
- mprintf("\b\b\b\b\b ");
- #endif
- if (!TestMode && (Command=='X' || Command=='E') &&
- !IsLink(Arc.NewLhd.FileAttr))
- {
- #if defined(_WIN_ALL) || defined(_EMX)
- if (Cmd->ClearArc)
- Arc.NewLhd.FileAttr&=~FA_ARCH;
- #endif
- if (!BrokenFile || Cmd->KeepBroken)
- {
- if (BrokenFile)
- CurFile.Truncate();
- CurFile.SetOpenFileTime(
- Cmd->xmtime==EXTTIME_NONE ? NULL:&Arc.NewLhd.mtime,
- Cmd->xctime==EXTTIME_NONE ? NULL:&Arc.NewLhd.ctime,
- Cmd->xatime==EXTTIME_NONE ? NULL:&Arc.NewLhd.atime);
- CurFile.Close();
- #if defined(_WIN_ALL) && !defined(_WIN_CE) && !defined(SFX_MODULE)
- if (Cmd->SetCompressedAttr &&
- (Arc.NewLhd.FileAttr & FILE_ATTRIBUTE_COMPRESSED)!=0 && WinNT())
- SetFileCompression(CurFile.FileName,CurFile.FileNameW,true);
- #endif
- CurFile.SetCloseFileTime(
- Cmd->xmtime==EXTTIME_NONE ? NULL:&Arc.NewLhd.mtime,
- Cmd->xatime==EXTTIME_NONE ? NULL:&Arc.NewLhd.atime);
- if (!Cmd->IgnoreGeneralAttr)
- SetFileAttr(CurFile.FileName,CurFile.FileNameW,Arc.NewLhd.FileAttr);
- PrevExtracted=true;
- }
- }
- }
- }
- if (ExactMatch)
- MatchedArgs++;
- if (DataIO.NextVolumeMissing/* || !Arc.IsOpened()*/)
- return(false);
- if (!ExtrFile)
- if (!Arc.Solid)
- Arc.SeekToNext();
- else
- if (!SkipSolid)
- return(false);
- return(true);
- }
- void CmdExtract::UnstoreFile(ComprDataIO &DataIO,int64 DestUnpSize)
- {
- Array<byte> Buffer(0x10000);
- while (1)
- {
- uint Code=DataIO.UnpRead(&Buffer[0],Buffer.Size());
- if (Code==0 || (int)Code==-1)
- break;
- Code=Code<DestUnpSize ? Code:(uint)DestUnpSize;
- DataIO.UnpWrite(&Buffer[0],Code);
- if (DestUnpSize>=0)
- DestUnpSize-=Code;
- }
- }
|