diff --git a/libdigidocpp.dox b/libdigidocpp.dox
index 84b5e9633..97d30fedb 100644
--- a/libdigidocpp.dox
+++ b/libdigidocpp.dox
@@ -1400,6 +1400,8 @@ Signature Validation Policy
Default POLv2
http://open-eid.github.io/SiVa/siva/appendix/validation_policy/"
+
\-\-warnings=
(ignore, warning, error) | Optional |
diff --git a/libdigidocpp.i b/libdigidocpp.i
index 7b1e0c678..ba5273a43 100644
--- a/libdigidocpp.i
+++ b/libdigidocpp.i
@@ -241,7 +241,7 @@ namespace std {
%include "crypto/Signer.h"
%include "crypto/PKCS12Signer.h"
%include "crypto/PKCS11Signer.h"
-#ifdef SWIGCSHARP
+#ifdef _WIN32
%include "crypto/WinSigner.h"
#endif
%include "libdigidocpp.i.h"
@@ -277,16 +277,21 @@ namespace std {
}
}
%extend digidoc::Container {
+ static digidoc::Container* open(const std::string &path, OpenFlags flags)
+ {
+ return digidoc::Container::openPtr(path, flags).release();
+ }
+
Signature* prepareWebSignature(const std::vector &cert, const std::string &profile = {},
const std::vector &roles = {},
const std::string &city = {}, const std::string &state = {},
const std::string &postalCode = {}, const std::string &country = {})
{
- class : public digidoc::Signer
+ class final: public digidoc::Signer
{
public:
- digidoc::X509Cert cert() const override { return _cert; }
- std::vector sign(const std::string &, const std::vector &) const override
+ digidoc::X509Cert cert() const final { return _cert; }
+ std::vector sign(const std::string &, const std::vector &) const final
{
THROW("Not implemented");
}
diff --git a/src/ASiC_E.cpp b/src/ASiC_E.cpp
index 48045dea3..fd21a05c2 100644
--- a/src/ASiC_E.cpp
+++ b/src/ASiC_E.cpp
@@ -113,7 +113,7 @@ void ASiC_E::save(const string &path)
s.addFile("META-INF/manifest.xml", manifest, zproperty("META-INF/manifest.xml"));
for(const DataFile *file: dataFiles())
- s.addFile(file->fileName(), *(static_cast(file)->m_is.get()), zproperty(file->fileName()));
+ s.addFile(file->fileName(), *(static_cast(file)->m_is), zproperty(file->fileName()));
unsigned int i = 0;
for(Signature *iter: signatures())
@@ -158,9 +158,9 @@ void ASiC_E::addAdESSignature(istream &sigdata)
}
}
-unique_ptr ASiC_E::openInternal(const string &path)
+unique_ptr ASiC_E::openInternal(const string &path, OpenFlags flags)
{
- DEBUG("ASiC_E::openInternal(%s)", path.c_str());
+ DEBUG("ASiC_E::openInternal(%s, %d)", path.c_str(), flags);
return unique_ptr(new ASiC_E(path));
}
@@ -181,13 +181,13 @@ void ASiC_E::createManifest(ostream &os)
try
{
Manifest manifest;
- manifest.file_entry().push_back({"/", mediaType()});
+ manifest.file_entry().push_back(make_unique("/", mediaType()));
for(const DataFile *file: dataFiles())
- manifest.file_entry().push_back({file->fileName(), file->mediaType()});
+ manifest.file_entry().push_back(make_unique(file->fileName(), file->mediaType()));
xml_schema::NamespaceInfomap map;
map["manifest"].name = ASiC_E::MANIFEST_NAMESPACE;
- manifest::manifest(os, manifest, map, {}, xml_schema::Flags::dont_initialize);
+ manifest::manifest(os, manifest, map, "UTF-8", xml_schema::Flags::dont_initialize);
if(os.fail())
THROW("Failed to create manifest XML");
}
@@ -233,8 +233,8 @@ void ASiC_E::parseManifestAndLoadFiles(const ZipSerialize &z)
z.extract("META-INF/manifest.xml", manifestdata);
xml_schema::Properties p;
p.schema_location(ASiC_E::MANIFEST_NAMESPACE,
- File::fullPathUrl(Conf::instance()->xsdPath() + "/OpenDocument_manifest.xsd"));
- unique_ptr doc = SecureDOMParser(p.schema_location(), true).parseIStream(manifestdata);
+ File::fullPathUrl(Conf::instance()->xsdPath() + "/OpenDocument_manifest.xsd"));
+ unique_ptr doc = SecureDOMParser(p.schema_location(), true).parseIStream(manifestdata);
unique_ptr manifest = manifest::manifest(*doc, {}, p);
set manifestFiles;
diff --git a/src/ASiC_E.h b/src/ASiC_E.h
index 56bbc3b32..8411735f9 100644
--- a/src/ASiC_E.h
+++ b/src/ASiC_E.h
@@ -53,7 +53,7 @@ namespace digidoc
Signature* sign(Signer* signer) final;
static std::unique_ptr createInternal(const std::string &path);
- static std::unique_ptr openInternal(const std::string &path);
+ static std::unique_ptr openInternal(const std::string &path, OpenFlags flags);
private:
ASiC_E();
diff --git a/src/ASiC_S.cpp b/src/ASiC_S.cpp
index bd288a443..84b56eb3c 100644
--- a/src/ASiC_S.cpp
+++ b/src/ASiC_S.cpp
@@ -58,7 +58,7 @@ void ASiC_S::addDataFile(const string &path, const string &mediaType)
{
if(!dataFiles().empty())
THROW("Can not add document to ASiC-S container which already contains a document.");
-
+
ASiContainer::addDataFile(path, mediaType);
}
@@ -80,11 +80,11 @@ void ASiC_S::addAdESSignature(istream & /*signature*/)
THROW("Not implemented.");
}
-unique_ptr ASiC_S::openInternal(const string &path)
+unique_ptr ASiC_S::openInternal(const string &path, OpenFlags flags)
{
if (!isContainerSimpleFormat(path))
return nullptr;
- DEBUG("ASiC_S::openInternal(%s)", path.c_str());
+ DEBUG("ASiC_S::openInternal(%s, %d)", path.c_str(), flags);
return unique_ptr(new ASiC_S(path));
}
@@ -149,10 +149,10 @@ bool ASiC_S::isTimestampedASiC_S(const vector &list)
{
DEBUG("isTimestampedASiC_S()");
bool isASiCS = false;
-
+
auto dataFiles = 0;
auto hasTimestamp = false;
-
+
// container has only one file in root folder and has a timestamp
for(const string &file: list)
{
@@ -191,7 +191,7 @@ bool ASiC_S::isContainerSimpleFormat(const string &path)
{
ZipSerialize z(path, false);
vector list = z.list();
- if(find(list.begin(), list.end(), "mimetype") != list.end())
+ if(find(list.cbegin(), list.cend(), "mimetype") != list.cend())
{
stringstream iss;
z.extract("mimetype", iss);
diff --git a/src/ASiC_S.h b/src/ASiC_S.h
index 65e94621f..2e608ec41 100644
--- a/src/ASiC_S.h
+++ b/src/ASiC_S.h
@@ -44,7 +44,7 @@ namespace digidoc
Signature* sign(Signer* signer) override;
static std::unique_ptr createInternal(const std::string &path);
- static std::unique_ptr openInternal(const std::string &path);
+ static std::unique_ptr openInternal(const std::string &path, OpenFlags flags);
private:
ASiC_S();
diff --git a/src/Container.cpp b/src/Container.cpp
index 37a8aef5a..1fc846261 100644
--- a/src/Container.cpp
+++ b/src/Container.cpp
@@ -63,14 +63,15 @@ using namespace digidoc;
using namespace std;
using namespace xercesc;
-using plugin = unique_ptr (*)(const std::string &);
+using pluginCreate = unique_ptr (*)(const std::string &);
+using pluginOpen = unique_ptr (*)(const std::string &, Container::OpenFlags);
namespace digidoc
{
static string m_appName = "libdigidocpp";
static string m_userAgent = "libdigidocpp";
-static vector m_createList = {};
-static vector m_openList = {};
+static vector m_createList = {};
+static vector m_openList = {};
}
/**
@@ -349,13 +350,25 @@ Container* Container::open(const string &path)
* @throws Exception
*/
unique_ptr Container::openPtr(const string &path)
+{
+ return openPtr(path, OpenDefault);
+}
+
+/**
+ * Opens container from a file
+ *
+ * @param path
+ * @param flags
+ * @throws Exception
+ */
+unique_ptr Container::openPtr(const string &path, OpenFlags flags)
{
for(auto open: m_openList)
{
- if(unique_ptr container = open(path))
+ if(unique_ptr container = open(path, flags))
return container;
}
- return ASiC_E::openInternal(path);
+ return ASiC_E::openInternal(path, flags);
}
/**
@@ -418,7 +431,7 @@ unique_ptr Container::openPtr(const string &path)
*
* It must contain static members:
* * static Container* createInternal(const std::string &path);
- * * static Container* openInternal(const std::string &path);
+ * * static Container* openInternal(const std::string &path, OpenFlags flags);
*
* @see Container::create, Container::open
*/
diff --git a/src/Container.h b/src/Container.h
index c2f9ac6d7..d4bf6f5d8 100644
--- a/src/Container.h
+++ b/src/Container.h
@@ -43,6 +43,10 @@ DIGIDOCPP_EXPORT std::string version();
class DIGIDOCPP_EXPORT Container
{
public:
+ enum OpenFlags {
+ OpenDefault = 0,
+ OpenOffline = 1,
+ };
virtual ~Container();
virtual void save(const std::string &path = "") = 0;
@@ -66,6 +70,7 @@ class DIGIDOCPP_EXPORT Container
static std::unique_ptr createPtr(const std::string &path);
DIGIDOCPP_DEPRECATED static Container* open(const std::string &path);
static std::unique_ptr openPtr(const std::string &path);
+ static std::unique_ptr openPtr(const std::string &path, OpenFlags flags);
template
static void addContainerImplementation();
diff --git a/src/SiVaContainer.cpp b/src/SiVaContainer.cpp
index f6d65d535..e46784037 100644
--- a/src/SiVaContainer.cpp
+++ b/src/SiVaContainer.cpp
@@ -140,7 +140,7 @@ void SignatureSiVa::validate(const string &policy) const
}
-SiVaContainer::SiVaContainer(const string &path, const string &ext, bool useHashCode)
+SiVaContainer::SiVaContainer(const string &path, const string &ext, bool useHashCode, bool offline)
: d(new Private)
{
DEBUG("SiVaContainer::SiVaContainer(%s, %s, %d)", path.c_str(), ext.c_str(), useHashCode);
@@ -159,6 +159,10 @@ SiVaContainer::SiVaContainer(const string &path, const string &ext, bool useHash
d->dataFiles.push_back(new DataFilePrivate(move(ifs), File::fileName(path), "application/pdf", File::fileName(path)));
}
+ if(offline) {
+ return;
+ }
+
XMLByte buf[48*100];
string b64;
is->clear();
@@ -185,6 +189,7 @@ SiVaContainer::SiVaContainer(const string &path, const string &ext, bool useHash
Connect::Result r = Connect(url, "POST", 0, {}, CONF(verifyServiceCerts)).exec({
{"Content-Type", "application/json;charset=UTF-8"}
}, (const unsigned char*)req.c_str(), req.size());
+ req.clear();
if(!r.isOK() && !r.isStatusCode("400"))
THROW("Failed to send request to SiVa");
@@ -254,7 +259,7 @@ SiVaContainer::SiVaContainer(const string &path, const string &ext, bool useHash
for(const json &error: signature.value("errors", {}))
{
string message = error["content"];
- if(message.find("Bad digest for DataFile") == 0 && useHashCode)
+ if(message.find("Bad digest for DataFile") != string::npos && useHashCode)
THROW(message.c_str());
s->_exceptions.emplace_back(EXCEPTION_PARAMS(message.c_str()));
}
@@ -265,7 +270,7 @@ SiVaContainer::SiVaContainer(const string &path, const string &ext, bool useHash
if(message == "X509IssuerName has none or invalid namespace: null" ||
message == "X509SerialNumber has none or invalid namespace: null")
ex.setCode(Exception::IssuerNameSpaceWarning);
- else if(message.find("Bad digest for DataFile") == 0)
+ else if(message.find("Bad digest for DataFile") != string::npos)
ex.setCode(Exception::DataFileNameSpaceWarning);
else if(message == "Old and unsupported format: SK-XML version: 1.0")
continue;
@@ -277,10 +282,8 @@ SiVaContainer::SiVaContainer(const string &path, const string &ext, bool useHash
SiVaContainer::~SiVaContainer()
{
- for(const Signature *s: d->signatures)
- delete s;
- for(const DataFile *f: d->dataFiles)
- delete f;
+ for_each(d->signatures.cbegin(), d->signatures.cend(), default_delete());
+ for_each(d->dataFiles.cbegin(), d->dataFiles.cend(), default_delete());
delete d;
}
@@ -314,7 +317,7 @@ vector SiVaContainer::dataFiles() const
return d->dataFiles;
}
-unique_ptr SiVaContainer::openInternal(const string &path)
+unique_ptr SiVaContainer::openInternal(const string &path, OpenFlags flags)
{
static const set supported = {"PDF", "DDOC"};
string ext = File::fileExtension(path);
@@ -322,22 +325,20 @@ unique_ptr SiVaContainer::openInternal(const string &path)
if(!supported.count(ext))
return {};
try {
- return unique_ptr(new SiVaContainer(path, ext, true));
+ return unique_ptr(new SiVaContainer(path, ext, true, flags & OpenOffline));
} catch(const Exception &e) {
- if(e.msg().find("Bad digest for DataFile") == 0)
- return unique_ptr(new SiVaContainer(path, ext, false));
+ if(e.msg().find("Bad digest for DataFile") != string::npos)
+ return unique_ptr(new SiVaContainer(path, ext, false, flags & OpenOffline));
throw;
}
}
stringstream* SiVaContainer::parseDDoc(istream &is, bool useHashCode)
{
- auto transcode = [](const XMLCh *chr) {
- return xsd::cxx::xml::transcode(chr);
- };
+ using xsd::cxx::xml::transcode;
+ using cpXMLCh = const XMLCh*;
try
{
- using cpXMLCh = const XMLCh*;
unique_ptr dom(SecureDOMParser().parseIStream(is));
DOMNodeList *nodeList = dom->getElementsByTagName(cpXMLCh(u"DataFile"));
for(XMLSize_t i = 0; i < nodeList->getLength(); ++i)
@@ -354,7 +355,9 @@ stringstream* SiVaContainer::parseDDoc(istream &is, bool useHashCode)
if(const XMLCh *b64 = item->getTextContent())
{
d->dataFiles.push_back(new DataFilePrivate(unique_ptr(new stringstream(base64_decode(b64))),
- transcode(item->getAttribute(cpXMLCh(u"Filename"))), transcode(item->getAttribute(cpXMLCh(u"MimeType"))), transcode(item->getAttribute(cpXMLCh(u"Id")))));
+ transcode(item->getAttribute(cpXMLCh(u"Filename"))),
+ transcode(item->getAttribute(cpXMLCh(u"MimeType"))),
+ transcode(item->getAttribute(cpXMLCh(u"Id")))));
}
if(!useHashCode)
@@ -387,7 +390,7 @@ stringstream* SiVaContainer::parseDDoc(istream &is, bool useHashCode)
catch(const XMLException& e)
{
try {
- string result = transcode(e.getMessage());
+ string result = transcode(e.getMessage());
THROW("Failed to parse DDoc XML: %s", result.c_str());
} catch(const xsd::cxx::xml::invalid_utf16_string & /* ex */) {
THROW("Failed to parse DDoc XML.");
@@ -396,7 +399,7 @@ stringstream* SiVaContainer::parseDDoc(istream &is, bool useHashCode)
catch(const DOMException& e)
{
try {
- string result = transcode(e.getMessage());
+ string result = transcode(e.getMessage());
THROW("Failed to parse DDoc XML: %s", result.c_str());
} catch(const xsd::cxx::xml::invalid_utf16_string & /* ex */) {
THROW("Failed to parse DDoc XML.");
diff --git a/src/SiVaContainer.h b/src/SiVaContainer.h
index 122f8f149..768212b76 100644
--- a/src/SiVaContainer.h
+++ b/src/SiVaContainer.h
@@ -99,10 +99,10 @@ class SiVaContainer final: public Container
Signature* sign(Signer* signer) final;
static std::unique_ptr createInternal(const std::string &path);
- static std::unique_ptr openInternal(const std::string &path);
+ static std::unique_ptr openInternal(const std::string &path, OpenFlags flags);
private:
- SiVaContainer(const std::string &path, const std::string &ext, bool useHashCode);
+ SiVaContainer(const std::string &path, const std::string &ext, bool useHashCode = true, bool offline = true);
DISABLE_COPY(SiVaContainer);
std::stringstream* parseDDoc(std::istream &is, bool useHashCode);
diff --git a/src/digidoc-tool.1.cmake b/src/digidoc-tool.1.cmake
index 44ed91b31..fdfb0a5c5 100644
--- a/src/digidoc-tool.1.cmake
+++ b/src/digidoc-tool.1.cmake
@@ -24,7 +24,8 @@ Command open:
--warnings=(ignore,warning,error) - warning handling
--policy=(POLv1,POLv2) - Signature Validation Policy (default POLv2)
http://open-eid.github.io/SiVa/siva/appendix/validation_policy/
- --extractAll[=path] - extracts documents (to path when provided)
+ --extractAll[=path] - extracts documents (to path when provided)
+ --offline - open container offline (eg. Don't send to SiVa)
Command add:
Example: digidoc-tool add --file=file1.txt container-file.asice
diff --git a/src/digidoc-tool.cpp b/src/digidoc-tool.cpp
index 624f88be1..95f2c9fb7 100644
--- a/src/digidoc-tool.cpp
+++ b/src/digidoc-tool.cpp
@@ -310,7 +310,8 @@ static void printUsage(const char *executable)
<< " --warnings=(ignore,warning,error) - warning handling" << endl
<< " --policy=(POLv1,POLv2) - Signature Validation Policy (default POLv2)" << endl
<< " http://open-eid.github.io/SiVa/siva/appendix/validation_policy/" << endl
- << " --extractAll[=path] - extracts documents (to path when provided)" << endl << endl
+ << " --extractAll[=path] - extracts documents (to path when provided)" << endl << endl
+ << " --offline - open container offline (eg. Don't send to SiVa)" << endl << endl
<< " Command add:" << endl
<< " Example: " << executable << " add --file=file1.txt container-file.asice" << endl
<< " Available options:" << endl
@@ -368,10 +369,10 @@ const map ToolConfig::profiles = {
{"time-mark-archive", "time-mark-archive"},
{"time-stamp-archive", "time-stamp-archive"},
};
-string ToolConfig::RED = "\033[31m";
-string ToolConfig::GREEN = "\033[32m";
-string ToolConfig::YELLOW = "\033[33m";
-string ToolConfig::RESET = "\033[0m";
+string ToolConfig::RED = "\e[31m";
+string ToolConfig::GREEN = "\e[32m";
+string ToolConfig::YELLOW = "\e[33m";
+string ToolConfig::RESET = "\e[0m";
ToolConfig::ToolConfig(int argc, char *argv[])
: _logLevel(XmlConfCurrent::logLevel())
@@ -395,8 +396,8 @@ ToolConfig::ToolConfig(int argc, char *argv[])
else if(arg.find("--file=") == 0)
{
string arg2(i+1 < argc ? decodeParameter(argv[i+1]) : string());
- files.emplace_back(pair(arg.substr(7),
- arg2.find("--mime=") == 0 ? arg2.substr(7) : "application/octet-stream"));
+ files.emplace_back(arg.substr(7),
+ arg2.find("--mime=") == 0 ? arg2.substr(7) : "application/octet-stream");
}
#ifdef _WIN32
else if(arg == "--cng") cng = true;
@@ -553,6 +554,7 @@ static int open(int argc, char* argv[])
{
ToolConfig::Warning reportwarnings = ToolConfig::WWarning;
string path, extractPath, policy;
+ Container::OpenFlags flags = Container::OpenDefault;
int returnCode = EXIT_SUCCESS;
// Parse command line arguments.
@@ -575,6 +577,8 @@ static int open(int argc, char* argv[])
}
else if(arg.find("--policy=") == 0)
policy = arg.substr(9);
+ else if(arg.find("--offline") == 0)
+ flags = Container::OpenOffline;
else
path = arg;
}
@@ -587,7 +591,7 @@ static int open(int argc, char* argv[])
unique_ptr doc;
try {
- doc = Container::openPtr(path);
+ doc = Container::openPtr(path, flags);
} catch(const Exception &e) {
cout << "Failed to parse container" << endl;
cout << " Exception:" << endl << e;
@@ -1055,6 +1059,7 @@ int main(int argc, char *argv[])
#endif
info << ")";
digidoc::initialize("digidoc-tool", info.str());
+ std::atexit(&digidoc::terminate);
} catch(const Exception &e) {
cout << "Failed to initalize library:" << endl;
cout << "Caught Exception:" << endl << e;
@@ -1064,39 +1069,32 @@ int main(int argc, char *argv[])
if(argc < 2)
{
printUsage(argv[0]);
- digidoc::terminate();
return EXIT_SUCCESS;
}
- int returnCode = EXIT_FAILURE;
try {
string command(argv[1]);
if(command == "open")
- returnCode = open(argc, argv);
- else if(command == "create")
- returnCode = create(*conf, argv[0]);
- else if(command == "add")
- returnCode = add(*conf, argv[0]);
- else if(command == "createBatch")
- returnCode = createBatch(*conf, argv[0]);
- else if(command == "remove")
- returnCode = remove(argc, argv);
- else if(command == "sign")
- returnCode = sign(*conf, argv[0]);
- else if(command == "websign")
- returnCode = websign(*conf, argv[0]);
- else if(command == "tsl")
- returnCode = tslcmd(argc, argv);
- else if(command == "version")
- returnCode = EXIT_SUCCESS;
- else
- printUsage(argv[0]);
+ return open(argc, argv);
+ if(command == "create")
+ return create(*conf, argv[0]);
+ if(command == "add")
+ return add(*conf, argv[0]);
+ if(command == "createBatch")
+ return createBatch(*conf, argv[0]);
+ if(command == "remove")
+ return remove(argc, argv);
+ if(command == "sign")
+ return sign(*conf, argv[0]);
+ if(command == "websign")
+ return websign(*conf, argv[0]);
+ if(command == "tsl")
+ return tslcmd(argc, argv);
+ if(command == "version")
+ return EXIT_SUCCESS;
+ printUsage(argv[0]);
} catch(const Exception &e) {
cout << "Caught Exception:" << endl << e;
- returnCode = EXIT_FAILURE;
}
-
- digidoc::terminate();
-
- return returnCode;
+ return EXIT_FAILURE;
}
|