diff --git a/src/ASiContainer.h b/src/ASiContainer.h index 6be4cb088..e7e8c7769 100644 --- a/src/ASiContainer.h +++ b/src/ASiContainer.h @@ -58,6 +58,8 @@ namespace digidoc void removeSignature(unsigned int id) override; std::vector signatures() const override; + static std::string readMimetype(std::istream &is); + protected: ASiContainer(const std::string &mimetype); @@ -72,8 +74,6 @@ namespace digidoc ZipSerialize::Properties zproperty(const std::string &file) const; void zproperty(const std::string &file, ZipSerialize::Properties &&prop); - static std::string readMimetype(std::istream &path); - private: DISABLE_COPY(ASiContainer); diff --git a/src/SiVaContainer.cpp b/src/SiVaContainer.cpp index 4f1676e00..2f60cd6b1 100644 --- a/src/SiVaContainer.cpp +++ b/src/SiVaContainer.cpp @@ -24,6 +24,7 @@ #include "SiVaContainer.h" +#include "ASiContainer.h" #include "Conf.h" #include "DataFile_p.h" #include "Signature.h" @@ -31,6 +32,7 @@ #include "crypto/Digest.h" #include "util/File.h" #include "util/log.h" +#include "util/ZipSerialize.h" #include "xml/xml.hxx" #include "xml/SecureDOMParser.h" @@ -142,13 +144,15 @@ void SignatureSiVa::validate(const string &policy) const } -SiVaContainer::SiVaContainer(const string &path, const string &ext, bool useHashCode) +SiVaContainer::SiVaContainer(const string &path, bool useHashCode) : d(make_unique()) { + string ext = File::fileExtension(path); DEBUG("SiVaContainer::SiVaContainer(%s, %s, %d)", path.c_str(), ext.c_str(), useHashCode); unique_ptr ifs = make_unique(File::encodeName(d->path = path), ifstream::binary); auto fileName = File::fileName(path); istream *is = ifs.get(); + static const array asic {"asice", "sce", "asics", "scs"}; if(ext == "ddoc") { d->mediaType = "application/x-ddoc"; @@ -156,13 +160,43 @@ SiVaContainer::SiVaContainer(const string &path, const string &ext, bool useHash ifs = parseDDoc(useHashCode); is = ifs.get(); } - else + else if(ext == "pdf") { d->mediaType = "application/pdf"; d->dataFiles.push_back(new DataFilePrivate(move(ifs), fileName, "application/pdf")); } + else if(find(asic.cbegin(), asic.cend(), ext) != asic.cend()) + { + ZipSerialize z(path, false); + vector list = z.list(); + if(list.empty() || list.front() != "mimetype") + THROW("Missing mimetype"); + stringstream data; + z.extract(list.front(), data); + if(d->mediaType = ASiContainer::readMimetype(data); + d->mediaType != ASiContainer::MIMETYPE_ASIC_E && d->mediaType != ASiContainer::MIMETYPE_ASIC_S) + THROW("Unknown file"); + if(none_of(list.cbegin(), list.cend(), [](const string &file) { return file.find("p7s") != string::npos; })) + THROW("Unknown file"); + + static const string metaInf = "META-INF/"; + for(const string &file: list) + { + if(file == "mimetype" || file.substr(0, metaInf.size()) == metaInf) + continue; + const auto directory = File::directory(file); + if(directory.empty() || directory == "/" || directory == "./") + { + auto data = make_unique(); + z.extract(file, *data); + d->dataFiles.push_back(new DataFilePrivate(move(data), file, "application/octet-stream")); + } + } + } + else + THROW("Unknown file"); - array buf{}; + array buf{}; string b64; is->clear(); is->seekg(0); @@ -314,15 +348,13 @@ vector SiVaContainer::dataFiles() const unique_ptr SiVaContainer::openInternal(const string &path) { - static const array supported {"pdf", "ddoc"}; - string ext = File::fileExtension(path); - if(find(supported.cbegin(), supported.cend(), ext) == supported.cend()) - return {}; try { - return unique_ptr(new SiVaContainer(path, ext, true)); + return unique_ptr(new SiVaContainer(path, true)); } catch(const Exception &e) { if(e.msg().find("Bad digest for DataFile") == 0) - return unique_ptr(new SiVaContainer(path, ext, false)); + return unique_ptr(new SiVaContainer(path, false)); + if(e.msg() == "Unknown file") + return {}; throw; } } @@ -337,7 +369,7 @@ unique_ptr SiVaContainer::parseDDoc(bool useHashCode) DOMNodeList *nodeList = dom->getElementsByTagName(cpXMLCh(u"DataFile")); for(XMLSize_t i = 0; i < nodeList->getLength(); ++i) { - DOMElement *item = static_cast(nodeList->item(i)); + auto *item = static_cast(nodeList->item(i)); if(!item) continue; diff --git a/src/SiVaContainer.h b/src/SiVaContainer.h index 060796615..ce93edff7 100644 --- a/src/SiVaContainer.h +++ b/src/SiVaContainer.h @@ -102,7 +102,7 @@ class SiVaContainer final: public Container static std::unique_ptr openInternal(const std::string &path); private: - SiVaContainer(const std::string &path, const std::string &ext, bool useHashCode); + SiVaContainer(const std::string &path, bool useHashCode); DISABLE_COPY(SiVaContainer); std::unique_ptr parseDDoc(bool useHashCode);