29 #include "xml/OpenDocument_manifest.hxx"
76 std::auto_ptr<ISerialize> serializer(
new ZipSerialize(path));
99 while(!d->signatures.empty())
101 delete (d->signatures.back());
102 d->signatures.pop_back();
118 DEBUG(
"BDoc::readFrom(serializer = %p '%s')", serializer.get(), serializer->getPath().c_str());
121 d->serializer = serializer;
124 std::string tmpPath = d->serializer->extract();
127 readMimetype(tmpPath);
130 parseManifestAndLoadFiles(tmpPath);
144 if(!d->serializer.get())
145 THROW_BDOCEXCEPTION(
"You can not use save() method if you didn't open a container with readFrom() method. Use saveTo() method in case of new a BDoc container.");
148 if( d->documents.empty() )
152 d->serializer->create();
155 d->serializer->addFile(
"mimetype", createMimetype());
160 d->serializer->addFile(
"META-INF/manifest.xml", createManifest());
163 for(std::vector<Document>::const_iterator iter = d->documents.begin(); iter != d->documents.end(); iter++)
165 d->serializer->addFile(iter->getFileName(), iter->getFilePath());
166 std::cout <<
"added file " << iter->getFileName() <<
" to documents." << std::endl;
171 for(std::vector<Signature*>::const_iterator iter = d->signatures.begin(); iter != d->signatures.end(); iter++)
173 d->serializer->addFile(
Log::format(
"META-INF/signature%u.xml", i++), (*iter)->saveToXml());
177 d->serializer->save();
206 if(!d->signatures.empty())
207 THROW_BDOCEXCEPTION(
"Can not add document to container which has signatures, remove all signatures before adding new document.");
214 for(std::vector<Document>::const_iterator iter = d->documents.begin(); iter != d->documents.end(); iter++)
216 if(document.getFileName().compare(iter->getFileName()) == 0)
217 THROW_BDOCEXCEPTION(
"Document with same file name '%s' already exists '%s'.", document.getFileName().c_str(), iter->getFileName().c_str());
220 d->documents.push_back(document);
232 if(
id >= d->documents.size())
233 THROW_BDOCEXCEPTION(
"Incorrect document id %u, there are only %u documents in container.",
id, d->documents.size());
234 return d->documents[id];
247 if(!d->signatures.empty())
248 THROW_BDOCEXCEPTION(
"Can not remove document from container which has signatures, remove all signatures before removing document.");
250 if(d->documents.size() > id)
251 d->documents.erase(d->documents.begin() + id);
253 THROW_BDOCEXCEPTION(
"Incorrect document id %u, there are only %u documents in container.",
id, d->documents.size());
261 return (
unsigned int)d->documents.size();
280 addSignature(signature, TM);
291 if(signature.empty())
293 if(d->documents.empty())
298 ofs <<
"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\" ?>\n";
299 for(std::vector<unsigned char>::const_iterator
i = signature.begin();
i != signature.end(); ++
i)
307 d->signatures.push_back(
new SignatureTM(fileName, *
this));
310 d->signatures.push_back(
new SignatureBES(fileName, *
this));
330 if(d->documents.empty())
332 d->signatures.push_back(signature);
344 if(
id >= d->signatures.size() )
345 THROW_BDOCEXCEPTION(
"Incorrect signature id %u, there are only %u signatures in container.",
id, d->signatures.size());
346 return d->signatures[id];
357 if(d->signatures.size() > id)
359 std::vector<Signature*>::iterator it = (d->signatures.begin() + id);
361 d->signatures.erase(it);
364 THROW_BDOCEXCEPTION(
"Incorrect signature id %u, there are only %u signatures in container.",
id, d->signatures.size());
372 return (
unsigned int)d->signatures.size();
401 DEBUG(
"BDoc::createMimetype()");
406 ofs << getMimeType();
427 DEBUG(
"digidoc::BDoc::createManifest()");
433 manifest::Manifest manifest;
436 manifest.file_entry().push_back(manifest::File_entry(
"/", getMimeType()));
439 for(std::vector<Document>::const_iterator iter = d->documents.begin(); iter != d->documents.end(); iter++)
441 manifest::File_entry fileEntry(iter->getFileName(), iter->getMediaType());
442 manifest.file_entry().push_back(fileEntry);
447 for(std::vector<Signature*>::const_iterator iter = d->signatures.begin(); iter != d->signatures.end(); iter++)
449 manifest::File_entry fileEntry(
Log::format(
"META-INF/signature%u.xml", i++), (*iter)->getMediaType());
450 manifest.file_entry().push_back(fileEntry);
454 xml_schema::NamespaceInfomap map;
456 DEBUG(
"Serializing manifest XML to '%s'", fileName.c_str());
459 manifest::manifest(ofs, manifest, map,
"", xml_schema::Flags::dont_initialize);
463 THROW_IOEXCEPTION(
"Failed to create manifest XML file to '%s'.", fileName.c_str());
465 catch(
const xml_schema::Exception&
e)
467 std::ostringstream oss;
469 THROW_IOEXCEPTION(
"Failed to create manifest XML file. Error: %s", oss.str().c_str());
484 DEBUG(
"BDoc::readMimetype(path = '%s')", path.c_str());
489 unsigned char bom[] = { 0, 0, 0 };
490 ifs.read((
char*)bom,
sizeof(bom));
492 if((bom[0] == 0xFF && bom[1] == 0xEF) ||
493 (bom[0] == 0xEF && bom[1] == 0xFF))
496 if(!(bom[0] == 0xEF && bom[1] == 0xBB && bom[2] == 0xBF))
497 ifs.seekg(0, std::ios::beg);
499 std::string mimetype;
507 DEBUG(
"mimetype = '%s'", mimetype.c_str());
508 if(getMimeType() != mimetype)
509 THROW_BDOCEXCEPTION(
"Incorrect mimetype '%s', expecting '%s'", mimetype.c_str(), getMimeType().c_str());
525 DEBUG(
"BDoc::readManifest(path = '%s')", path.c_str());
531 xml_schema::Properties properties;
533 std::auto_ptr<manifest::Manifest> manifest(manifest::manifest(fileName, xml_schema::Flags::dont_initialize, properties));
536 std::set<std::string> manifestFiles;
537 bool mimetypeChecked =
false;
538 for(manifest::Manifest::File_entrySequence::const_iterator iter = manifest->file_entry().begin();
539 iter != manifest->file_entry().end(); iter++)
541 DEBUG(
"full_path = '%s', media_type = '%s'", iter->full_path().c_str(), iter->media_type().c_str());
543 if(std::string(
"/").compare(iter->full_path()) == 0)
548 if(getMimeType().compare(iter->media_type()) != 0)
550 THROW_BDOCEXCEPTION(
"Manifest has incorrect BDCO container media type defined '%s', expecting '%s'.", iter->media_type().c_str(), getMimeType().c_str());
553 DEBUG(
"BDOC mimetype OK");
554 mimetypeChecked =
true;
559 if(manifestFiles.find(iter->full_path()) != manifestFiles.end())
560 THROW_BDOCEXCEPTION(
"Manifest multiple entries defined for file '%s'.", iter->media_type().c_str());
566 manifestFiles.insert(iter->full_path());
570 if(iter->full_path().find_first_of(
"/") == std::string::npos)
574 THROW_BDOCEXCEPTION(
"File described in manifest '%s' does not exist in BDOC container.", iter->full_path().c_str());
581 DEBUG(
"%s :: %u", iter->full_path().c_str(), iter->full_path().find_first_of(
"META-INF/"));
582 std::string signatureFileName = (iter->full_path().substr((iter->full_path().find(
'/'))+1));
584 if(iter->full_path().find_first_of(
"META-INF/") == 0)
586 DEBUG(
"signature filename :: '%s'", signatureFileName.c_str());
588 if(signatureFileName.find_first_of(
"/") != std::string::npos)
589 THROW_BDOCEXCEPTION(
"Unexpected file described in manifest '%s'.", iter->full_path().c_str());
592 THROW_BDOCEXCEPTION(
"File described in manifest '%s' does not exist in BDOC container.", iter->full_path().c_str());
599 d->signatures.push_back(
new SignatureBES(signaturePath, *
this));
601 d->signatures.push_back(
new SignatureTM(signaturePath, *
this));
607 THROW_BDOCEXCEPTION_CAUSE(e,
"Failed to parse signature '%s', type '%s'.", signaturePath.c_str(), iter->media_type().c_str());
622 for(std::vector<std::string>::const_iterator iter = containerFiles.begin(); iter != containerFiles.end(); iter++)
625 std::string containerFile = *iter;
626 if(std::string(
"mimetype").compare(containerFile) == 0
627 || std::string(
"META-INF/manifest.xml").compare(containerFile) == 0)
630 std::replace(containerFile.begin(), containerFile.end(),
'\\',
'/');
631 if(manifestFiles.find(containerFile) == manifestFiles.end())
632 THROW_BDOCEXCEPTION(
"File '%s' found in BDOC container is not described in manifest.", containerFile.c_str());
635 catch(
const xml_schema::Exception&
e)
637 std::ostringstream oss;
666 DEBUG(
"sign(signer = %p, profile=%d)", signer, profile);
676 signature =
new SignatureTM(newSignatureId(), *
this);
686 signature->
sign(signer);
700 addSignature(signature);