1
0
mirror of https://github.com/stefanocasazza/ULib.git synced 2025-09-28 19:05:55 +08:00
ULib/examples/XAdES/utility.cpp
stefanocasazza 1e7b31e10a sync
2018-06-20 18:51:31 +02:00

334 lines
9.2 KiB
C++

// utility.cpp
#include "utility.h"
void UXAdESUtility::handlerConfig(UFileConfig& cfg)
{
U_TRACE(5, "UXAdESUtility::handlerConfig(%p)", &cfg)
UString tmp;
MSname = cfg[U_STRING_FROM_CONSTANT( "MS-WORD.SignatureContent")];
OOname = cfg[U_STRING_FROM_CONSTANT("OPEN-OFFICE.SignatureContent")];
MSname.duplicate();
OOname.duplicate();
tmp = cfg[U_STRING_FROM_CONSTANT("OPEN-OFFICE.ToBeSigned")];
(void) OOToBeSigned.split(U_STRING_TO_PARAM(tmp));
tmp = cfg[U_STRING_FROM_CONSTANT("OPEN-OFFICE.ZipStructure")];
(void) OOZipStructure.split(U_STRING_TO_PARAM(tmp));
tmp = cfg[U_STRING_FROM_CONSTANT("MS-WORD.ToBeSigned")];
(void) MSToBeSigned.split(U_STRING_TO_PARAM(tmp));
tmp = cfg[U_STRING_FROM_CONSTANT("MS-WORD.ZipStructure")];
(void) MSZipStructure.split(U_STRING_TO_PARAM(tmp));
tmp = cfg[U_STRING_FROM_CONSTANT("MS-WORD.SignatureStructure")];
(void) MSSignatureStructure.split(U_STRING_TO_PARAM(tmp));
cfg.destroy();
}
// ---------------------------------------------------------------------------------------------------------------
// check for OOffice or MS-Word document...
// ---------------------------------------------------------------------------------------------------------------
bool UXAdESUtility::checkDocument(const UString& document, const char* pathname, bool adjust)
{
U_TRACE(5, "UXAdESUtility::checkDocument(%.*S,%S,%b)", U_STRING_TO_TRACE(document), pathname, adjust)
msword = ooffice = false;
(void) tmpdir.reserve(100U);
tmpdir.snprintf(U_CONSTANT_TO_PARAM("%s/%s"), u_tmpdir, u_basename(pathname, strlen(pathname)));
if (zip.extract(document, &tmpdir, false))
{
UString namefile;
uint32_t i, n, index;
for (i = 0, n = zip.getFilesCount(); i < n; ++i)
{
namefile = zip.getFilenameAt(i);
ZipStructure.push_back(namefile);
ZipContent.push_back(zip.getFileContentAt(i));
U_INTERNAL_DUMP("Part %d: Filename=%.*S", i+1, U_STRING_TO_TRACE(namefile));
}
U_INTERNAL_DUMP("ZIP: %d parts", n)
msword = true;
for (i = 0, n = MSZipStructure.size(); i < n; ++i)
{
namefile = MSZipStructure[i];
if (ZipStructure.isContained(namefile)) continue;
msword = false;
ooffice = true;
for (i = 0, n = OOZipStructure.size(); i < n; ++i)
{
namefile = OOZipStructure[i];
if (ZipStructure.isContained(namefile)) continue;
ooffice = false;
break;
}
break;
}
(void) docout.reserve(100U);
if (msword)
{
UString content,
content1_name = U_STRING_FROM_CONSTANT("[Content_Types].xml"), content1,
content2_name = U_STRING_FROM_CONSTANT("_rels/.rels"), content2;
if (adjust)
{
index = ZipStructure.contains(content1_name);
if (index != U_NOT_FOUND)
{
content1 = ZipContent[index];
content1.duplicate();
(void) content1.erase(U_STRING_RFIND(content1, "</Types>"));
(void) content1.append(U_CONSTANT_TO_PARAM("<Default Extension=\"sigs\" "
"ContentType=\"application/vnd.openxmlformats-package.digital-signature-origin\" />"
"<Override PartName=\"/_xmlsignatures/sig1.xml\" "
"ContentType=\"application/vnd.openxmlformats-package.digital-signature-xmlsignature+xml\" />"
"</Types>"));
ZipContent.replace(index, content1);
docout.snprintf(U_CONSTANT_TO_PARAM("%.*s/[Content_Types].xml"), U_STRING_TO_TRACE(tmpdir));
(void) UFile::writeTo(docout, content1);
}
index = ZipStructure.contains(content2_name);
if (index != U_NOT_FOUND)
{
content2 = ZipContent[index];
content2.duplicate();
(void) content2.erase(U_STRING_RFIND(content2, "</Relationships>"));
(void) content2.append(U_CONSTANT_TO_PARAM("<Relationship Id=\"rId4\" "
"Type=\"http://schemas.openxmlformats.org/package/2006/relationships/digital-signature/origin\" "
"Target=\"_xmlsignatures/origin.sigs\" />"
"</Relationships>"));
ZipContent.replace(index, content2);
docout.snprintf(U_CONSTANT_TO_PARAM("%.*s/_rels/.rels"), U_STRING_TO_TRACE(tmpdir));
(void) UFile::writeTo(docout, content2);
}
}
for (i = 0, n = MSToBeSigned.size(); i < n; ++i)
{
namefile = MSToBeSigned[i];
index = ZipStructure.contains(namefile);
if (index == U_NOT_FOUND) continue;
content = ZipContent[index];
if (adjust)
{
if (namefile == content1_name) content = content1;
else if (namefile == content2_name) content = content2;
}
vuri.push_back(namefile);
vdocument.push_back(content);
}
docout.snprintf(U_CONSTANT_TO_PARAM("%.*s/%.*s"), U_STRING_TO_TRACE(tmpdir), U_STRING_TO_TRACE(MSname));
U_RETURN(true);
}
if (ooffice)
{
UString content(U_CAPACITY),
content1_name = U_STRING_FROM_CONSTANT("META-INF/manifest.xml"), content1;
if (adjust)
{
index = ZipStructure.contains(content1_name);
if (index != U_NOT_FOUND)
{
content1 = ZipContent[index];
content1.duplicate();
(void) content1.erase(U_STRING_RFIND(content1, "</manifest:manifest>"));
content.snprintf(U_CONSTANT_TO_PARAM("<manifest:file-entry manifest:media-type=\"\" manifest:full-path=\"META-INF/\"/>"
"<manifest:file-entry manifest:media-type=\"\" manifest:full-path=\"%.*s\"/>"
"</manifest:manifest>"), U_STRING_TO_TRACE(OOname));
(void) content1.append(content);
ZipContent.replace(index, content1);
docout.snprintf(U_CONSTANT_TO_PARAM("%.*s/META-INF/manifest.xml"), U_STRING_TO_TRACE(tmpdir));
(void) UFile::writeTo(docout, content1);
}
}
for (i = 0, n = OOToBeSigned.size(); i < n; ++i)
{
namefile = OOToBeSigned[i];
index = ZipStructure.contains(namefile);
if (index == U_NOT_FOUND) continue;
content = ZipContent[index];
if (adjust)
{
if (namefile == content1_name) content = content1;
}
vuri.push_back(namefile);
vdocument.push_back(content);
}
docout.snprintf(U_CONSTANT_TO_PARAM("%.*s/%.*s"), U_STRING_TO_TRACE(tmpdir), U_STRING_TO_TRACE(OOname));
U_RETURN(true);
}
}
vdocument.push_back(document);
vuri.push_back(UString(pathname));
U_RETURN(false);
}
UString UXAdESUtility::getSigned()
{
U_TRACE(5, "UXAdESUtility::getSigned()")
UString name = (msword ? MSname : OOname);
if (name)
{
uint32_t index = ZipStructure.contains(name);
if (index != U_NOT_FOUND)
{
UString firma = ZipContent[index];
U_RETURN_STRING(firma);
}
}
return UString::getStringNull();
}
void UXAdESUtility::outputDocument(const UString& firma)
{
U_TRACE(5, "UXAdESUtility::outputDocument(%.*S)", U_STRING_TO_TRACE(firma))
UString output = firma;
if (msword ||
ooffice)
{
UString x = getSigned();
if (x.empty()) x = (msword ? MSname : OOname);
const char* add_to_filenames[32];
add_to_filenames[0] = (x ? x.c_str() : U_NULLPTR);
add_to_filenames[1] = U_NULLPTR;
(void) UFile::writeTo(docout, firma, false, true);
if (msword &&
MSSignatureStructure.empty() == false)
{
UString namefile, pcontent, tpath(100U);
int32_t j = 1, n = MSSignatureStructure.size();
for (int32_t i = 0; i < n; i += 2)
{
namefile = MSSignatureStructure[i];
if (ZipStructure.isContained(namefile)) continue;
pcontent = MSSignatureStructure[i+1];
tpath.snprintf(U_CONSTANT_TO_PARAM("%.*s/%.*s"), U_STRING_TO_TRACE(tmpdir), U_STRING_TO_TRACE(namefile));
(void) UFile::writeTo(tpath, UFile::contentOf(pcontent), false, true);
add_to_filenames[j++] = strdup(namefile.c_str());
}
add_to_filenames[j] = U_NULLPTR;
}
output = zip.archive(add_to_filenames);
}
#ifdef _MSWINDOWS_
(void) setmode(1, O_BINARY);
#endif
std::cout.write(U_STRING_TO_PARAM(output));
output.clear();
clean();
}
void UXAdESUtility::clean()
{
U_TRACE(5, "UXAdESUtility::clean()")
vdocument.clear();
ZipContent.clear();
MSSignatureStructure.clear();
vuri.clear();
ZipStructure.clear();
OOToBeSigned.clear();
MSToBeSigned.clear();
OOZipStructure.clear();
MSZipStructure.clear();
zip.clear();
}