7 #include "Windows/Defs.h"
8 #include "Windows/FileDir.h"
10 #include "OpenArchive.h"
11 #include "SetProperties.h"
13 using namespace NWindows;
15 HRESULT DecompressArchive(
18 const UString &defaultName,
19 const NWildcard::CCensorNode &wildcardCensor,
20 const CExtractOptions &options,
21 IExtractCallbackUI *callback,
22 CArchiveExtractCallback *extractCallbackSpec,
23 UString &errorMessage)
25 CRecordVector<UInt32> realIndices;
27 RINOK(archive->GetNumberOfItems(&numItems));
29 for(UInt32 i = 0; i < numItems; i++)
32 RINOK(GetArchiveItemPath(archive, i, options.DefaultItemName, filePath));
34 RINOK(IsArchiveItemFolder(archive, i, isFolder));
35 if (!wildcardCensor.CheckPath(filePath, !isFolder))
39 if (realIndices.Size() == 0)
41 callback->ThereAreNoFiles();
45 UStringVector removePathParts;
47 UString outDir = options.OutputDir;
48 outDir.Replace(L"*", defaultName);
50 if(!NFile::NDirectory::CreateComplexDirectory(outDir))
52 HRESULT res = ::GetLastError();
55 errorMessage = ((UString)L"Can not create output directory ") + outDir;
59 extractCallbackSpec->Init(
65 options.DefaultItemName,
66 options.ArchiveFileInfo.LastWriteTime,
67 options.ArchiveFileInfo.Attributes,
71 RINOK(SetProperties(archive, options.Properties));
74 HRESULT result = archive->Extract(&realIndices.Front(),
75 realIndices.Size(), options.TestMode? 1: 0, extractCallbackSpec);
77 return callback->ExtractResult(result);
80 HRESULT DecompressArchives(
82 UStringVector &archivePaths, UStringVector &archivePathsFull,
83 const NWildcard::CCensorNode &wildcardCensor,
84 const CExtractOptions &optionsSpec,
85 IOpenCallbackUI *openCallback,
86 IExtractCallbackUI *extractCallback,
87 UString &errorMessage,
88 CDecompressStat &stat)
91 CExtractOptions options = optionsSpec;
93 UInt64 totalPackSize = 0;
94 CRecordVector<UInt64> archiveSizes;
95 for (i = 0; i < archivePaths.Size(); i++)
97 const UString &archivePath = archivePaths[i];
98 NFile::NFind::CFileInfoW archiveFileInfo;
99 if (!NFile::NFind::FindFile(archivePath, archiveFileInfo))
100 throw "there is no such archive";
101 if (archiveFileInfo.IsDirectory())
102 throw "can't decompress folder";
103 archiveSizes.Add(archiveFileInfo.Size);
104 totalPackSize += archiveFileInfo.Size;
106 CArchiveExtractCallback *extractCallbackSpec = new CArchiveExtractCallback;
107 CMyComPtr<IArchiveExtractCallback> ec(extractCallbackSpec);
108 bool multi = (archivePaths.Size() > 1);
109 extractCallbackSpec->InitForMulti(multi, options.PathMode, options.OverwriteMode);
112 RINOK(extractCallback->SetTotal(totalPackSize));
114 for (i = 0; i < archivePaths.Size(); i++)
116 const UString &archivePath = archivePaths[i];
117 NFile::NFind::CFileInfoW archiveFileInfo;
118 if (!NFile::NFind::FindFile(archivePath, archiveFileInfo))
119 throw "there is no such archive";
121 if (archiveFileInfo.IsDirectory())
122 throw "there is no such archive";
124 options.ArchiveFileInfo = archiveFileInfo;
127 openCallback->ClearPasswordWasAskedFlag();
130 RINOK(extractCallback->BeforeOpen(archivePath));
131 CArchiveLink archiveLink;
132 HRESULT result = MyOpenArchive(codecs, archivePath, archiveLink, openCallback);
134 bool crypted = false;
136 crypted = openCallback->WasPasswordAsked();
139 RINOK(extractCallback->OpenResult(archivePath, result, crypted));
143 for (int v = 0; v < archiveLink.VolumePaths.Size(); v++)
145 int index = archivePathsFull.FindInSorted(archiveLink.VolumePaths[v]);
146 if (index >= 0 && index > i)
148 archivePaths.Delete(index);
149 archivePathsFull.Delete(index);
150 totalPackSize -= archiveSizes[index];
151 archiveSizes.Delete(index);
154 if (archiveLink.VolumePaths.Size() != 0)
156 totalPackSize += archiveLink.VolumesSize;
157 RINOK(extractCallback->SetTotal(totalPackSize));
162 RINOK(openCallback->GetPasswordIfAny(password));
163 if (!password.IsEmpty())
165 RINOK(extractCallback->SetPassword(password));
169 options.DefaultItemName = archiveLink.GetDefaultItemName();
170 RINOK(DecompressArchive(
171 archiveLink.GetArchive(),
172 archiveFileInfo.Size + archiveLink.VolumesSize,
173 archiveLink.GetDefaultItemName(),
174 wildcardCensor, options, extractCallback, extractCallbackSpec, errorMessage));
175 extractCallbackSpec->LocalProgressSpec->InSize += archiveFileInfo.Size +
176 archiveLink.VolumesSize;
177 extractCallbackSpec->LocalProgressSpec->OutSize = extractCallbackSpec->UnpackSize;
178 if (!errorMessage.IsEmpty())
181 stat.NumFolders = extractCallbackSpec->NumFolders;
182 stat.NumFiles = extractCallbackSpec->NumFiles;
183 stat.UnpackSize = extractCallbackSpec->UnpackSize;
184 stat.NumArchives = archivePaths.Size();
185 stat.PackSize = extractCallbackSpec->LocalProgressSpec->InSize;