1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
11 #include <string_view>
13 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
14 #include <com/sun/star/uno/XComponentContext.hpp>
15 #include <com/sun/star/xml/crypto/SEInitializer.hpp>
17 #include <comphelper/processfactory.hxx>
18 #include <cppuhelper/bootstrap.hxx>
19 #include <osl/file.hxx>
20 #include <sal/log.hxx>
22 #include <comphelper/diagnose_ex.hxx>
23 #include <vcl/filter/PngImageWriter.hxx>
24 #include <vcl/svapp.hxx>
25 #include <vcl/graphicfilter.hxx>
26 #include <vcl/filter/pdfdocument.hxx>
27 #include <comphelper/scopeguard.hxx>
28 #include <svl/sigstruct.hxx>
30 #include <pdfsignaturehelper.hxx>
32 using namespace com::sun::star
;
36 /// Does PDF to PNG conversion using pdfium.
37 void generatePreview(std::string_view rPdfPath
, std::string_view rPngPath
)
39 GraphicFilter
& rFilter
= GraphicFilter::GetGraphicFilter();
42 osl::FileBase::getFileURLFromSystemPath(OUString::fromUtf8(rPdfPath
), aInURL
);
43 SvFileStream
aInStream(aInURL
, StreamMode::READ
);
44 if (rFilter
.ImportGraphic(aGraphic
, u
"", aInStream
, GRFILTER_FORMAT_DONTKNOW
, nullptr,
45 GraphicFilterImportFlags::NONE
)
49 BitmapEx aBitmapEx
= aGraphic
.GetBitmapEx();
51 osl::FileBase::getFileURLFromSystemPath(OUString::fromUtf8(rPngPath
), aOutURL
);
52 SvFileStream
aOutStream(aOutURL
, StreamMode::WRITE
);
53 vcl::PngImageWriter
aWriter(aOutStream
);
54 aWriter
.write(aBitmapEx
);
57 int pdfVerify(int nArgc
, char** pArgv
)
61 SAL_WARN("xmlsecurity.workben", "not enough parameters");
65 // Initialize nss / mscrypto.
66 uno::Reference
<uno::XComponentContext
> xComponentContext
;
69 xComponentContext
= cppu::defaultBootstrap_InitialComponentContext();
71 catch (const uno::RuntimeException
&)
73 TOOLS_WARN_EXCEPTION("xmlsecurity.workben",
74 "cppu::defaultBootstrap_InitialComponentContext() failed:");
77 uno::Reference
<lang::XMultiComponentFactory
> xMultiComponentFactory
78 = xComponentContext
->getServiceManager();
79 uno::Reference
<lang::XMultiServiceFactory
> xMultiServiceFactory(xMultiComponentFactory
,
81 comphelper::setProcessServiceFactory(xMultiServiceFactory
);
84 comphelper::ScopeGuard
g([] { DeInitVCL(); });
85 if (nArgc
> 3 && pArgv
[3] == std::string_view("-p"))
87 generatePreview(pArgv
[1], pArgv
[2]);
91 uno::Reference
<xml::crypto::XSEInitializer
> xSEInitializer
;
94 xSEInitializer
= xml::crypto::SEInitializer::create(xComponentContext
);
96 catch (const uno::DeploymentException
&)
98 TOOLS_WARN_EXCEPTION("xmlsecurity.workben",
99 "DeploymentException while creating SEInitializer:");
102 uno::Reference
<xml::crypto::XXMLSecurityContext
> xSecurityContext
103 = xSEInitializer
->createSecurityContext(OUString());
106 osl::FileBase::getFileURLFromSystemPath(OUString::fromUtf8(pArgv
[1]), aInURL
);
109 osl::FileBase::getFileURLFromSystemPath(OUString::fromUtf8(pArgv
[2]), aOutURL
);
111 bool bRemoveSignature
= false;
112 if (nArgc
> 3 && pArgv
[3] == std::string_view("-r"))
113 bRemoveSignature
= true;
115 SvFileStream
aStream(aInURL
, StreamMode::READ
);
116 if (aOutURL
.isEmpty() && !bRemoveSignature
)
118 std::cerr
<< "verifying signatures" << std::endl
;
119 PDFSignatureHelper aHelper
;
121 aHelper
.ReadAndVerifySignatureSvStream(aStream
);
122 if (aHelper
.GetSignatureInformations().empty())
123 std::cerr
<< "found no signatures" << std::endl
;
126 std::cerr
<< "found " << aHelper
.GetSignatureInformations().size() << " signatures"
128 for (size_t i
= 0; i
< aHelper
.GetSignatureInformations().size(); ++i
)
130 const SignatureInformation
& rInfo
= aHelper
.GetSignatureInformations()[i
];
132 = rInfo
.nStatus
== xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED
;
133 std::cerr
<< "signature #" << i
<< ": digest match? " << bSuccess
<< std::endl
;
134 std::cerr
<< "signature #" << i
<< ": partial? " << rInfo
.bPartialDocumentSignature
142 vcl::filter::PDFDocument aDocument
;
143 if (!aDocument
.Read(aStream
))
145 SAL_WARN("xmlsecurity.workben", "failed to read the document");
149 if (bRemoveSignature
)
151 std::cerr
<< "removing the last signature" << std::endl
;
152 std::vector
<vcl::filter::PDFObjectElement
*> aSignatures
= aDocument
.GetSignatureWidgets();
153 if (aSignatures
.empty())
155 std::cerr
<< "found no signatures" << std::endl
;
159 size_t nPosition
= aSignatures
.size() - 1;
160 if (!aDocument
.RemoveSignature(nPosition
))
162 SAL_WARN("xmlsecurity.workben", "failed to remove signature #" << nPosition
);
166 SvFileStream
aOutStream(aOutURL
, StreamMode::WRITE
| StreamMode::TRUNC
);
167 if (!aDocument
.Write(aOutStream
))
169 SAL_WARN("xmlsecurity.workben", "failed to write the document");
176 std::cerr
<< "adding a new signature" << std::endl
;
177 uno::Reference
<xml::crypto::XSecurityEnvironment
> xSecurityEnvironment
178 = xSecurityContext
->getSecurityEnvironment();
179 uno::Sequence
<uno::Reference
<security::XCertificate
>> aCertificates
180 = xSecurityEnvironment
->getPersonalCertificates();
181 if (!aCertificates
.hasElements())
183 SAL_WARN("xmlsecurity.workben", "no signing certificates found");
186 if (!aDocument
.Sign(aCertificates
[0], "pdfverify", /*bAdES=*/true))
188 SAL_WARN("xmlsecurity.workben", "failed to sign");
192 SvFileStream
aOutStream(aOutURL
, StreamMode::WRITE
| StreamMode::TRUNC
);
193 if (!aDocument
.Write(aOutStream
))
195 SAL_WARN("xmlsecurity.workben", "failed to write the document");
203 SAL_IMPLEMENT_MAIN_WITH_ARGS(nArgc
, pArgv
)
207 return pdfVerify(nArgc
, pArgv
);
211 std::cerr
<< "pdfverify: uncaught exception while invoking pdfVerify()" << std::endl
;
216 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */