OLD | NEW |
| (Empty) |
1 // Extract.cpp | |
2 | |
3 #include "StdAfx.h" | |
4 | |
5 #include "Extract.h" | |
6 | |
7 #include "Windows/Defs.h" | |
8 #include "Windows/FileDir.h" | |
9 | |
10 #include "OpenArchive.h" | |
11 #include "SetProperties.h" | |
12 | |
13 using namespace NWindows; | |
14 | |
15 static HRESULT DecompressArchive( | |
16 IInArchive *archive, | |
17 UInt64 packSize, | |
18 const NWildcard::CCensorNode &wildcardCensor, | |
19 const CExtractOptions &options, | |
20 IExtractCallbackUI *callback, | |
21 CArchiveExtractCallback *extractCallbackSpec, | |
22 UString &errorMessage) | |
23 { | |
24 CRecordVector<UInt32> realIndices; | |
25 UInt32 numItems; | |
26 RINOK(archive->GetNumberOfItems(&numItems)); | |
27 | |
28 for(UInt32 i = 0; i < numItems; i++) | |
29 { | |
30 UString filePath; | |
31 RINOK(GetArchiveItemPath(archive, i, options.DefaultItemName, filePath)); | |
32 bool isFolder; | |
33 RINOK(IsArchiveItemFolder(archive, i, isFolder)); | |
34 if (!wildcardCensor.CheckPath(filePath, !isFolder)) | |
35 continue; | |
36 realIndices.Add(i); | |
37 } | |
38 if (realIndices.Size() == 0) | |
39 { | |
40 callback->ThereAreNoFiles(); | |
41 return S_OK; | |
42 } | |
43 | |
44 UStringVector removePathParts; | |
45 | |
46 UString outDir = options.OutputDir; | |
47 outDir.Replace(L"*", options.DefaultItemName); | |
48 #ifdef _WIN32 | |
49 outDir.TrimRight(); | |
50 #endif | |
51 | |
52 if(!outDir.IsEmpty()) | |
53 if(!NFile::NDirectory::CreateComplexDirectory(outDir)) | |
54 { | |
55 HRESULT res = ::GetLastError(); | |
56 if (res == S_OK) | |
57 res = E_FAIL; | |
58 errorMessage = ((UString)L"Can not create output directory ") + outDir; | |
59 return res; | |
60 } | |
61 | |
62 extractCallbackSpec->Init( | |
63 archive, | |
64 callback, | |
65 options.StdOutMode, | |
66 outDir, | |
67 removePathParts, | |
68 options.DefaultItemName, | |
69 options.ArchiveFileInfo.MTime, | |
70 options.ArchiveFileInfo.Attrib, | |
71 packSize); | |
72 | |
73 #ifdef COMPRESS_MT | |
74 RINOK(SetProperties(archive, options.Properties)); | |
75 #endif | |
76 | |
77 HRESULT result = archive->Extract(&realIndices.Front(), | |
78 realIndices.Size(), options.TestMode? 1: 0, extractCallbackSpec); | |
79 | |
80 return callback->ExtractResult(result); | |
81 } | |
82 | |
83 HRESULT DecompressArchives( | |
84 CCodecs *codecs, const CIntVector &formatIndices, | |
85 UStringVector &archivePaths, UStringVector &archivePathsFull, | |
86 const NWildcard::CCensorNode &wildcardCensor, | |
87 const CExtractOptions &optionsSpec, | |
88 IOpenCallbackUI *openCallback, | |
89 IExtractCallbackUI *extractCallback, | |
90 UString &errorMessage, | |
91 CDecompressStat &stat) | |
92 { | |
93 stat.Clear(); | |
94 CExtractOptions options = optionsSpec; | |
95 int i; | |
96 UInt64 totalPackSize = 0; | |
97 CRecordVector<UInt64> archiveSizes; | |
98 for (i = 0; i < archivePaths.Size(); i++) | |
99 { | |
100 const UString &archivePath = archivePaths[i]; | |
101 NFile::NFind::CFileInfoW fi; | |
102 if (!NFile::NFind::FindFile(archivePath, fi)) | |
103 throw "there is no such archive"; | |
104 if (fi.IsDir()) | |
105 throw "can't decompress folder"; | |
106 archiveSizes.Add(fi.Size); | |
107 totalPackSize += fi.Size; | |
108 } | |
109 CArchiveExtractCallback *extractCallbackSpec = new CArchiveExtractCallback; | |
110 CMyComPtr<IArchiveExtractCallback> ec(extractCallbackSpec); | |
111 bool multi = (archivePaths.Size() > 1); | |
112 extractCallbackSpec->InitForMulti(multi, options.PathMode, options.OverwriteMo
de); | |
113 if (multi) | |
114 { | |
115 RINOK(extractCallback->SetTotal(totalPackSize)); | |
116 } | |
117 for (i = 0; i < archivePaths.Size(); i++) | |
118 { | |
119 const UString &archivePath = archivePaths[i]; | |
120 NFile::NFind::CFileInfoW fi; | |
121 if (!NFile::NFind::FindFile(archivePath, fi)) | |
122 throw "there is no such archive"; | |
123 | |
124 if (fi.IsDir()) | |
125 throw "there is no such archive"; | |
126 | |
127 options.ArchiveFileInfo = fi; | |
128 | |
129 #ifndef _NO_CRYPTO | |
130 openCallback->Open_ClearPasswordWasAskedFlag(); | |
131 #endif | |
132 | |
133 RINOK(extractCallback->BeforeOpen(archivePath)); | |
134 CArchiveLink archiveLink; | |
135 | |
136 CIntVector formatIndices2 = formatIndices; | |
137 #ifndef _SFX | |
138 if (formatIndices.IsEmpty()) | |
139 { | |
140 int pos = archivePath.ReverseFind(L'.'); | |
141 if (pos >= 0) | |
142 { | |
143 UString s = archivePath.Mid(pos + 1); | |
144 int index = codecs->FindFormatForExtension(s); | |
145 if (index >= 0 && s == L"001") | |
146 { | |
147 s = archivePath.Left(pos); | |
148 pos = s.ReverseFind(L'.'); | |
149 if (pos >= 0) | |
150 { | |
151 int index2 = codecs->FindFormatForExtension(s.Mid(pos + 1)); | |
152 if (index2 >= 0 && s.CompareNoCase(L"rar") != 0) | |
153 { | |
154 formatIndices2.Add(index2); | |
155 formatIndices2.Add(index); | |
156 } | |
157 } | |
158 } | |
159 } | |
160 } | |
161 #endif | |
162 HRESULT result = MyOpenArchive(codecs, formatIndices2, archivePath, archiveL
ink, openCallback); | |
163 if (result == E_ABORT) | |
164 return result; | |
165 | |
166 bool crypted = false; | |
167 #ifndef _NO_CRYPTO | |
168 crypted = openCallback->Open_WasPasswordAsked(); | |
169 #endif | |
170 | |
171 RINOK(extractCallback->OpenResult(archivePath, result, crypted)); | |
172 if (result != S_OK) | |
173 continue; | |
174 | |
175 for (int v = 0; v < archiveLink.VolumePaths.Size(); v++) | |
176 { | |
177 int index = archivePathsFull.FindInSorted(archiveLink.VolumePaths[v]); | |
178 if (index >= 0 && index > i) | |
179 { | |
180 archivePaths.Delete(index); | |
181 archivePathsFull.Delete(index); | |
182 totalPackSize -= archiveSizes[index]; | |
183 archiveSizes.Delete(index); | |
184 } | |
185 } | |
186 if (archiveLink.VolumePaths.Size() != 0) | |
187 { | |
188 totalPackSize += archiveLink.VolumesSize; | |
189 RINOK(extractCallback->SetTotal(totalPackSize)); | |
190 } | |
191 | |
192 #ifndef _NO_CRYPTO | |
193 UString password; | |
194 RINOK(openCallback->Open_GetPasswordIfAny(password)); | |
195 if (!password.IsEmpty()) | |
196 { | |
197 RINOK(extractCallback->SetPassword(password)); | |
198 } | |
199 #endif | |
200 | |
201 options.DefaultItemName = archiveLink.GetDefaultItemName(); | |
202 RINOK(DecompressArchive( | |
203 archiveLink.GetArchive(), | |
204 fi.Size + archiveLink.VolumesSize, | |
205 wildcardCensor, options, extractCallback, extractCallbackSpec, errorMess
age)); | |
206 extractCallbackSpec->LocalProgressSpec->InSize += fi.Size + | |
207 archiveLink.VolumesSize; | |
208 extractCallbackSpec->LocalProgressSpec->OutSize = extractCallbackSpec->Unpac
kSize; | |
209 if (!errorMessage.IsEmpty()) | |
210 return E_FAIL; | |
211 } | |
212 stat.NumFolders = extractCallbackSpec->NumFolders; | |
213 stat.NumFiles = extractCallbackSpec->NumFiles; | |
214 stat.UnpackSize = extractCallbackSpec->UnpackSize; | |
215 stat.NumArchives = archivePaths.Size(); | |
216 stat.PackSize = extractCallbackSpec->LocalProgressSpec->InSize; | |
217 return S_OK; | |
218 } | |
OLD | NEW |