LibreOffice Module unotest (master) 1
macros_test.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 */
9
11
12#include <vector>
13
14#include <com/sun/star/document/MacroExecMode.hpp>
15#include <com/sun/star/uno/XComponentContext.hpp>
16#include <com/sun/star/frame/DispatchHelper.hpp>
17#include <com/sun/star/packages/zip/ZipFileAccess.hpp>
18#include <com/sun/star/security/CertificateValidity.hpp>
19#include <com/sun/star/security/XCertificate.hpp>
20#include <com/sun/star/xml/crypto/XSecurityEnvironment.hpp>
21
22#include <basic/basrdll.hxx>
23#include <cppunit/TestAssert.h>
27#include <osl/file.hxx>
28#include <osl/process.h>
29#include <osl/thread.h>
30#include <tools/datetime.hxx>
31#include <unotools/tempfile.hxx>
33#include <vcl/scheduler.hxx>
34
35using namespace css;
36
37namespace unotest
38{
40 : mpDll(std::make_unique<BasicDLL>())
41{
42}
43
44MacrosTest::~MacrosTest() = default;
45
46uno::Reference<css::lang::XComponent>
47MacrosTest::loadFromDesktop(const OUString& rURL, const OUString& rDocService,
48 const uno::Sequence<beans::PropertyValue>& rExtraArgs)
49{
50 CPPUNIT_ASSERT_MESSAGE("no desktop", mxDesktop.is());
51 std::vector<beans::PropertyValue> args;
52 beans::PropertyValue aMacroValue;
53 aMacroValue.Name = "MacroExecutionMode";
54 aMacroValue.Handle = -1;
55 aMacroValue.Value <<= document::MacroExecMode::ALWAYS_EXECUTE_NO_WARN;
56 aMacroValue.State = beans::PropertyState_DIRECT_VALUE;
57 args.push_back(aMacroValue);
58
59 if (!rDocService.isEmpty())
60 {
61 beans::PropertyValue aValue;
62 aValue.Name = "DocumentService";
63 aValue.Handle = -1;
64 aValue.Value <<= rDocService;
65 aValue.State = beans::PropertyState_DIRECT_VALUE;
66 args.push_back(aValue);
67 }
68
69 args.insert(args.end(), rExtraArgs.begin(), rExtraArgs.end());
70
71 uno::Reference<lang::XComponent> xComponent = mxDesktop->loadComponentFromURL(
72 rURL, "_default", 0, comphelper::containerToSequence(args));
73 OUString sMessage = "loading failed: " + rURL;
74 CPPUNIT_ASSERT_MESSAGE(OUStringToOString(sMessage, RTL_TEXTENCODING_UTF8).getStr(),
75 xComponent.is());
76 return xComponent;
77}
78
79css::uno::Any
80MacrosTest::dispatchCommand(const uno::Reference<lang::XComponent>& xComponent,
81 const OUString& rCommand,
82 const uno::Sequence<beans::PropertyValue>& rPropertyValues)
83{
84 uno::Reference<frame::XController> xController
85 = uno::Reference<frame::XModel>(xComponent, uno::UNO_QUERY_THROW)->getCurrentController();
86 CPPUNIT_ASSERT(xController.is());
87 uno::Reference<frame::XDispatchProvider> xFrame(xController->getFrame(), uno::UNO_QUERY);
88 CPPUNIT_ASSERT(xFrame.is());
89
90 uno::Reference<uno::XComponentContext> xContext = ::comphelper::getProcessComponentContext();
91 uno::Reference<frame::XDispatchHelper> xDispatchHelper(frame::DispatchHelper::create(xContext));
92 CPPUNIT_ASSERT(xDispatchHelper.is());
93
94 auto ret = xDispatchHelper->executeDispatch(xFrame, rCommand, OUString(), 0, rPropertyValues);
96
97 return ret;
98}
99
100std::unique_ptr<SvStream> MacrosTest::parseExportStream(const OUString& url,
101 const OUString& rStreamName)
102{
103 uno::Reference<uno::XComponentContext> xComponentContext
105 uno::Reference<packages::zip::XZipFileAccess2> const xZipNames(
106 packages::zip::ZipFileAccess::createWithURL(xComponentContext, url));
107 uno::Reference<io::XInputStream> const xInputStream(xZipNames->getByName(rStreamName),
108 uno::UNO_QUERY);
109 std::unique_ptr<SvStream> pStream(utl::UcbStreamHelper::CreateStream(xInputStream, true));
110 return pStream;
111}
112
113void MacrosTest::setUpNssGpg(const test::Directories& rDirectories, const OUString& rTestName)
114{
115 OUString aSourceDir = rDirectories.getURLFromSrc(u"/test/signing-keys/");
116 OUString aTargetDir
117 = rDirectories.getURLFromWorkdir(Concat2View("CppunitTest/" + rTestName + ".test.user"));
118
119 // Set up NSS database in workdir/CppunitTest/
120 osl::File::copy(aSourceDir + "cert9.db", aTargetDir + "/cert9.db");
121 osl::File::copy(aSourceDir + "key4.db", aTargetDir + "/key4.db");
122 osl::File::copy(aSourceDir + "pkcs11.txt", aTargetDir + "/pkcs11.txt");
123
124 // Make gpg use our own defined setup & keys
125 osl::File::copy(aSourceDir + "pubring.gpg", aTargetDir + "/pubring.gpg");
126 osl::File::copy(aSourceDir + "random_seed", aTargetDir + "/random_seed");
127 osl::File::copy(aSourceDir + "secring.gpg", aTargetDir + "/secring.gpg");
128 osl::File::copy(aSourceDir + "trustdb.gpg", aTargetDir + "/trustdb.gpg");
129
130 OUString aTargetPath;
131 osl::FileBase::getSystemPathFromFileURL(aTargetDir, aTargetPath);
132
133#ifdef _WIN32
134 // CryptoAPI test certificates
135 osl::File::copy(aSourceDir + "test.p7b", aTargetDir + "/test.p7b");
136 OUString caVar("LIBO_TEST_CRYPTOAPI_PKCS7");
137 osl_setEnvironment(caVar.pData, aTargetPath.pData);
138#else
139 OUString mozCertVar("MOZILLA_CERTIFICATE_FOLDER");
140 // explicit prefix with "sql:" needed for CentOS7 system NSS 3.67
141 osl_setEnvironment(mozCertVar.pData, OUString("sql:" + aTargetPath).pData);
142#endif
143 OUString gpgHomeVar("GNUPGHOME");
144 osl_setEnvironment(gpgHomeVar.pData, aTargetPath.pData);
145
146#if HAVE_GPGCONF_SOCKETDIR
147 auto const ldPath = std::getenv("LIBO_LD_PATH");
148 m_gpgconfCommandPrefix
149 = ldPath == nullptr ? OString() : OString::Concat("LD_LIBRARY_PATH=") + ldPath + " ";
150 OString path;
151 bool ok = aTargetPath.convertToString(&path, osl_getThreadTextEncoding(),
152 RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR
153 | RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR);
154 // if conversion fails, at least provide a best-effort conversion in the message here, for
155 // context
156 CPPUNIT_ASSERT_MESSAGE(OUStringToOString(aTargetPath, RTL_TEXTENCODING_UTF8).getStr(), ok);
157 m_gpgconfCommandPrefix += "GNUPGHOME=" + path + " " GPGME_GPGCONF;
158 // HAVE_GPGCONF_SOCKETDIR is only defined in configure.ac for Linux for now, so (a) std::system
159 // behavior will conform to POSIX (and the relevant env var to set is named LD_LIBRARY_PATH), and
160 // (b) gpgconf --create-socketdir should return zero:
161 OString cmd = m_gpgconfCommandPrefix + " --create-socketdir";
162 int res = std::system(cmd.getStr());
163 CPPUNIT_ASSERT_EQUAL_MESSAGE(cmd.getStr(), 0, res);
164#else
165 (void)this;
166#endif
167}
168
170{
171#if HAVE_GPGCONF_SOCKETDIR
172 // HAVE_GPGCONF_SOCKETDIR is only defined in configure.ac for Linux for now, so (a) std::system
173 // behavior will conform to POSIX, and (b) gpgconf --remove-socketdir should return zero:
174 OString cmd = m_gpgconfCommandPrefix + " --remove-socketdir";
175 int res = std::system(cmd.getStr());
176 CPPUNIT_ASSERT_EQUAL_MESSAGE(cmd.getStr(), 0, res);
177#else
178 (void)this;
179#endif
180}
181
182namespace
183{
184struct Valid
185{
187 OUString subjectName;
188 const css::uno::Reference<css::xml::crypto::XSecurityEnvironment>& env;
189 Valid(const css::uno::Sequence<css::beans::PropertyValue>& rFilterData,
190 const css::uno::Reference<css::xml::crypto::XSecurityEnvironment>& rEnv)
191 : now(DateTime::SYSTEM)
192 , env(rEnv)
193 {
194 for (const auto& propVal : rFilterData)
195 {
196 if (propVal.Name == "SignCertificateSubjectName")
197 propVal.Value >>= subjectName;
198 }
199 }
200 bool operator()(const css::uno::Reference<css::security::XCertificate>& cert) const
201 {
202 if (!now.IsBetween(cert->getNotValidBefore(), cert->getNotValidAfter()))
203 return false;
204 if (!subjectName.isEmpty() && subjectName != cert->getSubjectName())
205 return false;
206 if (env->verifyCertificate(cert, {}) != css::security::CertificateValidity::VALID)
207 return false;
208 return true;
209 }
210};
211}
212
213bool MacrosTest::IsValid(const css::uno::Reference<css::security::XCertificate>& cert,
214 const css::uno::Reference<css::xml::crypto::XSecurityEnvironment>& env)
215{
216 const Valid test({}, env);
217 return test(cert);
218}
219
220css::uno::Reference<css::security::XCertificate> MacrosTest::GetValidCertificate(
221 const css::uno::Sequence<css::uno::Reference<css::security::XCertificate>>& certs,
222 const css::uno::Reference<css::xml::crypto::XSecurityEnvironment>& env,
223 const css::uno::Sequence<css::beans::PropertyValue>& rFilterData)
224{
225 if (auto it = std::find_if(certs.begin(), certs.end(), Valid(rFilterData, env));
226 it != certs.end())
227 return *it;
228 return {};
229}
230}
231
232/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
bool IsBetween(const DateTime &rFrom, const DateTime &rTo) const
static void ProcessEventsToIdle()
OUString getURLFromWorkdir(std::u16string_view rPath) const
Definition: directories.cxx:56
OUString getURLFromSrc(std::u16string_view rPath) const
Definition: directories.cxx:46
static css::uno::Any dispatchCommand(const css::uno::Reference< css::lang::XComponent > &xComponent, const OUString &rCommand, const css::uno::Sequence< css::beans::PropertyValue > &rPropertyValues)
Definition: macros_test.cxx:80
static css::uno::Reference< css::security::XCertificate > GetValidCertificate(const css::uno::Sequence< css::uno::Reference< css::security::XCertificate > > &certs, const css::uno::Reference< css::xml::crypto::XSecurityEnvironment > &env, const css::uno::Sequence< css::beans::PropertyValue > &rFilterData={})
static bool IsValid(const css::uno::Reference< css::security::XCertificate > &cert, const css::uno::Reference< css::xml::crypto::XSecurityEnvironment > &env)
css::uno::Reference< css::frame::XDesktop2 > mxDesktop
static std::unique_ptr< SvStream > parseExportStream(const OUString &url, const OUString &rStreamName)
Opens rStreamName from rTempFile, assuming it's a ZIP storage.
void setUpNssGpg(const test::Directories &rDirectories, const OUString &rTestName)
css::uno::Reference< css::lang::XComponent > loadFromDesktop(const OUString &rURL, const OUString &rDocService=OUString(), const css::uno::Sequence< css::beans::PropertyValue > &rExtra_args=css::uno::Sequence< css::beans::PropertyValue >())
Definition: macros_test.cxx:47
static std::unique_ptr< SvStream > CreateStream(const OUString &rFileName, StreamMode eOpenMode, css::uno::Reference< css::awt::XWindow > xParentWin=nullptr)
float u
OUString subjectName
const css::uno::Reference< css::xml::crypto::XSecurityEnvironment > & env
DateTime now
std::unique_ptr< sal_Int32[]> pData
css::uno::Sequence< DstElementType > containerToSequence(const SrcType &i_Container)
Reference< XComponentContext > getProcessComponentContext()
OString OUStringToOString(std::u16string_view str, ConnectionSettings const *settings)
OUString sMessage
Reference< XController > xController
Reference< XFrame > xFrame