Ejemplo n.º 1
0
HRESULT CPlugin::AfterUpdate(CWorkDirTempFile &tempFile, const UStringVector &pathVector)
{
  _folder.Release();
  m_ArchiveHandler->Close();
  
  RINOK(tempFile.MoveToOriginal(true));
  
  RINOK(m_ArchiveHandler->ReOpen(NULL)); // check it

  m_ArchiveHandler->BindToRootFolder(&_folder);
  FOR_VECTOR (i, pathVector)
  {
    CMyComPtr<IFolderFolder> newFolder;
    _folder->BindToFolder(pathVector[i], &newFolder);
    if (!newFolder)
      break;
    _folder = newFolder;
  }
Ejemplo n.º 2
0
HRESULT CompressFiles(const CObjectVector<PluginPanelItem> &pluginPanelItems)
{
  if (pluginPanelItems.Size() == 0)
    return E_FAIL;

  UStringVector fileNames;
  int i;
  for (i = 0; i < pluginPanelItems.Size(); i++)
  {
    const PluginPanelItem &panelItem = pluginPanelItems[i];
    if (strcmp(panelItem.FindData.cFileName, "..") == 0 &&
        NFind::NAttributes::IsDir(panelItem.FindData.dwFileAttributes))
      return E_FAIL;
    if (strcmp(panelItem.FindData.cFileName, ".") == 0 &&
        NFind::NAttributes::IsDir(panelItem.FindData.dwFileAttributes))
      return E_FAIL;
    FString fullPath;
    FString fileNameUnicode = us2fs(MultiByteToUnicodeString(panelItem.FindData.cFileName, CP_OEMCP));
    if (!MyGetFullPathName(fileNameUnicode, fullPath))
      return E_FAIL;
    fileNames.Add(fs2us(fullPath));
  }

  NCompression::CInfo compressionInfo;
  compressionInfo.Load();
  
  int archiverIndex = 0;

  CCodecs *codecs = new CCodecs;
  CMyComPtr<ICompressCodecsInfo> compressCodecsInfo = codecs;
  if (codecs->Load() != S_OK)
    throw "Can't load 7-Zip codecs";
  {
    for (int i = 0; i < codecs->Formats.Size(); i++)
    {
      const CArcInfoEx &arcInfo = codecs->Formats[i];
      if (arcInfo.UpdateEnabled)
      {
        if (archiverIndex == -1)
          archiverIndex = i;
        if (arcInfo.Name.CompareNoCase(compressionInfo.ArcType) == 0)
          archiverIndex = i;
      }
    }
  }


  UString resultPath;
  {
    CParsedPath parsedPath;
    parsedPath.ParsePath(fileNames.Front());
    if (parsedPath.PathParts.Size() == 0)
      return E_FAIL;
    if (fileNames.Size() == 1 || parsedPath.PathParts.Size() == 1)
    {
      // CSysString pureName, dot, extension;
      resultPath = parsedPath.PathParts.Back();
    }
    else
    {
      parsedPath.PathParts.DeleteBack();
      resultPath = parsedPath.PathParts.Back();
    }
  }
  UString archiveNameSrc = resultPath;
  UString archiveName = archiveNameSrc;

  const CArcInfoEx &arcInfo = codecs->Formats[archiverIndex];
  int prevFormat = archiverIndex;
 
  if (!arcInfo.KeepName)
  {
    int dotPos = archiveName.ReverseFind('.');
    int slashPos = MyMax(archiveName.ReverseFind('\\'), archiveName.ReverseFind('/'));
    if (dotPos > slashPos)
      archiveName = archiveName.Left(dotPos);
  }
  archiveName += L'.';
  archiveName += arcInfo.GetMainExt();
  
  const CActionSet *actionSet = &kAddActionSet;

  for (;;)
  {
    AString archiveNameA = UnicodeStringToMultiByte(archiveName, CP_OEMCP);
    const int kYSize = 16;
    const int kXMid = 38;
  
    const int kArchiveNameIndex = 2;
    const int kMethodRadioIndex = kArchiveNameIndex + 2;
    const int kModeRadioIndex = kMethodRadioIndex + 7;

    const CArcInfoEx &arcInfo = codecs->Formats[archiverIndex];

    char updateAddToArchiveString[512];
    const AString s = UnicodeStringToMultiByte(arcInfo.Name, CP_OEMCP);

    sprintf(updateAddToArchiveString,
        g_StartupInfo.GetMsgString(NMessageID::kUpdateAddToArchive), (const char *)s);

    int methodIndex = 0;
    int i;
    for (i = sizeof(g_MethodMap) / sizeof(g_MethodMap[0]) - 1; i >= 0; i--)
      if (compressionInfo.Level >= g_MethodMap[i])
      {
        methodIndex = i;
        break;
      }

    struct CInitDialogItem initItems[]=
    {
      { DI_DOUBLEBOX, 3, 1, 72, kYSize - 2, false, false, 0, false, NMessageID::kUpdateTitle, NULL, NULL },

      { DI_TEXT, 5, 2, 0, 0, false, false, 0, false, -1, updateAddToArchiveString, NULL },
      
      { DI_EDIT, 5, 3, 70, 3, true, false, DIF_HISTORY, false, -1, archiveNameA, kArchiveHistoryKeyName},
      // { DI_EDIT, 5, 3, 70, 3, true, false, 0, false, -1, archiveName, NULL},
      
      { DI_SINGLEBOX, 4, 4, kXMid - 2, 4 + 7, false, false, 0, false, NMessageID::kUpdateMethod, NULL, NULL },
      { DI_RADIOBUTTON, 6, 5, 0, 0, false, methodIndex == 0,
          DIF_GROUP, false, NMessageID::kUpdateMethodStore, NULL, NULL },
      { DI_RADIOBUTTON, 6, 6, 0, 0, false, methodIndex == 1,
          0, false, NMessageID::kUpdateMethodFastest, NULL, NULL },
      { DI_RADIOBUTTON, 6, 7, 0, 0, false, methodIndex == 2,
          0, false, NMessageID::kUpdateMethodFast, NULL, NULL },
      { DI_RADIOBUTTON, 6, 8, 0, 0, false, methodIndex == 3,
          0, false, NMessageID::kUpdateMethodNormal, NULL, NULL },
      { DI_RADIOBUTTON, 6, 9, 0, 0, false, methodIndex == 4,
          false, 0, NMessageID::kUpdateMethodMaximum, NULL, NULL },
      { DI_RADIOBUTTON, 6, 10, 0, 0, false, methodIndex == 5,
          false, 0, NMessageID::kUpdateMethodUltra, NULL, NULL },
      
      { DI_SINGLEBOX, kXMid, 4, 70, 4 + 5, false, false, 0, false, NMessageID::kUpdateMode, NULL, NULL },
      { DI_RADIOBUTTON, kXMid + 2, 5, 0, 0, false,
          actionSet == &kAddActionSet,
          DIF_GROUP, false, NMessageID::kUpdateModeAdd, NULL, NULL },
      { DI_RADIOBUTTON, kXMid + 2, 6, 0, 0, false,
          actionSet == &kUpdateActionSet,
          0, false, NMessageID::kUpdateModeUpdate, NULL, NULL },
      { DI_RADIOBUTTON, kXMid + 2, 7, 0, 0, false,
          actionSet == &kFreshActionSet,
          0, false, NMessageID::kUpdateModeFreshen, NULL, NULL },
      { DI_RADIOBUTTON, kXMid + 2, 8, 0, 0, false,
          actionSet == &kSynchronizeActionSet,
          0, false, NMessageID::kUpdateModeSynchronize, NULL, NULL },
      
      { DI_TEXT, 3, kYSize - 4, 0, 0, false, false, DIF_BOXCOLOR|DIF_SEPARATOR, false, -1, "", NULL  },
      
      { DI_BUTTON, 0, kYSize - 3, 0, 0, false, false, DIF_CENTERGROUP, true, NMessageID::kUpdateAdd, NULL, NULL  },
      { DI_BUTTON, 0, kYSize - 3, 0, 0, false, false, DIF_CENTERGROUP, false, NMessageID::kUpdateSelectArchiver, NULL, NULL  },
      { DI_BUTTON, 0, kYSize - 3, 0, 0, false, false, DIF_CENTERGROUP, false, NMessageID::kCancel, NULL, NULL  }
    };

    const int kNumDialogItems = sizeof(initItems) / sizeof(initItems[0]);
    
    const int kOkButtonIndex = kNumDialogItems - 3;
    const int kSelectarchiverButtonIndex = kNumDialogItems - 2;

    FarDialogItem dialogItems[kNumDialogItems];
    g_StartupInfo.InitDialogItems(initItems, dialogItems, kNumDialogItems);
    int askCode = g_StartupInfo.ShowDialog(76, kYSize,
        kHelpTopic, dialogItems, kNumDialogItems);

    archiveNameA = dialogItems[kArchiveNameIndex].Data;
    archiveNameA.Trim();
    archiveName = MultiByteToUnicodeString(archiveNameA, CP_OEMCP);

    compressionInfo.Level = g_MethodMap[0];
    for (i = 0; i < sizeof(g_MethodMap)/ sizeof(g_MethodMap[0]); i++)
      if (dialogItems[kMethodRadioIndex + i].Selected)
        compressionInfo.Level = g_MethodMap[i];

    if (dialogItems[kModeRadioIndex].Selected)
      actionSet = &kAddActionSet;
    else if (dialogItems[kModeRadioIndex + 1].Selected)
      actionSet = &kUpdateActionSet;
    else if (dialogItems[kModeRadioIndex + 2].Selected)
      actionSet = &kFreshActionSet;
    else if (dialogItems[kModeRadioIndex + 3].Selected)
      actionSet = &kSynchronizeActionSet;
    else
      throw 51751;

    if (askCode == kSelectarchiverButtonIndex)
    {
      CIntVector indices;
      CSysStringVector archiverNames;
      for (int i = 0; i < codecs->Formats.Size(); i++)
      {
        const CArcInfoEx &arc = codecs->Formats[i];
        if (arc.UpdateEnabled)
        {
          indices.Add(i);
          archiverNames.Add(GetSystemString(arc.Name, CP_OEMCP));
        }
      }
    
      int index = g_StartupInfo.Menu(FMENU_AUTOHIGHLIGHT,
          g_StartupInfo.GetMsgString(NMessageID::kUpdateSelectArchiverMenuTitle),
          NULL, archiverNames, archiverIndex);
      if (index >= 0)
      {
        const CArcInfoEx &prevArchiverInfo = codecs->Formats[prevFormat];
        if (prevArchiverInfo.KeepName)
        {
          const UString &prevExtension = prevArchiverInfo.GetMainExt();
          const int prevExtensionLen = prevExtension.Length();
          if (archiveName.Right(prevExtensionLen).CompareNoCase(prevExtension) == 0)
          {
            int pos = archiveName.Length() - prevExtensionLen;
            if (pos > 1)
            {
              int dotPos = archiveName.ReverseFind('.');
              if (dotPos == pos - 1)
                archiveName = archiveName.Left(dotPos);
            }
          }
        }

        archiverIndex = indices[index];
        const CArcInfoEx &arcInfo = codecs->Formats[archiverIndex];
        prevFormat = archiverIndex;
        
        if (arcInfo.KeepName)
          archiveName = archiveNameSrc;
        else
        {
          int dotPos = archiveName.ReverseFind('.');
          int slashPos = MyMax(archiveName.ReverseFind('\\'), archiveName.ReverseFind('/'));
          if (dotPos > slashPos)
            archiveName = archiveName.Left(dotPos);
        }
        archiveName += L'.';
        archiveName += arcInfo.GetMainExt();
      }
      continue;
    }

    if (askCode != kOkButtonIndex)
      return E_ABORT;
    
    break;
  }

  const CArcInfoEx &archiverInfoFinal = codecs->Formats[archiverIndex];
  compressionInfo.ArcType = archiverInfoFinal.Name;
  compressionInfo.Save();

  NWorkDir::CInfo workDirInfo;
  workDirInfo.Load();

  FString fullArchiveName;
  if (!MyGetFullPathName(us2fs(archiveName), fullArchiveName))
    return E_FAIL;
   
  CWorkDirTempFile tempFile;
  RINOK(tempFile.CreateTempFile(fullArchiveName));

  CScreenRestorer screenRestorer;
  CProgressBox progressBox;
  CProgressBox *progressBoxPointer = NULL;

  screenRestorer.Save();

  progressBoxPointer = &progressBox;
  progressBox.Init(
      // g_StartupInfo.GetMsgString(NMessageID::kWaitTitle),
      g_StartupInfo.GetMsgString(NMessageID::kUpdating), 48);


  NFind::CFileInfo fileInfo;

  CMyComPtr<IOutFolderArchive> outArchive;

  CMyComPtr<IInFolderArchive> archiveHandler;
  if (fileInfo.Find(fullArchiveName))
  {
    if (fileInfo.IsDir())
      throw "There is Directory with such name";

    CAgent *agentSpec = new CAgent;
    archiveHandler = agentSpec;
    // CLSID realClassID;
    CMyComBSTR archiveType;
    RINOK(agentSpec->Open(NULL,
        GetUnicodeString(fullArchiveName, CP_OEMCP), UString(),
        // &realClassID,
        &archiveType,
        NULL));

    if (archiverInfoFinal.Name.CompareNoCase((const wchar_t *)archiveType) != 0)
      throw "Type of existing archive differs from specified type";
    HRESULT result = archiveHandler.QueryInterface(
        IID_IOutFolderArchive, &outArchive);
    if (result != S_OK)
    {
      g_StartupInfo.ShowMessage(NMessageID::kUpdateNotSupportedForThisArchive);
      return E_FAIL;
    }
  }
  else
  {
    // HRESULT result = outArchive.CoCreateInstance(classID);
    CAgent *agentSpec = new CAgent;
    outArchive = agentSpec;

    /*
    HRESULT result = outArchive.CoCreateInstance(CLSID_CAgentArchiveHandler);
    if (result != S_OK)
    {
      g_StartupInfo.ShowMessage(NMessageID::kUpdateNotSupportedForThisArchive);
      return E_FAIL;
    }
    */
  }

  CRecordVector<const wchar_t *> fileNamePointers;
  fileNamePointers.Reserve(fileNames.Size());
  for (i = 0; i < fileNames.Size(); i++)
    fileNamePointers.Add(fileNames[i]);

  outArchive->SetFolder(NULL);
  outArchive->SetFiles(L"", &fileNamePointers.Front(), fileNamePointers.Size());
  BYTE actionSetByte[NUpdateArchive::NPairState::kNumValues];
  for (i = 0; i < NUpdateArchive::NPairState::kNumValues; i++)
    actionSetByte[i] = (BYTE)actionSet->StateActions[i];

  CUpdateCallback100Imp *updateCallbackSpec = new CUpdateCallback100Imp;
  CMyComPtr<IFolderArchiveUpdateCallback> updateCallback(updateCallbackSpec );
  
  updateCallbackSpec->Init(/* archiveHandler, */ progressBoxPointer);


  RINOK(SetOutProperties(outArchive, compressionInfo.Level));

  HRESULT result = outArchive->DoOperation(
      codecs, archiverIndex,
      tempFile.OutStream, actionSetByte,
      NULL, updateCallback);
  updateCallback.Release();
  outArchive.Release();

  if (result != S_OK)
  {
    ShowErrorMessage(result);
    return result;
  }
 
  if (archiveHandler)
  {
    archiveHandler->Close();
  }
  if (!tempFile.MoveToOriginal(archiveHandler != NULL))
  {
    ShowLastErrorMessage();
    return E_FAIL;
  }
  return S_OK;
}
Ejemplo n.º 3
0
HRESULT CAgentFolder::CommonUpdateOperation(
    AGENT_OP operation,
    bool moveMode,
    const wchar_t *newItemName,
    const NUpdateArchive::CActionSet *actionSet,
    const UInt32 *indices, UInt32 numItems,
    IProgress *progress)
{
  if (!_agentSpec->CanUpdate())
    return E_NOTIMPL;

  CMyComPtr<IFolderArchiveUpdateCallback> updateCallback100;
  if (progress)
    progress->QueryInterface(IID_IFolderArchiveUpdateCallback, (void **)&updateCallback100);

  try
  {

  RINOK(_agentSpec->SetFolder(this));

  // ---------- Save FolderItem ----------

  UStringVector pathParts;
  bool isAltStreamFolder = false;
  GetPathParts(pathParts, isAltStreamFolder);

  FStringVector requestedPaths;
  FStringVector processedPaths;

  CWorkDirTempFile tempFile;
  RINOK(tempFile.CreateTempFile(us2fs(_agentSpec->_archiveFilePath)));
  {
    CMyComPtr<IOutStream> tailStream;
    const CArc &arc = *_agentSpec->_archiveLink.GetArc();

    if (arc.ArcStreamOffset == 0)
      tailStream = tempFile.OutStream;
    else
    {
      if (arc.Offset < 0)
        return E_NOTIMPL;
      RINOK(arc.InStream->Seek(0, STREAM_SEEK_SET, NULL));
      RINOK(NCompress::CopyStream_ExactSize(arc.InStream, tempFile.OutStream, arc.ArcStreamOffset, NULL));
      CTailOutStream *tailStreamSpec = new CTailOutStream;
      tailStream = tailStreamSpec;
      tailStreamSpec->Stream = tempFile.OutStream;
      tailStreamSpec->Offset = arc.ArcStreamOffset;
      tailStreamSpec->Init();
    }
    
    HRESULT result;

    switch (operation)
    {
      case AGENT_OP_Delete:
        result = _agentSpec->DeleteItems(tailStream, indices, numItems, updateCallback100);
        break;
      case AGENT_OP_CreateFolder:
        result = _agentSpec->CreateFolder(tailStream, newItemName, updateCallback100);
        break;
      case AGENT_OP_Rename:
        result = _agentSpec->RenameItem(tailStream, indices, numItems, newItemName, updateCallback100);
        break;
      case AGENT_OP_Comment:
        result = _agentSpec->CommentItem(tailStream, indices, numItems, newItemName, updateCallback100);
        break;
      case AGENT_OP_CopyFromFile:
        result = _agentSpec->UpdateOneFile(tailStream, indices, numItems, newItemName, updateCallback100);
        break;
      case AGENT_OP_Uni:
        {
          Byte actionSetByte[NUpdateArchive::NPairState::kNumValues];
          for (int i = 0; i < NUpdateArchive::NPairState::kNumValues; i++)
            actionSetByte[i] = (Byte)actionSet->StateActions[i];
          result = _agentSpec->DoOperation2(
              moveMode ? &requestedPaths : NULL,
              moveMode ? &processedPaths : NULL,
              tailStream, actionSetByte, NULL, updateCallback100);
          break;
        }
      default:
        return E_FAIL;
    }
    
    RINOK(result);
  }

  _agentSpec->KeepModeForNextOpen();
  _agentSpec->Close();
  
  // before 9.26: if there was error for MoveToOriginal archive was closed.
  // now: we reopen archive after close

  // m_FolderItem = NULL;
  
  HRESULT res = tempFile.MoveToOriginal(true);

  // RINOK(res);
  if (res == S_OK)
  {
    if (moveMode)
    {
      unsigned i;
      for (i = 0; i < processedPaths.Size(); i++)
      {
        DeleteFileAlways(processedPaths[i]);
      }
      for (i = 0; i < requestedPaths.Size(); i++)
      {
        const FString &fs = requestedPaths[i];
        if (NFind::DoesDirExist(fs))
          DeleteEmptyFolderAndEmptySubFolders(fs);
      }
    }
  }

  {
    CMyComPtr<IArchiveOpenCallback> openCallback;
    if (updateCallback100)
      updateCallback100->QueryInterface(IID_IArchiveOpenCallback, (void **)&openCallback);
    RINOK(_agentSpec->ReOpen(openCallback));
  }
   
  // CAgent::ReOpen() deletes _proxy and _proxy2
  _items.Clear();
  _proxy = NULL;
  _proxy2 = NULL;
  _proxyDirIndex = k_Proxy_RootDirIndex;
  _isAltStreamFolder = false;
  
  
  // ---------- Restore FolderItem ----------

  CMyComPtr<IFolderFolder> archiveFolder;
  RINOK(_agentSpec->BindToRootFolder(&archiveFolder));

  // CAgent::BindToRootFolder() changes _proxy and _proxy2
  _proxy = _agentSpec->_proxy;
  _proxy2 = _agentSpec->_proxy2;

  if (_proxy)
  {
    FOR_VECTOR (i, pathParts)
    {
      int next = _proxy->FindSubDir(_proxyDirIndex, pathParts[i]);
      if (next < 0)
        break;
      _proxyDirIndex = next;
    }
  }
  
  if (_proxy2)
  {
    if (pathParts.IsEmpty() && isAltStreamFolder)
    {
      _proxyDirIndex = k_Proxy2_AltRootDirIndex;
    }
    else FOR_VECTOR (i, pathParts)
    {
      bool dirOnly = (i + 1 < pathParts.Size() || !isAltStreamFolder);
      int index = _proxy2->FindItem(_proxyDirIndex, pathParts[i], dirOnly);
      if (index < 0)
        break;
      
      const CProxyFile2 &file = _proxy2->Files[_proxy2->Dirs[_proxyDirIndex].Items[index]];
  
      if (dirOnly)
        _proxyDirIndex = file.DirIndex;
      else
      {
        if (file.AltDirIndex >= 0)
          _proxyDirIndex = file.AltDirIndex;
        break;
      }
    }
  }