summaryrefslogtreecommitdiffstats
path: root/desktop/source/pkgchk/unopkg/unopkg_misc.cxx
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:06:44 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:06:44 +0000
commited5640d8b587fbcfed7dd7967f3de04b37a76f26 (patch)
tree7a5f7c6c9d02226d7471cb3cc8fbbf631b415303 /desktop/source/pkgchk/unopkg/unopkg_misc.cxx
parentInitial commit. (diff)
downloadlibreoffice-ed5640d8b587fbcfed7dd7967f3de04b37a76f26.tar.xz
libreoffice-ed5640d8b587fbcfed7dd7967f3de04b37a76f26.zip
Adding upstream version 4:7.4.7.upstream/4%7.4.7upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'desktop/source/pkgchk/unopkg/unopkg_misc.cxx')
-rw-r--r--desktop/source/pkgchk/unopkg/unopkg_misc.cxx458
1 files changed, 458 insertions, 0 deletions
diff --git a/desktop/source/pkgchk/unopkg/unopkg_misc.cxx b/desktop/source/pkgchk/unopkg/unopkg_misc.cxx
new file mode 100644
index 000000000..402833aa5
--- /dev/null
+++ b/desktop/source/pkgchk/unopkg/unopkg_misc.cxx
@@ -0,0 +1,458 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+
+#include <string_view>
+
+#include <config_folders.h>
+
+#include <vcl/svapp.hxx>
+#include <vcl/weld.hxx>
+#include <rtl/bootstrap.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <sal/log.hxx>
+#include <osl/process.h>
+#include <osl/file.hxx>
+#include <unotools/configmgr.hxx>
+#include <unotools/bootstrap.hxx>
+#include <cppuhelper/bootstrap.hxx>
+#include <comphelper/sequence.hxx>
+#include <comphelper/processfactory.hxx>
+
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/ucb/UniversalContentBroker.hpp>
+
+#include <strings.hrc>
+#include "unopkg_shared.h"
+#include <dp_identifier.hxx>
+#include <dp_misc.h>
+#include <dp_shared.hxx>
+#include <lockfile.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::ucb;
+
+namespace unopkg {
+
+OUString toString( OptionInfo const * info )
+{
+ assert(info != nullptr);
+ OUStringBuffer buf;
+ buf.append("--");
+ buf.appendAscii(info->m_name);
+ if (info->m_short_option != '\0')
+ {
+ buf.append(" (short -" );
+ buf.append(info->m_short_option );
+ buf.append(")");
+ }
+ if (info->m_has_argument)
+ buf.append(" <argument>" );
+ return buf.makeStringAndClear();
+}
+
+
+OptionInfo const * getOptionInfo(
+ OptionInfo const * list,
+ OUString const & opt )
+{
+ for ( ; list->m_name != nullptr; ++list )
+ {
+ OptionInfo const & option_info = *list;
+ if (!opt.isEmpty())
+ {
+ if (opt.equalsAsciiL(
+ option_info.m_name, option_info.m_name_length ))
+ {
+ return &option_info;
+ }
+ }
+ }
+ SAL_WARN( "desktop", opt );
+ return nullptr;
+}
+
+
+bool isOption( OptionInfo const * option_info, sal_uInt32 * pIndex )
+{
+ assert(option_info != nullptr);
+ if (osl_getCommandArgCount() <= *pIndex)
+ return false;
+
+ OUString arg;
+ osl_getCommandArg( *pIndex, &arg.pData );
+ sal_Int32 len = arg.getLength();
+
+ if (len < 2 || arg[ 0 ] != '-')
+ return false;
+
+ if (len == 2 && arg[ 1 ] == option_info->m_short_option)
+ {
+ ++(*pIndex);
+ dp_misc::TRACE(__FILE__ ": identified option \'\'"
+ + OUStringChar( option_info->m_short_option ) + "\n");
+ return true;
+ }
+ if (arg[ 1 ] == '-' && rtl_ustr_ascii_compare(
+ arg.pData->buffer + 2, option_info->m_name ) == 0)
+ {
+ ++(*pIndex);
+ dp_misc::TRACE(__FILE__ ": identified option \'"
+ + OUString::createFromAscii(option_info->m_name) + "\'\n");
+ return true;
+ }
+ return false;
+}
+
+
+bool isBootstrapVariable(sal_uInt32 * pIndex)
+{
+ OSL_ASSERT(osl_getCommandArgCount() >= *pIndex);
+
+ OUString arg;
+ osl_getCommandArg(*pIndex, &arg.pData);
+ if (arg.match("-env:"))
+ {
+ ++(*pIndex);
+ return true;
+ }
+ return false;
+}
+
+
+bool readArgument(
+ OUString * pValue, OptionInfo const * option_info, sal_uInt32 * pIndex )
+{
+ if (isOption( option_info, pIndex ))
+ {
+ if (*pIndex < osl_getCommandArgCount())
+ {
+ OSL_ASSERT( pValue != nullptr );
+ osl_getCommandArg( *pIndex, &pValue->pData );
+ dp_misc::TRACE(__FILE__ ": argument value: "
+ + *pValue + "\n");
+ ++(*pIndex);
+ return true;
+ }
+ --(*pIndex);
+ }
+ return false;
+}
+
+
+OUString const & getExecutableDir()
+{
+ static const OUString EXEC =
+ []()
+ {
+ OUString path;
+ if (osl_getExecutableFile( &path.pData ) != osl_Process_E_None) {
+ throw RuntimeException("cannot locate executable directory!",nullptr);
+ }
+ return path.copy( 0, path.lastIndexOf( '/' ) );
+ }();
+ return EXEC;
+}
+
+
+OUString const & getProcessWorkingDir()
+{
+ static const OUString WORKING =
+ []()
+ {
+ OUString workingDir;
+ utl::Bootstrap::getProcessWorkingDir(workingDir);
+ return workingDir;
+ }();
+ return WORKING;
+}
+
+
+OUString makeAbsoluteFileUrl(
+ OUString const & sys_path, OUString const & base_url )
+{
+ // system path to file url
+ OUString file_url;
+ oslFileError rc = osl_getFileURLFromSystemPath( sys_path.pData, &file_url.pData );
+ if ( rc != osl_File_E_None) {
+ OUString tempPath;
+ if ( osl_getSystemPathFromFileURL( sys_path.pData, &tempPath.pData) != osl_File_E_None )
+ {
+ throw RuntimeException("cannot get file url from system path: " +
+ sys_path );
+ }
+ file_url = sys_path;
+ }
+
+ OUString abs;
+ if (osl_getAbsoluteFileURL(
+ base_url.pData, file_url.pData, &abs.pData ) != osl_File_E_None)
+ {
+ throw RuntimeException(
+ "making absolute file url failed: \"" + base_url
+ + "\" (base-url) and \"" + file_url + "\" (file-url)!" );
+ }
+ return abs[ abs.getLength() -1 ] == '/'
+ ? abs.copy( 0, abs.getLength() -1 ) : abs;
+}
+
+
+namespace {
+
+
+void printf_space( sal_Int32 space )
+{
+ while (space--)
+ dp_misc::writeConsole(u" ");
+}
+
+
+void printf_line(
+ std::u16string_view name, std::u16string_view value, sal_Int32 level )
+{
+ printf_space( level );
+ dp_misc::writeConsole(OUStringConcatenation(OUString::Concat(name) + ": " + value + "\n"));
+}
+
+
+void printf_package(
+ Reference<deployment::XPackage> const & xPackage,
+ Reference<XCommandEnvironment> const & xCmdEnv, sal_Int32 level )
+{
+ beans::Optional< OUString > id(
+ level == 0
+ ? beans::Optional< OUString >(
+ true, dp_misc::getIdentifier( xPackage ) )
+ : xPackage->getIdentifier() );
+ if (id.IsPresent)
+ printf_line( u"Identifier", id.Value, level );
+ OUString version(xPackage->getVersion());
+ if (!version.isEmpty())
+ printf_line( u"Version", version, level + 1 );
+ printf_line( u"URL", xPackage->getURL(), level + 1 );
+
+ beans::Optional< beans::Ambiguous<sal_Bool> > option(
+ xPackage->isRegistered( Reference<task::XAbortChannel>(), xCmdEnv ) );
+ OUString value;
+ if (option.IsPresent) {
+ beans::Ambiguous<sal_Bool> const & reg = option.Value;
+ if (reg.IsAmbiguous)
+ value = "unknown";
+ else
+ value = reg.Value ? std::u16string_view(u"yes") : std::u16string_view(u"no");
+ }
+ else
+ value = "n/a";
+ printf_line( u"is registered", value, level + 1 );
+
+ const Reference<deployment::XPackageTypeInfo> xPackageType(
+ xPackage->getPackageType() );
+ OSL_ASSERT( xPackageType.is() );
+ if (xPackageType.is()) {
+ printf_line( u"Media-Type", xPackageType->getMediaType(), level + 1 );
+ }
+ printf_line( u"Description", xPackage->getDescription(), level + 1 );
+ if (!xPackage->isBundle())
+ return;
+
+ Sequence< Reference<deployment::XPackage> > seq(
+ xPackage->getBundle( Reference<task::XAbortChannel>(), xCmdEnv ) );
+ printf_space( level + 1 );
+ dp_misc::writeConsole(u"bundled Packages: {\n");
+ std::vector<Reference<deployment::XPackage> >vec_bundle;
+ ::comphelper::sequenceToContainer(vec_bundle, seq);
+ printf_packages( vec_bundle, std::vector<bool>(vec_bundle.size()),
+ xCmdEnv, level + 2 );
+ printf_space( level + 1 );
+ dp_misc::writeConsole(u"}\n");
+}
+
+} // anon namespace
+
+static void printf_unaccepted_licenses(
+ Reference<deployment::XPackage> const & ext)
+{
+ OUString id(
+ dp_misc::getIdentifier(ext) );
+ printf_line( u"Identifier", id, 0 );
+ printf_space(1);
+ dp_misc::writeConsole(u"License not accepted\n\n");
+}
+
+
+void printf_packages(
+ std::vector< Reference<deployment::XPackage> > const & allExtensions,
+ std::vector<bool> const & vecUnaccepted,
+ Reference<XCommandEnvironment> const & xCmdEnv, sal_Int32 level )
+{
+ OSL_ASSERT(allExtensions.size() == vecUnaccepted.size());
+
+ if (allExtensions.empty())
+ {
+ printf_space( level );
+ dp_misc::writeConsole(u"<none>\n");
+ }
+ else
+ {
+ int index = 0;
+ for (auto const& extension : allExtensions)
+ {
+ if (vecUnaccepted[index])
+ printf_unaccepted_licenses(extension);
+ else
+ printf_package( extension, xCmdEnv, level );
+ dp_misc::writeConsole(u"\n");
+ ++index;
+ }
+ }
+}
+
+
+namespace {
+
+
+Reference<XComponentContext> bootstrapStandAlone()
+{
+ Reference<XComponentContext> xContext =
+ ::cppu::defaultBootstrap_InitialComponentContext();
+
+ Reference<lang::XMultiServiceFactory> xServiceManager(
+ xContext->getServiceManager(), UNO_QUERY_THROW );
+ // set global process service factory used by unotools config helpers
+ ::comphelper::setProcessServiceFactory( xServiceManager );
+
+ // Initialize the UCB (for backwards compatibility, in case some code still
+ // uses plain createInstance w/o args directly to obtain an instance):
+ UniversalContentBroker::create( xContext );
+
+ return xContext;
+}
+
+
+Reference<XComponentContext> connectToOffice(
+ Reference<XComponentContext> const & xLocalComponentContext,
+ bool verbose )
+{
+ OUString pipeId( ::dp_misc::generateRandomPipeId() );
+ OUString acceptArg = "--accept=pipe,name=" + pipeId + ";urp;";
+
+ Sequence<OUString> args { "--nologo", "--nodefault", acceptArg };
+ OUString appURL( getExecutableDir() + "/soffice" );
+
+ if (verbose)
+ {
+ dp_misc::writeConsole(OUStringConcatenation(
+ "Raising process: " + appURL +
+ "\nArguments: --nologo --nodefault " + args[2] +
+ "\n"));
+ }
+
+ ::dp_misc::raiseProcess( appURL, args );
+
+ if (verbose)
+ dp_misc::writeConsole(u"OK. Connecting...");
+
+ OUString sUnoUrl = "uno:pipe,name=" + pipeId + ";urp;StarOffice.ComponentContext";
+ Reference<XComponentContext> xRet(
+ ::dp_misc::resolveUnoURL(
+ sUnoUrl, xLocalComponentContext ),
+ UNO_QUERY_THROW );
+ if (verbose)
+ dp_misc::writeConsole(u"OK.\n");
+
+ return xRet;
+}
+
+} // anon namespace
+
+/** returns the path to the lock file used by unopkg.
+ @return the path. An empty string signifies an error.
+*/
+static OUString getLockFilePath()
+{
+ OUString ret;
+ OUString sBootstrap("${$BRAND_BASE_DIR/" LIBO_ETC_FOLDER "/" SAL_CONFIGFILE("bootstrap") ":UserInstallation}");
+ rtl::Bootstrap::expandMacros(sBootstrap);
+ OUString sAbs;
+ if (::osl::File::E_None == ::osl::File::getAbsoluteFileURL(
+ sBootstrap, ".lock", sAbs))
+ {
+ if (::osl::File::E_None ==
+ ::osl::File::getSystemPathFromFileURL(sAbs, sBootstrap))
+ {
+ ret = sBootstrap;
+ }
+ }
+
+ return ret;
+}
+
+Reference<XComponentContext> getUNO(
+ bool verbose, bool bGui, const OUString& sTempDir,
+ Reference<XComponentContext> & out_localContext)
+{
+ // do not create any user data (for the root user) in --shared mode:
+ if (!sTempDir.isEmpty())
+ rtl::Bootstrap::set("UserInstallation", sTempDir);
+
+ // hold lock during process runtime:
+ static ::desktop::Lockfile s_lockfile( false /* no IPC server */ );
+ Reference<XComponentContext> xComponentContext( bootstrapStandAlone() );
+ out_localContext = xComponentContext;
+ if (::dp_misc::office_is_running()) {
+ xComponentContext.set(
+ connectToOffice( xComponentContext, verbose ) );
+ }
+ else
+ {
+ if (! s_lockfile.check( nullptr ))
+ {
+ OUString sMsg(DpResId(RID_STR_CONCURRENTINSTANCE));
+ OUString sError(DpResId(RID_STR_UNOPKG_ERROR));
+
+ sMsg += "\n" + getLockFilePath();
+
+ if (bGui)
+ {
+ //We show a message box or print to the console that there
+ //is another instance already running
+ if ( ! InitVCL() )
+ throw RuntimeException( "Cannot initialize VCL!" );
+ {
+ std::unique_ptr<weld::MessageDialog> xWarn(Application::CreateMessageDialog(nullptr,
+ VclMessageType::Warning, VclButtonsType::Ok,
+ sMsg));
+ xWarn->set_title(utl::ConfigManager::getProductName());
+ xWarn->run();
+ }
+ DeInitVCL();
+ }
+
+ throw LockFileException(sError + sMsg);
+ }
+ }
+
+ return xComponentContext;
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */