misc/libphysfs/lzma/CPP/7zip/UI/Common/Extract.cpp
changeset 12213 bb5522e88ab2
equal deleted inserted replaced
12212:ea891871f481 12213:bb5522e88ab2
       
     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 HRESULT DecompressArchive(
       
    16     IInArchive *archive,
       
    17     UInt64 packSize,
       
    18     const UString &defaultName,
       
    19     const NWildcard::CCensorNode &wildcardCensor,
       
    20     const CExtractOptions &options,
       
    21     IExtractCallbackUI *callback,
       
    22     CArchiveExtractCallback *extractCallbackSpec,
       
    23     UString &errorMessage)
       
    24 {
       
    25   CRecordVector<UInt32> realIndices;
       
    26   UInt32 numItems;
       
    27   RINOK(archive->GetNumberOfItems(&numItems));
       
    28 
       
    29   for(UInt32 i = 0; i < numItems; i++)
       
    30   {
       
    31     UString filePath;
       
    32     RINOK(GetArchiveItemPath(archive, i, options.DefaultItemName, filePath));
       
    33     bool isFolder;
       
    34     RINOK(IsArchiveItemFolder(archive, i, isFolder));
       
    35     if (!wildcardCensor.CheckPath(filePath, !isFolder))
       
    36       continue;
       
    37     realIndices.Add(i);
       
    38   }
       
    39   if (realIndices.Size() == 0)
       
    40   {
       
    41     callback->ThereAreNoFiles();
       
    42     return S_OK;
       
    43   }
       
    44 
       
    45   UStringVector removePathParts;
       
    46 
       
    47   UString outDir = options.OutputDir;
       
    48   outDir.Replace(L"*", defaultName);
       
    49   if(!outDir.IsEmpty())
       
    50     if(!NFile::NDirectory::CreateComplexDirectory(outDir))
       
    51     {
       
    52       HRESULT res = ::GetLastError();
       
    53       if (res == S_OK)
       
    54         res = E_FAIL;
       
    55       errorMessage = ((UString)L"Can not create output directory ") + outDir;
       
    56       return res;
       
    57     }
       
    58 
       
    59   extractCallbackSpec->Init(
       
    60       archive, 
       
    61       callback,
       
    62       options.StdOutMode,
       
    63       outDir, 
       
    64       removePathParts, 
       
    65       options.DefaultItemName, 
       
    66       options.ArchiveFileInfo.LastWriteTime,
       
    67       options.ArchiveFileInfo.Attributes,
       
    68       packSize);
       
    69 
       
    70   #ifdef COMPRESS_MT
       
    71   RINOK(SetProperties(archive, options.Properties));
       
    72   #endif
       
    73 
       
    74   HRESULT result = archive->Extract(&realIndices.Front(), 
       
    75     realIndices.Size(), options.TestMode? 1: 0, extractCallbackSpec);
       
    76 
       
    77   return callback->ExtractResult(result);
       
    78 }
       
    79 
       
    80 HRESULT DecompressArchives(
       
    81     CCodecs *codecs,
       
    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)
       
    89 {
       
    90   stat.Clear();
       
    91   CExtractOptions options = optionsSpec;
       
    92   int i;
       
    93   UInt64 totalPackSize = 0;
       
    94   CRecordVector<UInt64> archiveSizes;
       
    95   for (i = 0; i < archivePaths.Size(); i++)
       
    96   {
       
    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;
       
   105   }
       
   106   CArchiveExtractCallback *extractCallbackSpec = new CArchiveExtractCallback;
       
   107   CMyComPtr<IArchiveExtractCallback> ec(extractCallbackSpec);
       
   108   bool multi = (archivePaths.Size() > 1);
       
   109   extractCallbackSpec->InitForMulti(multi, options.PathMode, options.OverwriteMode);
       
   110   if (multi)
       
   111   {
       
   112     RINOK(extractCallback->SetTotal(totalPackSize));  
       
   113   }
       
   114   for (i = 0; i < archivePaths.Size(); i++)
       
   115   {
       
   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";
       
   120 
       
   121     if (archiveFileInfo.IsDirectory())
       
   122       throw "there is no such archive";
       
   123 
       
   124     options.ArchiveFileInfo = archiveFileInfo;
       
   125 
       
   126     #ifndef _NO_CRYPTO
       
   127     openCallback->ClearPasswordWasAskedFlag();
       
   128     #endif
       
   129 
       
   130     RINOK(extractCallback->BeforeOpen(archivePath));
       
   131     CArchiveLink archiveLink;
       
   132     HRESULT result = MyOpenArchive(codecs, archivePath, archiveLink, openCallback);
       
   133 
       
   134     bool crypted = false;
       
   135     #ifndef _NO_CRYPTO
       
   136     crypted = openCallback->WasPasswordAsked();
       
   137     #endif
       
   138 
       
   139     RINOK(extractCallback->OpenResult(archivePath, result, crypted));
       
   140     if (result != S_OK)
       
   141       continue;
       
   142 
       
   143     for (int v = 0; v < archiveLink.VolumePaths.Size(); v++)
       
   144     {
       
   145       int index = archivePathsFull.FindInSorted(archiveLink.VolumePaths[v]);
       
   146       if (index >= 0 && index > i)
       
   147       {
       
   148         archivePaths.Delete(index);
       
   149         archivePathsFull.Delete(index);
       
   150         totalPackSize -= archiveSizes[index];
       
   151         archiveSizes.Delete(index);
       
   152       }
       
   153     }
       
   154     if (archiveLink.VolumePaths.Size() != 0)
       
   155     {
       
   156       totalPackSize += archiveLink.VolumesSize;
       
   157       RINOK(extractCallback->SetTotal(totalPackSize));  
       
   158     }
       
   159 
       
   160     #ifndef _NO_CRYPTO
       
   161     UString password;
       
   162     RINOK(openCallback->GetPasswordIfAny(password));
       
   163     if (!password.IsEmpty())
       
   164     {
       
   165       RINOK(extractCallback->SetPassword(password));
       
   166     }
       
   167     #endif
       
   168 
       
   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())
       
   179       return E_FAIL;
       
   180   }
       
   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;
       
   186   return S_OK;
       
   187 }