mirror of
https://github.com/tfussell/xlnt.git
synced 2024-03-22 13:11:17 +08:00
intermediate commit
This commit is contained in:
parent
2fc692d694
commit
126f22816b
|
@ -27,24 +27,26 @@
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include <xlnt/utils/exceptions.hpp>
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
using byte = std::uint8_t;
|
using byte = std::uint8_t;
|
||||||
|
|
||||||
class byte_reader
|
class binary_reader
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
byte_reader() = delete;
|
binary_reader() = delete;
|
||||||
|
|
||||||
byte_reader(const std::vector<byte> &bytes)
|
binary_reader(const std::vector<byte> &bytes)
|
||||||
: bytes_(&bytes)
|
: bytes_(&bytes)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
byte_reader(const byte_reader &other) = default;
|
binary_reader(const binary_reader &other) = default;
|
||||||
|
|
||||||
byte_reader &operator=(const byte_reader &other)
|
binary_reader &operator=(const binary_reader &other)
|
||||||
{
|
{
|
||||||
offset_ = other.offset_;
|
offset_ = other.offset_;
|
||||||
bytes_ = other.bytes_;
|
bytes_ = other.bytes_;
|
||||||
|
@ -52,7 +54,7 @@ public:
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
~byte_reader()
|
~binary_reader()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,7 +91,7 @@ public:
|
||||||
template<typename T>
|
template<typename T>
|
||||||
std::vector<T> as_vector_of() const
|
std::vector<T> as_vector_of() const
|
||||||
{
|
{
|
||||||
auto result = std::vector<T>(size() / sizeof(T), 0);
|
auto result = std::vector<T>(size() / sizeof(T), T());
|
||||||
std::memcpy(result.data(), bytes_->data(), size());
|
std::memcpy(result.data(), bytes_->data(), size());
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
@ -105,108 +107,59 @@ private:
|
||||||
const std::vector<std::uint8_t> *bytes_;
|
const std::vector<std::uint8_t> *bytes_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class byte_vector
|
class binary_writer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
template<typename T>
|
binary_writer(std::vector<byte> &bytes)
|
||||||
static byte_vector from(const std::vector<T> &ints)
|
: bytes_(&bytes)
|
||||||
{
|
|
||||||
byte_vector result;
|
|
||||||
|
|
||||||
result.resize(ints.size() * sizeof(T));
|
|
||||||
std::memcpy(result.bytes_.data(), ints.data(), result.bytes_.size());
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
static byte_vector from(const std::basic_string<T> &string)
|
|
||||||
{
|
|
||||||
byte_vector result;
|
|
||||||
|
|
||||||
result.resize(string.size() * sizeof(T));
|
|
||||||
std::memcpy(result.bytes_.data(), string.data(), result.bytes_.size());
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
byte_vector()
|
|
||||||
: reader_(bytes_)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
byte_vector(std::vector<byte> &bytes)
|
binary_writer(const binary_writer &other)
|
||||||
: bytes_(bytes),
|
|
||||||
reader_(bytes_)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
byte_vector(const std::vector<T> &ints)
|
|
||||||
: byte_vector()
|
|
||||||
{
|
|
||||||
bytes_ = from(ints).data();
|
|
||||||
}
|
|
||||||
|
|
||||||
byte_vector(const byte_vector &other)
|
|
||||||
: byte_vector()
|
|
||||||
{
|
{
|
||||||
*this = other;
|
*this = other;
|
||||||
}
|
}
|
||||||
|
|
||||||
~byte_vector()
|
~binary_writer()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
byte_vector &operator=(const byte_vector &other)
|
binary_writer &operator=(const binary_writer &other)
|
||||||
{
|
{
|
||||||
bytes_ = other.bytes_;
|
bytes_ = other.bytes_;
|
||||||
reader_ = byte_reader(bytes_);
|
offset_ = other.offset_;
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<byte> &data() const
|
template<typename T>
|
||||||
|
void assign(const std::vector<T> &ints)
|
||||||
{
|
{
|
||||||
return bytes_;
|
resize(ints.size() * sizeof(T));
|
||||||
|
std::memcpy(bytes_->data(), ints.data(), bytes_->size());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<byte> data()
|
template<typename T>
|
||||||
|
void assign(const std::basic_string<T> &string)
|
||||||
{
|
{
|
||||||
return bytes_;
|
resize(string.size() * sizeof(T));
|
||||||
|
std::memcpy(bytes_->data(), string.data(), bytes_->size());
|
||||||
}
|
}
|
||||||
|
|
||||||
void data(std::vector<byte> &bytes)
|
void offset(std::size_t new_offset)
|
||||||
{
|
{
|
||||||
bytes_ = bytes;
|
offset_ = new_offset;
|
||||||
}
|
|
||||||
|
|
||||||
void offset(std::size_t offset)
|
|
||||||
{
|
|
||||||
reader_.offset(offset);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t offset() const
|
std::size_t offset() const
|
||||||
{
|
{
|
||||||
return reader_.offset();
|
return offset_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void reset()
|
void reset()
|
||||||
{
|
{
|
||||||
reader_.reset();
|
offset_ = 0;
|
||||||
bytes_.clear();
|
bytes_->clear();
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
T read()
|
|
||||||
{
|
|
||||||
return reader_.read<T>();
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
std::vector<T> as_vector_of() const
|
|
||||||
{
|
|
||||||
return reader_.as_vector_of<T>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
@ -219,35 +172,47 @@ public:
|
||||||
extend(offset() + num_bytes - size());
|
extend(offset() + num_bytes - size());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::memcpy(bytes_.data() + offset(), &value, num_bytes);
|
std::memcpy(bytes_->data() + offset(), &value, num_bytes);
|
||||||
reader_.offset(reader_.offset() + num_bytes);
|
offset_ += num_bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t size() const
|
std::size_t size() const
|
||||||
{
|
{
|
||||||
return bytes_.size();
|
return bytes_->size();
|
||||||
}
|
}
|
||||||
|
|
||||||
void resize(std::size_t new_size, byte fill = 0)
|
void resize(std::size_t new_size, byte fill = 0)
|
||||||
{
|
{
|
||||||
bytes_.resize(new_size, fill);
|
bytes_->resize(new_size, fill);
|
||||||
}
|
}
|
||||||
|
|
||||||
void extend(std::size_t amount, byte fill = 0)
|
void extend(std::size_t amount, byte fill = 0)
|
||||||
{
|
{
|
||||||
bytes_.resize(size() + amount, fill);
|
bytes_->resize(size() + amount, fill);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<byte>::iterator iterator()
|
std::vector<byte>::iterator iterator()
|
||||||
{
|
{
|
||||||
return bytes_.begin() + static_cast<std::ptrdiff_t>(offset());
|
return bytes_->begin() + static_cast<std::ptrdiff_t>(offset());
|
||||||
}
|
}
|
||||||
|
|
||||||
void append(const std::vector<std::uint8_t> &data, std::size_t offset, std::size_t count)
|
void append(const std::vector<std::uint8_t> &data, std::size_t offset, std::size_t count)
|
||||||
{
|
{
|
||||||
auto end_index = size();
|
auto end_index = size();
|
||||||
extend(count);
|
extend(count);
|
||||||
std::memcpy(bytes_.data() + end_index, data.data() + offset, count);
|
std::memcpy(bytes_->data() + end_index, data.data() + offset, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
void append(const byte *data, const std::size_t data_size, std::size_t offset, std::size_t count)
|
||||||
|
{
|
||||||
|
if (offset + count > data_size)
|
||||||
|
{
|
||||||
|
throw xlnt::exception("out of bounds read");
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto end_index = size();
|
||||||
|
extend(count);
|
||||||
|
std::memcpy(bytes_->data() + end_index, data + offset, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
void append(const std::vector<std::uint8_t> &data)
|
void append(const std::vector<std::uint8_t> &data)
|
||||||
|
@ -256,9 +221,19 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<byte> bytes_;
|
std::vector<byte> *bytes_;
|
||||||
byte_reader reader_;
|
std::size_t offset_ = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
std::vector<byte> string_to_bytes(const std::basic_string<T> &string)
|
||||||
|
{
|
||||||
|
std::vector<byte> bytes;
|
||||||
|
binary_writer writer(bytes);
|
||||||
|
writer.assign(string);
|
||||||
|
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
} // namespace xlnt
|
} // namespace xlnt
|
|
@ -31,13 +31,15 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include <detail/bytes.hpp>
|
#include <detail/binary.hpp>
|
||||||
#include <detail/cryptography/compound_document.hpp>
|
#include <detail/cryptography/compound_document.hpp>
|
||||||
#include <xlnt/utils/exceptions.hpp>
|
#include <xlnt/utils/exceptions.hpp>
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
using xlnt::detail::byte_vector;
|
using xlnt::detail::byte;
|
||||||
|
using xlnt::detail::binary_reader;
|
||||||
|
using xlnt::detail::binary_writer;
|
||||||
|
|
||||||
using directory_id = std::int32_t;
|
using directory_id = std::int32_t;
|
||||||
using sector_id = std::int32_t;
|
using sector_id = std::int32_t;
|
||||||
|
@ -124,14 +126,11 @@ public:
|
||||||
return chain;
|
return chain;
|
||||||
}
|
}
|
||||||
|
|
||||||
void load(const byte_vector &data)
|
void load(std::size_t new_sector_size, const std::vector<byte> §ors)
|
||||||
{
|
{
|
||||||
data_ = data.as_vector_of<sector_id>();
|
sector_size(new_sector_size);
|
||||||
}
|
auto reader = binary_reader(sectors);
|
||||||
|
data_ = reader.as_vector_of<sector_id>();
|
||||||
byte_vector save() const
|
|
||||||
{
|
|
||||||
return byte_vector::from(data_);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t sector_size() const
|
std::size_t sector_size() const
|
||||||
|
@ -174,14 +173,14 @@ public:
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void load(byte_vector &data)
|
void load(binary_reader &reader)
|
||||||
{
|
{
|
||||||
if (data.size() < 512)
|
if (reader.size() < 512)
|
||||||
{
|
{
|
||||||
throw xlnt::exception("bad header");
|
throw xlnt::exception("bad header");
|
||||||
}
|
}
|
||||||
|
|
||||||
*this = data.read<header>();
|
*this = reader.read<header>();
|
||||||
|
|
||||||
if (file_id_ != 0xe11ab1a1e011cfd0)
|
if (file_id_ != 0xe11ab1a1e011cfd0)
|
||||||
{
|
{
|
||||||
|
@ -194,14 +193,6 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
byte_vector save() const
|
|
||||||
{
|
|
||||||
byte_vector out;
|
|
||||||
out.write(*this);
|
|
||||||
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::size_t sector_size() const
|
std::size_t sector_size() const
|
||||||
{
|
{
|
||||||
return std::size_t(1) << sector_size_power_;
|
return std::size_t(1) << sector_size_power_;
|
||||||
|
@ -436,43 +427,17 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void load(byte_vector &data)
|
void load(const std::vector<byte> &data)
|
||||||
{
|
{
|
||||||
entries.clear();
|
auto reader = binary_reader(data);
|
||||||
|
entries = reader.as_vector_of<directory_entry>();
|
||||||
|
|
||||||
auto num_entries = data.size() / sizeof(directory_entry);
|
auto is_empty = [](const directory_entry &entry)
|
||||||
|
|
||||||
for (auto i = std::size_t(0); i < num_entries; ++i)
|
|
||||||
{
|
{
|
||||||
auto e = data.read<directory_entry>();
|
return entry.type == directory_entry::entry_type::Empty;
|
||||||
|
};
|
||||||
|
|
||||||
if (e.type == directory_entry::entry_type::Empty)
|
entries.erase(std::remove_if(entries.begin(), entries.end(), is_empty));
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((e.type != directory_entry::entry_type::UserStream)
|
|
||||||
&& (e.type != directory_entry::entry_type::UserStorage)
|
|
||||||
&& (e.type != directory_entry::entry_type::RootStorage))
|
|
||||||
{
|
|
||||||
throw xlnt::exception("invalid entry");
|
|
||||||
}
|
|
||||||
|
|
||||||
entries.push_back(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
byte_vector save() const
|
|
||||||
{
|
|
||||||
auto result = byte_vector();
|
|
||||||
|
|
||||||
for (auto &entry : entries)
|
|
||||||
{
|
|
||||||
result.write(entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
directory_entry create_root_entry() const
|
directory_entry create_root_entry() const
|
||||||
|
@ -606,62 +571,72 @@ namespace detail {
|
||||||
class compound_document_reader_impl
|
class compound_document_reader_impl
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
compound_document_reader_impl(const std::vector<std::uint8_t> &data)
|
compound_document_reader_impl(const std::vector<byte> &bytes)
|
||||||
|
: sectors_(bytes.data() + sizeof(header)),
|
||||||
|
sectors_size_(bytes.size())
|
||||||
{
|
{
|
||||||
auto reader = byte_vector(data);
|
auto reader = binary_reader(bytes);
|
||||||
|
|
||||||
header_.load(reader);
|
header_.load(reader);
|
||||||
|
|
||||||
sector_table_.sector_size(header_.sector_size());
|
const auto sector_size = header_.sector_size();
|
||||||
short_sector_table_.sector_size(header_.short_sector_size());
|
const auto master_table_chain = load_master_table();
|
||||||
|
const auto master_sectors = read(master_table_chain);
|
||||||
|
sector_table_.load(sector_size, master_sectors);
|
||||||
|
|
||||||
sectors_.append(data, 512, data.size() - 512);
|
const auto short_sector_size = header_.short_sector_size();
|
||||||
|
const auto short_start = header_.short_table_start();
|
||||||
|
const auto short_table_chain = sector_table_.follow(short_start);
|
||||||
|
const auto short_sectors = read(short_table_chain);
|
||||||
|
short_sector_table_.load(short_sector_size, short_sectors);
|
||||||
|
|
||||||
sector_table_.load(load_sectors(load_msat(reader)));
|
const auto directory_start = header_.directory_start();
|
||||||
short_sector_table_.load(load_sectors(sector_table_.follow(header_.short_table_start())));
|
const auto directory_chain = sector_table_.follow(directory_start);
|
||||||
auto directory_data = load_sectors(sector_table_.follow(header_.directory_start()));
|
const auto directory_sectors = read(directory_chain);
|
||||||
directory_.load(directory_data);
|
directory_.load(directory_sectors);
|
||||||
|
|
||||||
auto first_short_sector = directory_.entry(u"/Root Entry", false).first;
|
auto first_short_sector = directory_.entry(u"/Root Entry", false).first;
|
||||||
short_container_stream_ = sector_table_.follow(first_short_sector);
|
short_container_stream_ = sector_table_.follow(first_short_sector);
|
||||||
}
|
}
|
||||||
|
|
||||||
byte_vector load_sectors(const std::vector<sector_id> §ors) const
|
std::vector<byte> read(const std::vector<sector_id> §ors) const
|
||||||
{
|
{
|
||||||
auto result = byte_vector();
|
|
||||||
const auto sector_size = sector_table_.sector_size();
|
const auto sector_size = sector_table_.sector_size();
|
||||||
|
auto result = std::vector<byte>();
|
||||||
|
auto writer = binary_writer(result);
|
||||||
|
|
||||||
for (auto sector : sectors)
|
for (auto sector : sectors)
|
||||||
{
|
{
|
||||||
auto position = sector_size * static_cast<std::size_t>(sector);
|
auto position = sizeof(header) + sector_size * static_cast<std::size_t>(sector);
|
||||||
result.append(sectors_.data(), position, sector_size);
|
writer.append(sectors_, sectors_size_, position, sector_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
byte_vector load_short_sectors(const std::vector<sector_id> §ors) const
|
std::vector<byte> read_short(const std::vector<sector_id> §ors) const
|
||||||
{
|
{
|
||||||
auto result = byte_vector();
|
|
||||||
const auto short_sector_size = short_sector_table_.sector_size();
|
const auto short_sector_size = short_sector_table_.sector_size();
|
||||||
const auto sector_size = sector_table_.sector_size();
|
const auto sector_size = sector_table_.sector_size();
|
||||||
|
auto result = std::vector<byte>();
|
||||||
|
auto writer = binary_writer(result);
|
||||||
|
|
||||||
for (auto sector : sectors)
|
for (auto sector : sectors)
|
||||||
{
|
{
|
||||||
auto position = short_sector_size * static_cast<std::size_t>(sector);
|
auto position = short_sector_size * static_cast<std::size_t>(sector);
|
||||||
auto master_allocation_table_index = position / sector_size;
|
auto master_allocation_table_index = position / sector_size;
|
||||||
|
|
||||||
auto sector_data = load_sectors({ short_container_stream_[master_allocation_table_index] });
|
auto sector_data = read({ short_container_stream_[master_allocation_table_index] });
|
||||||
|
|
||||||
auto offset = position % sector_size;
|
auto offset = position % sector_size;
|
||||||
result.append(sector_data.data(), offset, short_sector_size);
|
writer.append(sector_data, offset, short_sector_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<sector_id> load_msat(byte_vector &/*data*/)
|
std::vector<sector_id> load_master_table()
|
||||||
{
|
{
|
||||||
const auto sector_size = header_.sector_size();
|
|
||||||
auto master_sectors = header_.sectors();
|
auto master_sectors = header_.sectors();
|
||||||
|
|
||||||
if (header_.num_master_sectors() > 109)
|
if (header_.num_master_sectors() > 109)
|
||||||
|
@ -670,60 +645,56 @@ public:
|
||||||
|
|
||||||
for (auto r = std::size_t(0); r < header_.num_master_sectors(); ++r)
|
for (auto r = std::size_t(0); r < header_.num_master_sectors(); ++r)
|
||||||
{
|
{
|
||||||
auto msat = load_sectors({ current_sector });
|
auto current_sector_data = read({ current_sector });
|
||||||
auto index = sector_id(0);
|
auto current_sector_reader = binary_reader(current_sector_data);
|
||||||
|
auto current_sector_sectors = current_sector_reader.as_vector_of<sector_id>();
|
||||||
|
|
||||||
while (index < static_cast<sector_id>((sector_size - 1) / sizeof(sector_id)))
|
current_sector = current_sector_sectors.back();
|
||||||
{
|
current_sector_sectors.pop_back();
|
||||||
master_sectors.push_back(msat.read<sector_id>());
|
|
||||||
}
|
|
||||||
|
|
||||||
current_sector = msat.read<sector_id>();
|
master_sectors.insert(
|
||||||
|
current_sector_sectors.begin(),
|
||||||
|
current_sector_sectors.end(),
|
||||||
|
master_sectors.end());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return master_sectors;
|
return master_sectors;
|
||||||
}
|
}
|
||||||
|
|
||||||
byte_vector read_stream(const std::u16string &name) const
|
std::vector<byte> read_stream(const std::u16string &name) const
|
||||||
{
|
{
|
||||||
const auto entry = directory_.entry(name);
|
const auto entry = directory_.entry(name);
|
||||||
byte_vector result;
|
|
||||||
|
|
||||||
if (entry.size < header_.threshold())
|
auto result = entry.size < header_.threshold()
|
||||||
{
|
? read_short(short_sector_table_.follow(entry.first))
|
||||||
result = load_short_sectors(short_sector_table_.follow(entry.first));
|
: read(sector_table_.follow(entry.first));
|
||||||
result.resize(entry.size);
|
result.resize(entry.size);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
result = load_sectors(sector_table_.follow(entry.first));
|
|
||||||
result.resize(entry.size);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
const byte *sectors_;
|
||||||
|
const std::size_t sectors_size_;
|
||||||
directory_tree directory_;
|
directory_tree directory_;
|
||||||
header header_;
|
header header_;
|
||||||
allocation_table sector_table_;
|
allocation_table sector_table_;
|
||||||
byte_vector sectors_;
|
|
||||||
allocation_table short_sector_table_;
|
allocation_table short_sector_table_;
|
||||||
byte_vector short_sectors_;
|
|
||||||
std::vector<sector_id> short_container_stream_;
|
std::vector<sector_id> short_container_stream_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class compound_document_writer_impl
|
class compound_document_writer_impl
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
compound_document_writer_impl(std::vector<std::uint8_t> &data)
|
compound_document_writer_impl(std::vector<byte> &bytes)
|
||||||
|
: writer_(bytes)
|
||||||
{
|
{
|
||||||
sector_table_.sector_size(header_.sector_size());
|
sector_table_.sector_size(header_.sector_size());
|
||||||
short_sector_table_.sector_size(header_.short_sector_size());
|
short_sector_table_.sector_size(header_.short_sector_size());
|
||||||
}
|
}
|
||||||
|
|
||||||
void write_sectors(const byte_vector &data, directory_entry &/*entry*/)
|
void write_sectors(const std::vector<byte> &data, directory_entry &/*entry*/)
|
||||||
{
|
{
|
||||||
const auto sector_size = sector_table_.sector_size();
|
const auto sector_size = sector_table_.sector_size();
|
||||||
const auto num_sectors = data.size() / sector_size;
|
const auto num_sectors = data.size() / sector_size;
|
||||||
|
@ -732,11 +703,11 @@ public:
|
||||||
{
|
{
|
||||||
auto position = sector_size * i;
|
auto position = sector_size * i;
|
||||||
auto current_sector_size = data.size() % sector_size;
|
auto current_sector_size = data.size() % sector_size;
|
||||||
sectors_.append(data.data(), position, current_sector_size);
|
writer_.append(data, position, current_sector_size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void write_short_sectors(const byte_vector &data, directory_entry &/*entry*/)
|
void write_short_sectors(const std::vector<byte> &data, directory_entry &/*entry*/)
|
||||||
{
|
{
|
||||||
const auto sector_size = sector_table_.sector_size();
|
const auto sector_size = sector_table_.sector_size();
|
||||||
const auto num_sectors = data.size() / sector_size;
|
const auto num_sectors = data.size() / sector_size;
|
||||||
|
@ -745,24 +716,11 @@ public:
|
||||||
{
|
{
|
||||||
auto position = sector_size * i;
|
auto position = sector_size * i;
|
||||||
auto current_sector_size = data.size() % sector_size;
|
auto current_sector_size = data.size() % sector_size;
|
||||||
sectors_.append(data.data(), position, current_sector_size);
|
writer_.append(data, position, current_sector_size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
byte_vector save() const
|
void write_stream(const std::u16string &name, const std::vector<byte> &data)
|
||||||
{
|
|
||||||
auto result = byte_vector();
|
|
||||||
|
|
||||||
result.append(header_.save().data());
|
|
||||||
result.append(sector_table_.save().data());
|
|
||||||
result.append(short_sector_table_.save().data());
|
|
||||||
result.append(directory_.save().data());
|
|
||||||
result.append(sectors_.data());
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void write_stream(const std::u16string &name, const byte_vector &data)
|
|
||||||
{
|
{
|
||||||
auto &entry = directory_.entry(name, true);
|
auto &entry = directory_.entry(name, true);
|
||||||
|
|
||||||
|
@ -777,12 +735,11 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
binary_writer writer_;
|
||||||
directory_tree directory_;
|
directory_tree directory_;
|
||||||
header header_;
|
header header_;
|
||||||
allocation_table sector_table_;
|
allocation_table sector_table_;
|
||||||
byte_vector sectors_;
|
|
||||||
allocation_table short_sector_table_;
|
allocation_table short_sector_table_;
|
||||||
byte_vector short_sectors_;
|
|
||||||
std::vector<sector_id> short_container_stream_;
|
std::vector<sector_id> short_container_stream_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -797,7 +754,7 @@ compound_document_reader::~compound_document_reader()
|
||||||
|
|
||||||
std::vector<std::uint8_t> compound_document_reader::read_stream(const std::u16string &name) const
|
std::vector<std::uint8_t> compound_document_reader::read_stream(const std::u16string &name) const
|
||||||
{
|
{
|
||||||
return d_->read_stream(name).data();
|
return d_->read_stream(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
compound_document_writer::compound_document_writer(std::vector<std::uint8_t> &data)
|
compound_document_writer::compound_document_writer(std::vector<std::uint8_t> &data)
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include <detail/bytes.hpp>
|
#include <detail/binary.hpp>
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
|
|
||||||
#include <detail/bytes.hpp>
|
#include <detail/binary.hpp>
|
||||||
#include <detail/cryptography/aes.hpp>
|
#include <detail/cryptography/aes.hpp>
|
||||||
#include <detail/cryptography/encryption_info.hpp>
|
#include <detail/cryptography/encryption_info.hpp>
|
||||||
|
|
||||||
|
@ -37,7 +37,7 @@ std::vector<std::uint8_t> calculate_standard_key(
|
||||||
{
|
{
|
||||||
// H_0 = H(salt + password)
|
// H_0 = H(salt + password)
|
||||||
auto salt_plus_password = info.salt;
|
auto salt_plus_password = info.salt;
|
||||||
auto password_bytes = xlnt::detail::byte_vector::from(password).data();
|
auto password_bytes = xlnt::detail::string_to_bytes(password);
|
||||||
std::copy(password_bytes.begin(),
|
std::copy(password_bytes.begin(),
|
||||||
password_bytes.end(),
|
password_bytes.end(),
|
||||||
std::back_inserter(salt_plus_password));
|
std::back_inserter(salt_plus_password));
|
||||||
|
@ -107,7 +107,7 @@ std::vector<std::uint8_t> calculate_agile_key(
|
||||||
{
|
{
|
||||||
// H_0 = H(salt + password)
|
// H_0 = H(salt + password)
|
||||||
auto salt_plus_password = info.key_encryptor.salt_value;
|
auto salt_plus_password = info.key_encryptor.salt_value;
|
||||||
auto password_bytes = xlnt::detail::byte_vector::from(password).data();
|
auto password_bytes = xlnt::detail::string_to_bytes(password);
|
||||||
std::copy(password_bytes.begin(),
|
std::copy(password_bytes.begin(),
|
||||||
password_bytes.end(),
|
password_bytes.end(),
|
||||||
std::back_inserter(salt_plus_password));
|
std::back_inserter(salt_plus_password));
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include <detail/bytes.hpp>
|
#include <detail/binary.hpp>
|
||||||
#include <detail/constants.hpp>
|
#include <detail/constants.hpp>
|
||||||
#include <detail/unicode.hpp>
|
#include <detail/unicode.hpp>
|
||||||
#include <detail/cryptography/encryption_info.hpp>
|
#include <detail/cryptography/encryption_info.hpp>
|
||||||
|
@ -42,7 +42,7 @@
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
using xlnt::detail::byte;
|
using xlnt::detail::byte;
|
||||||
using xlnt::detail::byte_vector;
|
using xlnt::detail::binary_reader;
|
||||||
using xlnt::detail::encryption_info;
|
using xlnt::detail::encryption_info;
|
||||||
|
|
||||||
std::vector<std::uint8_t> decrypt_xlsx_standard(
|
std::vector<std::uint8_t> decrypt_xlsx_standard(
|
||||||
|
@ -51,7 +51,7 @@ std::vector<std::uint8_t> decrypt_xlsx_standard(
|
||||||
{
|
{
|
||||||
const auto key = info.calculate_key();
|
const auto key = info.calculate_key();
|
||||||
|
|
||||||
auto reader = xlnt::detail::byte_reader(encrypted_package);
|
auto reader = binary_reader(encrypted_package);
|
||||||
auto decrypted_size = reader.read<std::uint64_t>();
|
auto decrypted_size = reader.read<std::uint64_t>();
|
||||||
auto decrypted = xlnt::detail::aes_ecb_decrypt(encrypted_package, key, reader.offset());
|
auto decrypted = xlnt::detail::aes_ecb_decrypt(encrypted_package, key, reader.offset());
|
||||||
decrypted.resize(static_cast<std::size_t>(decrypted_size));
|
decrypted.resize(static_cast<std::size_t>(decrypted_size));
|
||||||
|
@ -107,7 +107,7 @@ encryption_info::standard_encryption_info read_standard_encryption_info(const st
|
||||||
{
|
{
|
||||||
encryption_info::standard_encryption_info result;
|
encryption_info::standard_encryption_info result;
|
||||||
|
|
||||||
auto reader = xlnt::detail::byte_reader(info_bytes);
|
auto reader = binary_reader(info_bytes);
|
||||||
|
|
||||||
// skip version info
|
// skip version info
|
||||||
reader.read<std::uint32_t>();
|
reader.read<std::uint32_t>();
|
||||||
|
@ -275,7 +275,7 @@ encryption_info read_encryption_info(const std::vector<std::uint8_t> &info_bytes
|
||||||
|
|
||||||
info.password = password;
|
info.password = password;
|
||||||
|
|
||||||
auto reader = xlnt::detail::byte_reader(info_bytes);
|
auto reader = binary_reader(info_bytes);
|
||||||
|
|
||||||
auto version_major = reader.read<std::uint16_t>();
|
auto version_major = reader.read<std::uint16_t>();
|
||||||
auto version_minor = reader.read<std::uint16_t>();
|
auto version_minor = reader.read<std::uint16_t>();
|
||||||
|
|
|
@ -171,40 +171,41 @@ std::vector<std::uint8_t> write_agile_encryption_info(
|
||||||
|
|
||||||
std::vector<std::uint8_t> write_standard_encryption_info(const encryption_info &info)
|
std::vector<std::uint8_t> write_standard_encryption_info(const encryption_info &info)
|
||||||
{
|
{
|
||||||
xlnt::detail::byte_vector result;
|
auto result = std::vector<std::uint8_t>();
|
||||||
|
auto writer = xlnt::detail::binary_writer(result);
|
||||||
|
|
||||||
const auto version_major = std::uint16_t(4);
|
const auto version_major = std::uint16_t(4);
|
||||||
const auto version_minor = std::uint16_t(2);
|
const auto version_minor = std::uint16_t(2);
|
||||||
const auto encryption_flags = std::uint32_t(0b00010000 & 0b00100000);
|
const auto encryption_flags = std::uint32_t(0b00010000 & 0b00100000);
|
||||||
|
|
||||||
result.write(version_major);
|
writer.write(version_major);
|
||||||
result.write(version_minor);
|
writer.write(version_minor);
|
||||||
result.write(encryption_flags);
|
writer.write(encryption_flags);
|
||||||
|
|
||||||
const auto header_length = std::uint32_t(32); // calculate this!
|
const auto header_length = std::uint32_t(32); // calculate this!
|
||||||
|
|
||||||
result.write(header_length);
|
writer.write(header_length);
|
||||||
result.write(std::uint32_t(0)); // skip_flags
|
writer.write(std::uint32_t(0)); // skip_flags
|
||||||
result.write(std::uint32_t(0)); // size_extra
|
writer.write(std::uint32_t(0)); // size_extra
|
||||||
result.write(std::uint32_t(0x0000660E));
|
writer.write(std::uint32_t(0x0000660E));
|
||||||
result.write(std::uint32_t(0x00008004));
|
writer.write(std::uint32_t(0x00008004));
|
||||||
result.write(std::uint32_t(info.standard.key_bits));
|
writer.write(std::uint32_t(info.standard.key_bits));
|
||||||
result.write(std::uint32_t(0x00000018));
|
writer.write(std::uint32_t(0x00000018));
|
||||||
result.write(std::uint32_t(0));
|
writer.write(std::uint32_t(0));
|
||||||
result.write(std::uint32_t(0));
|
writer.write(std::uint32_t(0));
|
||||||
|
|
||||||
const auto provider = u"Microsoft Enhanced RSA and AES Cryptographic Provider";
|
const auto provider = std::u16string(u"Microsoft Enhanced RSA and AES Cryptographic Provider");
|
||||||
result.append(xlnt::detail::byte_vector::from(std::u16string(provider)).data());
|
writer.append(xlnt::detail::string_to_bytes(provider));
|
||||||
|
|
||||||
result.write(std::uint32_t(info.standard.salt.size()));
|
writer.write(std::uint32_t(info.standard.salt.size()));
|
||||||
result.append(info.standard.salt);
|
writer.append(info.standard.salt);
|
||||||
|
|
||||||
result.append(info.standard.encrypted_verifier);
|
writer.append(info.standard.encrypted_verifier);
|
||||||
|
|
||||||
result.write(std::uint32_t(20));
|
writer.write(std::uint32_t(20));
|
||||||
result.append(info.standard.encrypted_verifier_hash);
|
writer.append(info.standard.encrypted_verifier_hash);
|
||||||
|
|
||||||
return result.data();
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::uint8_t> encrypt_xlsx_agile(
|
std::vector<std::uint8_t> encrypt_xlsx_agile(
|
||||||
|
|
Loading…
Reference in New Issue
Block a user