Skip to content

Commit

Permalink
Add support for setting archive properties
Browse files Browse the repository at this point in the history
  • Loading branch information
thebrandre committed Feb 18, 2024
1 parent a867cd9 commit 12fe17f
Show file tree
Hide file tree
Showing 4 changed files with 119 additions and 1 deletion.
69 changes: 69 additions & 0 deletions ArchiveProperties.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
#include "ArchiveProperties.h"

#include <algorithm>
#include <7zip/Archive/IArchive.h>

void Archive7zProperties::applyProperties(IUnknown* Archive)
{
CMyComPtr<ISetProperties> SetProperties = [&]
{
void* Interface{};
Archive->QueryInterface(IID_ISetProperties, &Interface);
return static_cast<ISetProperties*>(Interface);
}();

std::vector<const wchar_t*> PropKeys(Properties.size());
std::ranges::transform(Properties, PropKeys.begin(), &std::wstring::c_str);

SetProperties->SetProperties(PropKeys.data(), Values.data(), PropKeys.size());
}

Archive7zProperties& Archive7zProperties::set(CompressHeaders Value)
{
return set(L"hc", Value.Value);
}

Archive7zProperties& Archive7zProperties::set(CompressHeadersFull Value)
{
return set(L"hcf", Value.Value);
}

Archive7zProperties& Archive7zProperties::set(EncryptHeaders Value)
{
return set(L"he", Value.Value);
}

Archive7zProperties& Archive7zProperties::set(Level Value)
{
return set(L"x", Value.Value);
}

Archive7zProperties& Archive7zProperties::set(NumberOfThreads Value)
{
return set(L"mt", Value.Value);
}

Archive7zProperties& Archive7zProperties::set(HashSize Value)
{
return set(L"crc", Value.Value);
}

Archive7zProperties& Archive7zProperties::set(const wchar_t* Name, bool Value)
{
Properties.emplace_back(Name);
auto& PropValue = Values.emplace_back();
PropVariantClear(&PropValue);
PropValue.vt = VT_BOOL;
PropValue.boolVal = Value ? VARIANT_TRUE : VARIANT_FALSE;
return *this;
}

Archive7zProperties& Archive7zProperties::set(const wchar_t* Name, std::uint32_t Value)
{
Properties.emplace_back(Name);
auto& PropValue = Values.emplace_back();
PropVariantClear(&PropValue);
PropValue.vt = VT_UI4;
PropValue.ulVal = Value;
return *this;
}
39 changes: 39 additions & 0 deletions ArchiveProperties.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#pragma once
#include <string>
#include <vector>
#include <Common/MyCom.h>


class Archive7zProperties
{
public:
struct CompressHeaders {bool Value;};
struct CompressHeadersFull {bool Value;};
struct EncryptHeaders {bool Value;};
struct Level {std::uint32_t Value;};
struct NumberOfThreads {std::uint32_t Value;};
struct HashSize {std::uint32_t Value;};

template<typename... PropertyTypes>
static void set(IUnknown* Archive, PropertyTypes... Values)
{
Archive7zProperties Props;
(Props.set(Values), ...);
Props.applyProperties(Archive);
}

private:
void applyProperties(IUnknown* Archive);
Archive7zProperties& set(CompressHeaders Value);
Archive7zProperties& set(CompressHeadersFull Value);
Archive7zProperties& set(EncryptHeaders Value);
Archive7zProperties& set(Level Value);
Archive7zProperties& set(NumberOfThreads Value);
Archive7zProperties& set(HashSize Value);

Archive7zProperties& set(const wchar_t* Name, bool Value);
Archive7zProperties& set(const wchar_t* Name, std::uint32_t Value);

std::vector<std::wstring> Properties;
std::vector<PROPVARIANT> Values;
};
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ target_sources(7zip-examples
"InMemoryArchiveUpdateCallback.cpp"
"ArchiveFactory.h"
"ArchiveFactory.cpp"
"ArchiveProperties.h"
"ArchiveProperties.cpp"
"ExportGUID.cpp"
"ExportGUID.h"
"InMemoryArchiveOpenCallback.cpp"
Expand Down
10 changes: 9 additions & 1 deletion main.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "ArchiveFactory.h"
#include "ArchiveProperties.h"
#include <Shlwapi.h>
#include <7zip/ICoder.h>
#include <7zip/IPassword.h>
Expand Down Expand Up @@ -74,6 +75,8 @@ void compressStuff(ArchiveFactory& Factory)
{
const unsigned ArchiveFormatId = 0x07;
CMyComPtr<IOutArchive> OutArchive = Factory.createOutArchive(ArchiveFormatId);
Archive7zProperties::set(OutArchive, Archive7zProperties::EncryptHeaders{true}, Archive7zProperties::NumberOfThreads{1});

InMemoryArchive TempArchive;
TempArchive.Password = u8"Password";
unsigned char FileContent[] = "ASCII and stuff";
Expand All @@ -85,14 +88,19 @@ void compressStuff(ArchiveFactory& Factory)
CMyComPtr<ISequentialOutStream> InMemoryOutStreamInstance(new InMemoryOutStream(Buffer));
OutArchive->UpdateItems(InMemoryOutStreamInstance, 1, UpdateCallback);

std::ofstream OutFile(fmt::format("generatedArchive.{}", ArchiveFactory::getFileExtensionFromFormatId(ArchiveFormatId)), std::ios_base::trunc | std::ios_base::binary);

// dump buffer to file
std::filesystem::path OutFileName = std::filesystem::current_path() / fmt::format("generatedArchive.{}", ArchiveFactory::getFileExtensionFromFormatId(ArchiveFormatId));
if (std::filesystem::exists(OutFileName)) { std::filesystem::remove(OutFileName); }
std::ofstream OutFile(OutFileName, std::ios_base::trunc | std::ios_base::binary);
OutFile.write((const char*)Buffer.data(), Buffer.size());
}

int main()
{
fmt::print("Running in directory {}.\n", std::filesystem::current_path());
ArchiveFactory Factory;
fmt::print("Number of supported formats {}.\n", Factory.getNumberOfFormats());
//extractStuff(Factory);
compressStuff(Factory);
return 0;
Expand Down

0 comments on commit 12fe17f

Please sign in to comment.