Skip to content

Commit 3a42624

Browse files
committed
Option to open container offline mode
IB-7287 Signed-off-by: Raul Metsma <[email protected]>
1 parent 42a8cfd commit 3a42624

12 files changed

+108
-81
lines changed

libdigidocpp.dox

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1400,6 +1400,8 @@ Signature Validation Policy
14001400
Default POLv2
14011401

14021402
http://open-eid.github.io/SiVa/siva/appendix/validation_policy/"</td></tr>
1403+
<tr><td>\-\-offline </td><td>Optional</td><td>
1404+
open container offline (eg. Don't send to SiVa)</td></tr>
14031405
<tr><td>\-\-warnings=
14041406

14051407
(ignore, warning, error) </td><td>Optional</td><td>

libdigidocpp.i

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,7 @@ namespace std {
241241
%include "crypto/Signer.h"
242242
%include "crypto/PKCS12Signer.h"
243243
%include "crypto/PKCS11Signer.h"
244-
#ifdef SWIGCSHARP
244+
#ifdef _WIN32
245245
%include "crypto/WinSigner.h"
246246
#endif
247247
%include "libdigidocpp.i.h"
@@ -277,16 +277,21 @@ namespace std {
277277
}
278278
}
279279
%extend digidoc::Container {
280+
static Container* open(const std::string &path, OpenFlags flags)
281+
{
282+
return Container::openPtr(path, flags).release();
283+
}
284+
280285
Signature* prepareWebSignature(const std::vector<unsigned char> &cert, const std::string &profile = {},
281286
const std::vector<std::string> &roles = {},
282287
const std::string &city = {}, const std::string &state = {},
283288
const std::string &postalCode = {}, const std::string &country = {})
284289
{
285-
class : public digidoc::Signer
290+
class final: public digidoc::Signer
286291
{
287292
public:
288-
digidoc::X509Cert cert() const override { return _cert; }
289-
std::vector<unsigned char> sign(const std::string &, const std::vector<unsigned char> &) const override
293+
digidoc::X509Cert cert() const final { return _cert; }
294+
std::vector<unsigned char> sign(const std::string &, const std::vector<unsigned char> &) const final
290295
{
291296
THROW("Not implemented");
292297
}

src/ASiC_E.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ void ASiC_E::save(const string &path)
113113
s.addFile("META-INF/manifest.xml", manifest, zproperty("META-INF/manifest.xml"));
114114

115115
for(const DataFile *file: dataFiles())
116-
s.addFile(file->fileName(), *(static_cast<const DataFilePrivate*>(file)->m_is.get()), zproperty(file->fileName()));
116+
s.addFile(file->fileName(), *(static_cast<const DataFilePrivate*>(file)->m_is), zproperty(file->fileName()));
117117

118118
unsigned int i = 0;
119119
for(Signature *iter: signatures())
@@ -158,9 +158,9 @@ void ASiC_E::addAdESSignature(istream &sigdata)
158158
}
159159
}
160160

161-
unique_ptr<Container> ASiC_E::openInternal(const string &path)
161+
unique_ptr<Container> ASiC_E::openInternal(const string &path, OpenFlags flags)
162162
{
163-
DEBUG("ASiC_E::openInternal(%s)", path.c_str());
163+
DEBUG("ASiC_E::openInternal(%s, %d)", path.c_str(), flags);
164164
return unique_ptr<Container>(new ASiC_E(path));
165165
}
166166

@@ -181,13 +181,13 @@ void ASiC_E::createManifest(ostream &os)
181181
try
182182
{
183183
Manifest manifest;
184-
manifest.file_entry().push_back({"/", mediaType()});
184+
manifest.file_entry().push_back(make_unique<File_entry>("/", mediaType()));
185185
for(const DataFile *file: dataFiles())
186-
manifest.file_entry().push_back({file->fileName(), file->mediaType()});
186+
manifest.file_entry().push_back(make_unique<File_entry>(file->fileName(), file->mediaType()));
187187

188188
xml_schema::NamespaceInfomap map;
189189
map["manifest"].name = ASiC_E::MANIFEST_NAMESPACE;
190-
manifest::manifest(os, manifest, map, {}, xml_schema::Flags::dont_initialize);
190+
manifest::manifest(os, manifest, map, "UTF-8", xml_schema::Flags::dont_initialize);
191191
if(os.fail())
192192
THROW("Failed to create manifest XML");
193193
}
@@ -233,8 +233,8 @@ void ASiC_E::parseManifestAndLoadFiles(const ZipSerialize &z)
233233
z.extract("META-INF/manifest.xml", manifestdata);
234234
xml_schema::Properties p;
235235
p.schema_location(ASiC_E::MANIFEST_NAMESPACE,
236-
File::fullPathUrl(Conf::instance()->xsdPath() + "/OpenDocument_manifest.xsd"));
237-
unique_ptr<xercesc::DOMDocument> doc = SecureDOMParser(p.schema_location(), true).parseIStream(manifestdata);
236+
File::fullPathUrl(Conf::instance()->xsdPath() + "/OpenDocument_manifest.xsd"));
237+
unique_ptr<xercesc::DOMDocument> doc = SecureDOMParser(p.schema_location(), true).parseIStream(manifestdata);
238238
unique_ptr<Manifest> manifest = manifest::manifest(*doc, {}, p);
239239

240240
set<string> manifestFiles;

src/ASiC_E.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ namespace digidoc
5353
Signature* sign(Signer* signer) final;
5454

5555
static std::unique_ptr<Container> createInternal(const std::string &path);
56-
static std::unique_ptr<Container> openInternal(const std::string &path);
56+
static std::unique_ptr<Container> openInternal(const std::string &path, OpenFlags flags);
5757

5858
private:
5959
ASiC_E();

src/ASiC_S.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ void ASiC_S::addDataFile(const string &path, const string &mediaType)
5858
{
5959
if(!dataFiles().empty())
6060
THROW("Can not add document to ASiC-S container which already contains a document.");
61-
61+
6262
ASiContainer::addDataFile(path, mediaType);
6363
}
6464

@@ -80,11 +80,11 @@ void ASiC_S::addAdESSignature(istream & /*signature*/)
8080
THROW("Not implemented.");
8181
}
8282

