HRESULT SetProperties(IUnknown *unknown, const CObjectVector<CProperty> &properties)
{
  if (properties.IsEmpty())
    return S_OK;
  CMyComPtr<ISetProperties> setProperties;
  unknown->QueryInterface(IID_ISetProperties, (void **)&setProperties);
  if (!setProperties)
    return S_OK;

  UStringVector realNames;
  CPropVariant *values = new CPropVariant[properties.Size()];
  try
  {
    int i;
    for(i = 0; i < properties.Size(); i++)
    {
      const CProperty &property = properties[i];
      NCOM::CPropVariant propVariant;
      UString name = property.Name;
      if (property.Value.IsEmpty())
      {
        if (!name.IsEmpty())
        {
          wchar_t c = name.Back();
          if (c == L'-')
            propVariant = false;
          else if (c == L'+')
            propVariant = true;
          if (propVariant.vt != VT_EMPTY)
            name.DeleteBack();
        }
      }
      else
        ParseNumberString(property.Value, propVariant);
      realNames.Add(name);
      values[i] = propVariant;
    }
    CRecordVector<const wchar_t *> names;
    for(i = 0; i < realNames.Size(); i++)
      names.Add((const wchar_t *)realNames[i]);
    
    RINOK(setProperties->SetProperties(&names.Front(), values, names.Size()));
  }
  catch(...)
  {
    delete []values;
    throw;
  }
  delete []values;
  return S_OK;
}
Beispiel #2
0
HRESULT CFieldPrinter::PrintSummaryInfo(UInt64 numFiles, UInt64 numDirs,
    const UInt64 *size, const UInt64 *compressedSize)
{
  for (int i = 0; i < _fields.Size(); i++)
  {
    const CFieldInfo &fieldInfo = _fields[i];
    PrintSpaces(fieldInfo.PrefixSpacesWidth);
    NCOM::CPropVariant prop;
    if (fieldInfo.PropID == kpidSize)
      PrintNumberString(fieldInfo.TextAdjustment, fieldInfo.Width, size);
    else if (fieldInfo.PropID == kpidPackSize)
      PrintNumberString(fieldInfo.TextAdjustment, fieldInfo.Width, compressedSize);
    else if (fieldInfo.PropID == kpidPath)
    {
      wchar_t textString[32];
      ConvertUInt64ToString(numFiles, textString);
      UString temp = textString;
      temp += L" ";
      temp += kFilesMessage;
      temp += L", ";
      ConvertUInt64ToString(numDirs, textString);
      temp += textString;
      temp += L" ";
      temp += kDirsMessage;
      PrintString(fieldInfo.TextAdjustment, 0, temp);
    }
    else
      PrintString(fieldInfo.TextAdjustment, fieldInfo.Width, L"");
  }
  return S_OK;
}
Beispiel #3
0
bool CLangPage::OnInit()
{
  LangSetDlgItemsText(HWND(*this), kIDLangPairs, sizeof(kIDLangPairs) / sizeof(kIDLangPairs[0]));

  _langCombo.Attach(GetItem(IDC_LANG_COMBO_LANG));

  UString s = NWindows::MyLoadStringW(IDS_LANG_ENGLISH) +
      NativeLangString(NWindows::MyLoadStringW(IDS_LANG_NATIVE));
  int index = (int)_langCombo.AddString(s);
  _langCombo.SetItemData(index, _paths.Size());
  _paths.Add(L"-");
  _langCombo.SetCurSel(0);

  CObjectVector<CLangEx> langs;
  LoadLangs(langs);
  for (int i = 0; i < langs.Size(); i++)
  {
    const CLangEx &lang = langs[i];
    UString name, nationalName;
    if (!lang.Lang.GetMessage(0, name))
      name = lang.ShortName;
    if (lang.Lang.GetMessage(1, nationalName) && !nationalName.IsEmpty())
      name += NativeLangString(nationalName);

    index = (int)_langCombo.AddString(name);
    _langCombo.SetItemData(index, _paths.Size());
    _paths.Add(lang.ShortName);
    if (g_LangID.CompareNoCase(lang.ShortName) == 0)
      _langCombo.SetCurSel(index);
  }
  return CPropertyPage::OnInit();
}
static void SplitFilesToGroups(
    const CCompressionMethodMode &method, 
    bool useFilters, bool maxFilter,
    const CObjectVector<CUpdateItem> &updateItems,
    CObjectVector<CSolidGroup> &groups)
{
  if (method.Methods.Size() != 1 || method.Binds.Size() != 0)
    useFilters = false;
  groups.Clear();
  groups.Add(CSolidGroup());
  groups.Add(CSolidGroup());
  CSolidGroup &generalGroup = groups[0];
  CSolidGroup &exeGroup = groups[1];
  generalGroup.Method = method;
  int i;
  for (i = 0; i < updateItems.Size(); i++)
  {
    const CUpdateItem &updateItem = updateItems[i];
    if (!updateItem.NewData)
      continue;
    if (!updateItem.HasStream())
      continue;
    if (useFilters)
    {
      const UString name = updateItem.Name;
      int dotPos = name.ReverseFind(L'.');
      if (dotPos >= 0)
      {
        UString ext = name.Mid(dotPos + 1);
        if (IsExeFile(ext))
        {
          exeGroup.Indices.Add(i);
          continue;
        }
      }
    }
    generalGroup.Indices.Add(i);
  }
  if (exeGroup.Indices.Size() > 0)
    if (!MakeExeMethod(method, maxFilter, exeGroup.Method))
      exeGroup.Method = method;
  for (i = 0; i < groups.Size();)
    if (groups[i].Indices.Size() == 0)
      groups.Delete(i);
    else
      i++;
}
Beispiel #5
0
void CExtDatabase::Read()
{
  CObjectVector<CExtInfo> extItems;
  ReadInternalAssociations(extItems);
  ReadFileFolderPluginInfoList(Plugins);
  for (int i = 0; i < extItems.Size(); i++)
  {
    const CExtInfo &extInfo = extItems[i];
    CExtInfoBig extInfoBig;
    extInfoBig.Ext = extInfo.Ext;
    extInfoBig.Associated = false;
    for (int p = 0; p < extInfo.Plugins.Size(); p++)
    {
      int pluginIndex = FindPlugin(extInfo.Plugins[p]);
      if (pluginIndex >= 0)
        extInfoBig.PluginsPairs.Add(CPluginEnabledPair(pluginIndex, true));
    }
    ExtBigItems.Add(extInfoBig);
  }
  for (int pluginIndex = 0; pluginIndex < Plugins.Size(); pluginIndex++)
  {
    const CPluginInfo &pluginInfo = Plugins[pluginIndex];

    CPluginLibrary pluginLibrary;
    CMyComPtr<IFolderManager> folderManager;

    if (pluginInfo.FilePath.IsEmpty())
      folderManager = new CArchiveFolderManager;
    else if (pluginLibrary.LoadAndCreateManager(pluginInfo.FilePath,
         pluginInfo.ClassID, &folderManager) != S_OK)
      continue;
    CMyComBSTR extBSTR;
    if (folderManager->GetExtensions(&extBSTR) != S_OK)
      return;
    const UString ext2 = (const wchar_t *)extBSTR;
    UStringVector exts;
    SplitString(ext2, exts);
    for (int i = 0; i < exts.Size(); i++)
    {
      const UString &ext = exts[i];
      int index = FindExtInfoBig(ext);
      if (index < 0)
      {
        CExtInfoBig extInfo;
        extInfo.PluginsPairs.Add(CPluginEnabledPair(pluginIndex, false));
        extInfo.Associated = false;
        extInfo.Ext = ext;
        ExtBigItems.Add(extInfo);
      }
      else
      {
        CExtInfoBig &extInfo = ExtBigItems[index];
        int pluginIndexIndex = extInfo.FindPlugin(pluginIndex);
        if (pluginIndexIndex < 0)
          extInfo.PluginsPairs.Add(CPluginEnabledPair(pluginIndex, false));
      }
    }
  }
}
Beispiel #6
0
static int FindPlugin(const CObjectVector<CPluginInfo> &plugins,
    const UString &pluginName)
{
  for (int i = 0; i < plugins.Size(); i++)
    if (plugins[i].Name.CompareNoCase(pluginName) == 0)
      return i;
  return -1;
}
Beispiel #7
0
void COutArchive::WriteCentralDir(const CObjectVector<CItem> &items, const CByteBuffer *comment)
{
  SeekTo(m_BasePosition);
  
  UInt64 cdOffset = GetCurrentPosition();
  for(int i = 0; i < items.Size(); i++)
    WriteCentralHeader(items[i]);
  UInt64 cd64EndOffset = GetCurrentPosition();
  UInt64 cdSize = cd64EndOffset - cdOffset;
  bool cdOffset64 = cdOffset >= 0xFFFFFFFF;
  bool cdSize64 = cdSize >= 0xFFFFFFFF;
  bool items64 = items.Size() >= 0xFFFF;
  bool isZip64 = (cdOffset64 || cdSize64 || items64);

  if (isZip64)
  {
    WriteUInt32(NSignature::kZip64EndOfCentralDir);
    WriteUInt64(kZip64EcdSize); // ThisDiskNumber = 0;
    WriteUInt16(45); // version
    WriteUInt16(45); // version
    WriteUInt32(0); // ThisDiskNumber = 0;
    WriteUInt32(0); // StartCentralDirectoryDiskNumber;;
    WriteUInt64((UInt64)items.Size());
    WriteUInt64((UInt64)items.Size());
    WriteUInt64((UInt64)cdSize);
    WriteUInt64((UInt64)cdOffset);

    WriteUInt32(NSignature::kZip64EndOfCentralDirLocator);
    WriteUInt32(0); // number of the disk with the start of the zip64 end of central directory
    WriteUInt64(cd64EndOffset);
    WriteUInt32(1); // total number of disks
  }
  WriteUInt32(NSignature::kEndOfCentralDir);
  WriteUInt16(0); // ThisDiskNumber = 0;
  WriteUInt16(0); // StartCentralDirectoryDiskNumber;
  WriteUInt16((UInt16)(items64 ? 0xFFFF: items.Size()));
  WriteUInt16((UInt16)(items64 ? 0xFFFF: items.Size()));
  WriteUInt32(cdSize64 ? 0xFFFFFFFF: (UInt32)cdSize);
  WriteUInt32(cdOffset64 ? 0xFFFFFFFF: (UInt32)cdOffset);
  UInt32 commentSize = (UInt32)(comment ? comment->GetCapacity() : 0);
  WriteUInt16((UInt16)commentSize);
  if (commentSize > 0)
    WriteBytes((const Byte *)*comment, commentSize);
  m_OutBuffer.FlushWithCheck();
}
static void ConvertToLongNames(const UString &prefix, CObjectVector<NWildcard::CItem> &items)
{
  for (int i = 0; i < items.Size(); i++)
  {
    NWildcard::CItem &item = items[i];
    if (item.Recursive || item.PathParts.Size() != 1)
      continue;
    ConvertToLongName(prefix, item.PathParts.Front());
  }
}
Beispiel #9
0
void CFieldPrinter::PrintTitle()
{
  for (int i = 0; i < _fields.Size(); i++)
  {
    const CFieldInfo &fieldInfo = _fields[i];
    PrintSpaces(fieldInfo.PrefixSpacesWidth);
    PrintString(fieldInfo.TitleAdjustment,
      ((fieldInfo.PropID == kpidPath) ? 0: fieldInfo.Width), fieldInfo.Name);
  }
}
Beispiel #10
0
void CFieldPrinter::PrintTitleLines()
{
  for (int i = 0; i < _fields.Size(); i++)
  {
    const CFieldInfo &fieldInfo = _fields[i];
    PrintSpaces(fieldInfo.PrefixSpacesWidth);
    for (int i = 0; i < fieldInfo.Width; i++)
      g_StdOut << '-';
  }
}
Beispiel #11
0
void UpdateProduce(
    const CObjectVector<CDirItem> &dirItems, 
    const CObjectVector<CArchiveItem> &archiveItems, 
    const CObjectVector<CUpdatePair> &updatePairs,
    const NUpdateArchive::CActionSet &actionSet,
    CObjectVector<CUpdatePair2> &operationChain)
{
  for(int i = 0; i < updatePairs.Size(); i++)
  {
    // CUpdateArchiveRange aRange;
    const CUpdatePair &pair = updatePairs[i];

    CUpdatePair2 pair2;
    pair2.IsAnti = false;
    pair2.ArchiveItemIndex = pair.ArchiveItemIndex;
    pair2.DirItemIndex = pair.DirItemIndex;
    pair2.ExistInArchive = (pair.State != NPairState::kOnlyOnDisk);
    pair2.ExistOnDisk = (pair.State != NPairState::kOnlyInArchive);
    switch(actionSet.StateActions[pair.State])
    {
      case NPairAction::kIgnore:
        /*
        if (pair.State != NPairState::kOnlyOnDisk)
          IgnoreArchiveItem(m_ArchiveItems[pair.ArchiveItemIndex]);
        // cout << "deleting";
        */
        break;
      case NPairAction::kCopy:
        {
          if (pair.State == NPairState::kOnlyOnDisk)
            throw kUpdateActionSetCollision;
          pair2.NewData = pair2.NewProperties = false;
          operationChain.Add(pair2);
          break;
        }
      case NPairAction::kCompress:
        {
          if (pair.State == NPairState::kOnlyInArchive || 
            pair.State == NPairState::kNotMasked)
            throw kUpdateActionSetCollision;
          pair2.NewData = pair2.NewProperties = true;
          operationChain.Add(pair2);
          break;
        }
      case NPairAction::kCompressAsAnti:
        {
          pair2.IsAnti = true;
          pair2.NewData = pair2.NewProperties = true;
          operationChain.Add(pair2);
          break;
        }
    }
  }
}
Beispiel #12
0
bool GetMethodInfo(const UString &name, CMethodInfo2 &methodInfo)
{
  for(int i = 0; i < g_Methods.Size(); i++)
  {
    const CMethodInfo2 &method = g_Methods[i];
    if (method.Name.CompareNoCase(name) == 0)
    {
      methodInfo = method;
      return true;
    }
  }
  return false;
}
Beispiel #13
0
bool GetMethodInfo(const CMethodID &methodID, CMethodInfo &methodInfo)
{
  for(int i = 0; i < g_Methods.Size(); i++)
  {
    const CMethodInfo2 &method = g_Methods[i];
    if (method.MethodID == methodID)
    {
      methodInfo = (CMethodInfo)method;
      return true;
    }
  }
  return false;
}
Beispiel #14
0
HRESULT CInArchive::TryReadCd(CObjectVector<CItemEx> &items, UInt64 cdOffset, UInt64 cdSize, CProgressVirt *progress)
{
  items.Clear();
  RINOK(Stream->Seek(cdOffset, STREAM_SEEK_SET, &m_Position));
  if (m_Position != cdOffset)
    return S_FALSE;

  _inBuffer.Init();
  _inBufMode = true;

  while (m_Position - cdOffset < cdSize)
  {
    if (ReadUInt32() != NSignature::kCentralFileHeader)
      return S_FALSE;
    CItemEx cdItem;
    RINOK(ReadCdItem(cdItem));
    items.Add(cdItem);
    if (progress && items.Size() % 1 == 0)
      RINOK(progress->SetCompletedCD(items.Size()));
  }
  return (m_Position - cdOffset == cdSize) ? S_OK : S_FALSE;
}
Beispiel #15
0
HRESULT CInArchive::ReadLocals(
    CObjectVector<CItemEx> &items, CProgressVirt *progress)
{
  items.Clear();
  while (m_Signature == NSignature::kLocalFileHeader)
  {
    CItemEx item;
    item.LocalHeaderPos = m_Position - 4 - ArcInfo.MarkerPos;
    // we write ralative LocalHeaderPos here. Later we can correct it to real Base.
    try
    {
      ReadLocalItem(item);
      item.FromLocal = true;
      if (item.HasDescriptor())
        ReadLocalItemDescriptor(item);
      else
      {
        RINOK(IncreaseRealPosition(item.PackSize));
      }
      items.Add(item);
      m_Signature = ReadUInt32();
    }
    catch (CUnexpectEnd &)
    {
      if (items.IsEmpty() || items.Size() == 1 && IsStrangeItem(items[0]))
        return S_FALSE;
      throw;
    }
    if (progress && items.Size() % 1 == 0)
      RINOK(progress->SetCompletedLocal(items.Size(), item.LocalHeaderPos));
  }

  if (items.Size() == 1 && m_Signature != NSignature::kCentralFileHeader)
    if (IsStrangeItem(items[0]))
      return S_FALSE;
  return S_OK;
}
Beispiel #16
0
static int FindInSorted_Ext(const CObjectVector<CExtIconPair> &vect, const wchar_t *ext, int &insertPos)
{
    unsigned left = 0, right = vect.Size();
    while (left != right)
    {
        unsigned mid = (left + right) / 2;
        int compare = MyStringCompareNoCase(ext, vect[mid].Ext);
        if (compare == 0)
            return mid;
        if (compare < 0)
            right = mid;
        else
            left = mid + 1;
    }
    insertPos = left;
    return -1;
}
Beispiel #17
0
static HRESULT FindItem(const CObjectVector<CItemEx> &items, UInt64 offset)
{
  unsigned left = 0, right = items.Size();
  for (;;)
  {
    if (left >= right)
      return -1;
    unsigned index = (left + right) / 2;
    UInt64 position = items[index].LocalHeaderPos;
    if (offset == position)
      return index;
    if (offset < position)
      right = index;
    else
      left = index + 1;
  }
}
Beispiel #18
0
void WriteInternalAssociations(const CObjectVector<CExtInfo> &items)
{
  NSynchronization::CCriticalSectionLock lock(g_CriticalSection);
  CKey mainKey;
  mainKey.Create(HKEY_CURRENT_USER, kCUKeyPath);
  mainKey.RecurseDeleteKey(kAssociations);
  CKey associationsKey;
  associationsKey.Create(mainKey, kAssociations);
  for(int i = 0; i < items.Size(); i++)
  {
    const CExtInfo &extInfo = items[i];
    CKey key;
    key.Create(associationsKey, GetSystemString(extInfo.Ext));
    key.SetValue(kExtPlugins, JoinStrings(extInfo.Plugins));
    // key.SetValue(kExtEnabled, extInfo.Enabled);
  }
}
Beispiel #19
0
void ReadFileFolderPluginInfoList(CObjectVector<CPluginInfo> &plugins)
{
  ReadPluginInfoList(plugins);
  for (int i = 0; i < plugins.Size();)
    if (plugins[i].Type != kPluginTypeFF)
      plugins.Delete(i);
    else
      i++;
  {
    CPluginInfo p;
    // p.FilePath.Empty();
    p.Type = kPluginTypeFF;
    p.Name = L"7-Zip";
    // p.ClassID = CLSID_CAgentArchiveHandler;
    p.ClassIDDefined = true;
    // p.OptionsClassID;
    p.OptionsClassIDDefined = false;
    plugins.Add(p);
  }
}
HRESULT CHashBundle::SetMethods(DECL_EXTERNAL_CODECS_LOC_VARS const UStringVector &hashMethods)
{
  UStringVector names = hashMethods;
  if (names.IsEmpty())
  {
    UString s;
    s.SetFromAscii(k_DefaultHashMethod);
    names.Add(s);
  }

  CRecordVector<CMethodId> ids;
  CObjectVector<COneMethodInfo> methods;
  
  unsigned i;
  for (i = 0; i < names.Size(); i++)
  {
    COneMethodInfo m;
    RINOK(m.ParseMethodFromString(names[i]));

    if (m.MethodName.IsEmpty())
      m.MethodName = k_DefaultHashMethod;
    
    if (m.MethodName == "*")
    {
      CRecordVector<CMethodId> tempMethods;
      GetHashMethods(EXTERNAL_CODECS_LOC_VARS tempMethods);
      methods.Clear();
      ids.Clear();
      FOR_VECTOR (t, tempMethods)
      {
        unsigned index = ids.AddToUniqueSorted(tempMethods[t]);
        if (ids.Size() != methods.Size())
          methods.Insert(index, m);
      }
      break;
    }
Beispiel #21
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;
}
Beispiel #22
0
HRESULT OpenFileFolderPlugin(
    const UString &path,
    HMODULE *module,
    IFolderFolder **resultFolder,
    HWND parentWindow,
    bool &encrypted, UString &password)
{
  CObjectVector<CPluginInfo> plugins;
  ReadFileFolderPluginInfoList(plugins);

  UString extension;
  UString name, pureName, dot;

  if(!NFile::NDirectory::GetOnlyName(path, name))
    return E_FAIL;
  NFile::NName::SplitNameToPureNameAndExtension(name, pureName, dot, extension);


  int slashPos = path.ReverseFind(WCHAR_PATH_SEPARATOR);
  UString dirPrefix;
  UString fileName;
  if (slashPos >= 0)
  {
    dirPrefix = path.Left(slashPos + 1);
    fileName = path.Mid(slashPos + 1);
  }
  else
    fileName = path;

  if (!extension.IsEmpty())
  {
    CExtInfo extInfo;
    if (ReadInternalAssociation(extension, extInfo))
    {
      for (int i = extInfo.Plugins.Size() - 1; i >= 0; i--)
      {
        int pluginIndex = FindPlugin(plugins, extInfo.Plugins[i]);
        if (pluginIndex >= 0)
        {
          const CPluginInfo plugin = plugins[pluginIndex];
          plugins.Delete(pluginIndex);
          plugins.Insert(0, plugin);
        }
      }
    }
  }

  for (int i = 0; i < plugins.Size(); i++)
  {
    const CPluginInfo &plugin = plugins[i];
    if (!plugin.ClassIDDefined)
      continue;
    CPluginLibrary library;

    CThreadArchiveOpen t;

    if (plugin.FilePath.IsEmpty())
      t.FolderManager = new CArchiveFolderManager;
    else if (library.LoadAndCreateManager(plugin.FilePath, plugin.ClassID, &t.FolderManager) != S_OK)
      continue;

    t.OpenCallbackSpec = new COpenArchiveCallback;
    t.OpenCallback = t.OpenCallbackSpec;
    t.OpenCallbackSpec->PasswordIsDefined = encrypted;
    t.OpenCallbackSpec->Password = password;
    t.OpenCallbackSpec->ParentWindow = parentWindow;
    t.OpenCallbackSpec->LoadFileInfo(dirPrefix, fileName);

    t.Path = path;

    UString progressTitle = LangString(IDS_OPENNING, 0x03020283);
    t.OpenCallbackSpec->ProgressDialog.MainWindow = parentWindow;
    t.OpenCallbackSpec->ProgressDialog.MainTitle = LangString(IDS_APP_TITLE, 0x03000000);
    t.OpenCallbackSpec->ProgressDialog.MainAddTitle = progressTitle + UString(L" ");

    NWindows::CThread thread;
    if (thread.Create(CThreadArchiveOpen::MyThreadFunction, &t) != S_OK)
      throw 271824;
    t.OpenCallbackSpec->StartProgressDialog(progressTitle);

    if (t.Result == E_ABORT)
      return t.Result;

    if (t.Result == S_OK)
    {
      // if (openCallbackSpec->PasswordWasAsked)
      {
        encrypted = t.OpenCallbackSpec->PasswordIsDefined;
        password = t.OpenCallbackSpec->Password;
      }
      *module = library.Detach();
      *resultFolder = t.Folder.Detach();
      return S_OK;
    }
    
    if (t.Result != S_FALSE)
      return t.Result;
  }
  return S_FALSE;
}
Beispiel #23
0
HRESULT CInArchive::ReadAndDecodePackedStreams(
    DECL_EXTERNAL_CODECS_LOC_VARS
    UInt64 baseOffset,
    UInt64 &dataOffset, CObjectVector<CByteBuffer> &dataVector
    #ifndef _NO_CRYPTO
    , ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined
    #endif
    )
{
  CRecordVector<UInt64> packSizes;
  CBoolVector packCRCsDefined;
  CRecordVector<UInt32> packCRCs;
  CObjectVector<CFolder> folders;
  
  CRecordVector<CNum> numUnpackStreamsInFolders;
  CRecordVector<UInt64> unpackSizes;
  CBoolVector digestsDefined;
  CRecordVector<UInt32> digests;
  
  ReadStreamsInfo(NULL,
    dataOffset,
    packSizes,
    packCRCsDefined,
    packCRCs,
    folders,
    numUnpackStreamsInFolders,
    unpackSizes,
    digestsDefined,
    digests);
  
  // db.ArchiveInfo.DataStartPosition2 += db.ArchiveInfo.StartPositionAfterHeader;
  
  CNum packIndex = 0;
  CDecoder decoder(
    #ifdef _ST_MODE
    false
    #else
    true
    #endif
    );
  UInt64 dataStartPos = baseOffset + dataOffset;
  for (int i = 0; i < folders.Size(); i++)
  {
    const CFolder &folder = folders[i];
    dataVector.Add(CByteBuffer());
    CByteBuffer &data = dataVector.Back();
    UInt64 unpackSize64 = folder.GetUnpackSize();
    size_t unpackSize = (size_t)unpackSize64;
    if (unpackSize != unpackSize64)
      ThrowUnsupported();
    data.SetCapacity(unpackSize);
    
    CBufPtrSeqOutStream *outStreamSpec = new CBufPtrSeqOutStream;
    CMyComPtr<ISequentialOutStream> outStream = outStreamSpec;
    outStreamSpec->Init(data, unpackSize);
    
    HRESULT result = decoder.Decode(
      EXTERNAL_CODECS_LOC_VARS
      _stream, dataStartPos,
      &packSizes[packIndex], folder, outStream, NULL
      #ifndef _NO_CRYPTO
      , getTextPassword, passwordIsDefined
      #endif
      #if !defined(_7ZIP_ST) && !defined(_SFX)
      , false, 1
      #endif
      );
    RINOK(result);
    
    if (folder.UnpackCRCDefined)
      if (CrcCalc(data, unpackSize) != folder.UnpackCRC)
        ThrowIncorrect();
    for (int j = 0; j < folder.PackStreams.Size(); j++)
    {
      UInt64 packSize = packSizes[packIndex++];
      dataStartPos += packSize;
      HeadersSize += packSize;
    }
  }
  return S_OK;
}
HRESULT UpdateVolume(
    IInStream *inStream,
    const CArchiveDatabaseEx *database,
    CObjectVector<CUpdateItem> &updateItems,
    ISequentialOutStream *seqOutStream,
    IArchiveUpdateCallback *updateCallback,
    const CUpdateOptions &options)
{
  if (updateItems.Size() != 1)
    return E_NOTIMPL;

  CMyComPtr<IArchiveUpdateCallback2> volumeCallback;
  RINOK(updateCallback->QueryInterface(IID_IArchiveUpdateCallback2, (void **)&volumeCallback));
  if (!volumeCallback)
    return E_NOTIMPL;

  CMyComPtr<ISequentialInStream> fileStream;
  HRESULT result = updateCallback->GetStream(0, &fileStream);
  if (result != S_OK && result != S_FALSE)
    return result;
  if (result == S_FALSE)
    return E_FAIL;
  
  CFileItem file;
  
  const CUpdateItem &updateItem = updateItems[0];
  if (updateItem.NewProperties)
    FromUpdateItemToFileItem(updateItem, file);
  else
    file = database->Files[updateItem.IndexInArchive];
  if (file.IsAnti || file.IsDirectory)
    return E_FAIL;

  UInt64 complexity = 0;
  file.IsStartPosDefined = true;
  file.StartPos = 0;
  for (UInt64 volumeIndex = 0; true; volumeIndex++)
  { 
    UInt64 volSize;
    RINOK(volumeCallback->GetVolumeSize(volumeIndex, &volSize));
    UInt64 pureSize = COutArchive::GetVolPureSize(volSize, file.Name.Length(), true);
    CMyComPtr<ISequentialOutStream> volumeStream;
    RINOK(volumeCallback->GetVolumeStream(volumeIndex, &volumeStream));
   
    COutArchive archive;
    RINOK(archive.Create(volumeStream, true));
    RINOK(archive.SkeepPrefixArchiveHeader());
        
    CSequentialInStreamWithCRC *inCrcStreamSpec = new CSequentialInStreamWithCRC;
    CMyComPtr<ISequentialInStream> inCrcStream = inCrcStreamSpec;
    inCrcStreamSpec->Init(fileStream);

    RINOK(WriteRange(inCrcStream, volumeStream, pureSize, updateCallback, complexity));
    file.UnPackSize = inCrcStreamSpec->GetSize();
    if (file.UnPackSize == 0)
      break;
    file.FileCRC = inCrcStreamSpec->GetCRC();
    RINOK(WriteVolumeHeader(archive, file, options));
    file.StartPos += file.UnPackSize;
    if (file.UnPackSize < pureSize)
      break;
  }
  return S_OK;
}
Beispiel #25
0
HRESULT CInArchive::ReadDatabase2(
    DECL_EXTERNAL_CODECS_LOC_VARS
    CArchiveDatabaseEx &db
    #ifndef _NO_CRYPTO
    , ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined
    #endif
    )
{
  db.Clear();
  db.ArchiveInfo.StartPosition = _arhiveBeginStreamPosition;

  db.ArchiveInfo.Version.Major = _header[6];
  db.ArchiveInfo.Version.Minor = _header[7];

  if (db.ArchiveInfo.Version.Major != kMajorVersion)
    ThrowUnsupportedVersion();

  UInt32 crcFromArchive = Get32(_header + 8);
  UInt64 nextHeaderOffset = Get64(_header + 0xC);
  UInt64 nextHeaderSize = Get64(_header + 0x14);
  UInt32 nextHeaderCRC = Get32(_header + 0x1C);
  UInt32 crc = CrcCalc(_header + 0xC, 20);

  #ifdef FORMAT_7Z_RECOVERY
  if (crcFromArchive == 0 && nextHeaderOffset == 0 && nextHeaderSize == 0 && nextHeaderCRC == 0)
  {
    UInt64 cur, cur2;
    RINOK(_stream->Seek(0, STREAM_SEEK_CUR, &cur));
    const int kCheckSize = 500;
    Byte buf[kCheckSize];
    RINOK(_stream->Seek(0, STREAM_SEEK_END, &cur2));
    int checkSize = kCheckSize;
    if (cur2 - cur < kCheckSize)
      checkSize = (int)(cur2 - cur);
    RINOK(_stream->Seek(-checkSize, STREAM_SEEK_END, &cur2));
    
    RINOK(ReadStream_FALSE(_stream, buf, (size_t)checkSize));

    int i;
    for (i = (int)checkSize - 2; i >= 0; i--)
      if (buf[i] == 0x17 && buf[i + 1] == 0x6 || buf[i] == 0x01 && buf[i + 1] == 0x04)
        break;
    if (i < 0)
      return S_FALSE;
    nextHeaderSize = checkSize - i;
    nextHeaderOffset = cur2 - cur + i;
    nextHeaderCRC = CrcCalc(buf + i, (size_t)nextHeaderSize);
    RINOK(_stream->Seek(cur, STREAM_SEEK_SET, NULL));
  }
  else
  #endif
  {
    if (crc != crcFromArchive)
      ThrowIncorrect();
  }

  db.ArchiveInfo.StartPositionAfterHeader = _arhiveBeginStreamPosition + kHeaderSize;

  if (nextHeaderSize == 0)
    return S_OK;

  if (nextHeaderSize > (UInt64)0xFFFFFFFF)
    return S_FALSE;

  if ((Int64)nextHeaderOffset < 0)
    return S_FALSE;

  RINOK(_stream->Seek(nextHeaderOffset, STREAM_SEEK_CUR, NULL));

  CByteBuffer buffer2;
  buffer2.SetCapacity((size_t)nextHeaderSize);

  RINOK(ReadStream_FALSE(_stream, buffer2, (size_t)nextHeaderSize));
  HeadersSize += kHeaderSize + nextHeaderSize;
  db.PhySize = kHeaderSize + nextHeaderOffset + nextHeaderSize;

  if (CrcCalc(buffer2, (UInt32)nextHeaderSize) != nextHeaderCRC)
    ThrowIncorrect();
  
  CStreamSwitch streamSwitch;
  streamSwitch.Set(this, buffer2);
  
  CObjectVector<CByteBuffer> dataVector;
  
  UInt64 type = ReadID();
  if (type != NID::kHeader)
  {
    if (type != NID::kEncodedHeader)
      ThrowIncorrect();
    HRESULT result = ReadAndDecodePackedStreams(
        EXTERNAL_CODECS_LOC_VARS
        db.ArchiveInfo.StartPositionAfterHeader,
        db.ArchiveInfo.DataStartPosition2,
        dataVector
        #ifndef _NO_CRYPTO
        , getTextPassword, passwordIsDefined
        #endif
        );
    RINOK(result);
    if (dataVector.Size() == 0)
      return S_OK;
    if (dataVector.Size() > 1)
      ThrowIncorrect();
    streamSwitch.Remove();
    streamSwitch.Set(this, dataVector.Front());
    if (ReadID() != NID::kHeader)
      ThrowIncorrect();
  }

  db.HeadersSize = HeadersSize;

  return ReadHeader(
    EXTERNAL_CODECS_LOC_VARS
    db
    #ifndef _NO_CRYPTO
    , getTextPassword, passwordIsDefined
    #endif
    );
}
Beispiel #26
0
static bool AddItem(const CXmlItem &item, CObjectVector<CFile> &files, int parent)
{
  if (!item.IsTag)
    return true;
  if (item.Name == "file")
  {
    CFile file;
    file.Parent = parent;
    parent = files.Size();
    file.Name = item.GetSubStringForTag("name");
    AString type = item.GetSubStringForTag("type");
    if (type == "directory")
      file.IsDir = true;
    else if (type == "file")
      file.IsDir = false;
    else
      return false;

    int dataIndex = item.FindSubTag("data");
    if (dataIndex >= 0 && !file.IsDir)
    {
      file.HasData = true;
      const CXmlItem &dataItem = item.SubItems[dataIndex];
      if (!ParseUInt64(dataItem, "size", file.Size))
        return false;
      if (!ParseUInt64(dataItem, "length", file.PackSize))
        return false;
      if (!ParseUInt64(dataItem, "offset", file.Offset))
        return false;
      file.Sha1IsDefined = ParseSha1(dataItem, "extracted-checksum", file.Sha1);
      // file.packSha1IsDefined = ParseSha1(dataItem, "archived-checksum",  file.packSha1);
      int encodingIndex = dataItem.FindSubTag("encoding");
      if (encodingIndex >= 0)
      {
        const CXmlItem &encodingItem = dataItem.SubItems[encodingIndex];
        if (encodingItem.IsTag)
        {
          AString s = encodingItem.GetPropertyValue("style");
          if (s.Length() >= 0)
          {
            AString appl = "application/";
            if (s.Left(appl.Length()) == appl)
            {
              s = s.Mid(appl.Length());
              AString xx = "x-";
              if (s.Left(xx.Length()) == xx)
              {
                s = s.Mid(xx.Length());
                if (s == "gzip")
                  s = METHOD_NAME_ZLIB;
              }
            }
            file.Method = s;
          }
        }
      }
    }

    file.CTime = ParseTime(item, "ctime");
    file.MTime = ParseTime(item, "mtime");
    file.ATime = ParseTime(item, "atime");
    files.Add(file);
  }
  for (int i = 0; i < item.SubItems.Size(); i++)
    if (!AddItem(item.SubItems[i], files, parent))
      return false;
  return true;
}
Beispiel #27
0
HRESULT CFieldPrinter::PrintItemInfo(const CArc &arc, UInt32 index, bool techMode)
{
  /*
  if (techMode)
  {
    g_StdOut << "Index = ";
    g_StdOut << (UInt64)index;
    g_StdOut << endl;
  }
  */
  for (int i = 0; i < _fields.Size(); i++)
  {
    const CFieldInfo &fieldInfo = _fields[i];
    if (!techMode)
      PrintSpaces(fieldInfo.PrefixSpacesWidth);

    NCOM::CPropVariant prop;
    if (fieldInfo.PropID == kpidPath)
    {
      UString s;
      RINOK(arc.GetItemPath(index, s));
      prop = s;
    }
    else
    {
      RINOK(arc.Archive->GetProperty(index, fieldInfo.PropID, &prop));
    }
    if (techMode)
    {
      g_StdOut << fieldInfo.Name << " = ";
    }
    int width = (fieldInfo.PropID == kpidPath) ? 0: fieldInfo.Width;
    if (fieldInfo.PropID == kpidAttrib && (prop.vt == VT_EMPTY || prop.vt == VT_UI4))
    {
      UInt32 attrib = (prop.vt == VT_EMPTY) ? 0 : prop.ulVal;
      bool isFolder;
      RINOK(IsArchiveItemFolder(arc.Archive, index, isFolder));
      char s[8];
      GetAttribString(attrib, isFolder, s);
      g_StdOut << s;
    }
    else if (prop.vt == VT_EMPTY)
    {
      if (!techMode)
        PrintSpaces(width);
    }
    else if (fieldInfo.PropID == kpidMTime)
    {
      PrintTime(prop);
    }
    else if (prop.vt == VT_BSTR)
    {
      if (techMode)
        g_StdOut << prop.bstrVal;
      else
        PrintString(fieldInfo.TextAdjustment, width, prop.bstrVal);
    }
    else
    {
      UString s = ConvertPropertyToString(prop, fieldInfo.PropID);
      s.Replace(wchar_t(0xA), L' ');
      s.Replace(wchar_t(0xD), L' ');

      if (techMode)
        g_StdOut << s;
      else
        PrintString(fieldInfo.TextAdjustment, width, s);
    }
    if (techMode)
      g_StdOut << endl;
  }
  return S_OK;
}
Beispiel #28
0
HRESULT CHandler::SetCompressionMethod(
    CCompressionMethodMode &methodMode,
    CObjectVector<COneMethodInfo> &methodsInfo
    #ifdef COMPRESS_MT
    , UInt32 numThreads
    #endif
    )
{
  UInt32 level = _level;
  
  if (methodsInfo.IsEmpty())
  {
    COneMethodInfo oneMethodInfo;
    oneMethodInfo.MethodName = ((level == 0) ? kCopyMethod : kDefaultMethodName);
    methodsInfo.Add(oneMethodInfo);
  }

  bool needSolid = false;
  for(int i = 0; i < methodsInfo.Size(); i++)
  {
    COneMethodInfo &oneMethodInfo = methodsInfo[i];
    SetCompressionMethod2(oneMethodInfo
      #ifdef COMPRESS_MT
      , numThreads
      #endif
      );

    if (!IsCopyMethod(oneMethodInfo.MethodName))
      needSolid = true;

    CMethodFull methodFull;

    if (!FindMethod(
        EXTERNAL_CODECS_VARS
        oneMethodInfo.MethodName, methodFull.Id, methodFull.NumInStreams, methodFull.NumOutStreams))
      return E_INVALIDARG;
    methodFull.Props = oneMethodInfo.Props;
    methodMode.Methods.Add(methodFull);

    if (!_numSolidBytesDefined)
    {
      for (int j = 0; j < methodFull.Props.Size(); j++)
      {
        const CProp &prop = methodFull.Props[j];
        if ((prop.Id == NCoderPropID::kDictionarySize ||
             prop.Id == NCoderPropID::kUsedMemorySize) && prop.Value.vt == VT_UI4)
        {
          _numSolidBytes = ((UInt64)prop.Value.ulVal) << 7;
          const UInt64 kMinSize = (1 << 24);
          if (_numSolidBytes < kMinSize)
            _numSolidBytes = kMinSize;
          _numSolidBytesDefined = true;
          break;
        }
      }
    }
  }

  if (!needSolid && !_numSolidBytesDefined)
  {
    _numSolidBytesDefined = true;
    _numSolidBytes  = 0;
  }
  return S_OK;
}
Beispiel #29
0
void CInArchive::ReadSubStreamsInfo(
    const CObjectVector<CFolder> &folders,
    CRecordVector<CNum> &numUnpackStreamsInFolders,
    CRecordVector<UInt64> &unpackSizes,
    CBoolVector &digestsDefined,
    CRecordVector<UInt32> &digests)
{
  numUnpackStreamsInFolders.Clear();
  numUnpackStreamsInFolders.Reserve(folders.Size());
  UInt64 type;
  for (;;)
  {
    type = ReadID();
    if (type == NID::kNumUnpackStream)
    {
      for (int i = 0; i < folders.Size(); i++)
        numUnpackStreamsInFolders.Add(ReadNum());
      continue;
    }
    if (type == NID::kCRC || type == NID::kSize)
      break;
    if (type == NID::kEnd)
      break;
    SkipData();
  }

  if (numUnpackStreamsInFolders.IsEmpty())
    for (int i = 0; i < folders.Size(); i++)
      numUnpackStreamsInFolders.Add(1);

  int i;
  for (i = 0; i < numUnpackStreamsInFolders.Size(); i++)
  {
    // v3.13 incorrectly worked with empty folders
    // v4.07: we check that folder is empty
    CNum numSubstreams = numUnpackStreamsInFolders[i];
    if (numSubstreams == 0)
      continue;
    UInt64 sum = 0;
    for (CNum j = 1; j < numSubstreams; j++)
      if (type == NID::kSize)
      {
        UInt64 size = ReadNumber();
        unpackSizes.Add(size);
        sum += size;
      }
    unpackSizes.Add(folders[i].GetUnpackSize() - sum);
  }
  if (type == NID::kSize)
    type = ReadID();

  int numDigests = 0;
  int numDigestsTotal = 0;
  for (i = 0; i < folders.Size(); i++)
  {
    CNum numSubstreams = numUnpackStreamsInFolders[i];
    if (numSubstreams != 1 || !folders[i].UnpackCRCDefined)
      numDigests += numSubstreams;
    numDigestsTotal += numSubstreams;
  }

  for (;;)
  {
    if (type == NID::kCRC)
    {
      CBoolVector digestsDefined2;
      CRecordVector<UInt32> digests2;
      ReadHashDigests(numDigests, digestsDefined2, digests2);
      int digestIndex = 0;
      for (i = 0; i < folders.Size(); i++)
      {
        CNum numSubstreams = numUnpackStreamsInFolders[i];
        const CFolder &folder = folders[i];
        if (numSubstreams == 1 && folder.UnpackCRCDefined)
        {
          digestsDefined.Add(true);
          digests.Add(folder.UnpackCRC);
        }
        else
          for (CNum j = 0; j < numSubstreams; j++, digestIndex++)
          {
            digestsDefined.Add(digestsDefined2[digestIndex]);
            digests.Add(digests2[digestIndex]);
          }
      }
    }
    else if (type == NID::kEnd)
    {
      if (digestsDefined.IsEmpty())
      {
        BoolVector_Fill_False(digestsDefined, numDigestsTotal);
        digests.Clear();
        for (int i = 0; i < numDigestsTotal; i++)
          digests.Add(0);
      }
      return;
    }
    else
      SkipData();
    type = ReadID();
  }
}
static HRESULT Update2(
    DECL_EXTERNAL_CODECS_LOC_VARS
    IInStream *inStream,
    const CArchiveDatabaseEx *database,
    const CObjectVector<CUpdateItem> &updateItems,
    ISequentialOutStream *seqOutStream,
    IArchiveUpdateCallback *updateCallback,
    const CUpdateOptions &options)
{
  UInt64 numSolidFiles = options.NumSolidFiles;
  if (numSolidFiles == 0)
    numSolidFiles = 1;
  /*
  CMyComPtr<IOutStream> outStream;
  RINOK(seqOutStream->QueryInterface(IID_IOutStream, (void **)&outStream));
  if (!outStream)
    return E_NOTIMPL;
  */

  UInt64 startBlockSize = database != 0 ? database->ArchiveInfo.StartPosition: 0;
  if (startBlockSize > 0 && !options.RemoveSfxBlock)
  {
    RINOK(WriteRange(inStream, seqOutStream, 0, startBlockSize, NULL));
  }

  CRecordVector<int> fileIndexToUpdateIndexMap;
  if (database != 0)
  {
    fileIndexToUpdateIndexMap.Reserve(database->Files.Size());
    for (int i = 0; i < database->Files.Size(); i++)
      fileIndexToUpdateIndexMap.Add(-1);
  }
  int i;
  for(i = 0; i < updateItems.Size(); i++)
  {
    int index = updateItems[i].IndexInArchive;
    if (index != -1)
      fileIndexToUpdateIndexMap[index] = i;
  }

  CRecordVector<int> folderRefs;
  if (database != 0)
  {
    for(i = 0; i < database->Folders.Size(); i++)
    {
      CNum indexInFolder = 0;
      CNum numCopyItems = 0;
      CNum numUnPackStreams = database->NumUnPackStreamsVector[i];
      for (CNum fileIndex = database->FolderStartFileIndex[i];
      indexInFolder < numUnPackStreams; fileIndex++)
      {
        if (database->Files[fileIndex].HasStream)
        {
          indexInFolder++;
          int updateIndex = fileIndexToUpdateIndexMap[fileIndex];
          if (updateIndex >= 0)
            if (!updateItems[updateIndex].NewData)
              numCopyItems++;
        }
      }
      if (numCopyItems != numUnPackStreams && numCopyItems != 0)
        return E_NOTIMPL; // It needs repacking !!!
      if (numCopyItems > 0)
        folderRefs.Add(i);
    }
    folderRefs.Sort(CompareFolderRefs, (void *)database);
  }

  CArchiveDatabase newDatabase;

  ////////////////////////////

  COutArchive archive;
  RINOK(archive.Create(seqOutStream, false));
  RINOK(archive.SkeepPrefixArchiveHeader());
  UInt64 complexity = 0;
  for(i = 0; i < folderRefs.Size(); i++)
    complexity += database->GetFolderFullPackSize(folderRefs[i]);
  UInt64 inSizeForReduce = 0;
  for(i = 0; i < updateItems.Size(); i++)
  {
    const CUpdateItem &updateItem = updateItems[i];
    if (updateItem.NewData)
    {
      complexity += updateItem.Size;
      if (numSolidFiles == 1)
      {
        if (updateItem.Size > inSizeForReduce)
          inSizeForReduce = updateItem.Size;
      }
      else
        inSizeForReduce += updateItem.Size;
    }
  }
  RINOK(updateCallback->SetTotal(complexity));
  complexity = 0;
  RINOK(updateCallback->SetCompleted(&complexity));


  CLocalProgress *lps = new CLocalProgress;
  CMyComPtr<ICompressProgressInfo> progress = lps;
  lps->Init(updateCallback, true);

  /////////////////////////////////////////
  // Write Copy Items

  for(i = 0; i < folderRefs.Size(); i++)
  {
    int folderIndex = folderRefs[i];
    
    lps->ProgressOffset = complexity;
    UInt64 packSize = database->GetFolderFullPackSize(folderIndex);
    RINOK(WriteRange(inStream, archive.SeqStream,
        database->GetFolderStreamPos(folderIndex, 0), packSize, progress));
    complexity += packSize;
    
    const CFolder &folder = database->Folders[folderIndex];
    CNum startIndex = database->FolderStartPackStreamIndex[folderIndex];
    for (int j = 0; j < folder.PackStreams.Size(); j++)
    {
      newDatabase.PackSizes.Add(database->PackSizes[startIndex + j]);
      // newDatabase.PackCRCsDefined.Add(database.PackCRCsDefined[startIndex + j]);
      // newDatabase.PackCRCs.Add(database.PackCRCs[startIndex + j]);
    }
    newDatabase.Folders.Add(folder);

    CNum numUnPackStreams = database->NumUnPackStreamsVector[folderIndex];
    newDatabase.NumUnPackStreamsVector.Add(numUnPackStreams);

    CNum indexInFolder = 0;
    for (CNum fi = database->FolderStartFileIndex[folderIndex];
        indexInFolder < numUnPackStreams; fi++)
    {
      CFileItem file = database->Files[fi];
      if (file.HasStream)
      {
        indexInFolder++;
        int updateIndex = fileIndexToUpdateIndexMap[fi];
        if (updateIndex >= 0)
        {
          const CUpdateItem &updateItem = updateItems[updateIndex];
          if (updateItem.NewProperties)
          {
            CFileItem file2;
            FromUpdateItemToFileItem(updateItem, file2);
            file2.UnPackSize = file.UnPackSize;
            file2.FileCRC = file.FileCRC;
            file2.IsFileCRCDefined = file.IsFileCRCDefined;
            file2.HasStream = file.HasStream;
            file = file2;
          }
        }
        newDatabase.Files.Add(file);
      }
    }
  }

  /////////////////////////////////////////
  // Compress New Files

  CObjectVector<CSolidGroup> groups;
  SplitFilesToGroups(*options.Method, options.UseFilters, options.MaxFilter, 
      updateItems, groups);

  const UInt32 kMinReduceSize = (1 << 16);
  if (inSizeForReduce < kMinReduceSize)
    inSizeForReduce = kMinReduceSize;

  for (int groupIndex = 0; groupIndex < groups.Size(); groupIndex++)
  {
    const CSolidGroup &group = groups[groupIndex];
    int numFiles = group.Indices.Size();
    if (numFiles == 0)
      continue;
    CRecordVector<CRefItem> refItems;
    refItems.Reserve(numFiles);
    bool sortByType = (numSolidFiles > 1);
    for (i = 0; i < numFiles; i++)
      refItems.Add(CRefItem(group.Indices[i], updateItems[group.Indices[i]], sortByType));
    refItems.Sort(CompareUpdateItems, (void *)&sortByType);
    
    CRecordVector<UInt32> indices;
    indices.Reserve(numFiles);

    for (i = 0; i < numFiles; i++)
    {
      UInt32 index = refItems[i].Index;
      indices.Add(index);
      /*
      const CUpdateItem &updateItem = updateItems[index];
      CFileItem file;
      if (updateItem.NewProperties)
        FromUpdateItemToFileItem(updateItem, file);
      else
        file = database.Files[updateItem.IndexInArchive];
      if (file.IsAnti || file.IsDirectory)
        return E_FAIL;
      newDatabase.Files.Add(file);
      */
    }
    
    CEncoder encoder(group.Method);

    for (i = 0; i < numFiles;)
    {
      UInt64 totalSize = 0;
      int numSubFiles;
      UString prevExtension;
      for (numSubFiles = 0; i + numSubFiles < numFiles && 
          numSubFiles < numSolidFiles; numSubFiles++)
      {
        const CUpdateItem &updateItem = updateItems[indices[i + numSubFiles]];
        totalSize += updateItem.Size;
        if (totalSize > options.NumSolidBytes)
          break;
        if (options.SolidExtension)
        {
          UString ext = updateItem.GetExtension();
          if (numSubFiles == 0)
            prevExtension = ext;
          else
            if (ext.CompareNoCase(prevExtension) != 0)
              break;
        }
      }
      if (numSubFiles < 1)
        numSubFiles = 1;

      CFolderInStream *inStreamSpec = new CFolderInStream;
      CMyComPtr<ISequentialInStream> solidInStream(inStreamSpec);
      inStreamSpec->Init(updateCallback, &indices[i], numSubFiles);
      
      CFolder folderItem;

      int startPackIndex = newDatabase.PackSizes.Size();
      RINOK(encoder.Encode(
          EXTERNAL_CODECS_LOC_VARS
          solidInStream, NULL, &inSizeForReduce, folderItem, 
          archive.SeqStream, newDatabase.PackSizes, progress));

      for (; startPackIndex < newDatabase.PackSizes.Size(); startPackIndex++)
        lps->OutSize += newDatabase.PackSizes[startPackIndex];

      lps->InSize += folderItem.GetUnPackSize();
      // for()
      // newDatabase.PackCRCsDefined.Add(false);
      // newDatabase.PackCRCs.Add(0);
      
      newDatabase.Folders.Add(folderItem);
      
      CNum numUnPackStreams = 0;
      for (int subIndex = 0; subIndex < numSubFiles; subIndex++)
      {
        const CUpdateItem &updateItem = updateItems[indices[i + subIndex]];
        CFileItem file;
        if (updateItem.NewProperties)
          FromUpdateItemToFileItem(updateItem, file);
        else
          file = database->Files[updateItem.IndexInArchive];
        if (file.IsAnti || file.IsDirectory)
          return E_FAIL;
        
        /*
        CFileItem &file = newDatabase.Files[
              startFileIndexInDatabase + i + subIndex];
        */
        if (!inStreamSpec->Processed[subIndex])
        {
          continue;
          // file.Name += L".locked";
        }

        file.FileCRC = inStreamSpec->CRCs[subIndex];
        file.UnPackSize = inStreamSpec->Sizes[subIndex];
        if (file.UnPackSize != 0)
        {
          file.IsFileCRCDefined = true;
          file.HasStream = true;
          numUnPackStreams++;
        }
        else
        {
          file.IsFileCRCDefined = false;
          file.HasStream = false;
        }
        newDatabase.Files.Add(file);
      }
      // numUnPackStreams = 0 is very bad case for locked files
      // v3.13 doesn't understand it.
      newDatabase.NumUnPackStreamsVector.Add(numUnPackStreams);
      i += numSubFiles;
    }
  }

  {
    /////////////////////////////////////////
    // Write Empty Files & Folders
    
    CRecordVector<int> emptyRefs;
    for(i = 0; i < updateItems.Size(); i++)
    {
      const CUpdateItem &updateItem = updateItems[i];
      if (updateItem.NewData)
      {
        if (updateItem.HasStream())
          continue;
      }
      else
        if (updateItem.IndexInArchive != -1)
          if (database->Files[updateItem.IndexInArchive].HasStream)
            continue;
      emptyRefs.Add(i);
    }
    emptyRefs.Sort(CompareEmptyItems, (void *)&updateItems);
    for(i = 0; i < emptyRefs.Size(); i++)
    {
      const CUpdateItem &updateItem = updateItems[emptyRefs[i]];
      CFileItem file;
      if (updateItem.NewProperties)
        FromUpdateItemToFileItem(updateItem, file);
      else
        file = database->Files[updateItem.IndexInArchive];
      newDatabase.Files.Add(file);
    }
  }
    
  /*
  if (newDatabase.Files.Size() != updateItems.Size())
    return E_FAIL;
  */

  return archive.WriteDatabase(EXTERNAL_CODECS_LOC_VARS
      newDatabase, options.HeaderMethod, options.HeaderOptions);
}