00001
00002
00003
00004
00005 #include "StdAfx.h"
00006
00007 #include "Extract.h"
00008
00009 #include "Defs.h"
00010 #include "PropVariant.h"
00011 #include "FileDir.h"
00012
00013 #include "OpenArchive.h"
00014
00015 #ifndef EXCLUDE_COM
00016 #include "Windows/DLL.h"
00017 #endif
00018
00019 using namespace NWindows;
00020
00021 HRESULT DecompressArchive(
00022 IInArchive *archive,
00023 const UString &defaultName,
00024 const NWildcard::CCensorNode &wildcardCensor,
00025 const CExtractOptions &options,
00026 IExtractCallbackUI *callback)
00027 {
00028 CRecordVector<UInt32> realIndices;
00029 UInt32 numItems;
00030 RINOK(archive->GetNumberOfItems(&numItems));
00031
00032 for(UInt32 i = 0; i < numItems; i++)
00033 {
00034 UString filePath;
00035 RINOK(GetArchiveItemPath(archive, i, options.DefaultItemName, filePath));
00036 bool isFolder;
00037 RINOK(IsArchiveItemFolder(archive, i, isFolder));
00038 if (!wildcardCensor.CheckPath(filePath, !isFolder))
00039 continue;
00040 realIndices.Add(i);
00041 }
00042 if (realIndices.Size() == 0)
00043 {
00044 callback->ThereAreNoFiles();
00045 return S_OK;
00046 }
00047
00048 CArchiveExtractCallback *extractCallbackSpec = new CArchiveExtractCallback;
00049 CMyComPtr<IArchiveExtractCallback> extractCallback(extractCallbackSpec);
00050
00051 UStringVector removePathParts;
00052
00053 UString outDir = options.OutputDir;
00054 outDir.Replace(L"*", defaultName);
00055 if(!outDir.IsEmpty())
00056 if(!NFile::NDirectory::CreateComplexDirectory(outDir))
00057 {
00058 throw UString(L"Can not create output directory ") + outDir;
00059 }
00060
00061 extractCallbackSpec->Init(
00062 archive,
00063 callback,
00064 options.StdOutMode,
00065 outDir,
00066 options.PathMode,
00067 options.OverwriteMode,
00068 removePathParts,
00069 options.DefaultItemName,
00070 options.ArchiveFileInfo.LastWriteTime,
00071 options.ArchiveFileInfo.Attributes);
00072
00073 HRESULT result = archive->Extract(&realIndices.Front(),
00074 realIndices.Size(), options.TestMode? 1: 0,
00075 extractCallback);
00076
00077 return callback->ExtractResult(result);
00078 }
00079
00080 HRESULT DecompressArchives(
00081 UStringVector &archivePaths, UStringVector &archivePathsFull,
00082 const NWildcard::CCensorNode &wildcardCensor,
00083 const CExtractOptions &optionsSpec,
00084 IOpenCallbackUI *openCallback,
00085 IExtractCallbackUI *extractCallback)
00086 {
00087 CExtractOptions options = optionsSpec;
00088 for (int i = 0; i < archivePaths.Size(); i++)
00089 {
00090 const UString &archivePath = archivePaths[i];
00091 NFile::NFind::CFileInfoW archiveFileInfo;
00092 if (!NFile::NFind::FindFile(archivePath, archiveFileInfo))
00093 throw "there is no such archive";
00094
00095 if (archiveFileInfo.IsDirectory())
00096 throw "there is no such archive";
00097
00098 options.ArchiveFileInfo = archiveFileInfo;
00099
00100 RINOK(extractCallback->BeforeOpen(archivePath));
00101 CArchiveLink archiveLink;
00102 HRESULT result = MyOpenArchive(archivePath, archiveLink, openCallback);
00103 RINOK(extractCallback->OpenResult(archivePath, result));
00104 if (result != S_OK)
00105 continue;
00106
00107 for (int v = 0; v < archiveLink.VolumePaths.Size(); v++)
00108 {
00109 int index = archivePathsFull.FindInSorted(archiveLink.VolumePaths[v]);
00110 if (index >= 0 && index > i)
00111 {
00112 archivePaths.Delete(index);
00113 archivePathsFull.Delete(index);
00114 }
00115 }
00116
00117 #ifndef _NO_CRYPTO
00118 UString password;
00119 RINOK(openCallback->GetPasswordIfAny(password));
00120 if (!password.IsEmpty())
00121 {
00122 RINOK(extractCallback->SetPassword(password));
00123 }
00124 #endif
00125
00126 options.DefaultItemName = archiveLink.GetDefaultItemName();
00127 RINOK(DecompressArchive(
00128 archiveLink.GetArchive(), archiveLink.GetDefaultItemName(),
00129 wildcardCensor, options, extractCallback));
00130 }
00131 return S_OK;
00132 }