83-
unique_ptr<Container> ASiC_S::openInternal(const string &path)
83+
unique_ptr<Container> ASiC_S::openInternal(const string &path, OpenFlags flags)
8484
{
8585
if (!isContainerSimpleFormat(path))
8686
return nullptr;
87-
DEBUG("ASiC_S::openInternal(%s)", path.c_str());
87+
DEBUG("ASiC_S::openInternal(%s, %d)", path.c_str(), flags);
8888
return unique_ptr<Container>(new ASiC_S(path));
8989
}
9090

@@ -149,10 +149,10 @@ bool ASiC_S::isTimestampedASiC_S(const vector<string> &list)
149149
{
150150
DEBUG("isTimestampedASiC_S()");
151151
bool isASiCS = false;
152-
152+
153153
auto dataFiles = 0;
154154
auto hasTimestamp = false;
155-
155+
156156
// container has only one file in root folder and has a timestamp
157157
for(const string &file: list)
158158
{
@@ -191,7 +191,7 @@ bool ASiC_S::isContainerSimpleFormat(const string &path)
191191
{
192192
ZipSerialize z(path, false);
193193
vector<string> list = z.list();
194-
if(find(list.begin(), list.end(), "mimetype") != list.end())
194+
if(find(list.cbegin(), list.cend(), "mimetype") != list.cend())
195195
{
196196
stringstream iss;
197197
z.extract("mimetype", iss);

src/ASiC_S.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ namespace digidoc
4444
Signature* sign(Signer* signer) override;
4545

4646
static std::unique_ptr<Container> createInternal(const std::string &path);
47-
static std::unique_ptr<Container> openInternal(const std::string &path);
47+
static std::unique_ptr<Container> openInternal(const std::string &path, OpenFlags flags);
4848

4949
private:
5050
ASiC_S();

src/Container.cpp

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -63,14 +63,15 @@ using namespace digidoc;
6363
using namespace std;
6464
using namespace xercesc;
6565

66-
using plugin = unique_ptr<Container> (*)(const std::string &);
66+
using pluginCreate = unique_ptr<Container> (*)(const std::string &);
67+
using pluginOpen = unique_ptr<Container> (*)(const std::string &, Container::OpenFlags);
6768

6869
namespace digidoc
6970
{
7071
static string m_appName = "libdigidocpp";
7172
static string m_userAgent = "libdigidocpp";
72-
static vector<plugin> m_createList = {};
73-
static vector<plugin> m_openList = {};
73+
static vector<pluginCreate> m_createList = {};
74+
static vector<pluginOpen> m_openList = {};
7475
}
7576

7677
/**
@@ -349,13 +350,25 @@ Container* Container::open(const string &path)
349350
* @throws Exception
350351
*/
351352
unique_ptr<Container> Container::openPtr(const string &path)
353+
{
354+
return openPtr(path, OpenDefault);
355+
}
356+
357+
/**
358+
* Opens container from a file
359+
*
360+
* @param path
361+
* @param flags
362+
* @throws Exception
363+
*/
364+
unique_ptr<Container> Container::openPtr(const string &path, OpenFlags flags)
352365
{
353366
for(auto open: m_openList)
354367
{
355-
if(unique_ptr<Container> container = open(path))
368+
if(unique_ptr<Container> container = open(path, flags))
356369
return container;
357370
}
358-
return ASiC_E::openInternal(path);
371+
return ASiC_E::openInternal(path, flags);
359372
}
360373

361374
/**
@@ -418,7 +431,7 @@ unique_ptr<Container> Container::openPtr(const string &path)
418431
*
419432
* It must contain static members:
420433
* * static Container* createInternal(const std::string &path);
421-
* * static Container* openInternal(const std::string &path);
434+
* * static Container* openInternal(const std::string &path, OpenFlags flags);
422435
*
423436
* @see Container::create, Container::open
424437
*/

src/Container.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,10 @@ DIGIDOCPP_EXPORT std::string version();
4343
class DIGIDOCPP_EXPORT Container
4444
{
4545
public:
46+
enum OpenFlags {
47+
OpenDefault = 0,
48+
OpenOffline = 1,
49+
};
4650
virtual ~Container();
4751

4852
virtual void save(const std::string &path = "") = 0;
@@ -66,6 +70,7 @@ class DIGIDOCPP_EXPORT Container
6670
static std::unique_ptr<Container> createPtr(const std::string &path);
6771
DIGIDOCPP_DEPRECATED static Container* open(const std::string &path);
6872
static std::unique_ptr<Container> openPtr(const std::string &path);
73+
static std::unique_ptr<Container> openPtr(const std::string &path, OpenFlags flags);
6974
template<class T>
7075
static void addContainerImplementation();
7176

src/SiVaContainer.cpp

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ void SignatureSiVa::validate(const string &policy) const
140140
}
141141

142142

143-
SiVaContainer::SiVaContainer(const string &path, const string &ext, bool useHashCode)
143+
SiVaContainer::SiVaContainer(const string &path, const string &ext, bool useHashCode, bool offline)
144144
: d(new Private)
145145
{
146146
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
159159
d->dataFiles.push_back(new DataFilePrivate(move(ifs), File::fileName(path), "application/pdf", File::fileName(path)));
160160
}
161161

162+
if(offline) {
163+
return;
164+
}
165+
162166
XMLByte buf[48*100];
163167
string b64;
164168
is->clear();
@@ -185,6 +189,7 @@ SiVaContainer::SiVaContainer(const string &path, const string &ext, bool useHash
185189
Connect::Result r = Connect(url, "POST", 0, {}, CONF(verifyServiceCerts)).exec({
186190
{"Content-Type", "application/json;charset=UTF-8"}
187191
}, (const unsigned char*)req.c_str(), req.size());
192+
req.clear();
188193

189194
if(!r.isOK() && !r.isStatusCode("400"))
190195
THROW("Failed to send request to SiVa");
@@ -254,7 +259,7 @@ SiVaContainer::SiVaContainer(const string &path, const string &ext, bool useHash
254259
for(const json &error: signature.value<json>("errors", {}))
255260
{
256261
string message = error["content"];
257-
if(message.find("Bad digest for DataFile") == 0 && useHashCode)
262+
if(message.find("Bad digest for DataFile") != string::npos && useHashCode)
258263
THROW(message.c_str());
259264
s->_exceptions.emplace_back(EXCEPTION_PARAMS(message.c_str()));
260265
}
@@ -265,7 +270,7 @@ SiVaContainer::SiVaContainer(const string &path, const string &ext, bool useHash
265270
if(message == "X509IssuerName has none or invalid namespace: null" ||
266271
message == "X509SerialNumber has none or invalid namespace: null")
267272
ex.setCode(Exception::IssuerNameSpaceWarning);
268-
else if(message.find("Bad digest for DataFile") == 0)
273+
else if(message.find("Bad digest for DataFile") != string::npos)
269274
ex.setCode(Exception::DataFileNameSpaceWarning);
270275
else if(message == "Old and unsupported format: SK-XML version: 1.0")
271276
continue;
@@ -277,10 +282,8 @@ SiVaContainer::SiVaContainer(const string &path, const string &ext, bool useHash
277282

278283
SiVaContainer::~SiVaContainer()
279284
{
280-
for(const Signature *s: d->signatures)
281-
delete s;
282-
for(const DataFile *f: d->dataFiles)
283-
delete f;
285+
for_each(d->signatures.cbegin(), d->signatures.cend(), default_delete<Signature>());
286+
for_each(d->dataFiles.cbegin(), d->dataFiles.cend(), default_delete<DataFile>());
284287
delete d;
285288
}
286289

@@ -314,30 +317,28 @@ vector<DataFile *> SiVaContainer::dataFiles() const
314317
return d->dataFiles;
315318
}
316319

317-
unique_ptr<Container> SiVaContainer::openInternal(const string &path)
320+
unique_ptr<Container> SiVaContainer::openInternal(const string &path, OpenFlags flags)
318321
{
319322
static const set<string> supported = {"PDF", "DDOC"};
320323
string ext = File::fileExtension(path);
321324
transform(ext.begin(), ext.end(), ext.begin(), ::toupper);
322325
if(!supported.count(ext))
323326
return {};
324327
try {
325-
return unique_ptr<Container>(new SiVaContainer(path, ext, true));
328+
return unique_ptr<Container>(new SiVaContainer(path, ext, true, flags & OpenOffline));
326329
} catch(const Exception &e) {
327-
if(e.msg().find("Bad digest for DataFile") == 0)
328-
return unique_ptr<Container>(new SiVaContainer(path, ext, false));
330+
if(e.msg().find("Bad digest for DataFile") != string::npos)
331+
return unique_ptr<Container>(new SiVaContainer(path, ext, false, flags & OpenOffline));
329332
throw;
330333
}
331334
}
332335

333336
stringstream* SiVaContainer::parseDDoc(istream &is, bool useHashCode)
334337
{
335-
auto transcode = [](const XMLCh *chr) {
336-
return xsd::cxx::xml::transcode<char>(chr);
337-
};
338+
using xsd::cxx::xml::transcode;
339+
using cpXMLCh = const XMLCh*;
338340
try
339341
{
340-
using cpXMLCh = const XMLCh*;
341342
unique_ptr<DOMDocument> dom(SecureDOMParser().parseIStream(is));
342343
DOMNodeList *nodeList = dom->getElementsByTagName(cpXMLCh(u"DataFile"));
343344
for(XMLSize_t i = 0; i < nodeList->getLength(); ++i)
@@ -354,7 +355,9 @@ stringstream* SiVaContainer::parseDDoc(istream &is, bool useHashCode)
354355
if(const XMLCh *b64 = item->getTextContent())
355356
{
356357
d->dataFiles.push_back(new DataFilePrivate(unique_ptr<istream>(new stringstream(base64_decode(b64))),
357-
transcode(item->getAttribute(cpXMLCh(u"Filename"))), transcode(item->getAttribute(cpXMLCh(u"MimeType"))), transcode(item->getAttribute(cpXMLCh(u"Id")))));
358+
transcode<char>(item->getAttribute(cpXMLCh(u"Filename"))),
359+
transcode<char>(item->getAttribute(cpXMLCh(u"MimeType"))),
360+
transcode<char>(item->getAttribute(cpXMLCh(u"Id")))));
358361
}
359362

360363
if(!useHashCode)
@@ -387,7 +390,7 @@ stringstream* SiVaContainer::parseDDoc(istream &is, bool useHashCode)
387390
catch(const XMLException& e)
388391
{
389392
try {
390-
string result = transcode(e.getMessage());
393+
string result = transcode<char>(e.getMessage());
391394
THROW("Failed to parse DDoc XML: %s", result.c_str());
392395
} catch(const xsd::cxx::xml::invalid_utf16_string & /* ex */) {
393396
THROW("Failed to parse DDoc XML.");
@@ -396,7 +399,7 @@ stringstream* SiVaContainer::parseDDoc(istream &is, bool useHashCode)
396399
catch(const DOMException& e)
397400
{
398401
try {
399-
string result = transcode(e.getMessage());
402+
string result = transcode<char>(e.getMessage());
400403
THROW("Failed to parse DDoc XML: %s", result.c_str());
401404
} catch(const xsd::cxx::xml::invalid_utf16_string & /* ex */) {
402405
THROW("Failed to parse DDoc XML.");

src/SiVaContainer.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,10 +99,10 @@ class SiVaContainer final: public Container
9999
Signature* sign(Signer* signer) final;
100100

101101
static std::unique_ptr<Container> createInternal(const std::string &path);
102-
static std::unique_ptr<Container> openInternal(const std::string &path);
102+
static std::unique_ptr<Container> openInternal(const std::string &path, OpenFlags flags);
103103

104104
private:
105-
SiVaContainer(const std::string &path, const std::string &ext, bool useHashCode);
105+
SiVaContainer(const std::string &path, const std::string &ext, bool useHashCode = true, bool offline = true);
106106
DISABLE_COPY(SiVaContainer);
107107

108108
std::stringstream* parseDDoc(std::istream &is, bool useHashCode);

0 commit comments

Comments
 (0)