docthemes: Save themes def. to a file when added to ColorSets
[LibreOffice.git] / desktop / source / pkgchk / unopkg / unopkg_misc.cxx
blobc0b7058b22066561ab3c288ca0f73f351ef2b754
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <sal/config.h>
22 #include <string_view>
24 #include <config_folders.h>
26 #include <vcl/svapp.hxx>
27 #include <vcl/weld.hxx>
28 #include <rtl/bootstrap.hxx>
29 #include <rtl/ustrbuf.hxx>
30 #include <sal/log.hxx>
31 #include <osl/process.h>
32 #include <osl/file.hxx>
33 #include <unotools/configmgr.hxx>
34 #include <unotools/bootstrap.hxx>
35 #include <cppuhelper/bootstrap.hxx>
36 #include <comphelper/sequence.hxx>
37 #include <comphelper/processfactory.hxx>
39 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
40 #include <com/sun/star/ucb/UniversalContentBroker.hpp>
42 #include <strings.hrc>
43 #include "unopkg_shared.h"
44 #include <dp_identifier.hxx>
45 #include <dp_misc.h>
46 #include <dp_shared.hxx>
47 #include <lockfile.hxx>
49 using namespace ::com::sun::star;
50 using namespace ::com::sun::star::uno;
51 using namespace ::com::sun::star::ucb;
53 namespace unopkg {
55 OUString toString( OptionInfo const * info )
57 assert(info != nullptr);
58 OUStringBuffer buf("--");
59 buf.appendAscii(info->m_name);
60 if (info->m_short_option != '\0')
62 buf.append(" (short -" + OUStringChar(info->m_short_option) + ")");
64 if (info->m_has_argument)
65 buf.append(" <argument>" );
66 return buf.makeStringAndClear();
70 OptionInfo const * getOptionInfo(
71 OptionInfo const * list,
72 OUString const & opt )
74 for ( ; list->m_name != nullptr; ++list )
76 OptionInfo const & option_info = *list;
77 if (!opt.isEmpty())
79 if (opt.equalsAsciiL(
80 option_info.m_name, option_info.m_name_length ))
82 return &option_info;
86 SAL_WARN( "desktop", opt );
87 return nullptr;
91 bool isOption( OptionInfo const * option_info, sal_uInt32 * pIndex )
93 assert(option_info != nullptr);
94 if (osl_getCommandArgCount() <= *pIndex)
95 return false;
97 OUString arg;
98 osl_getCommandArg( *pIndex, &arg.pData );
99 sal_Int32 len = arg.getLength();
101 if (len < 2 || arg[ 0 ] != '-')
102 return false;
104 if (len == 2 && arg[ 1 ] == option_info->m_short_option)
106 ++(*pIndex);
107 dp_misc::TRACE(__FILE__ ": identified option \'\'"
108 + OUStringChar( option_info->m_short_option ) + "\n");
109 return true;
111 if (arg[ 1 ] == '-' && rtl_ustr_ascii_compare(
112 arg.pData->buffer + 2, option_info->m_name ) == 0)
114 ++(*pIndex);
115 dp_misc::TRACE(__FILE__ ": identified option \'"
116 + OUString::createFromAscii(option_info->m_name) + "\'\n");
117 return true;
119 return false;
123 bool isBootstrapVariable(sal_uInt32 * pIndex)
125 OSL_ASSERT(osl_getCommandArgCount() >= *pIndex);
127 OUString arg;
128 osl_getCommandArg(*pIndex, &arg.pData);
129 if (arg.match("-env:"))
131 ++(*pIndex);
132 return true;
134 return false;
138 bool readArgument(
139 OUString * pValue, OptionInfo const * option_info, sal_uInt32 * pIndex )
141 if (isOption( option_info, pIndex ))
143 if (*pIndex < osl_getCommandArgCount())
145 assert(pValue != nullptr);
146 osl_getCommandArg( *pIndex, &pValue->pData );
147 dp_misc::TRACE(__FILE__ ": argument value: "
148 + *pValue + "\n");
149 ++(*pIndex);
150 return true;
152 --(*pIndex);
154 return false;
158 static OUString getExecutableDirInit()
160 OUString path;
161 if (osl_getExecutableFile( &path.pData ) != osl_Process_E_None) {
162 throw RuntimeException(u"cannot locate executable directory!"_ustr,nullptr);
164 return path.copy( 0, path.lastIndexOf( '/' ) );
167 OUString const & getExecutableDir()
169 static const OUString EXEC = getExecutableDirInit();
170 return EXEC;
174 OUString const & getProcessWorkingDir()
176 static const OUString WORKING =
177 []()
179 OUString workingDir;
180 utl::Bootstrap::getProcessWorkingDir(workingDir);
181 return workingDir;
182 }();
183 return WORKING;
187 OUString makeAbsoluteFileUrl(
188 OUString const & sys_path, OUString const & base_url )
190 // system path to file url
191 OUString file_url;
192 oslFileError rc = osl_getFileURLFromSystemPath( sys_path.pData, &file_url.pData );
193 if ( rc != osl_File_E_None) {
194 OUString tempPath;
195 if ( osl_getSystemPathFromFileURL( sys_path.pData, &tempPath.pData) != osl_File_E_None )
197 throw RuntimeException("cannot get file url from system path: " +
198 sys_path );
200 file_url = sys_path;
203 OUString abs;
204 if (osl_getAbsoluteFileURL(
205 base_url.pData, file_url.pData, &abs.pData ) != osl_File_E_None)
207 throw RuntimeException(
208 "making absolute file url failed: \"" + base_url
209 + "\" (base-url) and \"" + file_url + "\" (file-url)!" );
211 return abs[ abs.getLength() -1 ] == '/'
212 ? abs.copy( 0, abs.getLength() -1 ) : abs;
216 namespace {
219 void printf_space( sal_Int32 space )
221 while (space--)
222 dp_misc::writeConsole(u" ");
226 void printf_line(
227 std::u16string_view name, std::u16string_view value, sal_Int32 level )
229 printf_space( level );
230 dp_misc::writeConsole(Concat2View(OUString::Concat(name) + ": " + value + "\n"));
234 void printf_package(
235 Reference<deployment::XPackage> const & xPackage,
236 Reference<XCommandEnvironment> const & xCmdEnv, sal_Int32 level )
238 beans::Optional< OUString > id(
239 level == 0
240 ? beans::Optional< OUString >(
241 true, dp_misc::getIdentifier( xPackage ) )
242 : xPackage->getIdentifier() );
243 if (id.IsPresent)
244 printf_line( u"Identifier", id.Value, level );
245 OUString version(xPackage->getVersion());
246 if (!version.isEmpty())
247 printf_line( u"Version", version, level + 1 );
248 printf_line( u"URL", xPackage->getURL(), level + 1 );
250 beans::Optional< beans::Ambiguous<sal_Bool> > option(
251 xPackage->isRegistered( Reference<task::XAbortChannel>(), xCmdEnv ) );
252 OUString value;
253 if (option.IsPresent) {
254 beans::Ambiguous<sal_Bool> const & reg = option.Value;
255 if (reg.IsAmbiguous)
256 value = "unknown";
257 else
258 value = reg.Value ? std::u16string_view(u"yes") : std::u16string_view(u"no");
260 else
261 value = "n/a";
262 printf_line( u"is registered", value, level + 1 );
264 const Reference<deployment::XPackageTypeInfo> xPackageType(
265 xPackage->getPackageType() );
266 OSL_ASSERT( xPackageType.is() );
267 if (xPackageType.is()) {
268 printf_line( u"Media-Type", xPackageType->getMediaType(), level + 1 );
270 printf_line( u"Description", xPackage->getDescription(), level + 1 );
271 if (!xPackage->isBundle())
272 return;
274 Sequence< Reference<deployment::XPackage> > seq(
275 xPackage->getBundle( Reference<task::XAbortChannel>(), xCmdEnv ) );
276 printf_space( level + 1 );
277 dp_misc::writeConsole(u"bundled Packages: {\n");
278 std::vector<Reference<deployment::XPackage> >vec_bundle;
279 ::comphelper::sequenceToContainer(vec_bundle, seq);
280 printf_packages( vec_bundle, std::vector<bool>(vec_bundle.size()),
281 xCmdEnv, level + 2 );
282 printf_space( level + 1 );
283 dp_misc::writeConsole(u"}\n");
286 } // anon namespace
288 static void printf_unaccepted_licenses(
289 Reference<deployment::XPackage> const & ext)
291 OUString id(
292 dp_misc::getIdentifier(ext) );
293 printf_line( u"Identifier", id, 0 );
294 printf_space(1);
295 dp_misc::writeConsole(u"License not accepted\n\n");
299 void printf_packages(
300 std::vector< Reference<deployment::XPackage> > const & allExtensions,
301 std::vector<bool> const & vecUnaccepted,
302 Reference<XCommandEnvironment> const & xCmdEnv, sal_Int32 level )
304 OSL_ASSERT(allExtensions.size() == vecUnaccepted.size());
306 if (allExtensions.empty())
308 printf_space( level );
309 dp_misc::writeConsole(u"<none>\n");
311 else
313 int index = 0;
314 for (auto const& extension : allExtensions)
316 if (vecUnaccepted[index])
317 printf_unaccepted_licenses(extension);
318 else
319 printf_package( extension, xCmdEnv, level );
320 dp_misc::writeConsole(u"\n");
321 ++index;
327 namespace {
330 Reference<XComponentContext> bootstrapStandAlone()
332 Reference<XComponentContext> xContext =
333 ::cppu::defaultBootstrap_InitialComponentContext();
335 Reference<lang::XMultiServiceFactory> xServiceManager(
336 xContext->getServiceManager(), UNO_QUERY_THROW );
337 // set global process service factory used by unotools config helpers
338 ::comphelper::setProcessServiceFactory( xServiceManager );
340 // Initialize the UCB (for backwards compatibility, in case some code still
341 // uses plain createInstance w/o args directly to obtain an instance):
342 UniversalContentBroker::create( xContext );
344 return xContext;
348 Reference<XComponentContext> connectToOffice(
349 Reference<XComponentContext> const & xLocalComponentContext,
350 bool verbose )
352 OUString pipeId( ::dp_misc::generateRandomPipeId() );
354 Sequence<OUString> args { u"--nologo"_ustr, u"--nodefault"_ustr, "--accept=pipe,name=" + pipeId + ";urp;" };
355 OUString appURL( getExecutableDir() + "/soffice" );
357 if (verbose)
359 dp_misc::writeConsole(Concat2View(
360 "Raising process: " + appURL +
361 "\nArguments: --nologo --nodefault " + args[2] +
362 "\n"));
365 ::dp_misc::raiseProcess( appURL, args );
367 if (verbose)
368 dp_misc::writeConsole(u"OK. Connecting...");
370 OUString sUnoUrl = "uno:pipe,name=" + pipeId + ";urp;StarOffice.ComponentContext";
371 Reference<XComponentContext> xRet(
372 ::dp_misc::resolveUnoURL(
373 sUnoUrl, xLocalComponentContext ),
374 UNO_QUERY_THROW );
375 if (verbose)
376 dp_misc::writeConsole(u"OK.\n");
378 return xRet;
381 } // anon namespace
383 /** returns the path to the lock file used by unopkg.
384 @return the path. An empty string signifies an error.
386 static OUString getLockFilePath()
388 OUString ret;
389 OUString sBootstrap(u"${$BRAND_BASE_DIR/" LIBO_ETC_FOLDER "/" SAL_CONFIGFILE("bootstrap") ":UserInstallation}"_ustr);
390 rtl::Bootstrap::expandMacros(sBootstrap);
391 OUString sAbs;
392 if (::osl::File::E_None == ::osl::File::getAbsoluteFileURL(
393 sBootstrap, u".lock"_ustr, sAbs))
395 if (::osl::File::E_None ==
396 ::osl::File::getSystemPathFromFileURL(sAbs, sBootstrap))
398 ret = sBootstrap;
402 return ret;
405 Reference<XComponentContext> getUNO(
406 bool verbose, bool bGui, const OUString& sTempDir,
407 Reference<XComponentContext> & out_localContext)
409 // do not create any user data (for the root user) in --shared mode:
410 if (!sTempDir.isEmpty())
411 rtl::Bootstrap::set(u"UserInstallation"_ustr, sTempDir);
413 // hold lock during process runtime:
414 static ::desktop::Lockfile s_lockfile( false /* no IPC server */ );
415 Reference<XComponentContext> xComponentContext( bootstrapStandAlone() );
416 out_localContext = xComponentContext;
417 if (::dp_misc::office_is_running()) {
418 xComponentContext.set(
419 connectToOffice( xComponentContext, verbose ) );
421 else
423 if (! s_lockfile.check( nullptr ))
425 OUString sMsg(DpResId(RID_STR_CONCURRENTINSTANCE));
426 OUString sError(DpResId(RID_STR_UNOPKG_ERROR));
428 sMsg += "\n" + getLockFilePath();
430 if (bGui)
432 //We show a message box or print to the console that there
433 //is another instance already running
434 if ( ! InitVCL() )
435 throw RuntimeException( u"Cannot initialize VCL!"_ustr );
437 std::unique_ptr<weld::MessageDialog> xWarn(Application::CreateMessageDialog(nullptr,
438 VclMessageType::Warning, VclButtonsType::Ok,
439 sMsg));
440 xWarn->set_title(utl::ConfigManager::getProductName());
441 xWarn->run();
443 DeInitVCL();
446 throw LockFileException(sError + sMsg);
450 return xComponentContext;
455 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */