STDMETHODIMP COpenArchiveCallback::GetStream(const wchar_t *name,
    IInStream **inStream)
{
  *inStream = NULL;
  if (_subArchiveMode)
    return S_FALSE;

  NFile::NFind::CFileInfoW fileInfo;

  UString fullPath = _folderPrefix + name;
  if (!fileInfo.Find(fullPath))
    return S_FALSE;
  _fileInfo = fileInfo;
  if (_fileInfo.IsDir())
    return S_FALSE;
  CInFileStream *inFile = new CInFileStream;
  CMyComPtr<IInStream> inStreamTemp = inFile;
  if (!inFile->Open(fullPath))
    return ::GetLastError();
  *inStream = inStreamTemp.Detach();
  return S_OK;
}
示例#2
0
HRESULT ListArchives(CCodecs *codecs, const CIntVector &formatIndices,
    bool stdInMode,
    UStringVector &arcPaths, UStringVector &arcPathsFull,
    const NWildcard::CCensorNode &wildcardCensor,
    bool enableHeaders, bool techMode,
    #ifndef _NO_CRYPTO
    bool &passwordEnabled, UString &password,
    #endif
    UInt64 &numErrors)
{
  numErrors = 0;
  CFieldPrinter fieldPrinter;
  if (!techMode)
    fieldPrinter.Init(kStandardFieldTable, sizeof(kStandardFieldTable) / sizeof(kStandardFieldTable[0]));

  UInt64 numFiles2 = 0, numDirs2 = 0, totalPackSize2 = 0, totalUnPackSize2 = 0;
  UInt64 *totalPackSizePointer2 = 0, *totalUnPackSizePointer2 = 0;
  int numArcs = /* stdInMode ? 1 : */ arcPaths.Size();
  for (int i = 0; i < numArcs; i++)
  {
    const UString &archiveName = arcPaths[i];
    UInt64 arcPackSize = 0;
    if (!stdInMode)
    {
      NFile::NFind::CFileInfoW fi;
      if (!fi.Find(archiveName) || fi.IsDir())
      {
        g_StdOut << endl << "Error: " << archiveName << " is not file" << endl;
        numErrors++;
        continue;
      }
      arcPackSize = fi.Size;
    }

    CArchiveLink archiveLink;

    COpenCallbackConsole openCallback;
    openCallback.OutStream = &g_StdOut;

    #ifndef _NO_CRYPTO

    openCallback.PasswordIsDefined = passwordEnabled;
    openCallback.Password = password;

    #endif

    HRESULT result = archiveLink.Open2(codecs, formatIndices, stdInMode, NULL, archiveName, &openCallback);
    if (result != S_OK)
    {
      if (result == E_ABORT)
        return result;
      g_StdOut << endl << "Error: " << archiveName << ": ";
      if (result == S_FALSE)
      {
        #ifndef _NO_CRYPTO
        if (openCallback.Open_WasPasswordAsked())
          g_StdOut << "Can not open encrypted archive. Wrong password?";
        else
        #endif
          g_StdOut << "Can not open file as archive";
      }
      else if (result == E_OUTOFMEMORY)
        g_StdOut << "Can't allocate required memory";
      else
        g_StdOut << NError::MyFormatMessage(result);
      g_StdOut << endl;
      numErrors++;
      continue;
    }

    if (!stdInMode)
    for (int v = 0; v < archiveLink.VolumePaths.Size(); v++)
    {
      int index = arcPathsFull.FindInSorted(archiveLink.VolumePaths[v]);
      if (index >= 0 && index > i)
      {
        arcPaths.Delete(index);
        arcPathsFull.Delete(index);
        numArcs = arcPaths.Size();
      }
    }

    if (enableHeaders)
    {
      g_StdOut << endl << kListing << archiveName << endl << endl;

      for (int i = 0; i < archiveLink.Arcs.Size(); i++)
      {
        const CArc &arc = archiveLink.Arcs[i];
        
        g_StdOut << "--\n";
        PrintPropPair(L"Path", arc.Path);
        PrintPropPair(L"Type", codecs->Formats[arc.FormatIndex].Name);
        if (!arc.ErrorMessage.IsEmpty())
          PrintPropPair(L"Error", arc.ErrorMessage);
        UInt32 numProps;
        IInArchive *archive = arc.Archive;
        if (archive->GetNumberOfArchiveProperties(&numProps) == S_OK)
        {
          for (UInt32 j = 0; j < numProps; j++)
          {
            CMyComBSTR name;
            PROPID propID;
            VARTYPE vt;
            RINOK(archive->GetArchivePropertyInfo(j, &name, &propID, &vt));
            NCOM::CPropVariant prop;
            RINOK(archive->GetArchiveProperty(propID, &prop));
            UString s = ConvertPropertyToString(prop, propID);
            if (!s.IsEmpty())
              PrintPropPair(GetPropName(propID, name), s);
          }
        }
        if (i != archiveLink.Arcs.Size() - 1)
        {
          UInt32 numProps;
          g_StdOut << "----\n";
          if (archive->GetNumberOfProperties(&numProps) == S_OK)
          {
            UInt32 mainIndex = archiveLink.Arcs[i + 1].SubfileIndex;
            for (UInt32 j = 0; j < numProps; j++)
            {
              CMyComBSTR name;
              PROPID propID;
              VARTYPE vt;
              RINOK(archive->GetPropertyInfo(j, &name, &propID, &vt));
              NCOM::CPropVariant prop;
              RINOK(archive->GetProperty(mainIndex, propID, &prop));
              UString s = ConvertPropertyToString(prop, propID);
              if (!s.IsEmpty())
                PrintPropPair(GetPropName(propID, name), s);
            }
          }
        }
        
      }
      g_StdOut << endl;
      if (techMode)
        g_StdOut << "----------\n";
    }

    if (enableHeaders && !techMode)
    {
      fieldPrinter.PrintTitle();
      g_StdOut << endl;
      fieldPrinter.PrintTitleLines();
      g_StdOut << endl;
    }

    const CArc &arc = archiveLink.Arcs.Back();
    IInArchive *archive = arc.Archive;
    if (techMode)
    {
      RINOK(fieldPrinter.Init(archive));
    }
    UInt64 numFiles = 0, numDirs = 0, totalPackSize = 0, totalUnPackSize = 0;
    UInt64 *totalPackSizePointer = 0, *totalUnPackSizePointer = 0;
    UInt32 numItems;
    RINOK(archive->GetNumberOfItems(&numItems));
    for (UInt32 i = 0; i < numItems; i++)
    {
      if (NConsoleClose::TestBreakSignal())
        return E_ABORT;

      UString filePath;
      HRESULT res = arc.GetItemPath(i, filePath);
      if (stdInMode && res == E_INVALIDARG)
        break;
      RINOK(res);

      bool isFolder;
      RINOK(IsArchiveItemFolder(archive, i, isFolder));
      if (!wildcardCensor.CheckPath(filePath, !isFolder))
        continue;
      
      fieldPrinter.PrintItemInfo(arc, i, techMode);
      
      UInt64 packSize, unpackSize;
      if (!GetUInt64Value(archive, i, kpidSize, unpackSize))
        unpackSize = 0;
      else
        totalUnPackSizePointer = &totalUnPackSize;
      if (!GetUInt64Value(archive, i, kpidPackSize, packSize))
        packSize = 0;
      else
        totalPackSizePointer = &totalPackSize;
      
      g_StdOut << endl;

      if (isFolder)
        numDirs++;
      else
        numFiles++;
      totalPackSize += packSize;
      totalUnPackSize += unpackSize;
    }

    if (!stdInMode && totalPackSizePointer == 0)
    {
      if (archiveLink.VolumePaths.Size() != 0)
        arcPackSize += archiveLink.VolumesSize;
      totalPackSize = (numFiles == 0) ? 0 : arcPackSize;
      totalPackSizePointer = &totalPackSize;
    }
    if (totalUnPackSizePointer == 0 && numFiles == 0)
    {
      totalUnPackSize = 0;
      totalUnPackSizePointer = &totalUnPackSize;
    }
    if (enableHeaders && !techMode)
    {
      fieldPrinter.PrintTitleLines();
      g_StdOut << endl;
      fieldPrinter.PrintSummaryInfo(numFiles, numDirs, totalUnPackSizePointer, totalPackSizePointer);
      g_StdOut << endl;
    }
    if (totalPackSizePointer != 0)
    {
      totalPackSizePointer2 = &totalPackSize2;
      totalPackSize2 += totalPackSize;
    }
    if (totalUnPackSizePointer != 0)
    {
      totalUnPackSizePointer2 = &totalUnPackSize2;
      totalUnPackSize2 += totalUnPackSize;
    }
    numFiles2 += numFiles;
    numDirs2 += numDirs;
  }
  if (enableHeaders && !techMode && numArcs > 1)
  {
    g_StdOut << endl;
    fieldPrinter.PrintTitleLines();
    g_StdOut << endl;
    fieldPrinter.PrintSummaryInfo(numFiles2, numDirs2, totalUnPackSizePointer2, totalPackSizePointer2);
    g_StdOut << endl;
    g_StdOut << "Archives: " << numArcs << endl;
  }
  return S_OK;
}
示例#3
0
STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu,
      UINT commandIDFirst, UINT commandIDLast, UINT flags)
{
  LoadLangOneTime();
  if (_fileNames.Size() == 0)
    return E_FAIL;
  UINT currentCommandID = commandIDFirst;
  if ((flags & 0x000F) != CMF_NORMAL  &&
      (flags & CMF_VERBSONLY) == 0 &&
      (flags & CMF_EXPLORE) == 0)
    return MAKE_HRESULT(SEVERITY_SUCCESS, 0, currentCommandID);

  _commandMap.Clear();

  CMenu popupMenu;
  CMenuDestroyer menuDestroyer;

  CContextMenuInfo ci;
  ci.Load();
  MENUITEMINFO menuItem;
  UINT subIndex = indexMenu;
  if (ci.Cascaded)
  {
    CCommandMapItem commandMapItem;
    if (!popupMenu.CreatePopup())
      return E_FAIL;
    menuDestroyer.Attach(popupMenu);
    commandMapItem.CommandInternalID = kCommandNULL;
    commandMapItem.Verb = kMainVerb;
    commandMapItem.HelpString = LangString(IDS_CONTEXT_CAPTION_HELP, 0x02000102);
    _commandMap.Add(commandMapItem);
    
    menuItem.wID = currentCommandID++;
    subIndex = 0;
  }
  else
  {
    popupMenu.Attach(hMenu);
  }

  UInt32 contextMenuFlags = ci.Flags;

  UString mainString;
  if (_fileNames.Size() == 1 && currentCommandID + 6 <= commandIDLast)
  {
    const UString &fileName = _fileNames.Front();
    UString folderPrefix;
    NFile::NDirectory::GetOnlyDirPrefix(fileName, folderPrefix);
   
    NFile::NFind::CFileInfoW fileInfo;
    if (!fileInfo.Find(fileName))
      return E_FAIL;
    if (!fileInfo.IsDir() && DoNeedExtract(fileInfo.Name))
    {
      // Open
      bool thereIsMainOpenItem = ((contextMenuFlags & NContextMenuFlags::kOpen) != 0);
      if (thereIsMainOpenItem)
      {
        CCommandMapItem commandMapItem;
        FillCommand(kOpen, mainString, commandMapItem);
        MyInsertMenu(popupMenu, subIndex++, currentCommandID++, mainString);
        _commandMap.Add(commandMapItem);
      }
      if ((contextMenuFlags & NContextMenuFlags::kOpenAs) != 0 &&
          (!thereIsMainOpenItem || !FindExt(kNoOpenAsExtensions, fileInfo.Name)))
      {
        CMenu subMenu;
        if (subMenu.CreatePopup())
        {
          CCommandMapItem commandMapItem;
          
          CMenuItem menuItem;
          menuItem.fType = MFT_STRING;
          menuItem.fMask = MIIM_SUBMENU | MIIM_TYPE | MIIM_ID;
          menuItem.wID = currentCommandID++;
          menuItem.hSubMenu = subMenu;
          menuItem.StringValue = LangString(IDS_CONTEXT_OPEN, 0x02000103);
          popupMenu.InsertItem(subIndex++, true, menuItem);
          
          commandMapItem.CommandInternalID = kCommandNULL;
          commandMapItem.Verb = kMainVerb;
          commandMapItem.HelpString = LangString(IDS_CONTEXT_OPEN_HELP, 0x02000104);
          _commandMap.Add(commandMapItem);
          
          UINT subIndex2 = 0;
          const wchar_t *exts[] = { L"", L"*", L"7z", L"zip", L"cab", L"rar" };
          for (int i = (thereIsMainOpenItem ? 1 : 0); i < sizeof(exts) / sizeof(exts[0]); i++)
          {
            CCommandMapItem commandMapItem;
            if (i == 0)
              FillCommand(kOpen, mainString, commandMapItem);
            else
            {
              mainString = exts[i];
              commandMapItem.CommandInternalID = kOpen;
              commandMapItem.Verb = (UString)kMainVerb + L".Open." + mainString;
              commandMapItem.HelpString = mainString;
              commandMapItem.ArcType = mainString;
            }
            MyInsertMenu(subMenu, subIndex2++, currentCommandID++, mainString);
            _commandMap.Add(commandMapItem);
          }
          subMenu.Detach();
        }
      }
    }
  }

  if (_fileNames.Size() > 0 && currentCommandID + 10 <= commandIDLast)
  {
    bool needExtract = false;
    for(int i = 0; i < _fileNames.Size(); i++)
    {
      NFile::NFind::CFileInfoW fileInfo;
      if (!fileInfo.Find(_fileNames[i]))
        return E_FAIL;
      if (!fileInfo.IsDir() && DoNeedExtract(fileInfo.Name))
        needExtract = true;
    }
    const UString &fileName = _fileNames.Front();
    if (needExtract)
    {
      UString folderPrefix;
      NFile::NDirectory::GetOnlyDirPrefix(fileName, folderPrefix);
      NFile::NFind::CFileInfoW fileInfo;
      if (!fileInfo.Find(fileName))
        return E_FAIL;
      // Extract
      if ((contextMenuFlags & NContextMenuFlags::kExtract) != 0)
      {
        CCommandMapItem commandMapItem;
        FillCommand(kExtract, mainString, commandMapItem);
        if (_dropMode)
          commandMapItem.Folder = _dropPath;
        else
          commandMapItem.Folder = folderPrefix;
        commandMapItem.Folder += GetSubFolderNameForExtract(fileInfo.Name) + UString(WCHAR_PATH_SEPARATOR);
        MyInsertMenu(popupMenu, subIndex++, currentCommandID++, mainString);
        _commandMap.Add(commandMapItem);
      }

      // Extract Here
      if ((contextMenuFlags & NContextMenuFlags::kExtractHere) != 0)
      {
        CCommandMapItem commandMapItem;
        FillCommand(kExtractHere, mainString, commandMapItem);
        MyInsertMenu(popupMenu, subIndex++, currentCommandID++, mainString);
        if (_dropMode)
          commandMapItem.Folder = _dropPath;
        else
          commandMapItem.Folder = folderPrefix;
        _commandMap.Add(commandMapItem);
      }

      // Extract To
      if ((contextMenuFlags & NContextMenuFlags::kExtractTo) != 0)
      {
        CCommandMapItem commandMapItem;
        UString s;
        FillCommand(kExtractTo, s, commandMapItem);
        UString folder;
        if (_fileNames.Size() == 1)
          folder = GetSubFolderNameForExtract(fileInfo.Name);
        else
          folder = L'*';
        if (_dropMode)
          commandMapItem.Folder = _dropPath;
        else
          commandMapItem.Folder = folderPrefix;
        commandMapItem.Folder += folder;
        s = MyFormatNew(s, GetQuotedReducedString(folder + UString(WCHAR_PATH_SEPARATOR)));
        MyInsertMenu(popupMenu, subIndex++, currentCommandID++, s);
        _commandMap.Add(commandMapItem);
      }
      // Test
      if ((contextMenuFlags & NContextMenuFlags::kTest) != 0)
      {
        CCommandMapItem commandMapItem;
        FillCommand(kTest, mainString, commandMapItem);
        MyInsertMenu(popupMenu, subIndex++, currentCommandID++, mainString);
        _commandMap.Add(commandMapItem);
      }
    }
    UString archiveName = CreateArchiveName(fileName, _fileNames.Size() > 1, false);
    UString archiveName7z = archiveName + L".7z";
    UString archiveNameZip = archiveName + L".zip";
    UString archivePathPrefix;
    NFile::NDirectory::GetOnlyDirPrefix(fileName, archivePathPrefix);

    // Compress
    if ((contextMenuFlags & NContextMenuFlags::kCompress) != 0)
    {
      CCommandMapItem commandMapItem;
      if (_dropMode)
        commandMapItem.Folder = _dropPath;
      else
        commandMapItem.Folder = archivePathPrefix;
      commandMapItem.ArcName = archiveName;
      FillCommand(kCompress, mainString, commandMapItem);
      MyInsertMenu(popupMenu, subIndex++, currentCommandID++, mainString);
      _commandMap.Add(commandMapItem);
    }

    #ifdef EMAIL_SUPPORT
    // CompressEmail
    if ((contextMenuFlags & NContextMenuFlags::kCompressEmail) != 0 && !_dropMode)
    {
      CCommandMapItem commandMapItem;
      commandMapItem.ArcName = archiveName;
      FillCommand(kCompressEmail, mainString, commandMapItem);
      MyInsertMenu(popupMenu, subIndex++, currentCommandID++, mainString);
      _commandMap.Add(commandMapItem);
    }
    #endif

    // CompressTo7z
    if (contextMenuFlags & NContextMenuFlags::kCompressTo7z)
    {
      CCommandMapItem commandMapItem;
      UString s;
      FillCommand(kCompressTo7z, s, commandMapItem);
      if (_dropMode)
        commandMapItem.Folder = _dropPath;
      else
        commandMapItem.Folder = archivePathPrefix;
      commandMapItem.ArcName = archiveName7z;
      commandMapItem.ArcType = L"7z";
      s = MyFormatNew(s, GetQuotedReducedString(archiveName7z));
      MyInsertMenu(popupMenu, subIndex++, currentCommandID++, s);
      _commandMap.Add(commandMapItem);
    }

    #ifdef EMAIL_SUPPORT
    // CompressTo7zEmail
    if ((contextMenuFlags & NContextMenuFlags::kCompressTo7zEmail) != 0  && !_dropMode)
    {
      CCommandMapItem commandMapItem;
      UString s;
      FillCommand(kCompressTo7zEmail, s, commandMapItem);
      commandMapItem.ArcName = archiveName7z;
      commandMapItem.ArcType = L"7z";
      s = MyFormatNew(s, GetQuotedReducedString(archiveName7z));
      MyInsertMenu(popupMenu, subIndex++, currentCommandID++, s);
      _commandMap.Add(commandMapItem);
    }
    #endif

    // CompressToZip
    if (contextMenuFlags & NContextMenuFlags::kCompressToZip)
    {
      CCommandMapItem commandMapItem;
      UString s;
      FillCommand(kCompressToZip, s, commandMapItem);
      if (_dropMode)
        commandMapItem.Folder = _dropPath;
      else
        commandMapItem.Folder = archivePathPrefix;
      commandMapItem.ArcName = archiveNameZip;
      commandMapItem.ArcType = L"zip";
      s = MyFormatNew(s, GetQuotedReducedString(archiveNameZip));
      MyInsertMenu(popupMenu, subIndex++, currentCommandID++, s);
      _commandMap.Add(commandMapItem);
    }

    #ifdef EMAIL_SUPPORT
    // CompressToZipEmail
    if ((contextMenuFlags & NContextMenuFlags::kCompressToZipEmail) != 0  && !_dropMode)
    {
      CCommandMapItem commandMapItem;
      UString s;
      FillCommand(kCompressToZipEmail, s, commandMapItem);
      commandMapItem.ArcName = archiveNameZip;
      commandMapItem.ArcType = L"zip";
      s = MyFormatNew(s, GetQuotedReducedString(archiveNameZip));
      MyInsertMenu(popupMenu, subIndex++, currentCommandID++, s);
      _commandMap.Add(commandMapItem);
    }
    #endif
  }


  // don't use InsertMenu:  See MSDN:
  // PRB: Duplicate Menu Items In the File Menu For a Shell Context Menu Extension
  // ID: Q214477

  if (ci.Cascaded)
  {
    CMenuItem menuItem;
    menuItem.fType = MFT_STRING;
    menuItem.fMask = MIIM_SUBMENU | MIIM_TYPE | MIIM_ID;
    menuItem.wID = currentCommandID++;
    menuItem.hSubMenu = popupMenu.Detach();
    menuDestroyer.Disable();
    menuItem.StringValue = LangString(IDS_CONTEXT_POPUP_CAPTION, 0x02000101);
    CMenu menu;
    menu.Attach(hMenu);
    menu.InsertItem(indexMenu++, true, menuItem);
  }

  return MAKE_HRESULT(SEVERITY_SUCCESS, 0, currentCommandID - commandIDFirst);
}
示例#4
0
void CApp::Combine()
{
  int srcPanelIndex = GetFocusedPanelIndex();
  CPanel &srcPanel = Panels[srcPanelIndex];
  if (!srcPanel.IsFSFolder())
  {
    srcPanel.MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED, 0x03020208);
    return;
  }
  CRecordVector<UInt32> indices;
  srcPanel.GetOperatedItemIndices(indices);
  if (indices.IsEmpty())
    return;
  int index = indices[0];
  if (indices.Size() != 1 || srcPanel.IsItemFolder(index))
  {
    srcPanel.MessageBoxErrorLang(IDS_COMBINE_SELECT_ONE_FILE, 0x03020620);
    return;
  }
  const UString itemName = srcPanel.GetItemName(index);

  UString srcPath = srcPanel._currentFolderPrefix + srcPanel.GetItemPrefix(index);
  UString path = srcPath;
  int destPanelIndex = (NumPanels <= 1) ? srcPanelIndex : (1 - srcPanelIndex);
  CPanel &destPanel = Panels[destPanelIndex];
  if (NumPanels > 1)
    if (destPanel.IsFSFolder())
      path = destPanel._currentFolderPrefix;

  CVolSeqName volSeqName;
  if (!volSeqName.ParseName(itemName))
  {
    srcPanel.MessageBoxErrorLang(IDS_COMBINE_CANT_DETECT_SPLIT_FILE, 0x03020621);
    return;
  }
  
  {
  CThreadCombine combiner;
  
  UString nextName = itemName;
  combiner.TotalSize = 0;
  for (;;)
  {
    NFile::NFind::CFileInfoW fileInfo;
    if (!fileInfo.Find(srcPath + nextName) || fileInfo.IsDir())
      break;
    combiner.Names.Add(nextName);
    combiner.TotalSize += fileInfo.Size;
    nextName = volSeqName.GetNextName();
  }
  if (combiner.Names.Size() == 1)
  {
    srcPanel.MessageBoxErrorLang(IDS_COMBINE_CANT_FIND_MORE_THAN_ONE_PART, 0x03020622);
    return;
  }
  
  if (combiner.TotalSize == 0)
  {
    srcPanel.MessageBoxMyError(L"No data");
    return;
  }
  
  UString info;
  AddValuePair2(IDS_FILES_COLON, 0x02000320, combiner.Names.Size(), combiner.TotalSize, info);
  
  info += L"\n";
  info += srcPath;
  
  int i;
  for (i = 0; i < combiner.Names.Size() && i < 2; i++)
    AddInfoFileName(combiner.Names[i], info);
  if (i != combiner.Names.Size())
  {
    if (i + 1 != combiner.Names.Size())
      AddInfoFileName(L"...", info);
    AddInfoFileName(combiner.Names.Back(), info);
  }
  
  {
    CCopyDialog copyDialog;
    copyDialog.Value = path;
    copyDialog.Title = LangString(IDS_COMBINE, 0x03020600);
    copyDialog.Title += ' ';
    copyDialog.Title += srcPanel.GetItemRelPath(index);
    copyDialog.Static = LangString(IDS_COMBINE_TO, 0x03020601);
    copyDialog.Info = info;
    if (copyDialog.Create(srcPanel.GetParent()) == IDCANCEL)
      return;
    path = copyDialog.Value;
  }

  NFile::NName::NormalizeDirPathPrefix(path);
  if (!NFile::NDirectory::CreateComplexDirectory(path))
  {
    srcPanel.MessageBoxMyError(MyFormatNew(IDS_CANNOT_CREATE_FOLDER, 0x02000603, path));
    return;
  }
  
  UString outName = volSeqName.UnchangedPart;
  while (!outName.IsEmpty())
  {
    int lastIndex = outName.Length() - 1;
    if (outName[lastIndex] != L'.')
      break;
    outName.Delete(lastIndex);
  }
  if (outName.IsEmpty())
    outName = L"file";
  
  NFile::NFind::CFileInfoW fileInfo;
  UString destFilePath = path + outName;
  combiner.OutputPath = destFilePath;
  if (fileInfo.Find(destFilePath))
  {
    srcPanel.MessageBoxMyError(MyFormatNew(IDS_FILE_EXIST, 0x03020A04, destFilePath));
    return;
  }
  
    CProgressDialog &progressDialog = combiner.ProgressDialog;
    progressDialog.ShowCompressionInfo = false;
  
    UString progressWindowTitle = LangString(IDS_APP_TITLE, 0x03000000);
    UString title = LangString(IDS_COMBINING, 0x03020610);
    
    progressDialog.MainWindow = _window;
    progressDialog.MainTitle = progressWindowTitle;
    progressDialog.MainAddTitle = title + UString(L" ");
    
    combiner.InputDirPrefix = srcPath;
    
    // CPanel::CDisableTimerProcessing disableTimerProcessing1(srcPanel);
    // CPanel::CDisableTimerProcessing disableTimerProcessing2(destPanel);
    
    if (combiner.Create(title, _window) != 0)
      return;
  }
  RefreshTitleAlways();

  // disableTimerProcessing1.Restore();
  // disableTimerProcessing2.Restore();
  // srcPanel.SetFocusToList();
  // srcPanel.RefreshListCtrlSaveFocused();
}
示例#5
0
void CApp::Split()
{
  int srcPanelIndex = GetFocusedPanelIndex();
  CPanel &srcPanel = Panels[srcPanelIndex];
  if (!srcPanel.IsFSFolder())
  {
    srcPanel.MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED, 0x03020208);
    return;
  }
  CRecordVector<UInt32> indices;
  srcPanel.GetOperatedItemIndices(indices);
  if (indices.IsEmpty())
    return;
  if (indices.Size() != 1)
  {
    srcPanel.MessageBoxErrorLang(IDS_SELECT_ONE_FILE, 0x03020A02);
    return;
  }
  int index = indices[0];
  if (srcPanel.IsItemFolder(index))
  {
    srcPanel.MessageBoxErrorLang(IDS_SELECT_ONE_FILE, 0x03020A02);
    return;
  }
  const UString itemName = srcPanel.GetItemName(index);

  UString srcPath = srcPanel._currentFolderPrefix + srcPanel.GetItemPrefix(index);
  UString path = srcPath;
  int destPanelIndex = (NumPanels <= 1) ? srcPanelIndex : (1 - srcPanelIndex);
  CPanel &destPanel = Panels[destPanelIndex];
  if (NumPanels > 1)
    if (destPanel.IsFSFolder())
      path = destPanel._currentFolderPrefix;
  CSplitDialog splitDialog;
  splitDialog.FilePath = srcPanel.GetItemRelPath(index);
  splitDialog.Path = path;
  if (splitDialog.Create(srcPanel.GetParent()) == IDCANCEL)
    return;

  NFile::NFind::CFileInfoW fileInfo;
  if (!fileInfo.Find(srcPath + itemName))
  {
    srcPanel.MessageBoxMyError(L"Can not find file");
    return;
  }
  if (fileInfo.Size <= splitDialog.VolumeSizes.Front())
  {
    srcPanel.MessageBoxErrorLang(IDS_SPLIT_VOL_MUST_BE_SMALLER, 0x03020522);
    return;
  }
  const UInt64 numVolumes = GetNumberOfVolumes(fileInfo.Size, splitDialog.VolumeSizes);
  if (numVolumes >= 100)
  {
    wchar_t s[32];
    ConvertUInt64ToString(numVolumes, s);
    if (::MessageBoxW(srcPanel, MyFormatNew(IDS_SPLIT_CONFIRM_MESSAGE, 0x03020521, s),
        LangString(IDS_SPLIT_CONFIRM_TITLE, 0x03020520),
        MB_YESNOCANCEL | MB_ICONQUESTION) != IDYES)
      return;
  }

  path = splitDialog.Path;
  NFile::NName::NormalizeDirPathPrefix(path);
  if (!NFile::NDirectory::CreateComplexDirectory(path))
  {
    srcPanel.MessageBoxMyError(MyFormatNew(IDS_CANNOT_CREATE_FOLDER, 0x02000603, path));
    return;
  }

  {
  CThreadSplit spliter;
  spliter.NumVolumes = numVolumes;

  CProgressDialog &progressDialog = spliter.ProgressDialog;

  UString progressWindowTitle = LangString(IDS_APP_TITLE, 0x03000000);
  UString title = LangString(IDS_SPLITTING, 0x03020510);

  progressDialog.ShowCompressionInfo = false;

  progressDialog.MainWindow = _window;
  progressDialog.MainTitle = progressWindowTitle;
  progressDialog.MainAddTitle = title + UString(L" ");
  progressDialog.Sync.SetTitleFileName(itemName);


  spliter.FilePath = srcPath + itemName;
  spliter.VolBasePath = path + itemName;
  spliter.VolumeSizes = splitDialog.VolumeSizes;
  
  // if (splitDialog.VolumeSizes.Size() == 0) return;

  // CPanel::CDisableTimerProcessing disableTimerProcessing1(srcPanel);
  // CPanel::CDisableTimerProcessing disableTimerProcessing2(destPanel);

  if (spliter.Create(title, _window) != 0)
    return;
  }
  RefreshTitleAlways();


  // disableTimerProcessing1.Restore();
  // disableTimerProcessing2.Restore();
  // srcPanel.SetFocusToList();
  // srcPanel.RefreshListCtrlSaveFocused();
}
示例#6
0
// Create a new 7z archive for each folder contained in the archive to be
// exploded.
HRESULT ExplodeArchives(CCodecs *codecs, const CIntVector &formatIndices,
	bool stdInMode,
	UStringVector &arcPaths, UStringVector &arcPathsFull,
	UString& outputPath, UInt64 maxDepth, UInt64 &numErrors)
{
	int numArcs = arcPaths.Size();
	for (int i = 0; i < numArcs; i++)
	{
		UString archivePath = arcPaths[i];
		
		/*UString outputPath = arcPaths[i];
		outputPath.Replace(L'\\', L'/'); // linux and windows consistent
		const UString archiveName = StripFile(outputPath);
		outputPath.Empty();*/
		archivePath.Replace(L'\\', L'/'); // linux, windows and archive consistent
		outputPath.Replace(L'\\', L'/'); 
		FixPathFormat(outputPath);
		const UString archiveName = GetFileFromPath(archivePath);

		g_StdOut << "Outputting into : " << outputPath << endl;

		UInt64 arcPackSize = 0;
		if (!stdInMode)
		{
			NFile::NFind::CFileInfoW fi;
			if (!fi.Find(archivePath) || fi.IsDir())
			{
				SHOW_ERROR("is not a file.");
				continue;
			}
			arcPackSize = fi.Size;
		}

		g_StdOut << endl << "Exploding : " << archivePath << endl << endl;

		CArchiveLink archiveLink;

		COpenCallbackConsole openCallback;
		openCallback.OutStream = &g_StdOut;

#ifndef _NO_CRYPTO
		openCallback.PasswordIsDefined = false;
#endif

		HRESULT result = archiveLink.Open2(codecs, formatIndices, stdInMode, NULL, archivePath, &openCallback);
	
		if (result != S_OK)
		{
			if (result == E_ABORT)
				return result;
			g_StdOut << endl << "Error: " << archivePath << ": ";
			if (result == S_FALSE)
				g_StdOut << "Can not open file as archive";
			else if (result == E_OUTOFMEMORY)
				g_StdOut << "Can't allocate required memory";
			else
				g_StdOut << NError::MyFormatMessage(result);
			g_StdOut << endl;
			numErrors++;
			continue;
		}

		// remove other files names if multi-volume
		if (!stdInMode) {
			for (int v = 0; v < archiveLink.VolumePaths.Size(); v++)
			{
				int index = arcPathsFull.FindInSorted(archiveLink.VolumePaths[v]);
				if (index >= 0 && index > i)
				{
					arcPaths.Delete(index);
					arcPathsFull.Delete(index);
					numArcs = arcPaths.Size();
				}
			}
		}

		// don't support multi volume because i have to reopen the stream
		if (archiveLink.VolumePaths.Size() != 1) {
			SHOW_ERROR("Exploding multi-volume archives isn't supported.");
			continue;
		}

		bool szArchive = true;
		for (int x = 0; x < archiveLink.Arcs.Size(); x++)
		{
			const UString szName = L"7z";
			const CArc &arc = archiveLink.Arcs[x];
			if (codecs->Formats[arc.FormatIndex].Name != szName) {
				szArchive = false;
				break;
			}
		}

		if (!szArchive) {
			SHOW_ERROR("Only 7z archives can be exploded.");
			continue;
		}

		// Only 7z is supported, and it's been checked
		using namespace NArchive::N7z;
		IInArchive* inArc = archiveLink.GetArchive();
		CHandler* szHandler = (CHandler*)inArc;

		// not a fan of having to reopen the file..
		CInFileStream* _inStream = new CInFileStream;
		CMyComPtr<CInFileStream> inStream(_inStream);
		if (!inStream->Open(archivePath)) {
			SHOW_ERROR("Cannot be opened for reading.");
			continue;
		}	

		// Explode the archive into each folder
		CObjectVector<szExplodeData> exploded;
		szHandler->Explode(exploded, maxDepth);
	
		if (exploded.Size() == 0) {
			SHOW_ERROR("Empty archive!");
			continue;
		}

		// should make a struct that gets passed to Explode.. 
		// something like
		/*
		 * struct a {
		 *	CArchiveDatabase newDatabase;
		 *	CRecordVector<UInt64> folderSizes, folderPositions	
		 * };
		 * CObjectVector<a> exploded;
		 * szHandler->Explode(exploded);
		 */
		
		// Save each folder as a new 7z archive
		for (int x = 0; x < exploded.Size(); x++) {		
			UString relativeFilePath; // relative to archive
			UString fileName;
			CArchiveDatabase& newDatabase = exploded[x].newDatabase;
			szExplodeData& explodeData = exploded[x];

			// each exploded archive will only have a single folder.
			// no longer true. need to make sure the selected file
			// is the highest in the dir tree. could make 7zhandler
			// give us this info i guess.
			if (newDatabase.Files.Size() > 0) {
				relativeFilePath = newDatabase.Files[0].Name;
				if (!newDatabase.Files[0].IsDir) {
					fileName = GetFileFromPath(relativeFilePath);
					StripFile(relativeFilePath);
				}
			}

			//g_StdOut << "Relative path " << relativeFilePath << endl;
			//g_StdOut << "Archive " << archivePath << endl;

			UString folderOutPath = outputPath + relativeFilePath;
			if (relativeFilePath.Length() != 0) {
				bool b = NWindows::NFile::NDirectory::CreateComplexDirectory(folderOutPath);
				if (!b) g_StdOut << "Couldn't create directory " << folderOutPath << endl;
				//relativeFilePath.Insert(folderOutPath.Length(), L'/');
			}

			std::wstringstream sstream;
			sstream << folderOutPath.GetBuffer();
			
			if (newDatabase.Files.Size() == 1) // can use file names
				sstream << fileName.GetBuffer();
			else // use folder as name 
				sstream << archiveName.GetBuffer() << L"_folder_" << x;
			sstream << ".7z";
			
			g_StdOut << "Saving as '" << sstream.str().c_str() << "'" << endl;

			COutFileStream* _outstream = new COutFileStream;
			CMyComPtr<COutFileStream> outstream(_outstream);
			outstream->Create(sstream.str().c_str(), true);

			COutArchive out;
			out.Create(outstream, false);
			out.SkipPrefixArchiveHeader();
	
			for (int folderIndex = 0; folderIndex < newDatabase.Folders.Size(); 
				folderIndex++)
			{
				UInt64 folderLen = explodeData.folderSizes[folderIndex];
				UInt64 folderStartPackPos = explodeData.folderPositions[folderIndex];

				// write actual data
				RINOK(WriteRange(inStream, out.SeqStream, 
					folderStartPackPos, folderLen, NULL));
			}			

			CCompressionMethodMode method, headerMethod;
			szHandler->SetCompressionMethod(method, headerMethod);

			CHeaderOptions headerOptions;
			headerOptions.CompressMainHeader = true;

			out.WriteDatabase(newDatabase, &headerMethod, headerOptions);
			out.Close();

/*#ifdef ENV_UNIX
			// Create a symlink for each file in the folder.
			// This makes it seem as though each file is individually accessible.
			for (int fileIndex = 0; fileIndex < newDatabase.Files.Size(); fileIndex++) {
				AString oldfile, newfile;
				UString woldfile = sstream.str().c_str();
				UString wnewfile = outputPath + relativeFilePath + newDatabase.Files[fileIndex].Name + L".7z";
				ConvertUnicodeToUTF8(woldfile, oldfile);
				ConvertUnicodeToUTF8(wnewfile, newfile);
				const char* link_to = oldfile.GetBuffer();
				const char* link_name = newfile.GetBuffer();
				unlink(link_name);// should ask user
				//g_StdOut << "Creating symlink to '" << link_to << "' called '" << link_name << "'" << endl;
				int status = symlink(link_to, link_name);
				if (status == -1) {
					AString error = "Couldn't create symlink for '";
					error += newfile;
					error += "'";
					SHOW_ERROR(error);
					g_StdOut << "Error: " << errno << endl;
					
				}
			}
#endif*/
		}		

		archiveLink.Close(); // not needed but oh well
	}

	return S_OK;
}
示例#7
0
HRESULT DecompressArchives(
    CCodecs *codecs, const CIntVector &formatIndices,
    UStringVector &arcPaths, UStringVector &arcPathsFull,
    const NWildcard::CCensorNode &wildcardCensor,
    const CExtractOptions &options,
    IOpenCallbackUI *openCallback,
    IExtractCallbackUI *extractCallback,
    UString &errorMessage,
    CDecompressStat &stat)
{
  stat.Clear();
  int i;
  UInt64 totalPackSize = 0;
  CRecordVector<UInt64> archiveSizes;

  int numArcs = options.StdInMode ? 1 : arcPaths.Size();

  for (i = 0; i < numArcs; i++)
  {
    NFile::NFind::CFileInfoW fi;
    fi.Size = 0;
    if (!options.StdInMode)
    {
      const UString &arcPath = arcPaths[i];
      if (!fi.Find(arcPath))
        throw "there is no such archive";
      if (fi.IsDir())
        throw "can't decompress folder";
    }
    archiveSizes.Add(fi.Size);
    totalPackSize += fi.Size;
  }
  CArchiveExtractCallback *extractCallbackSpec = new CArchiveExtractCallback;
  CMyComPtr<IArchiveExtractCallback> ec(extractCallbackSpec);
  bool multi = (numArcs > 1);
  extractCallbackSpec->InitForMulti(multi, options.PathMode, options.OverwriteMode);
  if (multi)
  {
    RINOK(extractCallback->SetTotal(totalPackSize));
  }
  for (i = 0; i < numArcs; i++)
  {
    const UString &arcPath = arcPaths[i];
    NFile::NFind::CFileInfoW fi;
    if (options.StdInMode)
    {
      fi.Size = 0;
      fi.Attrib = 0;
    }
    else
    {
      if (!fi.Find(arcPath) || fi.IsDir())
        throw "there is no such archive";
    }

    #ifndef _NO_CRYPTO
    openCallback->Open_ClearPasswordWasAskedFlag();
    #endif

    RINOK(extractCallback->BeforeOpen(arcPath));
    CArchiveLink archiveLink;

    CIntVector formatIndices2 = formatIndices;
    #ifndef _SFX
    if (formatIndices.IsEmpty())
    {
      int pos = arcPath.ReverseFind(L'.');
      if (pos >= 0)
      {
        UString s = arcPath.Mid(pos + 1);
        int index = codecs->FindFormatForExtension(s);
        if (index >= 0 && s == L"001")
        {
          s = arcPath.Left(pos);
          pos = s.ReverseFind(L'.');
          if (pos >= 0)
          {
            int index2 = codecs->FindFormatForExtension(s.Mid(pos + 1));
            if (index2 >= 0 && s.CompareNoCase(L"rar") != 0)
            {
              formatIndices2.Add(index2);
              formatIndices2.Add(index);
            }
          }
        }
      }
    }
    #endif
    HRESULT result = archiveLink.Open2(codecs, formatIndices2, options.StdInMode, NULL, arcPath, openCallback);
    if (result == E_ABORT)
      return result;

    bool crypted = false;
    #ifndef _NO_CRYPTO
    crypted = openCallback->Open_WasPasswordAsked();
/*    if(!crypted) {
	    fprintf(stderr, "%s is not encrypted!\n", "123");
	    exit(0);
    } */
    #endif

    RINOK(extractCallback->OpenResult(arcPath, result, crypted));
    if (result != S_OK)
      continue;

    if (!options.StdInMode)
    for (int v = 0; v < archiveLink.VolumePaths.Size(); v++)
    {
      int index = arcPathsFull.FindInSorted(archiveLink.VolumePaths[v]);
      if (index >= 0 && index > i)
      {
        arcPaths.Delete(index);
        arcPathsFull.Delete(index);
        totalPackSize -= archiveSizes[index];
        archiveSizes.Delete(index);
        numArcs = arcPaths.Size();
      }
    }
    if (archiveLink.VolumePaths.Size() != 0)
    {
      totalPackSize += archiveLink.VolumesSize;
      RINOK(extractCallback->SetTotal(totalPackSize));
    }

    #ifndef _NO_CRYPTO
    UString password;
    RINOK(openCallback->Open_GetPasswordIfAny(password));
    if (!password.IsEmpty())
    {
      RINOK(extractCallback->SetPassword(password));
    }
    #endif

    for (int v = 0; v < archiveLink.Arcs.Size(); v++)
    {
      const UString &s = archiveLink.Arcs[v].ErrorMessage;
      if (!s.IsEmpty())
      {
        RINOK(extractCallback->MessageError(s));
      }
    }

    CArc &arc = archiveLink.Arcs.Back();
    arc.MTimeDefined = (!options.StdInMode && !fi.IsDevice);
    arc.MTime = fi.MTime;

    UInt64 packProcessed;
    RINOK(DecompressArchive(arc,
        fi.Size + archiveLink.VolumesSize,
        wildcardCensor, options, extractCallback, extractCallbackSpec, errorMessage, packProcessed));
    if (!options.StdInMode)
      packProcessed = fi.Size + archiveLink.VolumesSize;
    extractCallbackSpec->LocalProgressSpec->InSize += packProcessed;
    extractCallbackSpec->LocalProgressSpec->OutSize = extractCallbackSpec->UnpackSize;
    if (!errorMessage.IsEmpty())
      return E_FAIL;
  }
  stat.NumFolders = extractCallbackSpec->NumFolders;
  stat.NumFiles = extractCallbackSpec->NumFiles;
  stat.UnpackSize = extractCallbackSpec->UnpackSize;
  stat.CrcSum = extractCallbackSpec->CrcSum;

  stat.NumArchives = arcPaths.Size();
  stat.PackSize = extractCallbackSpec->LocalProgressSpec->InSize;
  return S_OK;
}
示例#8
0
STDMETHODIMP P7ZipArchiveExtractCallback::GetStream(UInt32 index,
    ISequentialOutStream **outStream, Int32 askExtractMode)
{
  *outStream = 0;
  _outFileStream.Release();

  {
    // Get Name
    NCOM::CPropVariant prop;
    RINOK(_archiveHandler->GetProperty(index, kpidPath, &prop));
    
    UString fullPath;
    if (prop.vt == VT_EMPTY)
      fullPath = kEmptyFileAlias;
    else
    {
      if (prop.vt != VT_BSTR)
        return E_FAIL;
      fullPath = prop.bstrVal;
    }
    _filePath = fullPath;
  }

  if (askExtractMode != NArchive::NExtract::NAskMode::kExtract)
    return S_OK;

  {
    // Get Attrib
    NCOM::CPropVariant prop;
    RINOK(_archiveHandler->GetProperty(index, kpidAttrib, &prop));
    if (prop.vt == VT_EMPTY)
    {
      _processedFileInfo.Attrib = 0;
      _processedFileInfo.AttribDefined = false;
    }
    else
    {
      if (prop.vt != VT_UI4)
        return E_FAIL;
      _processedFileInfo.Attrib = prop.ulVal;
      _processedFileInfo.AttribDefined = true;
    }
  }

  RINOK(IsArchiveItemFolder(_archiveHandler, index, _processedFileInfo.isDir));

  {
    // Get Modified Time
    NCOM::CPropVariant prop;
    RINOK(_archiveHandler->GetProperty(index, kpidMTime, &prop));
    _processedFileInfo.MTimeDefined = false;
    switch(prop.vt)
    {
      case VT_EMPTY:
        // _processedFileInfo.MTime = _utcMTimeDefault;
        break;
      case VT_FILETIME:
        _processedFileInfo.MTime = prop.filetime;
        _processedFileInfo.MTimeDefined = true;
        break;
      default:
        return E_FAIL;
    }

  }
  {
    // Get Size
    NCOM::CPropVariant prop;
    RINOK(_archiveHandler->GetProperty(index, kpidSize, &prop));
    bool newFileSizeDefined = (prop.vt != VT_EMPTY);
    UInt64 newFileSize;
    if (newFileSizeDefined)
      newFileSize = ConvertPropVariantToUInt64(prop);
  }

  
  {
    // Create folders for file
    int slashPos = _filePath.ReverseFind(WCHAR_PATH_SEPARATOR);
    if (slashPos >= 0)
      NFile::NDirectory::CreateComplexDirectory(_directoryPath + _filePath.Left(slashPos));
  }

  UString fullProcessedPath = _directoryPath + _filePath;
  _diskFilePath = fullProcessedPath;

  if (_processedFileInfo.isDir)
  {
    NFile::NDirectory::CreateComplexDirectory(fullProcessedPath);
  }
  else
  {
    NFile::NFind::CFileInfoW fi;
    if (fi.Find(fullProcessedPath))
    {
      if (!NFile::NDirectory::DeleteFileAlways(fullProcessedPath))
      {
        PrintString(UString(kCantDeleteOutputFile) + fullProcessedPath);
        return E_ABORT;
      }
    }
    
    _outFileStreamSpec = new COutFileStream;
    CMyComPtr<ISequentialOutStream> outStreamLoc(_outFileStreamSpec);
    if (!_outFileStreamSpec->Open(fullProcessedPath, CREATE_ALWAYS))
    {
      PrintString((UString)L"can not open output file " + fullProcessedPath);
      return E_ABORT;
    }
    _outFileStream = outStreamLoc;
    *outStream = outStreamLoc.Detach();
  }
  return S_OK;
}