Mozilla ARchive file is Mozilla's own archive format to distribute software updates. Test files can be found on Mozilla's FTP site, for example:
This page hosts a formal specification of Mozilla ARchive using Kaitai Struct. This specification can be automatically translated into a variety of programming languages to get a parsing library.
All parsing code for C++98/STL generated by Kaitai Struct depends on the C++/STL runtime library. You have to install it before you can parse data.
For C++, the easiest way is to clone the runtime library sources and build them along with your project.
Using Kaitai Struct in C++/STL usually consists of 3 steps.
std::istream
). One can open local file for that, or use existing std::string
or char*
buffer.
#include <fstream>
std::ifstream is("path/to/local/file.mar", std::ifstream::binary);
#include <sstream>
std::istringstream is(str);
#include <sstream>
const char buf[] = { ... };
std::string str(buf, sizeof buf);
std::istringstream is(str);
#include "kaitai/kaitaistream.h"
kaitai::kstream ks(&is);
mozilla_mar_t data(&ks);
After that, one can get various attributes from the structure by invoking getter methods like:
data.magic() // => get magic
#ifndef MOZILLA_MAR_H_
#define MOZILLA_MAR_H_
// This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild
#include "kaitai/kaitaistruct.h"
#include <stdint.h>
#include <vector>
#if KAITAI_STRUCT_VERSION < 9000L
#error "Incompatible Kaitai Struct C++/STL API: version 0.9 or later is required"
#endif
/**
* Mozilla ARchive file is Mozilla's own archive format to distribute software updates.
* Test files can be found on Mozilla's FTP site, for example:
*
* <http://ftp.mozilla.org/pub/firefox/nightly/partials/>
* \sa https://wiki.mozilla.org/Software_Update:MAR Source
*/
class mozilla_mar_t : public kaitai::kstruct {
public:
class mar_index_t;
class index_entries_t;
class signature_t;
class product_information_block_t;
class index_entry_t;
class additional_section_t;
enum signature_algorithms_t {
SIGNATURE_ALGORITHMS_RSA_PKCS1_SHA1 = 1,
SIGNATURE_ALGORITHMS_RSA_PKCS1_SHA384 = 2
};
enum block_identifiers_t {
BLOCK_IDENTIFIERS_PRODUCT_INFORMATION = 1
};
mozilla_mar_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent = 0, mozilla_mar_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~mozilla_mar_t();
class mar_index_t : public kaitai::kstruct {
public:
mar_index_t(kaitai::kstream* p__io, mozilla_mar_t* p__parent = 0, mozilla_mar_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~mar_index_t();
private:
uint32_t m_len_index;
index_entries_t* m_index_entries;
mozilla_mar_t* m__root;
mozilla_mar_t* m__parent;
std::string m__raw_index_entries;
kaitai::kstream* m__io__raw_index_entries;
public:
uint32_t len_index() const { return m_len_index; }
index_entries_t* index_entries() const { return m_index_entries; }
mozilla_mar_t* _root() const { return m__root; }
mozilla_mar_t* _parent() const { return m__parent; }
std::string _raw_index_entries() const { return m__raw_index_entries; }
kaitai::kstream* _io__raw_index_entries() const { return m__io__raw_index_entries; }
};
class index_entries_t : public kaitai::kstruct {
public:
index_entries_t(kaitai::kstream* p__io, mozilla_mar_t::mar_index_t* p__parent = 0, mozilla_mar_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~index_entries_t();
private:
std::vector<index_entry_t*>* m_index_entry;
mozilla_mar_t* m__root;
mozilla_mar_t::mar_index_t* m__parent;
public:
std::vector<index_entry_t*>* index_entry() const { return m_index_entry; }
mozilla_mar_t* _root() const { return m__root; }
mozilla_mar_t::mar_index_t* _parent() const { return m__parent; }
};
class signature_t : public kaitai::kstruct {
public:
signature_t(kaitai::kstream* p__io, mozilla_mar_t* p__parent = 0, mozilla_mar_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~signature_t();
private:
signature_algorithms_t m_algorithm;
uint32_t m_len_signature;
std::string m_signature;
mozilla_mar_t* m__root;
mozilla_mar_t* m__parent;
public:
signature_algorithms_t algorithm() const { return m_algorithm; }
uint32_t len_signature() const { return m_len_signature; }
std::string signature() const { return m_signature; }
mozilla_mar_t* _root() const { return m__root; }
mozilla_mar_t* _parent() const { return m__parent; }
};
class product_information_block_t : public kaitai::kstruct {
public:
product_information_block_t(kaitai::kstream* p__io, mozilla_mar_t::additional_section_t* p__parent = 0, mozilla_mar_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~product_information_block_t();
private:
std::string m_mar_channel_name;
std::string m_product_version;
mozilla_mar_t* m__root;
mozilla_mar_t::additional_section_t* m__parent;
public:
std::string mar_channel_name() const { return m_mar_channel_name; }
std::string product_version() const { return m_product_version; }
mozilla_mar_t* _root() const { return m__root; }
mozilla_mar_t::additional_section_t* _parent() const { return m__parent; }
};
class index_entry_t : public kaitai::kstruct {
public:
index_entry_t(kaitai::kstream* p__io, mozilla_mar_t::index_entries_t* p__parent = 0, mozilla_mar_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~index_entry_t();
private:
bool f_body;
std::string m_body;
public:
std::string body();
private:
uint32_t m_ofs_content;
uint32_t m_len_content;
uint32_t m_flags;
std::string m_file_name;
mozilla_mar_t* m__root;
mozilla_mar_t::index_entries_t* m__parent;
public:
uint32_t ofs_content() const { return m_ofs_content; }
uint32_t len_content() const { return m_len_content; }
/**
* File permission bits (in standard unix-style format).
*/
uint32_t flags() const { return m_flags; }
std::string file_name() const { return m_file_name; }
mozilla_mar_t* _root() const { return m__root; }
mozilla_mar_t::index_entries_t* _parent() const { return m__parent; }
};
class additional_section_t : public kaitai::kstruct {
public:
additional_section_t(kaitai::kstream* p__io, mozilla_mar_t* p__parent = 0, mozilla_mar_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~additional_section_t();
private:
uint32_t m_len_block;
block_identifiers_t m_block_identifier;
product_information_block_t* m_bytes;
bool n_bytes;
public:
bool _is_null_bytes() { bytes(); return n_bytes; };
private:
mozilla_mar_t* m__root;
mozilla_mar_t* m__parent;
std::string m__raw_bytes;
kaitai::kstream* m__io__raw_bytes;
public:
uint32_t len_block() const { return m_len_block; }
block_identifiers_t block_identifier() const { return m_block_identifier; }
product_information_block_t* bytes() const { return m_bytes; }
mozilla_mar_t* _root() const { return m__root; }
mozilla_mar_t* _parent() const { return m__parent; }
std::string _raw_bytes() const { return m__raw_bytes; }
kaitai::kstream* _io__raw_bytes() const { return m__io__raw_bytes; }
};
private:
bool f_index;
mar_index_t* m_index;
public:
mar_index_t* index();
private:
std::string m_magic;
uint32_t m_ofs_index;
uint64_t m_file_size;
uint32_t m_len_signatures;
std::vector<signature_t*>* m_signatures;
uint32_t m_len_additional_sections;
std::vector<additional_section_t*>* m_additional_sections;
mozilla_mar_t* m__root;
kaitai::kstruct* m__parent;
public:
std::string magic() const { return m_magic; }
uint32_t ofs_index() const { return m_ofs_index; }
uint64_t file_size() const { return m_file_size; }
uint32_t len_signatures() const { return m_len_signatures; }
std::vector<signature_t*>* signatures() const { return m_signatures; }
uint32_t len_additional_sections() const { return m_len_additional_sections; }
std::vector<additional_section_t*>* additional_sections() const { return m_additional_sections; }
mozilla_mar_t* _root() const { return m__root; }
kaitai::kstruct* _parent() const { return m__parent; }
};
#endif // MOZILLA_MAR_H_
// This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild
#include "mozilla_mar.h"
#include "kaitai/exceptions.h"
mozilla_mar_t::mozilla_mar_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent, mozilla_mar_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = this;
m_signatures = 0;
m_additional_sections = 0;
m_index = 0;
f_index = false;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void mozilla_mar_t::_read() {
m_magic = m__io->read_bytes(4);
if (!(magic() == std::string("\x4D\x41\x52\x31", 4))) {
throw kaitai::validation_not_equal_error<std::string>(std::string("\x4D\x41\x52\x31", 4), magic(), _io(), std::string("/seq/0"));
}
m_ofs_index = m__io->read_u4be();
m_file_size = m__io->read_u8be();
m_len_signatures = m__io->read_u4be();
m_signatures = new std::vector<signature_t*>();
const int l_signatures = len_signatures();
for (int i = 0; i < l_signatures; i++) {
m_signatures->push_back(new signature_t(m__io, this, m__root));
}
m_len_additional_sections = m__io->read_u4be();
m_additional_sections = new std::vector<additional_section_t*>();
const int l_additional_sections = len_additional_sections();
for (int i = 0; i < l_additional_sections; i++) {
m_additional_sections->push_back(new additional_section_t(m__io, this, m__root));
}
}
mozilla_mar_t::~mozilla_mar_t() {
_clean_up();
}
void mozilla_mar_t::_clean_up() {
if (m_signatures) {
for (std::vector<signature_t*>::iterator it = m_signatures->begin(); it != m_signatures->end(); ++it) {
delete *it;
}
delete m_signatures; m_signatures = 0;
}
if (m_additional_sections) {
for (std::vector<additional_section_t*>::iterator it = m_additional_sections->begin(); it != m_additional_sections->end(); ++it) {
delete *it;
}
delete m_additional_sections; m_additional_sections = 0;
}
if (f_index) {
if (m_index) {
delete m_index; m_index = 0;
}
}
}
mozilla_mar_t::mar_index_t::mar_index_t(kaitai::kstream* p__io, mozilla_mar_t* p__parent, mozilla_mar_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
m_index_entries = 0;
m__io__raw_index_entries = 0;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void mozilla_mar_t::mar_index_t::_read() {
m_len_index = m__io->read_u4be();
m__raw_index_entries = m__io->read_bytes(len_index());
m__io__raw_index_entries = new kaitai::kstream(m__raw_index_entries);
m_index_entries = new index_entries_t(m__io__raw_index_entries, this, m__root);
}
mozilla_mar_t::mar_index_t::~mar_index_t() {
_clean_up();
}
void mozilla_mar_t::mar_index_t::_clean_up() {
if (m__io__raw_index_entries) {
delete m__io__raw_index_entries; m__io__raw_index_entries = 0;
}
if (m_index_entries) {
delete m_index_entries; m_index_entries = 0;
}
}
mozilla_mar_t::index_entries_t::index_entries_t(kaitai::kstream* p__io, mozilla_mar_t::mar_index_t* p__parent, mozilla_mar_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
m_index_entry = 0;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void mozilla_mar_t::index_entries_t::_read() {
m_index_entry = new std::vector<index_entry_t*>();
{
int i = 0;
while (!m__io->is_eof()) {
m_index_entry->push_back(new index_entry_t(m__io, this, m__root));
i++;
}
}
}
mozilla_mar_t::index_entries_t::~index_entries_t() {
_clean_up();
}
void mozilla_mar_t::index_entries_t::_clean_up() {
if (m_index_entry) {
for (std::vector<index_entry_t*>::iterator it = m_index_entry->begin(); it != m_index_entry->end(); ++it) {
delete *it;
}
delete m_index_entry; m_index_entry = 0;
}
}
mozilla_mar_t::signature_t::signature_t(kaitai::kstream* p__io, mozilla_mar_t* p__parent, mozilla_mar_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void mozilla_mar_t::signature_t::_read() {
m_algorithm = static_cast<mozilla_mar_t::signature_algorithms_t>(m__io->read_u4be());
m_len_signature = m__io->read_u4be();
m_signature = m__io->read_bytes(len_signature());
}
mozilla_mar_t::signature_t::~signature_t() {
_clean_up();
}
void mozilla_mar_t::signature_t::_clean_up() {
}
mozilla_mar_t::product_information_block_t::product_information_block_t(kaitai::kstream* p__io, mozilla_mar_t::additional_section_t* p__parent, mozilla_mar_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void mozilla_mar_t::product_information_block_t::_read() {
m_mar_channel_name = kaitai::kstream::bytes_to_str(kaitai::kstream::bytes_terminate(m__io->read_bytes(64), 0, false), std::string("UTF-8"));
m_product_version = kaitai::kstream::bytes_to_str(kaitai::kstream::bytes_terminate(m__io->read_bytes(32), 0, false), std::string("UTF-8"));
}
mozilla_mar_t::product_information_block_t::~product_information_block_t() {
_clean_up();
}
void mozilla_mar_t::product_information_block_t::_clean_up() {
}
mozilla_mar_t::index_entry_t::index_entry_t(kaitai::kstream* p__io, mozilla_mar_t::index_entries_t* p__parent, mozilla_mar_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
f_body = false;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void mozilla_mar_t::index_entry_t::_read() {
m_ofs_content = m__io->read_u4be();
m_len_content = m__io->read_u4be();
m_flags = m__io->read_u4be();
m_file_name = kaitai::kstream::bytes_to_str(m__io->read_bytes_term(0, false, true, true), std::string("UTF-8"));
}
mozilla_mar_t::index_entry_t::~index_entry_t() {
_clean_up();
}
void mozilla_mar_t::index_entry_t::_clean_up() {
if (f_body) {
}
}
std::string mozilla_mar_t::index_entry_t::body() {
if (f_body)
return m_body;
kaitai::kstream *io = _root()->_io();
std::streampos _pos = io->pos();
io->seek(ofs_content());
m_body = io->read_bytes(len_content());
io->seek(_pos);
f_body = true;
return m_body;
}
mozilla_mar_t::additional_section_t::additional_section_t(kaitai::kstream* p__io, mozilla_mar_t* p__parent, mozilla_mar_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
m__io__raw_bytes = 0;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void mozilla_mar_t::additional_section_t::_read() {
m_len_block = m__io->read_u4be();
m_block_identifier = static_cast<mozilla_mar_t::block_identifiers_t>(m__io->read_u4be());
n_bytes = true;
switch (block_identifier()) {
case mozilla_mar_t::BLOCK_IDENTIFIERS_PRODUCT_INFORMATION: {
n_bytes = false;
m__raw_bytes = m__io->read_bytes(((len_block() - 4) - 4));
m__io__raw_bytes = new kaitai::kstream(m__raw_bytes);
m_bytes = new product_information_block_t(m__io__raw_bytes, this, m__root);
break;
}
default: {
m__raw_bytes = m__io->read_bytes(((len_block() - 4) - 4));
break;
}
}
}
mozilla_mar_t::additional_section_t::~additional_section_t() {
_clean_up();
}
void mozilla_mar_t::additional_section_t::_clean_up() {
if (!n_bytes) {
if (m__io__raw_bytes) {
delete m__io__raw_bytes; m__io__raw_bytes = 0;
}
if (m_bytes) {
delete m_bytes; m_bytes = 0;
}
}
}
mozilla_mar_t::mar_index_t* mozilla_mar_t::index() {
if (f_index)
return m_index;
std::streampos _pos = m__io->pos();
m__io->seek(ofs_index());
m_index = new mar_index_t(m__io, this, m__root);
m__io->seek(_pos);
f_index = true;
return m_index;
}