Skip to content

Commit

Permalink
formatting
Browse files Browse the repository at this point in the history
  • Loading branch information
Hugoberry committed Mar 28, 2024
1 parent 28d1ad4 commit f9e0fe7
Showing 1 changed file with 56 additions and 42 deletions.
98 changes: 56 additions & 42 deletions src/abf/AbfParser.cpp
Original file line number Diff line number Diff line change
@@ -1,80 +1,92 @@
#include "AbfParser.h"
#include <fstream>
// tinyxml and sqlite3 linked through vcpkg


using namespace tinyxml2;

std::vector<uint8_t> AbfParser::read_buffer_bytes(const std::vector<uint8_t>& buffer, long offset, int size) {
std::vector<uint8_t> AbfParser::read_buffer_bytes(const std::vector<uint8_t> &buffer, long offset, int size)
{
std::vector<uint8_t> sub_buffer(size);
std::copy(buffer.begin() + offset, buffer.begin() + offset + size, sub_buffer.begin());
return sub_buffer;
}

std::vector<uint8_t> AbfParser::trim_buffer(const std::vector<uint8_t>& buffer) {
std::vector<uint8_t> AbfParser::trim_buffer(const std::vector<uint8_t> &buffer)
{
int last_non_zero_byte = buffer.size() - 1;
while (last_non_zero_byte >= 1 && buffer[last_non_zero_byte] == 0x00 && buffer[last_non_zero_byte - 1] == 0x00) {
while (last_non_zero_byte >= 1 && buffer[last_non_zero_byte] == 0x00 && buffer[last_non_zero_byte - 1] == 0x00)
{
last_non_zero_byte -= 2;
}
last_non_zero_byte++;
std::vector<uint8_t> trimmed_buffer(buffer.begin(), buffer.begin() + last_non_zero_byte + 1);
return trimmed_buffer;
}

std::vector<uint8_t> AbfParser::get_sqlite(const std::string &path) {
int offset = 72;
int page = 0x1000;
int trailing_chunks = 15;
bool parsed_backup_log_header = false;
int virtual_directory_offset=0;
int virtual_directory_size=0;
std::vector<uint8_t> AbfParser::get_sqlite(const std::string &path)
{
constexpr int backup_log_header_offset = 72;
constexpr int backup_log_header_size = 0x1000 - backup_log_header_offset;
constexpr int trailing_chunks = 15;
constexpr auto DataModelFileName = "DataModel";
constexpr uint32_t LocalFileType = 1027;

int virtual_directory_offset = 0;
int virtual_directory_size = 0;
int skip_offset = 0;
uint32_t block_index_iterator = 0;

std::ifstream is_pbix(path, std::ifstream::binary);
if (!is_pbix.is_open()) {
if (!is_pbix.is_open())
{
throw std::runtime_error("Failed to open PBIX file");
}
kaitai::kstream ks_pbix(&is_pbix);
pbix_t data(&ks_pbix);

// Loop through each section in the ZIP file
for (auto& section : *data.sections()) {
if (section->section_type() != 1027) { // Not a LOCAL_FILE, skip it
for (auto &section : *data.sections())
{
if (section->section_type() != LocalFileType)
{ // Not a LOCAL_FILE, skip it
continue;
}
auto localFile = static_cast<pbix_t::local_file_t*>(section->body());
if (localFile->header()->file_name() != "DataModel") { // Not "DataModel", skip it
auto localFile = static_cast<pbix_t::local_file_t *>(section->body());
if (localFile->header()->file_name() != DataModelFileName)
{ // Not "DataModel", skip it
continue;
}

// If we reach here, we have found the DataModel section
auto datamodel = localFile->datamodel();

std::vector<uint8_t> allDecompressedData;
XPress9Wrapper xpress9Wrapper;
if (!xpress9Wrapper.Initialize()) {
if (!xpress9Wrapper.Initialize())
{
throw std::runtime_error("Failed to initialize XPress9Wrapper");
}

auto total_chunks = datamodel->chunks()->size();

for (auto& chunk : *datamodel->chunks()) {
for (auto &chunk : *datamodel->chunks())
{

int block_index = chunk->node()->header()->block_index();
if(total_chunks > trailing_chunks && !(block_index == 0 || block_index >= total_chunks - trailing_chunks)){
if (total_chunks > trailing_chunks && !(block_index == 0 || block_index >= total_chunks - trailing_chunks))
{
skip_offset += chunk->uncompressed();
continue;
}
std::vector<uint8_t> compressedData;
if(chunk->node()->header()->block_index() != block_index_iterator){
if (block_index != block_index_iterator)
{
block_index_iterator++;
//make a copy of the header structure
// make a copy of the header structure
auto header = chunk->node()->header();
//searialize it back to a buffer
// searialize it back to a buffer
std::vector<uint8_t> header_buffer;
// UInt32 serialization routine
auto write_uint32 = [&](uint32_t value) {
auto write_uint32 = [&](uint32_t value)
{
header_buffer.push_back(value & 0xFF);
header_buffer.push_back((value >> 8) & 0xFF);
header_buffer.push_back((value >> 16) & 0xFF);
Expand All @@ -94,59 +106,61 @@ std::vector<uint8_t> AbfParser::get_sqlite(const std::string &path) {
auto segments = chunk->node()->segments();

header_buffer.insert(header_buffer.end(), segments.begin(), segments.end());
compressedData = std::vector<unsigned char>(header_buffer.begin(), header_buffer.end());
} else {
compressedData = std::vector<unsigned char>(header_buffer.begin(), header_buffer.end());
}
else
{
auto node = chunk->_raw_node();
compressedData = std::vector<unsigned char>(node.begin(), node.end());
compressedData = std::vector<unsigned char>(node.begin(), node.end());
}
// Buffers for storing decompressed data
std::vector<uint8_t> x9DecompressedBuffer(chunk->uncompressed());

// Decompress the entire data
uint32_t totalDecompressedSize = xpress9Wrapper.Decompress(compressedData.data(), chunk->compressed(), x9DecompressedBuffer.data(), x9DecompressedBuffer.size());
// Verify that the total decompressed size matches the expected size
if (totalDecompressedSize != chunk->uncompressed()) {
if (totalDecompressedSize != chunk->uncompressed())
{
throw std::runtime_error("Decompressed size does not match expected size.");
}
else {
else
{
// Add the decompressed data to the overall buffer
allDecompressedData.insert(allDecompressedData.end(), x9DecompressedBuffer.begin(), x9DecompressedBuffer.end());
}

if(!parsed_backup_log_header){
std::vector<uint8_t> backup_log_header_buffer = read_buffer_bytes(allDecompressedData, offset, page - offset);
if (block_index == 0)
{
std::vector<uint8_t> backup_log_header_buffer = read_buffer_bytes(allDecompressedData, backup_log_header_offset, backup_log_header_size);
backup_log_header_buffer = trim_buffer(backup_log_header_buffer);
BackupLogHeader backup_log_header = BackupLogHeader::from_xml(backup_log_header_buffer, "UTF-16");
virtual_directory_offset = static_cast<int>(backup_log_header.m_cbOffsetHeader);
virtual_directory_size = static_cast<int>(backup_log_header.DataSize);
parsed_backup_log_header = true;
}

if(skip_offset + allDecompressedData.size() >= virtual_directory_offset + virtual_directory_size){

if (skip_offset + allDecompressedData.size() >= virtual_directory_offset + virtual_directory_size)
{

std::string buffer_str(allDecompressedData.begin(), allDecompressedData.end());

std::vector<uint8_t> virtual_directory_buffer = read_buffer_bytes(allDecompressedData, virtual_directory_offset-skip_offset, virtual_directory_size);
std::vector<uint8_t> virtual_directory_buffer = read_buffer_bytes(allDecompressedData, virtual_directory_offset - skip_offset, virtual_directory_size);
VirtualDirectory virtual_directory = VirtualDirectory::from_xml(virtual_directory_buffer, "UTF-8");


BackupFile log = virtual_directory.backupFiles->back();
int backup_file_offset = static_cast<int>(log.m_cbOffsetHeader);
int backup_file_size = static_cast<int>(log.Size);

std::vector<uint8_t> backup_log_buffer = read_buffer_bytes(allDecompressedData, backup_file_offset+2-skip_offset, backup_file_size-2);
std::vector<uint8_t> backup_log_buffer = read_buffer_bytes(allDecompressedData, backup_file_offset + 2 - skip_offset, backup_file_size - 2);
BackupLog backup_log = BackupLog::from_xml(backup_log_buffer, "UTF-16");

auto sqlite = (*virtual_directory.backupFiles)[static_cast<int>(virtual_directory.backupFiles->size()) - 2];
int sqlite_offset = static_cast<int>(sqlite.m_cbOffsetHeader);
int sqlite_size = static_cast<int>(sqlite.Size);

std::vector<uint8_t> sqlite_buffer = read_buffer_bytes(allDecompressedData, sqlite_offset-skip_offset, sqlite_size);
std::vector<uint8_t> sqlite_buffer = read_buffer_bytes(allDecompressedData, sqlite_offset - skip_offset, sqlite_size);

return sqlite_buffer;
}

}

}
}

0 comments on commit f9e0fe7

Please sign in to comment.