Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 20 additions & 37 deletions src/ASiContainer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,10 @@

#include "DataFile_p.h"
#include "Signature.h"
#include "util/DateTime.h"
#include "util/File.h"
#include "util/log.h"
#include "util/ZipSerialize.h"

#include <algorithm>
#include <array>
#include <ctime>
#include <fstream>
#include <map>
Expand All @@ -48,29 +45,24 @@ class ASiContainer::Private
map<string, ZipSerialize::Properties> properties;
};

const string ASiContainer::MIMETYPE_ASIC_E = "application/vnd.etsi.asic-e+zip";
const string ASiContainer::MIMETYPE_ASIC_S = "application/vnd.etsi.asic-s+zip";
//https://signa.mitsoft.lt/static/signa-web/webResources/docs/ADOC_specification_approved20090907_EN.pdf
const string ASiContainer::MIMETYPE_ADOC = "application/vnd.lt.archyvai.adoc-2008";

/**
* Initialize BDOC container.
* Initialize Container.
*/
ASiContainer::ASiContainer(const string &mimetype)
ASiContainer::ASiContainer(string_view mimetype)
: d(make_unique<Private>())
{
d->mimetype = mimetype;
}

/**
* Loads ASi Container from a file.
* Loads Container from a file.
*
* @param path name of the container file.
* @param mimetypeRequired flag indicating if the mimetype must be present and checked.
* @param supported supported mimetypes.
* @return returns zip serializer for the container.
*/
unique_ptr<ZipSerialize> ASiContainer::load(const string &path, bool mimetypeRequired, const set<string> &supported)
unique_ptr<ZipSerialize> ASiContainer::load(const string &path, bool mimetypeRequired, const set<string_view> &supported)
{
DEBUG("ASiContainer::ASiContainer(path = '%s')", path.c_str());
auto z = make_unique<ZipSerialize>(d->path = path, false);
Expand All @@ -79,17 +71,17 @@ unique_ptr<ZipSerialize> ASiContainer::load(const string &path, bool mimetypeReq
if(list.empty())
THROW("Failed to parse container");

// ETSI TS 102 918: mimetype has to be the first in the archive
if(mimetypeRequired && list.front() != "mimetype")
THROW("required mimetype not found");

// ETSI TS 102 918: mimetype has to be the first in the archive
if(list.front() == "mimetype")
{
d->mimetype = readMimetype(*z);
DEBUG("mimetype = '%s'", d->mimetype.c_str());
if(supported.find(d->mimetype) == supported.cend())
THROW("Incorrect mimetype '%s'", d->mimetype.c_str());
}
DEBUG("mimetype = '%s'", d->mimetype.c_str());

for(const string &file: list)
d->properties[file] = z->properties(file);
Expand Down Expand Up @@ -167,24 +159,20 @@ void ASiContainer::addDataFile(const string &path, const string &mediaType)
{
string fileName = File::fileName(path);
addDataFileChecks(fileName, mediaType);
if(!File::fileExists(path))
THROW("Document file '%s' does not exist.", path.c_str());

ZipSerialize::Properties prop { appInfo(), File::modifiedTime(path), File::fileSize(path) };
bool useTempFile = prop.size > MAX_MEM_FILE;
zproperty(fileName, std::move(prop));
unique_ptr<istream> is;
if(useTempFile)
{
is = make_unique<ifstream>(File::encodeName(path), ifstream::binary);
}
else
auto size = File::fileSize(path);
if(size == 0)
THROW("Document file '%s' does not exist or is empty.", path.c_str());

unique_ptr<istream> is = make_unique<ifstream>(File::encodeName(path), ifstream::binary);
if(!*is)
THROW("Failed to open file for reading: %s.", path.c_str());
if(size <= MAX_MEM_FILE)
{
auto data = make_unique<stringstream>();
if(ifstream file{File::encodeName(path), ifstream::binary})
*data << file.rdbuf();
*data << is->rdbuf();
is = std::move(data);
}
d->properties[fileName] = { appInfo(), File::modifiedTime(path), size };
addDataFilePrivate(std::move(is), std::move(fileName), mediaType);
}

Expand Down Expand Up @@ -270,18 +258,13 @@ string ASiContainer::zpath() const
return d->path;
}

ZipSerialize::Properties ASiContainer::zproperty(const string &file) const
const ZipSerialize::Properties& ASiContainer::zproperty(const string &file) const
{
if(auto i = d->properties.find(file); i != d->properties.cend())
return i->second;
return d->properties[file] = { appInfo(), time(nullptr), 0 };
}

void ASiContainer::zproperty(const string &file, ZipSerialize::Properties &&prop)
{
d->properties[file] = std::move(prop);
}

/**
* Reads and parses container mimetype. Checks that the mimetype is supported.
*
Expand All @@ -294,9 +277,9 @@ string ASiContainer::readMimetype(const ZipSerialize &z)
DEBUG("ASiContainer::readMimetype()");
stringstream is;
z.extract("mimetype", is);
string text;
is >> text;
if(!is)
string text = is.str();
text.erase(text.find_last_not_of(" \n\r\f\t\v") + 1);
if(text.empty())
THROW("Failed to read mimetype.");
// Contains UTF-16 BOM
if(text.find("\xFF\xEF") == 0 || text.find("\xEF\xFF") == 0)
Expand Down
14 changes: 7 additions & 7 deletions src/ASiContainer.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,10 @@ namespace digidoc
class ASiContainer: public Container
{
public:
static const std::string MIMETYPE_ASIC_E;
static const std::string MIMETYPE_ASIC_S;
static const std::string MIMETYPE_ADOC;
static constexpr std::string_view MIMETYPE_ASIC_E = "application/vnd.etsi.asic-e+zip";
static constexpr std::string_view MIMETYPE_ASIC_S = "application/vnd.etsi.asic-s+zip";
//https://signa.mitsoft.lt/static/signa-web/webResources/docs/ADOC_specification_approved20090907_EN.pdf
static constexpr std::string_view MIMETYPE_ADOC = "application/vnd.lt.archyvai.adoc-2008";

~ASiContainer() override;
std::string mediaType() const override;
Expand All @@ -55,18 +56,17 @@ namespace digidoc
static std::string readMimetype(const ZipSerialize &z);

protected:
ASiContainer(const std::string &mimetype);
ASiContainer(std::string_view mimetype);

void addDataFilePrivate(std::unique_ptr<std::istream> is, std::string fileName, std::string mediaType);
Signature* addSignature(std::unique_ptr<Signature> &&signature);
std::unique_ptr<std::iostream> dataStream(const std::string &path, const ZipSerialize &z) const;
std::unique_ptr<ZipSerialize> load(const std::string &path, bool requireMimetype, const std::set<std::string> &supported);
std::unique_ptr<ZipSerialize> load(const std::string &path, bool requireMimetype, const std::set<std::string_view> &supported);
void deleteSignature(Signature* s);

void zpath(const std::string &file);
std::string zpath() const;
ZipSerialize::Properties zproperty(const std::string &file) const;
void zproperty(const std::string &file, ZipSerialize::Properties &&prop);
const ZipSerialize::Properties &zproperty(const std::string &file) const;

private:
DISABLE_COPY(ASiContainer);
Expand Down