Skip to content

Commit 036ab5d

Browse files
committed
Add extend Container validity method
IB-8265 Signed-off-by: Raul Metsma <[email protected]>
1 parent d08ea43 commit 036ab5d

12 files changed

+233
-142
lines changed

libdigidocpp.i

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,9 +215,11 @@ static std::vector<unsigned char>* SWIG_JavaArrayToVectorUnsignedChar(JNIEnv *je
215215
// std::unique_ptr is since swig 4.1
216216
%ignore digidoc::Container::createPtr;
217217
%ignore digidoc::Container::openPtr;
218+
%ignore digidoc::Container::extendContainerValidity;
218219

219220
%newobject digidoc::Container::open;
220221
%newobject digidoc::Container::create;
222+
%newobject digidoc::Container::extendContainerValidity;
221223

222224
%immutable digidoc::TSAInfo::cert;
223225
%immutable digidoc::TSAInfo::time;
@@ -281,7 +283,14 @@ def transfer(self):
281283
%template(Signatures) std::vector<digidoc::Signature*>;
282284
%template(TSAInfos) std::vector<digidoc::TSAInfo>;
283285

286+
%rename("%s") digidoc::Container::extendContainerValidity;
287+
284288
%extend digidoc::Container {
289+
static Container* extendContainerValidity(Container &doc, Signer *signer)
290+
{
291+
return digidoc::Container::extendContainerValidity(doc, signer).release();
292+
}
293+
285294
static digidoc::Container* open(const std::string &path, digidoc::ContainerOpenCB *cb)
286295
{
287296
return digidoc::Container::openPtr(path, cb).release();

src/ASiC_E.cpp

Lines changed: 82 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -51,21 +51,89 @@ class ASiC_E::Private
5151
/**
5252
* Initialize BDOC container.
5353
*/
54-
ASiC_E::ASiC_E()
55-
: ASiContainer(MIMETYPE_ASIC_E)
54+
ASiC_E::ASiC_E(const string &path, bool create)
55+
: ASiContainer(path, MIMETYPE_ASIC_E)
5656
, d(make_unique<Private>())
5757
{
58-
}
58+
if(create)
59+
return;
60+
auto z = load(true, {MIMETYPE_ASIC_E, MIMETYPE_ADOC});
5961

60-
/**
61-
* Opens ASiC container from a file
62-
*/
63-
ASiC_E::ASiC_E(const string &path)
64-
: ASiContainer(MIMETYPE_ASIC_E)
65-
, d(make_unique<Private>())
66-
{
67-
auto zip = load(path, true, {MIMETYPE_ASIC_E, MIMETYPE_ADOC});
68-
parseManifestAndLoadFiles(zip);
62+
try
63+
{
64+
auto manifestdata = z.extract<stringstream>("META-INF/manifest.xml");
65+
auto doc = XMLDocument::openStream(manifestdata, {"manifest", MANIFEST_NS});
66+
doc.validateSchema(File::path(Conf::instance()->xsdPath(), "OpenDocument_manifest_v1_2.xsd"));
67+
68+
set<string_view> manifestFiles;
69+
bool mimeFound = false;
70+
for(auto file = doc/"file-entry"; file; file++)
71+
{
72+
auto full_path = file[{"full-path", MANIFEST_NS}];
73+
auto media_type = file[{"media-type", MANIFEST_NS}];
74+
DEBUG("full_path = '%s', media_type = '%s'", full_path.data(), media_type.data());
75+
76+
if(manifestFiles.find(full_path) != manifestFiles.end())
77+
THROW("Manifest multiple entries defined for file '%s'.", full_path.data());
78+
79+
// ODF does not specify that mimetype should be first in manifest
80+
if(full_path == "/")
81+
{
82+
if(mediaType() != media_type)
83+
THROW("Manifest has incorrect container media type defined '%s', expecting '%s'.", media_type.data(), mediaType().c_str());
84+
mimeFound = true;
85+
continue;
86+
}
87+
if(full_path.back() == '/') // Skip Directory entries
88+
continue;
89+
90+
manifestFiles.insert(full_path);
91+
if(mediaType() == MIMETYPE_ADOC &&
92+
(full_path.compare(0, 9, "META-INF/") == 0 ||
93+
full_path.compare(0, 9, "metadata/") == 0))
94+
d->metadata.push_back(new DataFilePrivate(dataStream(full_path, z), string(full_path), string(media_type)));
95+
else
96+
addDataFilePrivate(dataStream(full_path, z), string(full_path), string(media_type));
97+
}
98+
if(!mimeFound)
99+
THROW("Manifest is missing mediatype file entry.");
100+
101+
for(const string &file: z.list())
102+
{
103+
/**
104+
* http://www.etsi.org/deliver/etsi_ts/102900_102999/102918/01.03.01_60/ts_102918v010301p.pdf
105+
* 6.2.2 Contents of Container
106+
* 3) The root element of each "*signatures*.xml" content shall be either:
107+
*/
108+
if(file.compare(0, 9, "META-INF/") == 0 &&
109+
file.find("signatures") != string::npos)
110+
{
111+
try
112+
{
113+
auto data = z.extract<stringstream>(file);
114+
loadSignatures(data, file);
115+
}
116+
catch(const Exception &e)
117+
{
118+
THROW_CAUSE(e, "Failed to parse signature '%s'.", file.c_str());
119+
}
120+
continue;
121+
}
122+
123+
if(file == "mimetype" || file.compare(0, 8,"META-INF") == 0)
124+
continue;
125+
if(manifestFiles.count(file) == 0)
126+
THROW("File '%s' found in container is not described in manifest.", file.c_str());
127+
}
128+
}
129+
catch(const Exception &e)
130+
{
131+
THROW_CAUSE(e, "Failed to parse manifest");
132+
}
133+
catch(...)
134+
{
135+
THROW("Failed to parse manifest XML: Unknown exception");
136+
}
69137
}
70138

71139
ASiC_E::~ASiC_E()
@@ -110,9 +178,7 @@ void ASiC_E::save(const ZipSerialize &s)
110178
unique_ptr<Container> ASiC_E::createInternal(const string &path)
111179
{
112180
DEBUG("ASiC_E::createInternal(%s)", path.c_str());
113-
unique_ptr<ASiC_E> doc = unique_ptr<ASiC_E>(new ASiC_E);
114-
doc->zpath(path);
115-
return doc;
181+
return unique_ptr<Container>(new ASiC_E(path, true));
116182
}
117183

118184
/**
@@ -146,7 +212,7 @@ void ASiC_E::canSave()
146212
unique_ptr<Container> ASiC_E::openInternal(const string &path)
147213
{
148214
DEBUG("ASiC_E::openInternal(%s)", path.c_str());
149-
return unique_ptr<Container>(new ASiC_E(path));
215+
return unique_ptr<Container>(new ASiC_E(path, false));
150216
}
151217

152218
void ASiC_E::loadSignatures(istream &data, const string &file)
@@ -157,94 +223,6 @@ void ASiC_E::loadSignatures(istream &data, const string &file)
157223
addSignature(make_unique<SignatureXAdES_LTA>(signatures, s, this));
158224
}
159225

160-
/**
161-
* Parses manifest file and checks that files described in manifest exist, also
162-
* checks that no extra file do exist that are not described in manifest.xml.
163-
*
164-
* @param path directory on disk of the BDOC container.
165-
* @throws Exception exception is thrown if the manifest.xml file parsing failed.
166-
*/
167-
void ASiC_E::parseManifestAndLoadFiles(const ZipSerialize &z)
168-
{
169-
DEBUG("ASiC_E::readManifest()");
170-
171-
try
172-
{
173-
auto manifestdata = z.extract<stringstream>("META-INF/manifest.xml");
174-
auto doc = XMLDocument::openStream(manifestdata, {"manifest", MANIFEST_NS});
175-
doc.validateSchema(File::path(Conf::instance()->xsdPath(), "OpenDocument_manifest_v1_2.xsd"));
176-
177-
set<string_view> manifestFiles;
178-
bool mimeFound = false;
179-
for(auto file = doc/"file-entry"; file; file++)
180-
{
181-
auto full_path = file[{"full-path", MANIFEST_NS}];
182-
auto media_type = file[{"media-type", MANIFEST_NS}];
183-
DEBUG("full_path = '%s', media_type = '%s'", full_path.data(), media_type.data());
184-
185-
if(manifestFiles.find(full_path) != manifestFiles.end())
186-
THROW("Manifest multiple entries defined for file '%s'.", full_path.data());
187-
188-
// ODF does not specify that mimetype should be first in manifest
189-
if(full_path == "/")
190-
{
191-
if(mediaType() != media_type)
192-
THROW("Manifest has incorrect container media type defined '%s', expecting '%s'.", media_type.data(), mediaType().c_str());
193-
mimeFound = true;
194-
continue;
195-
}
196-
if(full_path.back() == '/') // Skip Directory entries
197-
continue;
198-
199-
manifestFiles.insert(full_path);
200-
if(mediaType() == MIMETYPE_ADOC &&
201-
(full_path.compare(0, 9, "META-INF/") == 0 ||
202-
full_path.compare(0, 9, "metadata/") == 0))
203-
d->metadata.push_back(new DataFilePrivate(dataStream(full_path, z), string(full_path), string(media_type)));
204-
else
205-
addDataFilePrivate(dataStream(full_path, z), string(full_path), string(media_type));
206-
}
207-
if(!mimeFound)
208-
THROW("Manifest is missing mediatype file entry.");
209-
210-
for(const string &file: z.list())
211-
{
212-
/**
213-
* http://www.etsi.org/deliver/etsi_ts/102900_102999/102918/01.03.01_60/ts_102918v010301p.pdf
214-
* 6.2.2 Contents of Container
215-
* 3) The root element of each "*signatures*.xml" content shall be either:
216-
*/
217-
if(file.compare(0, 9, "META-INF/") == 0 &&
218-
file.find("signatures") != string::npos)
219-
{
220-
try
221-
{
222-
auto data = z.extract<stringstream>(file);
223-
loadSignatures(data, file);
224-
}
225-
catch(const Exception &e)
226-
{
227-
THROW_CAUSE(e, "Failed to parse signature '%s'.", file.c_str());
228-
}
229-
continue;
230-
}
231-
232-
if(file == "mimetype" || file.compare(0, 8,"META-INF") == 0)
233-
continue;
234-
if(manifestFiles.count(file) == 0)
235-
THROW("File '%s' found in container is not described in manifest.", file.c_str());
236-
}
237-
}
238-
catch(const Exception &e)
239-
{
240-
THROW_CAUSE(e, "Failed to parse manifest");
241-
}
242-
catch(...)
243-
{
244-
THROW("Failed to parse manifest XML: Unknown exception");
245-
}
246-
}
247-
248226
Signature* ASiC_E::prepareSignature(Signer *signer)
249227
{
250228
if(mediaType() != MIMETYPE_ASIC_E)

src/ASiC_E.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,12 +50,10 @@ namespace digidoc
5050
static std::unique_ptr<Container> openInternal(const std::string &path);
5151

5252
private:
53-
ASiC_E();
54-
ASiC_E(const std::string &path);
53+
ASiC_E(const std::string &path, bool create);
5554
DISABLE_COPY(ASiC_E);
5655
void canSave() final;
5756
void loadSignatures(std::istream &data, const std::string &file);
58-
void parseManifestAndLoadFiles(const ZipSerialize &z);
5957
void save(const ZipSerialize &s) final;
6058

6159
class Private;

src/ASiC_S.cpp

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -35,17 +35,12 @@ using namespace std;
3535
/**
3636
* Initialize ASiCS container.
3737
*/
38-
ASiC_S::ASiC_S()
39-
: ASiContainer(MIMETYPE_ASIC_S)
40-
{}
41-
42-
/**
43-
* Opens ASiC-S container from a file
44-
*/
45-
ASiC_S::ASiC_S(const string &path)
46-
: ASiContainer(MIMETYPE_ASIC_S)
38+
ASiC_S::ASiC_S(const string &path, bool create)
39+
: ASiContainer(path, MIMETYPE_ASIC_S)
4740
{
48-
auto z = load(path, false, {mediaType()});
41+
if(create)
42+
return;
43+
auto z = load(false, {mediaType()});
4944
bool foundTimestamp = false;
5045
for(const string &file: z.list())
5146
{
@@ -104,9 +99,7 @@ unique_ptr<Container> ASiC_S::createInternal(const string &path)
10499
if(!util::File::fileExtension(path, {"asics", "scs"}))
105100
return {};
106101
DEBUG("ASiC_S::createInternal(%s)", path.c_str());
107-
auto doc = unique_ptr<ASiC_S>(new ASiC_S());
108-
doc->zpath(path);
109-
return doc;
102+
return unique_ptr<Container>(new ASiC_S(path, true));
110103
}
111104

112105
void ASiC_S::addAdESSignature(istream & /*signature*/)
@@ -127,7 +120,7 @@ unique_ptr<Container> ASiC_S::openInternal(const string &path, ContainerOpenCB *
127120
{
128121
if(util::File::fileExtension(path, {"asice", "sce", "bdoc"}))
129122
return {};
130-
return unique_ptr<Container>(new ASiC_S(path));
123+
return unique_ptr<Container>(new ASiC_S(path, false));
131124
}
132125
catch(const Exception &)
133126
{

src/ASiC_S.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,7 @@ namespace digidoc
4141
static std::unique_ptr<Container> openInternal(const std::string &path, ContainerOpenCB *cb);
4242

4343
private:
44-
ASiC_S();
45-
ASiC_S(const std::string &path);
44+
ASiC_S(const std::string &path, bool create);
4645
DISABLE_COPY(ASiC_S);
4746

4847
void addDataFileChecks(const std::string &path, const std::string &mediaType) override;

src/ASiContainer.cpp

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ constexpr unsigned long MAX_MEM_FILE = 500UL*1024UL*1024UL;
4141
class ASiContainer::Private
4242
{
4343
public:
44-
string mimetype, path;
44+
string path, mimetype;
4545
vector<DataFile*> documents;
4646
vector<Signature*> signatures;
4747
map<string, ZipSerialize::Properties, std::less<>> properties;
@@ -50,9 +50,10 @@ class ASiContainer::Private
5050
/**
5151
* Initialize Container.
5252
*/
53-
ASiContainer::ASiContainer(string_view mimetype)
53+
ASiContainer::ASiContainer(string_view path, string_view mimetype)
5454
: d(make_unique<Private>())
5555
{
56+
d->path = string(path);
5657
d->mimetype = string(mimetype);
5758
}
5859

@@ -80,10 +81,10 @@ XMLDocument ASiContainer::createManifest() const
8081
* @param supported supported mimetypes.
8182
* @return returns zip serializer for the container.
8283
*/
83-
ZipSerialize ASiContainer::load(const string &path, bool mimetypeRequired, const set<string_view> &supported)
84+
ZipSerialize ASiContainer::load(bool mimetypeRequired, const set<string_view> &supported)
8485
{
85-
DEBUG("ASiContainer::ASiContainer(path = '%s')", path.c_str());
86-
ZipSerialize z(d->path = path, false);
86+
DEBUG("ASiContainer::ASiContainer(path = '%s')", d->path.c_str());
87+
ZipSerialize z(d->path, false);
8788
vector<string> list = z.list();
8889

8990
// ETSI TS 102 918: mimetype has to be the first in the archive
@@ -265,8 +266,8 @@ void ASiContainer::save(const string &path)
265266
THROW("Can not save, container is empty.");
266267
canSave();
267268
if(!path.empty())
268-
zpath(path);
269-
ZipSerialize s(zpath(), true);
269+
d->path = path;
270+
ZipSerialize s(d->path, true);
270271
s.addFile("mimetype", zproperty("mimetype"), false)(mediaType());
271272

272273
array<char,10240> buf{};
@@ -287,12 +288,7 @@ void ASiContainer::save(const string &path)
287288
save(s);
288289
}
289290

290-
void ASiContainer::zpath(const string &file)
291-
{
292-
d->path = file;
293-
}
294-
295-
string ASiContainer::zpath() const
291+
const string& ASiContainer::path() const
296292
{
297293
return d->path;
298294
}

src/ASiContainer.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,22 +59,21 @@ namespace digidoc
5959
std::vector<Signature*> signatures() const override;
6060

6161
static std::string readMimetype(const ZipSerialize &z);
62+
const std::string& path() const override;
6263

6364
protected:
64-
ASiContainer(std::string_view mimetype);
65+
ASiContainer(std::string_view path, std::string_view mimetype);
6566

6667
virtual void addDataFileChecks(const std::string &path, const std::string &mediaType);
6768
void addDataFilePrivate(std::unique_ptr<std::istream> is, std::string fileName, std::string mediaType);
6869
Signature* addSignature(std::unique_ptr<Signature> &&signature);
6970
virtual void canSave() = 0;
7071
XMLDocument createManifest() const;
7172
std::unique_ptr<std::iostream> dataStream(std::string_view path, const ZipSerialize &z) const;
72-
ZipSerialize load(const std::string &path, bool requireMimetype, const std::set<std::string_view> &supported);
73+
ZipSerialize load(bool requireMimetype, const std::set<std::string_view> &supported);
7374
virtual void save(const ZipSerialize &s) = 0;
7475
void deleteSignature(Signature* s);
7576

76-
void zpath(const std::string &file);
77-
std::string zpath() const;
7877
const ZipSerialize::Properties& zproperty(std::string_view file) const;
7978

8079
private:

0 commit comments

Comments
 (0)