7 #include "Windows/FileDir.h"
\r
8 #include "Windows/PropVariant.h"
\r
9 #include "Windows/PropVariantConversions.h"
\r
11 #include "../Common/ExtractingFilePath.h"
\r
13 #include "Extract.h"
\r
14 #include "SetProperties.h"
\r
16 using namespace NWindows;
\r
18 static HRESULT DecompressArchive(
\r
21 const NWildcard::CCensorNode &wildcardCensor,
\r
22 const CExtractOptions &options,
\r
23 IExtractCallbackUI *callback,
\r
24 CArchiveExtractCallback *extractCallbackSpec,
\r
25 UString &errorMessage,
\r
26 UInt64 &stdInProcessed)
\r
29 IInArchive *archive = arc.Archive;
\r
30 CRecordVector<UInt32> realIndices;
\r
31 if (!options.StdInMode)
\r
34 RINOK(archive->GetNumberOfItems(&numItems));
\r
36 for (UInt32 i = 0; i < numItems; i++)
\r
39 RINOK(arc.GetItemPath(i, filePath));
\r
41 RINOK(IsArchiveItemFolder(archive, i, isFolder));
\r
42 if (!wildcardCensor.CheckPath(filePath, !isFolder))
\r
46 if (realIndices.Size() == 0)
\r
48 callback->ThereAreNoFiles();
\r
53 UStringVector removePathParts;
\r
55 UString outDir = options.OutputDir;
\r
56 outDir.Replace(L"*", GetCorrectFsPath(arc.DefaultName));
\r
58 // GetCorrectFullFsPath doesn't like "..".
\r
59 // outDir.TrimRight();
\r
60 // outDir = GetCorrectFullFsPath(outDir);
\r
63 if (!outDir.IsEmpty())
\r
64 if (!NFile::NDirectory::CreateComplexDirectory(outDir))
\r
66 HRESULT res = ::GetLastError();
\r
69 errorMessage = ((UString)L"Can not create output directory ") + outDir;
\r
73 extractCallbackSpec->Init(
\r
74 options.StdInMode ? &wildcardCensor : NULL,
\r
77 options.StdOutMode, options.TestMode, options.CalcCrc,
\r
82 #if !defined(_7ZIP_ST) && !defined(_SFX)
\r
83 RINOK(SetProperties(archive, options.Properties));
\r
87 Int32 testMode = (options.TestMode && !options.CalcCrc) ? 1: 0;
\r
88 if (options.StdInMode)
\r
90 result = archive->Extract(NULL, (UInt32)(Int32)-1, testMode, extractCallbackSpec);
\r
91 NCOM::CPropVariant prop;
\r
92 if (archive->GetArchiveProperty(kpidPhySize, &prop) == S_OK)
\r
93 if (prop.vt == VT_UI8 || prop.vt == VT_UI4)
\r
94 stdInProcessed = ConvertPropVariantToUInt64(prop);
\r
97 result = archive->Extract(&realIndices.Front(), realIndices.Size(), testMode, extractCallbackSpec);
\r
99 return callback->ExtractResult(result);
\r
102 HRESULT DecompressArchives(
\r
103 CCodecs *codecs, const CIntVector &formatIndices,
\r
104 UStringVector &arcPaths, UStringVector &arcPathsFull,
\r
105 const NWildcard::CCensorNode &wildcardCensor,
\r
106 const CExtractOptions &options,
\r
107 IOpenCallbackUI *openCallback,
\r
108 IExtractCallbackUI *extractCallback,
\r
109 UString &errorMessage,
\r
110 CDecompressStat &stat)
\r
114 UInt64 totalPackSize = 0;
\r
115 CRecordVector<UInt64> archiveSizes;
\r
117 int numArcs = options.StdInMode ? 1 : arcPaths.Size();
\r
119 for (i = 0; i < numArcs; i++)
\r
121 NFile::NFind::CFileInfoW fi;
\r
123 if (!options.StdInMode)
\r
125 const UString &arcPath = arcPaths[i];
\r
126 if (!fi.Find(arcPath))
\r
127 throw "there is no such archive";
\r
129 throw "can't decompress folder";
\r
131 archiveSizes.Add(fi.Size);
\r
132 totalPackSize += fi.Size;
\r
134 CArchiveExtractCallback *extractCallbackSpec = new CArchiveExtractCallback;
\r
135 CMyComPtr<IArchiveExtractCallback> ec(extractCallbackSpec);
\r
136 bool multi = (numArcs > 1);
\r
137 extractCallbackSpec->InitForMulti(multi, options.PathMode, options.OverwriteMode);
\r
140 RINOK(extractCallback->SetTotal(totalPackSize));
\r
142 for (i = 0; i < numArcs; i++)
\r
144 const UString &arcPath = arcPaths[i];
\r
145 NFile::NFind::CFileInfoW fi;
\r
146 if (options.StdInMode)
\r
153 if (!fi.Find(arcPath) || fi.IsDir())
\r
154 throw "there is no such archive";
\r
158 openCallback->Open_ClearPasswordWasAskedFlag();
\r
161 RINOK(extractCallback->BeforeOpen(arcPath));
\r
162 CArchiveLink archiveLink;
\r
164 CIntVector formatIndices2 = formatIndices;
\r
166 if (formatIndices.IsEmpty())
\r
168 int pos = arcPath.ReverseFind(L'.');
\r
171 UString s = arcPath.Mid(pos + 1);
\r
172 int index = codecs->FindFormatForExtension(s);
\r
173 if (index >= 0 && s == L"001")
\r
175 s = arcPath.Left(pos);
\r
176 pos = s.ReverseFind(L'.');
\r
179 int index2 = codecs->FindFormatForExtension(s.Mid(pos + 1));
\r
180 if (index2 >= 0 && s.CompareNoCase(L"rar") != 0)
\r
182 formatIndices2.Add(index2);
\r
183 formatIndices2.Add(index);
\r
190 HRESULT result = archiveLink.Open2(codecs, formatIndices2, options.StdInMode, NULL, arcPath, openCallback);
\r
191 if (result == E_ABORT)
\r
194 bool crypted = false;
\r
196 crypted = openCallback->Open_WasPasswordAsked();
\r
199 RINOK(extractCallback->OpenResult(arcPath, result, crypted));
\r
200 if (result != S_OK)
\r
203 if (!options.StdInMode)
\r
204 for (int v = 0; v < archiveLink.VolumePaths.Size(); v++)
\r
206 int index = arcPathsFull.FindInSorted(archiveLink.VolumePaths[v]);
\r
207 if (index >= 0 && index > i)
\r
209 arcPaths.Delete(index);
\r
210 arcPathsFull.Delete(index);
\r
211 totalPackSize -= archiveSizes[index];
\r
212 archiveSizes.Delete(index);
\r
213 numArcs = arcPaths.Size();
\r
216 if (archiveLink.VolumePaths.Size() != 0)
\r
218 totalPackSize += archiveLink.VolumesSize;
\r
219 RINOK(extractCallback->SetTotal(totalPackSize));
\r
224 RINOK(openCallback->Open_GetPasswordIfAny(password));
\r
225 if (!password.IsEmpty())
\r
227 RINOK(extractCallback->SetPassword(password));
\r
231 for (int v = 0; v < archiveLink.Arcs.Size(); v++)
\r
233 const UString &s = archiveLink.Arcs[v].ErrorMessage;
\r
236 RINOK(extractCallback->MessageError(s));
\r
240 CArc &arc = archiveLink.Arcs.Back();
\r
241 arc.MTimeDefined = (!options.StdInMode && !fi.IsDevice);
\r
242 arc.MTime = fi.MTime;
\r
244 UInt64 packProcessed;
\r
245 RINOK(DecompressArchive(arc,
\r
246 fi.Size + archiveLink.VolumesSize,
\r
247 wildcardCensor, options, extractCallback, extractCallbackSpec, errorMessage, packProcessed));
\r
248 if (!options.StdInMode)
\r
249 packProcessed = fi.Size + archiveLink.VolumesSize;
\r
250 extractCallbackSpec->LocalProgressSpec->InSize += packProcessed;
\r
251 extractCallbackSpec->LocalProgressSpec->OutSize = extractCallbackSpec->UnpackSize;
\r
252 if (!errorMessage.IsEmpty())
\r
255 stat.NumFolders = extractCallbackSpec->NumFolders;
\r
256 stat.NumFiles = extractCallbackSpec->NumFiles;
\r
257 stat.UnpackSize = extractCallbackSpec->UnpackSize;
\r
258 stat.CrcSum = extractCallbackSpec->CrcSum;
\r
260 stat.NumArchives = arcPaths.Size();
\r
261 stat.PackSize = extractCallbackSpec->LocalProgressSpec->InSize;
\r