void EnumerateDirItems(
    const UString &baseFolderPrefix,   // base (disk) prefix for scanning  
    const UStringVector &fileNames,    // names relative to baseFolderPrefix
    const UString &archiveNamePrefix, 
    CObjectVector<CDirItem> &dirItems,
    UStringVector &errorPaths,
    CRecordVector<DWORD> &errorCodes)
{
  for(int i = 0; i < fileNames.Size(); i++)
  {
    const UString &fileName = fileNames[i];
    NFind::CFileInfoW fileInfo;
    if (!NFind::FindFile(baseFolderPrefix + fileName, fileInfo))
    {
      errorCodes.Add(::GetLastError());
      errorPaths.Add(baseFolderPrefix + fileName);
      continue;
    }
    AddDirFileInfo(archiveNamePrefix, fileName, fileInfo, dirItems);
    if (fileInfo.IsDirectory())
    {
      EnumerateDirectory(baseFolderPrefix, fileName + wchar_t(kDirDelimiter), 
          archiveNamePrefix + fileInfo.Name +  wchar_t(kDirDelimiter), 
          dirItems, errorPaths, errorCodes);
    }
  }
}
static void EnumerateDirectory(
    const UString &baseFolderPrefix,  // base (disk) prefix for scanning  
    const UString &directory,         // additional disk prefix starting from baseFolderPrefix
    const UString &prefix,            // logical prefix
    CObjectVector<CDirItem> &dirItems,
    UStringVector &errorPaths,
    CRecordVector<DWORD> &errorCodes)
{
  NFind::CEnumeratorW enumerator(baseFolderPrefix + directory + wchar_t(kAnyStringWildcard));
  for (;;)
  { 
    NFind::CFileInfoW fileInfo;
    bool found;
    if (!enumerator.Next(fileInfo, found))
    {
      errorCodes.Add(::GetLastError());
      errorPaths.Add(baseFolderPrefix + directory);
      return;
    }
    if (!found)
      break;
    AddDirFileInfo(prefix, directory + fileInfo.Name, fileInfo, dirItems);
    if (fileInfo.IsDirectory())
    {
      EnumerateDirectory(baseFolderPrefix, directory + fileInfo.Name + wchar_t(kDirDelimiter), 
          prefix + fileInfo.Name + wchar_t(kDirDelimiter), dirItems, errorPaths, errorCodes);
    }
  }
}
Exemple #3
0
bool CDirEnumerator::GetNextFile(NFind::CFileInfoW &fileInfo, bool &filled, UString &resPath, DWORD &errorCode)
{
    filled = false;
    for (;;)
    {
        if (Enumerators.IsEmpty())
        {
            if (Index >= FileNames.Size())
                return true;
            const UString &path = FileNames[Index];
            int pos = path.ReverseFind('\\');
            resPath.Empty();
            if (pos >= 0)
                resPath = path.Left(pos + 1);
            if (!NFind::FindFile(BasePrefix + path, fileInfo))
            {
                errorCode = ::GetLastError();
                resPath = path;
                return false;
            }
            Index++;
            break;
        }
        bool found;
        if (!Enumerators.Back().Next(fileInfo, found))
        {
            errorCode = ::GetLastError();
            resPath = Prefixes.Back();
            return false;
        }
        if (found)
        {
            resPath = Prefixes.Back();
            break;
        }
        Enumerators.DeleteBack();
        Prefixes.DeleteBack();
    }
    resPath += fileInfo.Name;
    if (!FlatMode && fileInfo.IsDirectory())
    {
        UString prefix = resPath + (UString)(wchar_t)kDirDelimiter;
        Enumerators.Add(NFind::CEnumeratorW(BasePrefix + prefix + (UString)(wchar_t)kAnyStringWildcard));
        Prefixes.Add(prefix);
    }
    filled = true;
    return true;
}
static UString GetBaseFolderPrefixFromRegistry()
{
  UString moduleFolderPrefix = GetModuleFolderPrefix();
  NFind::CFileInfoW fileInfo;
  if (NFind::FindFile(moduleFolderPrefix + kFormatFolderName, fileInfo))
    if (fileInfo.IsDirectory())
      return moduleFolderPrefix;
  UString path;
  #ifdef _WIN32
  if(ReadPathFromRegistry(HKEY_CURRENT_USER, path))
    return path;
  if(ReadPathFromRegistry(HKEY_LOCAL_MACHINE, path))
    return path;
  #endif
  return moduleFolderPrefix;
}
static HRESULT EnumerateDirItems(
    const NWildcard::CCensorNode &curNode, 
    const UString &diskPrefix,        // full disk path prefix 
    const UString &archivePrefix,     // prefix from root
    const UStringVector &addArchivePrefix,  // prefix from curNode
    CObjectVector<CDirItem> &dirItems, 
    bool enterToSubFolders,
    IEnumDirItemCallback *callback,
    UStringVector &errorPaths,
    CRecordVector<DWORD> &errorCodes)
{
  if (!enterToSubFolders)
    if (curNode.NeedCheckSubDirs())
      enterToSubFolders = true;
  if (callback)
    RINOK(callback->CheckBreak());

  // try direct_names case at first
  if (addArchivePrefix.IsEmpty() && !enterToSubFolders)
  {
    // check that all names are direct
    int i;
    for (i = 0; i < curNode.IncludeItems.Size(); i++)
    {
      const NWildcard::CItem &item = curNode.IncludeItems[i];
      if (item.Recursive || item.PathParts.Size() != 1)
        break;
      const UString &name = item.PathParts.Front();
      if (name.IsEmpty() || DoesNameContainWildCard(name))
        break;
    }
    if (i == curNode.IncludeItems.Size())
    {
      // all names are direct (no wildcards)
      // so we don't need file_system's dir enumerator
      CRecordVector<bool> needEnterVector;
      for (i = 0; i < curNode.IncludeItems.Size(); i++)
      {
        const NWildcard::CItem &item = curNode.IncludeItems[i];
        const UString &name = item.PathParts.Front();
        const UString fullPath = diskPrefix + name;
        NFind::CFileInfoW fileInfo;
        if (!NFind::FindFile(fullPath, fileInfo))
        {
          errorCodes.Add(::GetLastError());
          errorPaths.Add(fullPath);
          continue;
        }
        bool isDir = fileInfo.IsDirectory();
        if (isDir && !item.ForDir || !isDir && !item.ForFile)
        {
          errorCodes.Add((DWORD)E_FAIL);
          errorPaths.Add(fullPath);
          continue;
        }
        const UString realName = fileInfo.getFileName();
        const UString realDiskPath = diskPrefix + realName;
        {
          UStringVector pathParts;
          pathParts.Add(fileInfo.getFileName());
          if (curNode.CheckPathToRoot(false, pathParts, !isDir))
            continue;
        }
        AddDirFileInfo(archivePrefix, realDiskPath, fileInfo, dirItems);
        if (!isDir)
          continue;
        
        UStringVector addArchivePrefixNew;
        const NWildcard::CCensorNode *nextNode = 0;
        int index = curNode.FindSubNode(name);
        if (index >= 0)
        {
          for (int t = needEnterVector.Size(); t <= index; t++)
            needEnterVector.Add(true);
          needEnterVector[index] = false;
          nextNode = &curNode.SubNodes[index];
        }
        else
        {
          nextNode = &curNode;
          addArchivePrefixNew.Add(name); // don't change it to realName. It's for shortnames support
        }
        RINOK(EnumerateDirItems(*nextNode,   
            realDiskPath + wchar_t(kDirDelimiter), 
            archivePrefix + realName + wchar_t(kDirDelimiter), 
            addArchivePrefixNew, dirItems, true, callback, errorPaths, errorCodes));
      }
      for (i = 0; i < curNode.SubNodes.Size(); i++)
      {
        if (i < needEnterVector.Size())
          if (!needEnterVector[i])
            continue;
        const NWildcard::CCensorNode &nextNode = curNode.SubNodes[i];
        const UString fullPath = diskPrefix + nextNode.Name;
        NFind::CFileInfoW fileInfo;
        if (!NFind::FindFile(fullPath, fileInfo))
        {
          if (!nextNode.AreThereIncludeItems())
            continue;
          errorCodes.Add(::GetLastError());
          errorPaths.Add(fullPath);
          continue;
        }
        if (!fileInfo.IsDirectory())
        {
          errorCodes.Add((DWORD)E_FAIL);
          errorPaths.Add(fullPath);
          continue;
        }
        RINOK(EnumerateDirItems(nextNode, 
            diskPrefix + fileInfo.getFileName() + wchar_t(kDirDelimiter), 
            archivePrefix + fileInfo.getFileName() + wchar_t(kDirDelimiter), 
            UStringVector(), dirItems, false, callback, errorPaths, errorCodes));
      }
      return S_OK;
    }
  }


  NFind::CEnumeratorW enumerator(diskPrefix + wchar_t(kAnyStringWildcard));
  for (;;)
  {
    NFind::CFileInfoW fileInfo;
    bool found;
    if (!enumerator.Next(fileInfo, found))
    {
      errorCodes.Add(::GetLastError());
      errorPaths.Add(diskPrefix);
      break;
    }
    if (!found)
      break;

    if (callback)
      RINOK(callback->CheckBreak());
    const UString &name = fileInfo.getFileName();
    bool enterToSubFolders2 = enterToSubFolders;
    UStringVector addArchivePrefixNew = addArchivePrefix;
    addArchivePrefixNew.Add(name);
    {
      UStringVector addArchivePrefixNewTemp(addArchivePrefixNew);
      if (curNode.CheckPathToRoot(false, addArchivePrefixNewTemp, !fileInfo.IsDirectory()))
        continue;
    }
    if (curNode.CheckPathToRoot(true, addArchivePrefixNew, !fileInfo.IsDirectory()))
    {
      AddDirFileInfo(archivePrefix, diskPrefix + name, fileInfo, dirItems);
      if (fileInfo.IsDirectory())
        enterToSubFolders2 = true;
    }
    if (!fileInfo.IsDirectory())
      continue;

    const NWildcard::CCensorNode *nextNode = 0;
    if (addArchivePrefix.IsEmpty())
    {
      int index = curNode.FindSubNode(name);
      if (index >= 0)
        nextNode = &curNode.SubNodes[index];
    }
    if (!enterToSubFolders2 && nextNode == 0)
      continue;

    addArchivePrefixNew = addArchivePrefix;
    if (nextNode == 0)
    {
      nextNode = &curNode;
      addArchivePrefixNew.Add(name);
    }
    RINOK(EnumerateDirItems(*nextNode,   
        diskPrefix + name + wchar_t(kDirDelimiter), 
        archivePrefix + name + wchar_t(kDirDelimiter), 
        addArchivePrefixNew, dirItems, enterToSubFolders2, callback, errorPaths, errorCodes));
  }
  return S_OK;
}
void ReadArchiverInfoList(CObjectVector<CArchiverInfo> &archivers)
{
  archivers.Clear();
  
  #ifdef EXCLUDE_COM
  
  #ifdef FORMAT_7Z
  {
    CArchiverInfo item;
    item.UpdateEnabled = true;
    item.Name = L"7z";
    item.Extensions.Add(CArchiverExtInfo(L"7z"));
    #ifndef _SFX
    const unsigned char kSig[] = {'7' , 'z', 0xBC, 0xAF, 0x27, 0x1C};
    SetBuffer(item.StartSignature, kSig, 6);
    #endif
    archivers.Add(item);
  }
  #endif

  #ifdef FORMAT_BZIP2
  {
    CArchiverInfo item;
    item.UpdateEnabled = true;
    item.KeepName = true;
    item.Name = L"BZip2";
    item.Extensions.Add(CArchiverExtInfo(L"bz2"));
    item.Extensions.Add(CArchiverExtInfo(L"tbz2", L".tar"));
    #ifndef _SFX
    const unsigned char sig[] = {'B' , 'Z', 'h' };
    SetBuffer(item.StartSignature, sig, 3);
    #endif
    archivers.Add(item);
  }
  #endif

  #ifdef FORMAT_GZIP
  {
    CArchiverInfo item;
    item.UpdateEnabled = true;
    item.Name = L"GZip";
    item.Extensions.Add(CArchiverExtInfo(L"gz"));
    item.Extensions.Add(CArchiverExtInfo(L"tgz", L".tar"));
    #ifndef _SFX
    const unsigned char sig[] = { 0x1F, 0x8B };
    SetBuffer(item.StartSignature, sig, 2);
    #endif
    archivers.Add(item);
  }
  #endif

  #ifdef FORMAT_SPLIT
  {
    CArchiverInfo item;
    item.UpdateEnabled = false;
    item.KeepName = true;
    item.Name = L"Split";
    item.Extensions.Add(CArchiverExtInfo(L"001"));
    archivers.Add(item);
  }
  #endif

  #ifdef FORMAT_TAR
  {
    CArchiverInfo item;
    item.UpdateEnabled = true;
    item.Name = L"Tar";
    item.Extensions.Add(CArchiverExtInfo(L"tar"));
    archivers.Add(item);
  }
  #endif

  #ifdef FORMAT_ZIP
  {
    CArchiverInfo item;
    item.UpdateEnabled = true;
    item.Name = L"Zip";
    item.Extensions.Add(CArchiverExtInfo(L"zip"));
    #ifndef _SFX
    const unsigned char sig[] = { 0x50, 0x4B, 0x03, 0x04 };
    SetBuffer(item.StartSignature, sig, 4);
    #endif
    archivers.Add(item);
  }
  #endif

  #ifdef FORMAT_CPIO
  {
    CArchiverInfo item;
    item.Name = L"Cpio";
    item.Extensions.Add(CArchiverExtInfo(L"cpio"));
    archivers.Add(item);
  }
  #endif

  #ifdef FORMAT_RPM
  {
    CArchiverInfo item;
    item.Name = L"Rpm";
    item.Extensions.Add(CArchiverExtInfo(L"rpm", L".cpio.gz"));
    archivers.Add(item);
  }
  #endif

  #ifdef FORMAT_ARJ
  {
    CArchiverInfo item;
    item.Name = L"Arj";
    item.Extensions.Add(CArchiverExtInfo(L"arj"));
    #ifndef _SFX
    const unsigned char sig[] = { 0x60, 0xEA };
    SetBuffer(item.StartSignature, sig, 2);
    #endif
    archivers.Add(item);
  }
  #endif

  #ifdef FORMAT_Z
  {
    CArchiverInfo item;
    item.Name = L"Z";
    item.Extensions.Add(CArchiverExtInfo(L"Z"));
    #ifndef _SFX
    const unsigned char sig[] = { 0x1F, 0x9D };
    SetBuffer(item.StartSignature, sig, 2);
    #endif
    archivers.Add(item);
  }
  #endif
  
  #else

  UString folderPath = GetBaseFolderPrefixFromRegistry() + 
      (UString)kFormatFolderName + (UString)WSTRING_PATH_SEPARATOR;
  NFind::CEnumeratorW enumerator(folderPath + L"*");
  NFind::CFileInfoW fileInfo;
  while (enumerator.Next(fileInfo))
  {
    if (fileInfo.IsDirectory())
      continue;
    UString filePath = folderPath + fileInfo.Name;
    {
      NDLL::CLibrary library;
      if (!library.LoadEx(filePath, LOAD_LIBRARY_AS_DATAFILE))
        continue;
    }

    NDLL::CLibrary library;
    if (!library.Load(filePath))
      continue;
    GetHandlerPropertyFunc getHandlerProperty = (GetHandlerPropertyFunc)
        library.GetProcAddress("GetHandlerProperty");
    if (getHandlerProperty == NULL)
      continue;

    CArchiverInfo item;
    item.FilePath = filePath;
    
    NWindows::NCOM::CPropVariant prop;
    if (getHandlerProperty(NArchive::kName, &prop) != S_OK)
      continue;
    if (prop.vt != VT_BSTR)
      continue;
    item.Name = prop.bstrVal;
    prop.Clear();

    if (getHandlerProperty(NArchive::kClassID, &prop) != S_OK)
      continue;
    if (prop.vt != VT_BSTR)
      continue;
    item.ClassID = *(const GUID *)prop.bstrVal;
    prop.Clear();

    if (getHandlerProperty(NArchive::kExtension, &prop) != S_OK)
      continue;
    if (prop.vt != VT_BSTR)
      continue;

    UString ext  = prop.bstrVal;
    UString addExt;

    prop.Clear();

    if (getHandlerProperty(NArchive::kAddExtension, &prop) != S_OK)
      continue;
    if (prop.vt == VT_BSTR)
    {
      addExt = prop.bstrVal;
    }
    else if (prop.vt != VT_EMPTY)
      continue;
    prop.Clear();

    UStringVector exts, addExts;
    SplitString(ext, exts);
    SplitString(addExt, addExts);

    prop.Clear();
    for (int i = 0; i < exts.Size(); i++)
    {
      CArchiverExtInfo extInfo;
      extInfo.Ext = exts[i];
      if (addExts.Size() > 0)
        extInfo.AddExt = addExts[i];
      if (extInfo.AddExt == L"*")
        extInfo.AddExt.Empty();
      item.Extensions.Add(extInfo);
    }

    if (getHandlerProperty(NArchive::kUpdate, &prop) == S_OK)
      if (prop.vt == VT_BOOL)
        item.UpdateEnabled = VARIANT_BOOLToBool(prop.boolVal);
    prop.Clear();

    if (item.UpdateEnabled)
    {
      if (getHandlerProperty(NArchive::kKeepName, &prop) == S_OK)
        if (prop.vt == VT_BOOL)
          item.KeepName = VARIANT_BOOLToBool(prop.boolVal);
      prop.Clear();
    }

    if (getHandlerProperty(NArchive::kStartSignature, &prop) == S_OK)
    {
      if (prop.vt == VT_BSTR)
      {
        UINT len = ::SysStringByteLen(prop.bstrVal);
        item.StartSignature.SetCapacity(len);
        memmove(item.StartSignature, prop.bstrVal, len);
      }
    }
    prop.Clear();

    if (getHandlerProperty(NArchive::kAssociate, &prop) == S_OK)
      if (prop.vt == VT_BOOL)
        item.Associate = VARIANT_BOOLToBool(prop.boolVal);
    prop.Clear();


    archivers.Add(item);
  }

  #endif
}
Exemple #7
0
static HRESULT ShowDialog(
    CCodecs *codecs,
    const NWildcard::CCensor &censor,
    CUpdateOptions &options, CUpdateCallbackGUI *callback)
{
  if (options.Commands.Size() != 1)
    throw "It must be one command";
  UString currentDirPrefix;
  {
    if (!NDirectory::MyGetCurrentDirectory(currentDirPrefix))
      return E_FAIL;
    NName::NormalizeDirPathPrefix(currentDirPrefix);
  }

  bool oneFile = false;
  NFind::CFileInfoW fileInfo;
  if (censor.Pairs.Size() > 0)
  {
    const NWildcard::CPair &pair = censor.Pairs[0];
    if (pair.Head.IncludeItems.Size() > 0)
    {
      const NWildcard::CItem &item = pair.Head.IncludeItems[0];
      if (item.ForFile)
      {
        UString name = pair.Prefix;
        for (int i = 0; i < item.PathParts.Size(); i++)
        {
          if (i > 0)
            name += L'\\';
          name += item.PathParts[i];
        }
        if (NFind::FindFile(name, fileInfo))
        {
          if (censor.Pairs.Size() == 1 && pair.Head.IncludeItems.Size() == 1)
            oneFile = !fileInfo.IsDirectory();
        }
      }
    }
  }
    
  CCompressDialog dialog;
  NCompressDialog::CInfo &di = dialog.Info;
  for(int i = 0; i < codecs->Formats.Size(); i++)
  {
    const CArcInfoEx &ai = codecs->Formats[i];
    if (ai.UpdateEnabled && (oneFile || !ai.KeepName))
      dialog.m_ArchiverInfoList.Add(ai);
  }
  if(dialog.m_ArchiverInfoList.Size() == 0)
  {
    MyMessageBox(L"No Update Engines");
    return E_FAIL;
  }

  // di.ArchiveName = options.ArchivePath.GetFinalPath();
  di.ArchiveName = options.ArchivePath.GetPathWithoutExt();
  dialog.OriginalFileName = fileInfo.Name;
    
  di.CurrentDirPrefix = currentDirPrefix;
  di.SFXMode = options.SfxMode;
  di.OpenShareForWrite = options.OpenShareForWrite;
  
  if (callback->PasswordIsDefined)
    di.Password = callback->Password;
    
  di.KeepName = !oneFile;
    
  if(dialog.Create(0) != IDOK)
    return E_ABORT;
    
  options.VolumesSizes = di.VolumeSizes;
  /*
  if (di.VolumeSizeIsDefined)
  {
    MyMessageBox(L"Splitting to volumes is not supported");
    return E_FAIL;
  }
  */
  
  NUpdateArchive::CActionSet &actionSet = options.Commands.Front().ActionSet;
  
  switch(di.UpdateMode)
  {
    case NCompressDialog::NUpdateMode::kAdd:
      actionSet = NUpdateArchive::kAddActionSet;
      break;
    case NCompressDialog::NUpdateMode::kUpdate:
      actionSet = NUpdateArchive::kUpdateActionSet;
      break;
    case NCompressDialog::NUpdateMode::kFresh:
      actionSet = NUpdateArchive::kFreshActionSet;
      break;
    case NCompressDialog::NUpdateMode::kSynchronize:
      actionSet = NUpdateArchive::kSynchronizeActionSet;
      break;
    default:
      throw 1091756;
  }
  const CArcInfoEx &archiverInfo = dialog.m_ArchiverInfoList[di.ArchiverInfoIndex];
  callback->PasswordIsDefined = (!di.Password.IsEmpty());
  if (callback->PasswordIsDefined)
    callback->Password = di.Password;

  options.MethodMode.Properties.Clear();

  bool is7z = archiverInfo.Name.CompareNoCase(L"7z") == 0;
  bool methodOverride = IsThereMethodOverride(is7z, di.Options);

  SetOutProperties(
      options.MethodMode.Properties,
      is7z,
      di.Level, 
      !methodOverride,
      di.Method, 
      di.Dictionary, 
      di.OrderMode, di.Order,
      di.SolidIsSpecified, di.SolidBlockSize, 
      di.MultiThreadIsAllowed, di.NumThreads, 
      di.EncryptionMethod,
      di.EncryptHeadersIsAllowed, di.EncryptHeaders,
      di.SFXMode);
  
  options.OpenShareForWrite = di.OpenShareForWrite;
  ParseAndAddPropertires(options.MethodMode.Properties, di.Options);

  if (di.SFXMode)
    options.SfxMode = true;
  options.MethodMode.FormatIndex = archiverInfo.FormatIndex;

  options.ArchivePath.VolExtension = archiverInfo.GetMainExt();
  if(di.SFXMode)
    options.ArchivePath.BaseExtension = kSFXExtension;
  else
    options.ArchivePath.BaseExtension = options.ArchivePath.VolExtension;
  options.ArchivePath.ParseFromPath(di.ArchiveName);

  NWorkDir::CInfo workDirInfo;
  ReadWorkDirInfo(workDirInfo);
  options.WorkingDir.Empty();
  if (workDirInfo.Mode != NWorkDir::NMode::kCurrent)
  {
    UString fullPath;
    NDirectory::MyGetFullPathName(di.ArchiveName, fullPath);
    options.WorkingDir = GetWorkDir(workDirInfo, fullPath);
    NFile::NDirectory::CreateComplexDirectory(options.WorkingDir);
  }
  return S_OK;
}