Example #1
0
HRESULT CHandler::SetMainMethod(
    CCompressionMethodMode &methodMode
    #ifndef _7ZIP_ST
    , UInt32 numThreads
    #endif
    )
{
  methodMode.Bonds = _bonds;

  CObjectVector<COneMethodInfo> methods = _methods;

  {
    FOR_VECTOR (i, methods)
    {
      AString &methodName = methods[i].MethodName;
      if (methodName.IsEmpty())
        methodName = kDefaultMethodName;
    }
    if (methods.IsEmpty())
    {
      COneMethodInfo &m = methods.AddNew();
      m.MethodName = (GetLevel() == 0 ? k_Copy_Name : kDefaultMethodName);
      methodMode.DefaultMethod_was_Inserted = true;
    }
  }
Example #2
0
HRESULT CDirEnumerator::GetNextFile(NFind::CFileInfo &fileInfo, bool &filled, FString &resPath)
{
  filled = false;
  for (;;)
  {
    if (Enumerators.IsEmpty())
    {
      if (Index >= FileNames.Size())
        return S_OK;
      const FString &path = FileNames[Index];
      int pos = path.ReverseFind(FCHAR_PATH_SEPARATOR);
      resPath.Empty();
      if (pos >= 0)
        resPath = path.Left(pos + 1);

      #ifdef _WIN32
      // it's for "c:" paths/
      if (BasePrefix.IsEmpty() && path.Length() == 2 && path[1] == ':')
      {
        fileInfo.Name = path;
        fileInfo.Attrib = FILE_ATTRIBUTE_DIRECTORY;
        fileInfo.Size = 0;
      }
      else
      #endif
      if (!fileInfo.Find(BasePrefix + path))
      {
        WRes errorCode = GetNormalizedError();
        resPath = path;
        return errorCode;
      }
      Index++;
      break;
    }
    bool found;
    if (!Enumerators.Back().Next(fileInfo, found))
    {
      HRESULT errorCode = GetNormalizedError();
      resPath = Prefixes.Back();
      return errorCode;
    }
    if (found)
    {
      resPath = Prefixes.Back();
      break;
    }
    Enumerators.DeleteBack();
    Prefixes.DeleteBack();
  }
  resPath += fileInfo.Name;
  if (!FlatMode && fileInfo.IsDir())
  {
    FString prefix = resPath + FCHAR_PATH_SEPARATOR;
    Enumerators.Add(NFind::CEnumerator(BasePrefix + prefix + FCHAR_ANY_MASK));
    Prefixes.Add(prefix);
  }
  filled = true;
  return S_OK;
}
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;
}
Example #4
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(WCHAR_PATH_SEPARATOR);
            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.IsDir())
    {
        UString prefix = resPath + (UString)(wchar_t)kDirDelimiter;
        Enumerators.Add(NFind::CEnumeratorW(BasePrefix + prefix + (UString)(wchar_t)kAnyStringWildcard));
        Prefixes.Add(prefix);
    }
    filled = true;
    return true;
}
Example #5
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;
}
Example #6
0
HRESULT CInArchive::ReadHeaders(CObjectVector<CItemEx> &items, CProgressVirt *progress)
{
  HRESULT res;
  try
  {
    res = ReadHeaders2(items, progress);
  }
  catch (const CInBufferException &e) { res = e.ErrorCode; }
  catch (const CUnexpectEnd &)
  {
    if (items.IsEmpty())
      return S_FALSE;
    UnexpectedEnd = true;
    res = S_OK;
  }
  catch (...)
  {
    _inBufMode = false;
    throw;
  }
  ArcInfo.FinishPos = m_Position;
  _inBufMode = false;
  return res;
}
Example #7
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;
}
Example #8
0
HRESULT CInArchive::ReadHeaders2(CObjectVector<CItemEx> &items, CProgressVirt *progress)
{
  items.Clear();

  // m_Signature must be kLocalFileHeader or kEcd
  // m_Position points to next byte after signature
  RINOK(Stream->Seek(m_Position, STREAM_SEEK_SET, NULL));

  if (!_inBuffer.Create(1 << 15))
    return E_OUTOFMEMORY;
  _inBuffer.SetStream(Stream);

  bool needReadCd = true;
  bool localsWereRead = false;
  if (m_Signature == NSignature::kEcd)
  {
    // It must be empty archive or backware archive
    // we don't support backware archive still

    const unsigned kBufSize = kEcdSize - 4;
    Byte buf[kBufSize];
    SafeReadBytes(buf, kBufSize);
    CEcd ecd;
    ecd.Parse(buf);
    // if (ecd.cdSize != 0)
    // Do we need also to support the case where empty zip archive with PK00 uses cdOffset = 4 ??
    if (!ecd.IsEmptyArc())
      return S_FALSE;

    ArcInfo.Base = ArcInfo.MarkerPos;
    needReadCd = false;
    IsArc = true; // check it: we need more tests?
    RINOK(Stream->Seek(ArcInfo.MarkerPos2 + 4, STREAM_SEEK_SET, &m_Position));
  }

  UInt64 cdSize = 0, cdRelatOffset = 0, cdAbsOffset = 0;
  HRESULT res = S_OK;

  if (needReadCd)
  {
    CItemEx firstItem;
    // try
    {
      try
      {
        if (!ReadLocalItem(firstItem))
          return S_FALSE;
      }
      catch(CUnexpectEnd &)
      {
        return S_FALSE;
      }

      IsArc = true;
      res = ReadCd(items, cdRelatOffset, cdSize, progress);
      if (res == S_OK)
        m_Signature = ReadUInt32();
    }
    // catch() { res = S_FALSE; }
    if (res != S_FALSE && res != S_OK)
      return res;

    if (res == S_OK && items.Size() == 0)
      res = S_FALSE;

    if (res == S_OK)
    {
      // we can't read local items here to keep _inBufMode state
      firstItem.LocalHeaderPos = ArcInfo.MarkerPos2 - ArcInfo.Base;
      int index = FindItem(items, firstItem.LocalHeaderPos);
      if (index == -1)
        res = S_FALSE;
      else if (!AreItemsEqual(firstItem, items[index]))
        res = S_FALSE;
      ArcInfo.CdWasRead = true;
      ArcInfo.FirstItemRelatOffset = items[0].LocalHeaderPos;
    }
  }

  CObjectVector<CItemEx> cdItems;

  bool needSetBase = false;
  unsigned numCdItems = items.Size();

  if (res == S_FALSE)
  {
    // CD doesn't match firstItem so we clear items and read Locals.
    items.Clear();
    localsWereRead = true;
    _inBufMode = false;
    ArcInfo.Base = ArcInfo.MarkerPos;
    RINOK(Stream->Seek(ArcInfo.MarkerPos2, STREAM_SEEK_SET, &m_Position));
    m_Signature = ReadUInt32();

    RINOK(ReadLocals(items, progress));

    if (m_Signature != NSignature::kCentralFileHeader)
    {
      m_Position -= 4;
      NoCentralDir = true;
      HeadersError = true;
      return S_OK;
    }
    _inBufMode = true;
    _inBuffer.Init();
    cdAbsOffset = m_Position - 4;
    for (;;)
    {
      CItemEx cdItem;
      RINOK(ReadCdItem(cdItem));
      cdItems.Add(cdItem);
      if (progress && cdItems.Size() % 1 == 0)
        RINOK(progress->SetCompletedCD(items.Size()));
      m_Signature = ReadUInt32();
      if (m_Signature != NSignature::kCentralFileHeader)
        break;
    }

    cdSize = (m_Position - 4) - cdAbsOffset;
    needSetBase = true;
    numCdItems = cdItems.Size();

    if (!cdItems.IsEmpty())
    {
      ArcInfo.CdWasRead = true;
      ArcInfo.FirstItemRelatOffset = cdItems[0].LocalHeaderPos;
    }
  }

  CEcd64 ecd64;
  bool isZip64 = false;
  UInt64 ecd64AbsOffset = m_Position - 4;
  if (m_Signature == NSignature::kEcd64)
  {
    IsZip64 = isZip64 = true;
    UInt64 recordSize = ReadUInt64();

    const unsigned kBufSize = kEcd64_MainSize;
    Byte buf[kBufSize];
    SafeReadBytes(buf, kBufSize);
    ecd64.Parse(buf);

    Skip64(recordSize - kEcd64_MainSize);
    m_Signature = ReadUInt32();

    if (ecd64.thisDiskNumber != 0 || ecd64.startCDDiskNumber != 0)
      return E_NOTIMPL;

    if (needSetBase)
    {
      ArcInfo.Base = cdAbsOffset - ecd64.cdStartOffset;
      cdRelatOffset = ecd64.cdStartOffset;
      needSetBase = false;
    }

    if (ecd64.numEntriesInCDOnThisDisk != numCdItems ||
        ecd64.numEntriesInCD != numCdItems ||
        ecd64.cdSize != cdSize ||
        (ecd64.cdStartOffset != cdRelatOffset &&
        (!items.IsEmpty())))
      return S_FALSE;
  }
  if (m_Signature == NSignature::kEcd64Locator)
  {
    if (!isZip64)
      return S_FALSE;
    /* UInt32 startEndCDDiskNumber = */ ReadUInt32();
    UInt64 ecd64RelatOffset = ReadUInt64();
    /* UInt32 numberOfDisks = */ ReadUInt32();
    if (ecd64AbsOffset != ArcInfo.Base + ecd64RelatOffset)
      return S_FALSE;
    m_Signature = ReadUInt32();
  }
  if (m_Signature != NSignature::kEcd)
    return S_FALSE;

  const unsigned kBufSize = kEcdSize - 4;
  Byte buf[kBufSize];
  SafeReadBytes(buf, kBufSize);
  CEcd ecd;
  ecd.Parse(buf);

  COPY_ECD_ITEM_16(thisDiskNumber);
  COPY_ECD_ITEM_16(startCDDiskNumber);
  COPY_ECD_ITEM_16(numEntriesInCDOnThisDisk);
  COPY_ECD_ITEM_16(numEntriesInCD);
  COPY_ECD_ITEM_32(cdSize);
  COPY_ECD_ITEM_32(cdStartOffset);

  if (needSetBase)
  {
    ArcInfo.Base = cdAbsOffset - ecd64.cdStartOffset;
    cdRelatOffset = ecd64.cdStartOffset;
    needSetBase = false;
  }

  if (localsWereRead && (UInt64)ArcInfo.Base != ArcInfo.MarkerPos)
  {
    UInt64 delta = ArcInfo.MarkerPos - ArcInfo.Base;
    for (unsigned i = 0; i < items.Size(); i++)
      items[i].LocalHeaderPos += delta;
  }


  // ---------- merge Central Directory Items ----------

  if (!cdItems.IsEmpty())
  {
    for (unsigned i = 0; i < cdItems.Size(); i++)
    {
      const CItemEx &cdItem = cdItems[i];
      int index = FindItem(items, cdItem.LocalHeaderPos);
      if (index == -1)
      {
        items.Add(cdItem);
        continue;
      }
      CItemEx &item = items[index];
      if (item.Name != cdItem.Name
          // || item.Name.Len() != cdItem.Name.Len()
          || item.PackSize != cdItem.PackSize
          || item.Size != cdItem.Size
          // item.ExtractVersion != cdItem.ExtractVersion
          || !FlagsAreSame(item, cdItem)
          || item.Crc != cdItem.Crc)
        continue;

      // item.LocalHeaderPos = cdItem.LocalHeaderPos;
      // item.Name = cdItem.Name;
      item.MadeByVersion = cdItem.MadeByVersion;
      item.CentralExtra = cdItem.CentralExtra;
      item.InternalAttrib = cdItem.InternalAttrib;
      item.ExternalAttrib = cdItem.ExternalAttrib;
      item.Comment = cdItem.Comment;
      item.FromCentral = cdItem.FromCentral;
    }
  }

  if (ecd64.thisDiskNumber != 0 || ecd64.startCDDiskNumber != 0)
    return E_NOTIMPL;

  if (isZip64)
  {
    if (ecd64.numEntriesInCDOnThisDisk != items.Size())
      HeadersError = true;
  }
  else
  {
    // old 7-zip could store 32-bit number of CD items to 16-bit field.
    if ((UInt16)ecd64.numEntriesInCDOnThisDisk != (UInt16)numCdItems ||
        (UInt16)ecd64.numEntriesInCDOnThisDisk != (UInt16)items.Size())
      HeadersError = true;
  }

  ReadBuffer(ArcInfo.Comment, ecd.commentSize);
  _inBufMode = false;
  _inBuffer.Free();

  if (
      (UInt16)ecd64.numEntriesInCD != ((UInt16)numCdItems) ||
      (UInt32)ecd64.cdSize != (UInt32)cdSize ||
      ((UInt32)(ecd64.cdStartOffset) != (UInt32)cdRelatOffset &&
        (!items.IsEmpty())))
    return S_FALSE;

  // printf("\nOpen OK");
  return S_OK;
}
Example #9
0
DWORD CDirEnumerator::GetNextFile(NFind::CFileInfo &fi, bool &filled, FString &resPath)
{
  filled = false;
  resPath.Empty();

  for (;;)
  {
    #if defined(_WIN32) && !defined(UNDER_CE)
    bool isRootPrefix = (BasePrefix.IsEmpty() || (NName::IsSuperPath(BasePrefix) && BasePrefix[NName::kSuperPathPrefixSize] == 0));
    #endif

    if (Enumerators.IsEmpty())
    {
      if (Index >= FilePaths.Size())
        return S_OK;
      const FString &path = FilePaths[Index++];
      int pos = path.ReverseFind_PathSepar();
      if (pos >= 0)
        resPath.SetFrom(path, pos + 1);

      #if defined(_WIN32) && !defined(UNDER_CE)
      if (isRootPrefix && path.Len() == 2 && NName::IsDrivePath2(path))
      {
        // we use "c:" item as directory item
        fi.ClearBase();
        fi.Name = path;
        fi.SetAsDir();
        fi.Size = 0;
      }
      else
      #endif
      if (!fi.Find(BasePrefix + path))
      {
        DWORD error = GetNormalizedError();
        resPath = path;
        return error;
      }

      break;
    }

    bool found;

    if (Enumerators.Back().Next(fi, found))
    {
      if (found)
      {
        resPath = Prefixes.Back();
        break;
      }
    }
    else
    {
      DWORD error = GetNormalizedError();
      resPath = Prefixes.Back();
      Enumerators.DeleteBack();
      Prefixes.DeleteBack();
      return error;
    }

    Enumerators.DeleteBack();
    Prefixes.DeleteBack();
  }

  resPath += fi.Name;

  if (EnterToDirs && fi.IsDir())
  {
    FString s = resPath;
    s.Add_PathSepar();
    Prefixes.Add(s);
    s += FCHAR_ANY_MASK;
    Enumerators.Add(NFind::CEnumerator(BasePrefix + s));
  }
  filled = true;
  return S_OK;
}
Example #10
0
DWORD CDirEnumerator::GetNextFile(NFind::CFileInfo &fi, bool &filled, FString &resPath)
{
  filled = false;
  resPath.Empty();
  for (;;)
  {
    if (Enumerators.IsEmpty())
    {
      if (Index >= FilePaths.Size())
        return S_OK;
      const FString &path = FilePaths[Index++];
      int pos = path.ReverseFind(FCHAR_PATH_SEPARATOR);
      if (pos >= 0)
        resPath.SetFrom(path, pos + 1);

      #ifdef _WIN32
      if (BasePrefix.IsEmpty() && path.Len() == 2 && path[1] == ':')
      {
        // we use "c:" item as directory item
        fi.Clear();
        fi.Name = path;
        fi.SetAsDir();
        fi.Size = 0;
      }
      else
      #endif
      if (!fi.Find(BasePrefix + path))
      {
        DWORD error = GetNormalizedError();
        resPath = path;
        return error;
      }
      break;
    }
    bool found;
    if (Enumerators.Back().Next(fi, found))
    {
      if (found)
      {
        resPath = Prefixes.Back();
        break;
      }
    }
    else
    {
      DWORD error = GetNormalizedError();
      resPath = Prefixes.Back();
      Enumerators.DeleteBack();
      Prefixes.DeleteBack();
      return error;
    }
    Enumerators.DeleteBack();
    Prefixes.DeleteBack();
  }
  resPath += fi.Name;
  if (EnterToDirs && fi.IsDir())
  {
    FString s = resPath;
    s += FCHAR_PATH_SEPARATOR;
    Prefixes.Add(s);
    s += FCHAR_ANY_MASK;
    Enumerators.Add(NFind::CEnumerator(BasePrefix + s));
  }
  filled = true;
  return S_OK;
}