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/.
12 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
13 #include <com/sun/star/uno/XComponentContext.hpp>
14 #include <com/sun/star/xml/crypto/SEInitializer.hpp>
16 #include <comphelper/processfactory.hxx>
17 #include <cppuhelper/bootstrap.hxx>
18 #include <osl/file.hxx>
19 #include <sal/log.hxx>
21 #include <tools/diagnose_ex.h>
22 #include <vcl/pngwrite.hxx>
23 #include <vcl/svapp.hxx>
24 #include <vcl/graphicfilter.hxx>
25 #include <vcl/filter/pdfdocument.hxx>
27 #include <pdfio/pdfdocument.hxx>
29 #include <svl/sigstruct.hxx>
31 using namespace com::sun::star
;
35 /// Does PDF to PNG conversion using pdfium.
36 void generatePreview(const OString
& rPdfPath
, const OString
& rPngPath
)
38 GraphicFilter
& rFilter
= GraphicFilter::GetGraphicFilter();
41 osl::FileBase::getFileURLFromSystemPath(OUString::fromUtf8(rPdfPath
), aInURL
);
42 SvFileStream
aInStream(aInURL
, StreamMode::READ
);
43 WmfExternal
* pExtHeader
= nullptr;
44 if (rFilter
.ImportGraphic(aGraphic
, OUString(), aInStream
, GRFILTER_FORMAT_DONTKNOW
, nullptr,
45 GraphicFilterImportFlags::NONE
, pExtHeader
)
49 BitmapEx aBitmapEx
= aGraphic
.GetBitmapEx();
50 vcl::PNGWriter
aWriter(aBitmapEx
);
52 osl::FileBase::getFileURLFromSystemPath(OUString::fromUtf8(rPngPath
), aOutURL
);
53 SvFileStream
aOutStream(aOutURL
, StreamMode::WRITE
);
54 aWriter
.Write(aOutStream
);
57 int pdfVerify(int nArgc
, char** pArgv
)
61 SAL_WARN("xmlsecurity.pdfio", "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.pdfio",
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
);
83 if (nArgc
> 3 && OString(pArgv
[3]) == "-p")
86 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.pdfio",
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 && OString(pArgv
[3]) == "-r")
113 bRemoveSignature
= true;
115 SvFileStream
aStream(aInURL
, StreamMode::READ
);
116 vcl::filter::PDFDocument aDocument
;
117 if (!aDocument
.Read(aStream
))
119 SAL_WARN("xmlsecurity.pdfio", "failed to read the document");
123 if (bRemoveSignature
)
125 std::cerr
<< "removing the last signature" << std::endl
;
126 std::vector
<vcl::filter::PDFObjectElement
*> aSignatures
= aDocument
.GetSignatureWidgets();
127 if (aSignatures
.empty())
129 std::cerr
<< "found no signatures" << std::endl
;
133 size_t nPosition
= aSignatures
.size() - 1;
134 if (!aDocument
.RemoveSignature(nPosition
))
136 SAL_WARN("xmlsecurity.pdfio", "failed to remove signature #" << nPosition
);
140 SvFileStream
aOutStream(aOutURL
, StreamMode::WRITE
| StreamMode::TRUNC
);
141 if (!aDocument
.Write(aOutStream
))
143 SAL_WARN("xmlsecurity.pdfio", "failed to write the document");
150 if (aOutURL
.isEmpty())
152 std::cerr
<< "verifying signatures" << std::endl
;
153 std::vector
<vcl::filter::PDFObjectElement
*> aSignatures
= aDocument
.GetSignatureWidgets();
154 if (aSignatures
.empty())
155 std::cerr
<< "found no signatures" << std::endl
;
158 std::cerr
<< "found " << aSignatures
.size() << " signatures" << std::endl
;
159 for (size_t i
= 0; i
< aSignatures
.size(); ++i
)
161 SignatureInformation
aInfo(i
);
162 bool bLast
= i
== aSignatures
.size() - 1;
163 if (!xmlsecurity::pdfio::ValidateSignature(aStream
, aSignatures
[i
], aInfo
, bLast
))
165 SAL_WARN("xmlsecurity.pdfio", "failed to determine digest match");
170 = aInfo
.nStatus
== xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED
;
171 std::cerr
<< "signature #" << i
<< ": digest match? " << bSuccess
<< std::endl
;
178 std::cerr
<< "adding a new signature" << std::endl
;
179 uno::Reference
<xml::crypto::XSecurityEnvironment
> xSecurityEnvironment
180 = xSecurityContext
->getSecurityEnvironment();
181 uno::Sequence
<uno::Reference
<security::XCertificate
>> aCertificates
182 = xSecurityEnvironment
->getPersonalCertificates();
183 if (!aCertificates
.hasElements())
185 SAL_WARN("xmlsecurity.pdfio", "no signing certificates found");
188 if (!aDocument
.Sign(aCertificates
[0], "pdfverify", /*bAdES=*/true))
190 SAL_WARN("xmlsecurity.pdfio", "failed to sign");
194 SvFileStream
aOutStream(aOutURL
, StreamMode::WRITE
| StreamMode::TRUNC
);
195 if (!aDocument
.Write(aOutStream
))
197 SAL_WARN("xmlsecurity.pdfio", "failed to write the document");
205 SAL_IMPLEMENT_MAIN_WITH_ARGS(nArgc
, pArgv
)
209 return pdfVerify(nArgc
, pArgv
);
213 std::cerr
<< "pdfverify: uncaught exception while invoking pdfVerify()" << std::endl
;
218 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */