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 <tools/diagnose_ex.h>
23 #include <vcl/pngwrite.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 WmfExternal
* pExtHeader
= nullptr;
45 if (rFilter
.ImportGraphic(aGraphic
, OUString(), aInStream
, GRFILTER_FORMAT_DONTKNOW
, nullptr,
46 GraphicFilterImportFlags::NONE
, pExtHeader
)
50 BitmapEx aBitmapEx
= aGraphic
.GetBitmapEx();
51 vcl::PNGWriter
aWriter(aBitmapEx
);
53 osl::FileBase::getFileURLFromSystemPath(OUString::fromUtf8(rPngPath
), aOutURL
);
54 SvFileStream
aOutStream(aOutURL
, StreamMode::WRITE
);
55 aWriter
.Write(aOutStream
);
58 int pdfVerify(int nArgc
, char** pArgv
)
62 SAL_WARN("xmlsecurity.workben", "not enough parameters");
66 // Initialize nss / mscrypto.
67 uno::Reference
<uno::XComponentContext
> xComponentContext
;
70 xComponentContext
= cppu::defaultBootstrap_InitialComponentContext();
72 catch (const uno::RuntimeException
&)
74 TOOLS_WARN_EXCEPTION("xmlsecurity.workben",
75 "cppu::defaultBootstrap_InitialComponentContext() failed:");
78 uno::Reference
<lang::XMultiComponentFactory
> xMultiComponentFactory
79 = xComponentContext
->getServiceManager();
80 uno::Reference
<lang::XMultiServiceFactory
> xMultiServiceFactory(xMultiComponentFactory
,
82 comphelper::setProcessServiceFactory(xMultiServiceFactory
);
85 comphelper::ScopeGuard
g([] { DeInitVCL(); });
86 if (nArgc
> 3 && pArgv
[3] == std::string_view("-p"))
88 generatePreview(pArgv
[1], pArgv
[2]);
92 uno::Reference
<xml::crypto::XSEInitializer
> xSEInitializer
;
95 xSEInitializer
= xml::crypto::SEInitializer::create(xComponentContext
);
97 catch (const uno::DeploymentException
&)
99 TOOLS_WARN_EXCEPTION("xmlsecurity.workben",
100 "DeploymentException while creating SEInitializer:");
103 uno::Reference
<xml::crypto::XXMLSecurityContext
> xSecurityContext
104 = xSEInitializer
->createSecurityContext(OUString());
107 osl::FileBase::getFileURLFromSystemPath(OUString::fromUtf8(pArgv
[1]), aInURL
);
110 osl::FileBase::getFileURLFromSystemPath(OUString::fromUtf8(pArgv
[2]), aOutURL
);
112 bool bRemoveSignature
= false;
113 if (nArgc
> 3 && pArgv
[3] == std::string_view("-r"))
114 bRemoveSignature
= true;
116 SvFileStream
aStream(aInURL
, StreamMode::READ
);
117 if (aOutURL
.isEmpty() && !bRemoveSignature
)
119 std::cerr
<< "verifying signatures" << std::endl
;
120 PDFSignatureHelper aHelper
;
122 aHelper
.ReadAndVerifySignatureSvStream(aStream
);
123 if (aHelper
.GetSignatureInformations().empty())
124 std::cerr
<< "found no signatures" << std::endl
;
127 std::cerr
<< "found " << aHelper
.GetSignatureInformations().size() << " signatures"
129 for (size_t i
= 0; i
< aHelper
.GetSignatureInformations().size(); ++i
)
131 const SignatureInformation
& rInfo
= aHelper
.GetSignatureInformations()[i
];
133 = rInfo
.nStatus
== xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED
;
134 std::cerr
<< "signature #" << i
<< ": digest match? " << bSuccess
<< std::endl
;
135 std::cerr
<< "signature #" << i
<< ": partial? " << rInfo
.bPartialDocumentSignature
143 vcl::filter::PDFDocument aDocument
;
144 if (!aDocument
.Read(aStream
))
146 SAL_WARN("xmlsecurity.workben", "failed to read the document");
150 if (bRemoveSignature
)
152 std::cerr
<< "removing the last signature" << std::endl
;
153 std::vector
<vcl::filter::PDFObjectElement
*> aSignatures
= aDocument
.GetSignatureWidgets();
154 if (aSignatures
.empty())
156 std::cerr
<< "found no signatures" << std::endl
;
160 size_t nPosition
= aSignatures
.size() - 1;
161 if (!aDocument
.RemoveSignature(nPosition
))
163 SAL_WARN("xmlsecurity.workben", "failed to remove signature #" << nPosition
);
167 SvFileStream
aOutStream(aOutURL
, StreamMode::WRITE
| StreamMode::TRUNC
);
168 if (!aDocument
.Write(aOutStream
))
170 SAL_WARN("xmlsecurity.workben", "failed to write the document");
177 std::cerr
<< "adding a new signature" << std::endl
;
178 uno::Reference
<xml::crypto::XSecurityEnvironment
> xSecurityEnvironment
179 = xSecurityContext
->getSecurityEnvironment();
180 uno::Sequence
<uno::Reference
<security::XCertificate
>> aCertificates
181 = xSecurityEnvironment
->getPersonalCertificates();
182 if (!aCertificates
.hasElements())
184 SAL_WARN("xmlsecurity.workben", "no signing certificates found");
187 if (!aDocument
.Sign(aCertificates
[0], "pdfverify", /*bAdES=*/true))
189 SAL_WARN("xmlsecurity.workben", "failed to sign");
193 SvFileStream
aOutStream(aOutURL
, StreamMode::WRITE
| StreamMode::TRUNC
);
194 if (!aDocument
.Write(aOutStream
))
196 SAL_WARN("xmlsecurity.workben", "failed to write the document");
204 SAL_IMPLEMENT_MAIN_WITH_ARGS(nArgc
, pArgv
)
208 return pdfVerify(nArgc
, pArgv
);
212 std::cerr
<< "pdfverify: uncaught exception while invoking pdfVerify()" << std::endl
;
217 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */