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; }
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; }
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++; }
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)); } } } }
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; }
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()); } }
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); } }
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 << '-'; } }
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; } } } }
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; }
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; }
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; }
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; }
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; }
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; } }
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); } }
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; }
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; }
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; }
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; }
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 ); }
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; }
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; }
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; }
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); }