| 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 |