nss: upgrade to release 3.73
[LibreOffice.git] / desktop / source / pkgchk / unopkg / unopkg_misc.cxx
blobf4c691fec9aa34becad71449513030337a9d85c7
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.append("--");
60 buf.appendAscii(info->m_name);
61 if (info->m_short_option != '\0')
63 buf.append(" (short -" );
64 buf.append(info->m_short_option );
65 buf.append(")");
67 if (info->m_has_argument)
68 buf.append(" <argument>" );
69 return buf.makeStringAndClear();
73 OptionInfo const * getOptionInfo(
74 OptionInfo const * list,
75 OUString const & opt )
77 for ( ; list->m_name != nullptr; ++list )
79 OptionInfo const & option_info = *list;
80 if (!opt.isEmpty())
82 if (opt.equalsAsciiL(
83 option_info.m_name, option_info.m_name_length ))
85 return &option_info;
89 SAL_WARN( "desktop", opt );
90 return nullptr;
94 bool isOption( OptionInfo const * option_info, sal_uInt32 * pIndex )
96 assert(option_info != nullptr);
97 if (osl_getCommandArgCount() <= *pIndex)
98 return false;
100 OUString arg;
101 osl_getCommandArg( *pIndex, &arg.pData );
102 sal_Int32 len = arg.getLength();
104 if (len < 2 || arg[ 0 ] != '-')
105 return false;
107 if (len == 2 && arg[ 1 ] == option_info->m_short_option)
109 ++(*pIndex);
110 dp_misc::TRACE(__FILE__ ": identified option \'\'"
111 + OUStringChar( option_info->m_short_option ) + "\n");
112 return true;
114 if (arg[ 1 ] == '-' && rtl_ustr_ascii_compare(
115 arg.pData->buffer + 2, option_info->m_name ) == 0)
117 ++(*pIndex);
118 dp_misc::TRACE(__FILE__ ": identified option \'"
119 + OUString::createFromAscii(option_info->m_name) + "\'\n");
120 return true;
122 return false;
126 bool isBootstrapVariable(sal_uInt32 * pIndex)
128 OSL_ASSERT(osl_getCommandArgCount() >= *pIndex);
130 OUString arg;
131 osl_getCommandArg(*pIndex, &arg.pData);
132 if (arg.match("-env:"))
134 ++(*pIndex);
135 return true;
137 return false;
141 bool readArgument(
142 OUString * pValue, OptionInfo const * option_info, sal_uInt32 * pIndex )
144 if (isOption( option_info, pIndex ))
146 if (*pIndex < osl_getCommandArgCount())
148 OSL_ASSERT( pValue != nullptr );
149 osl_getCommandArg( *pIndex, &pValue->pData );
150 dp_misc::TRACE(__FILE__ ": argument value: "
151 + *pValue + "\n");
152 ++(*pIndex);
153 return true;
155 --(*pIndex);
157 return false;
161 namespace {
162 struct ExecutableDir : public rtl::StaticWithInit<
163 OUString, ExecutableDir> {
164 OUString operator () () {
165 OUString path;
166 if (osl_getExecutableFile( &path.pData ) != osl_Process_E_None) {
167 throw RuntimeException("cannot locate executable directory!",nullptr);
169 return path.copy( 0, path.lastIndexOf( '/' ) );
172 struct ProcessWorkingDir : public rtl::StaticWithInit<
173 OUString, ProcessWorkingDir> {
174 OUString operator () () {
175 OUString workingDir;
176 utl::Bootstrap::getProcessWorkingDir(workingDir);
177 return workingDir;
180 } // anon namespace
183 OUString const & getExecutableDir()
185 return ExecutableDir::get();
189 OUString const & getProcessWorkingDir()
191 return ProcessWorkingDir::get();
195 OUString makeAbsoluteFileUrl(
196 OUString const & sys_path, OUString const & base_url )
198 // system path to file url
199 OUString file_url;
200 oslFileError rc = osl_getFileURLFromSystemPath( sys_path.pData, &file_url.pData );
201 if ( rc != osl_File_E_None) {
202 OUString tempPath;
203 if ( osl_getSystemPathFromFileURL( sys_path.pData, &tempPath.pData) != osl_File_E_None )
205 throw RuntimeException("cannot get file url from system path: " +
206 sys_path );
208 file_url = sys_path;
211 OUString abs;
212 if (osl_getAbsoluteFileURL(
213 base_url.pData, file_url.pData, &abs.pData ) != osl_File_E_None)
215 throw RuntimeException(
216 "making absolute file url failed: \"" + base_url
217 + "\" (base-url) and \"" + file_url + "\" (file-url)!" );
219 return abs[ abs.getLength() -1 ] == '/'
220 ? abs.copy( 0, abs.getLength() -1 ) : abs;
224 namespace {
227 void printf_space( sal_Int32 space )
229 while (space--)
230 dp_misc::writeConsole(" ");
234 void printf_line(
235 OUString const & name, OUString const & value, sal_Int32 level )
237 printf_space( level );
238 dp_misc::writeConsole(name + ": " + value + "\n");
242 void printf_package(
243 Reference<deployment::XPackage> const & xPackage,
244 Reference<XCommandEnvironment> const & xCmdEnv, sal_Int32 level )
246 beans::Optional< OUString > id(
247 level == 0
248 ? beans::Optional< OUString >(
249 true, dp_misc::getIdentifier( xPackage ) )
250 : xPackage->getIdentifier() );
251 if (id.IsPresent)
252 printf_line( "Identifier", id.Value, level );
253 OUString version(xPackage->getVersion());
254 if (!version.isEmpty())
255 printf_line( "Version", version, level + 1 );
256 printf_line( "URL", xPackage->getURL(), level + 1 );
258 beans::Optional< beans::Ambiguous<sal_Bool> > option(
259 xPackage->isRegistered( Reference<task::XAbortChannel>(), xCmdEnv ) );
260 OUString value;
261 if (option.IsPresent) {
262 beans::Ambiguous<sal_Bool> const & reg = option.Value;
263 if (reg.IsAmbiguous)
264 value = "unknown";
265 else
266 value = reg.Value ? std::u16string_view(u"yes") : std::u16string_view(u"no");
268 else
269 value = "n/a";
270 printf_line( "is registered", value, level + 1 );
272 const Reference<deployment::XPackageTypeInfo> xPackageType(
273 xPackage->getPackageType() );
274 OSL_ASSERT( xPackageType.is() );
275 if (xPackageType.is()) {
276 printf_line( "Media-Type", xPackageType->getMediaType(), level + 1 );
278 printf_line( "Description", xPackage->getDescription(), level + 1 );
279 if (!xPackage->isBundle())
280 return;
282 Sequence< Reference<deployment::XPackage> > seq(
283 xPackage->getBundle( Reference<task::XAbortChannel>(), xCmdEnv ) );
284 printf_space( level + 1 );
285 dp_misc::writeConsole("bundled Packages: {\n");
286 std::vector<Reference<deployment::XPackage> >vec_bundle;
287 ::comphelper::sequenceToContainer(vec_bundle, seq);
288 printf_packages( vec_bundle, std::vector<bool>(vec_bundle.size()),
289 xCmdEnv, level + 2 );
290 printf_space( level + 1 );
291 dp_misc::writeConsole("}\n");
294 } // anon namespace
296 static void printf_unaccepted_licenses(
297 Reference<deployment::XPackage> const & ext)
299 OUString id(
300 dp_misc::getIdentifier(ext) );
301 printf_line( "Identifier", id, 0 );
302 printf_space(1);
303 dp_misc::writeConsole("License not accepted\n\n");
307 void printf_packages(
308 std::vector< Reference<deployment::XPackage> > const & allExtensions,
309 std::vector<bool> const & vecUnaccepted,
310 Reference<XCommandEnvironment> const & xCmdEnv, sal_Int32 level )
312 OSL_ASSERT(allExtensions.size() == vecUnaccepted.size());
314 if (allExtensions.empty())
316 printf_space( level );
317 dp_misc::writeConsole("<none>\n");
319 else
321 int index = 0;
322 for (auto const& extension : allExtensions)
324 if (vecUnaccepted[index])
325 printf_unaccepted_licenses(extension);
326 else
327 printf_package( extension, xCmdEnv, level );
328 dp_misc::writeConsole("\n");
329 ++index;
335 namespace {
338 Reference<XComponentContext> bootstrapStandAlone()
340 Reference<XComponentContext> xContext =
341 ::cppu::defaultBootstrap_InitialComponentContext();
343 Reference<lang::XMultiServiceFactory> xServiceManager(
344 xContext->getServiceManager(), UNO_QUERY_THROW );
345 // set global process service factory used by unotools config helpers
346 ::comphelper::setProcessServiceFactory( xServiceManager );
348 // Initialize the UCB (for backwards compatibility, in case some code still
349 // uses plain createInstance w/o args directly to obtain an instance):
350 UniversalContentBroker::create( xContext );
352 return xContext;
356 Reference<XComponentContext> connectToOffice(
357 Reference<XComponentContext> const & xLocalComponentContext,
358 bool verbose )
360 OUString pipeId( ::dp_misc::generateRandomPipeId() );
361 OUString acceptArg = "--accept=pipe,name=" + pipeId + ";urp;";
363 Sequence<OUString> args { "--nologo", "--nodefault", acceptArg };
364 OUString appURL( getExecutableDir() + "/soffice" );
366 if (verbose)
368 dp_misc::writeConsole(
369 "Raising process: " + appURL +
370 "\nArguments: --nologo --nodefault " + args[2] +
371 "\n");
374 ::dp_misc::raiseProcess( appURL, args );
376 if (verbose)
377 dp_misc::writeConsole("OK. Connecting...");
379 OUString sUnoUrl = "uno:pipe,name=" + pipeId + ";urp;StarOffice.ComponentContext";
380 Reference<XComponentContext> xRet(
381 ::dp_misc::resolveUnoURL(
382 sUnoUrl, xLocalComponentContext ),
383 UNO_QUERY_THROW );
384 if (verbose)
385 dp_misc::writeConsole("OK.\n");
387 return xRet;
390 } // anon namespace
392 /** returns the path to the lock file used by unopkg.
393 @return the path. An empty string signifies an error.
395 static OUString getLockFilePath()
397 OUString ret;
398 OUString sBootstrap("${$BRAND_BASE_DIR/" LIBO_ETC_FOLDER "/" SAL_CONFIGFILE("bootstrap") ":UserInstallation}");
399 rtl::Bootstrap::expandMacros(sBootstrap);
400 OUString sAbs;
401 if (::osl::File::E_None == ::osl::File::getAbsoluteFileURL(
402 sBootstrap, ".lock", sAbs))
404 if (::osl::File::E_None ==
405 ::osl::File::getSystemPathFromFileURL(sAbs, sBootstrap))
407 ret = sBootstrap;
411 return ret;
414 Reference<XComponentContext> getUNO(
415 bool verbose, bool bGui, const OUString& sTempDir,
416 Reference<XComponentContext> & out_localContext)
418 // do not create any user data (for the root user) in --shared mode:
419 if (!sTempDir.isEmpty())
420 rtl::Bootstrap::set("UserInstallation", sTempDir);
422 // hold lock during process runtime:
423 static ::desktop::Lockfile s_lockfile( false /* no IPC server */ );
424 Reference<XComponentContext> xComponentContext( bootstrapStandAlone() );
425 out_localContext = xComponentContext;
426 if (::dp_misc::office_is_running()) {
427 xComponentContext.set(
428 connectToOffice( xComponentContext, verbose ) );
430 else
432 if (! s_lockfile.check( nullptr ))
434 OUString sMsg(DpResId(RID_STR_CONCURRENTINSTANCE));
435 OUString sError(DpResId(RID_STR_UNOPKG_ERROR));
437 sMsg += "\n" + getLockFilePath();
439 if (bGui)
441 //We show a message box or print to the console that there
442 //is another instance already running
443 if ( ! InitVCL() )
444 throw RuntimeException( "Cannot initialize VCL!" );
446 std::unique_ptr<weld::MessageDialog> xWarn(Application::CreateMessageDialog(nullptr,
447 VclMessageType::Warning, VclButtonsType::Ok,
448 sMsg));
449 xWarn->set_title(utl::ConfigManager::getProductName());
450 xWarn->run();
452 DeInitVCL();
455 throw LockFileException(sError + sMsg);
459 return xComponentContext;
464 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */