diff options
Diffstat (limited to 'shell/source/backends')
-rw-r--r-- | shell/source/backends/desktopbe/desktopbackend.cxx | 301 | ||||
-rw-r--r-- | shell/source/backends/desktopbe/desktopbe1.component | 26 | ||||
-rw-r--r-- | shell/source/backends/kf5be/kf5access.cxx | 315 | ||||
-rw-r--r-- | shell/source/backends/kf5be/kf5access.hxx | 41 | ||||
-rw-r--r-- | shell/source/backends/kf5be/kf5backend.cxx | 260 | ||||
-rw-r--r-- | shell/source/backends/kf5be/kf5be1.component | 26 | ||||
-rw-r--r-- | shell/source/backends/localebe/localebackend.cxx | 333 | ||||
-rw-r--r-- | shell/source/backends/localebe/localebackend.hxx | 106 | ||||
-rw-r--r-- | shell/source/backends/localebe/localebe1.component | 26 | ||||
-rw-r--r-- | shell/source/backends/macbe/macbackend.hxx | 90 | ||||
-rw-r--r-- | shell/source/backends/macbe/macbackend.mm | 395 | ||||
-rw-r--r-- | shell/source/backends/macbe/macbe1.component | 26 | ||||
-rw-r--r-- | shell/source/backends/wininetbe/wininetbackend.cxx | 363 | ||||
-rw-r--r-- | shell/source/backends/wininetbe/wininetbackend.hxx | 110 | ||||
-rw-r--r-- | shell/source/backends/wininetbe/wininetbe1.component | 26 |
15 files changed, 2444 insertions, 0 deletions
diff --git a/shell/source/backends/desktopbe/desktopbackend.cxx b/shell/source/backends/desktopbe/desktopbackend.cxx new file mode 100644 index 000000000..4dcc91967 --- /dev/null +++ b/shell/source/backends/desktopbe/desktopbackend.cxx @@ -0,0 +1,301 @@ +/* -*- 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 <sal/log.hxx> + +#include <com/sun/star/beans/Optional.hpp> +#include <com/sun/star/beans/UnknownPropertyException.hpp> +#include <com/sun/star/beans/XPropertyChangeListener.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/beans/XPropertySetInfo.hpp> +#include <com/sun/star/beans/XVetoableChangeListener.hpp> +#include <com/sun/star/lang/IllegalArgumentException.hpp> +#include <com/sun/star/lang/XMultiComponentFactory.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/uno/Any.hxx> +#include <com/sun/star/uno/Exception.hpp> +#include <com/sun/star/uno/Reference.hxx> +#include <com/sun/star/uno/RuntimeException.hpp> +#include <com/sun/star/uno/Sequence.hxx> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <com/sun/star/uno/XCurrentContext.hpp> +#include <cppuhelper/implbase.hxx> +#include <cppuhelper/weak.hxx> +#include <osl/file.hxx> +#include <osl/security.hxx> +#include <rtl/byteseq.hxx> +#include <rtl/ustrbuf.hxx> +#include <rtl/ustring.hxx> +#include <sal/types.h> +#include <tools/diagnose_ex.h> +#include <uno/current_context.hxx> + +namespace { + +class Default: + public cppu::WeakImplHelper< + css::lang::XServiceInfo, css::beans::XPropertySet > +{ +public: + Default() {} + Default(const Default&) = delete; + Default& operator=(const Default&) = delete; + +private: + virtual ~Default() override {} + + virtual OUString SAL_CALL getImplementationName() override + { return "com.sun.star.comp.configuration.backend.DesktopBackend"; } + + virtual sal_Bool SAL_CALL supportsService(OUString const & ServiceName) override + { return ServiceName == getSupportedServiceNames()[0]; } + + virtual css::uno::Sequence< OUString > SAL_CALL + getSupportedServiceNames() override + { return { "com.sun.star.configuration.backend.DesktopBackend" }; } + + virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL + getPropertySetInfo() override + { return css::uno::Reference< css::beans::XPropertySetInfo >(); } + + virtual void SAL_CALL setPropertyValue( + OUString const &, css::uno::Any const &) override; + + virtual css::uno::Any SAL_CALL getPropertyValue( + OUString const & PropertyName) override; + + virtual void SAL_CALL addPropertyChangeListener( + OUString const &, + css::uno::Reference< css::beans::XPropertyChangeListener > const &) override + {} + + virtual void SAL_CALL removePropertyChangeListener( + OUString const &, + css::uno::Reference< css::beans::XPropertyChangeListener > const &) override + {} + + virtual void SAL_CALL addVetoableChangeListener( + OUString const &, + css::uno::Reference< css::beans::XVetoableChangeListener > const &) override + {} + + virtual void SAL_CALL removeVetoableChangeListener( + OUString const &, + css::uno::Reference< css::beans::XVetoableChangeListener > const &) override + {} +}; + +void Default::setPropertyValue(OUString const &, css::uno::Any const &) +{ + throw css::lang::IllegalArgumentException( + "setPropertyValue not supported", + static_cast< cppu::OWeakObject * >(this), -1); +} + +OUString xdg_user_dir_lookup (const char *type, bool bAllowHomeDir) +{ + size_t nLenType = strlen(type); + char *config_home; + char *p; + bool bError = false; + + osl::Security aSecurity; + oslFileHandle handle; + OUString aHomeDirURL; + OUString aDocumentsDirURL; + OUString aConfigFileURL; + OUStringBuffer aUserDirBuf; + + if (!aSecurity.getHomeDir( aHomeDirURL ) ) + { + osl::FileBase::getFileURLFromSystemPath("/tmp", aDocumentsDirURL); + return aDocumentsDirURL; + } + + config_home = getenv ("XDG_CONFIG_HOME"); + if (config_home == nullptr || config_home[0] == 0) + { + aConfigFileURL = aHomeDirURL + "/.config/user-dirs.dirs"; + } + else + { + aConfigFileURL = OUString::createFromAscii(config_home) + "/user-dirs.dirs"; + } + + if(osl_File_E_None == osl_openFile(aConfigFileURL.pData, &handle, osl_File_OpenFlag_Read)) + { + rtl::ByteSequence seq; + while (osl_File_E_None == osl_readLine(handle , reinterpret_cast<sal_Sequence **>(&seq))) + { + int relative = 0; + int len = seq.getLength(); + seq.realloc(len + 1); + seq[len] = 0; + + p = reinterpret_cast<char *>(seq.getArray()); + while (*p == ' ' || *p == '\t') + p++; + if (strncmp (p, "XDG_", 4) != 0) + continue; + p += 4; + if (strncmp (p, OString(type, nLenType).toAsciiUpperCase().getStr(), nLenType) != 0) + continue; + p += nLenType; + if (strncmp (p, "_DIR", 4) != 0) + continue; + p += 4; + while (*p == ' ' || *p == '\t') + p++; + if (*p != '=') + continue; + p++; + while (*p == ' ' || *p == '\t') + p++; + if (*p != '"') + continue; + p++; + if (strncmp (p, "$HOME/", 6) == 0) + { + p += 6; + relative = 1; + } + else if (*p != '/') + continue; + if (relative) + { + aUserDirBuf = aHomeDirURL + "/"; + } + else + { + aUserDirBuf.truncate(); + } + while (*p && *p != '"') + { + if ((*p == '\\') && (*(p+1) != 0)) + p++; + aUserDirBuf.append(static_cast<sal_Unicode>(*p++)); + } + }//end of while + osl_closeFile(handle); + } + else + bError = true; + if (aUserDirBuf.getLength()>0 && !bError) + { + aDocumentsDirURL = aUserDirBuf.makeStringAndClear(); + if ( bAllowHomeDir || + (aDocumentsDirURL != aHomeDirURL && aDocumentsDirURL != OUStringConcatenation(aHomeDirURL + "/")) ) + { + osl::Directory aDocumentsDir( aDocumentsDirURL ); + if( osl::FileBase::E_None == aDocumentsDir.open() ) + return aDocumentsDirURL; + } + } + /* Use fallbacks historical compatibility if nothing else exists */ + return aHomeDirURL + "/" + OUString::createFromAscii(type); +} + +css::uno::Any xdgDirectoryIfExists(char const * type, bool bAllowHomeDir) { + auto url = xdg_user_dir_lookup(type, bAllowHomeDir); + return css::uno::Any( + osl::Directory(url).open() == osl::FileBase::E_None + ? css::beans::Optional<css::uno::Any>(true, css::uno::Any(url)) + : css::beans::Optional<css::uno::Any>(false, css::uno::Any())); +} + +css::uno::Any Default::getPropertyValue(OUString const & PropertyName) +{ + if (PropertyName == "TemplatePathVariable") + { + // Never pick up the HOME directory as the default location of user's templates + return xdgDirectoryIfExists("Templates", false); + } + + if (PropertyName == "WorkPathVariable") + { + return xdgDirectoryIfExists("Documents", true); + } + + if ( PropertyName == "EnableATToolSupport" || + PropertyName == "ExternalMailer" || + PropertyName == "SourceViewFontHeight" || + PropertyName == "SourceViewFontName" || + PropertyName == "ooInetFTPProxyName" || + PropertyName == "ooInetFTPProxyPort" || + PropertyName == "ooInetHTTPProxyName" || + PropertyName == "ooInetHTTPProxyPort" || + PropertyName == "ooInetHTTPSProxyName" || + PropertyName == "ooInetHTTPSProxyPort" || + PropertyName == "ooInetNoProxy" || + PropertyName == "ooInetProxyType" || + PropertyName == "givenname" || + PropertyName == "sn" ) + { + return css::uno::Any(css::beans::Optional< css::uno::Any >()); + } + + throw css::beans::UnknownPropertyException( + PropertyName, static_cast< cppu::OWeakObject * >(this)); +} + +css::uno::Reference< css::uno::XInterface > createBackend( + css::uno::Reference< css::uno::XComponentContext > const & context, + OUString const & name) +{ + try { + return css::uno::Reference< css::lang::XMultiComponentFactory >( + context->getServiceManager(), css::uno::UNO_SET_THROW)-> + createInstanceWithContext(name, context); + } catch (css::uno::RuntimeException &) { + // Assuming these exceptions are real errors: + throw; + } catch (const css::uno::Exception &) { + // Assuming these exceptions indicate that the service is not installed: + TOOLS_WARN_EXCEPTION("shell", "createInstance(" << name << ") failed"); + return css::uno::Reference< css::uno::XInterface >(); + } +} + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface* +shell_DesktopBackend_get_implementation( + css::uno::XComponentContext* context , css::uno::Sequence<css::uno::Any> const&) +{ + OUString desktop; + css::uno::Reference< css::uno::XCurrentContext > current( + css::uno::getCurrentContext()); + if (current.is()) { + current->getValueByName("system.desktop-environment") >>= desktop; + } + + // Fall back to the default if the specific backend is not available: + css::uno::Reference< css::uno::XInterface > backend; + if (desktop == "PLASMA5") + backend = createBackend(context, + "com.sun.star.configuration.backend.KF5Backend"); + if (!backend) + backend = static_cast< cppu::OWeakObject * >(new Default); + backend->acquire(); + return backend.get(); +} + +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/shell/source/backends/desktopbe/desktopbe1.component b/shell/source/backends/desktopbe/desktopbe1.component new file mode 100644 index 000000000..abc47f042 --- /dev/null +++ b/shell/source/backends/desktopbe/desktopbe1.component @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + * 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 . + --> + +<component loader="com.sun.star.loader.SharedLibrary" environment="@CPPU_ENV@" + xmlns="http://openoffice.org/2010/uno-components"> + <implementation name="com.sun.star.comp.configuration.backend.DesktopBackend" + constructor="shell_DesktopBackend_get_implementation"> + <service name="com.sun.star.configuration.backend.DesktopBackend"/> + </implementation> +</component> diff --git a/shell/source/backends/kf5be/kf5access.cxx b/shell/source/backends/kf5be/kf5access.cxx new file mode 100644 index 000000000..bfb669cf2 --- /dev/null +++ b/shell/source/backends/kf5be/kf5access.cxx @@ -0,0 +1,315 @@ +/* -*- 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 "kf5access.hxx" + +#include <QtGui/QFont> +#include <QtCore/QString> +#include <QtGui/QFontDatabase> +#include <QtCore/QStandardPaths> +#include <QtCore/QDir> +#include <QtCore/QUrl> + +#include <kprotocolmanager.h> + +#include <kemailsettings.h> +// #include <kglobalsettings.h> + +#include <com/sun/star/uno/Any.hxx> +#include <osl/diagnose.h> +#include <osl/file.h> +#include <rtl/ustring.hxx> + +namespace kf5access +{ +namespace +{ +namespace uno = css::uno; +} + +namespace +{ +OUString fromQStringToOUString(QString const& s) +{ + // Conversion from QString size()'s int to OUString's sal_Int32 should be non-narrowing: + return { reinterpret_cast<char16_t const*>(s.utf16()), s.size() }; +} +} + +css::beans::Optional<css::uno::Any> getValue(std::u16string_view id) +{ + if (id == u"ExternalMailer") + { + KEMailSettings aEmailSettings; + QString aClientProgram; + OUString sClientProgram; + + aClientProgram = aEmailSettings.getSetting(KEMailSettings::ClientProgram); + if (aClientProgram.isEmpty()) + aClientProgram = QStringLiteral("kmail"); + else + aClientProgram = aClientProgram.section(QLatin1Char(' '), 0, 0); + sClientProgram = fromQStringToOUString(aClientProgram); + return css::beans::Optional<css::uno::Any>(true, uno::Any(sClientProgram)); + } + else if (id == u"SourceViewFontHeight") + { + const QFont aFixedFont = QFontDatabase::systemFont(QFontDatabase::FixedFont); + const short nFontHeight = aFixedFont.pointSize(); + return css::beans::Optional<css::uno::Any>(true, uno::Any(nFontHeight)); + } + else if (id == u"SourceViewFontName") + { + const QFont aFixedFont = QFontDatabase::systemFont(QFontDatabase::FixedFont); + const QString aFontName = aFixedFont.family(); + const OUString sFontName = fromQStringToOUString(aFontName); + return css::beans::Optional<css::uno::Any>(true, uno::Any(sFontName)); + } + else if (id == u"EnableATToolSupport") + { + /* does not make much sense without an accessibility bridge */ + bool ATToolSupport = false; + return css::beans::Optional<css::uno::Any>(true, + uno::Any(OUString::boolean(ATToolSupport))); + } + else if (id == u"WorkPathVariable") + { + QString aDocumentsDir(QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation)); + if (aDocumentsDir.isEmpty()) + aDocumentsDir = QDir::homePath(); + OUString sDocumentsDir; + OUString sDocumentsURL; + if (aDocumentsDir.endsWith(QLatin1Char('/'))) + aDocumentsDir.truncate(aDocumentsDir.length() - 1); + sDocumentsDir = fromQStringToOUString(aDocumentsDir); + osl_getFileURLFromSystemPath(sDocumentsDir.pData, &sDocumentsURL.pData); + return css::beans::Optional<css::uno::Any>(true, uno::Any(sDocumentsURL)); + } + else if (id == u"ooInetFTPProxyName") + { + QString aFTPProxy; + switch (KProtocolManager::proxyType()) + { + case KProtocolManager::ManualProxy: // Proxies are manually configured + aFTPProxy = KProtocolManager::proxyFor(QStringLiteral("FTP")); + break; + case KProtocolManager::PACProxy: // A proxy configuration URL has been given + case KProtocolManager::WPADProxy: // A proxy should be automatically discovered + case KProtocolManager::EnvVarProxy: // Proxy values set through environment variables + // In such cases, the proxy address is not stored in KDE, but determined dynamically. + // The proxy address may depend on the requested address, on the time of the day, on the speed of the wind... + // The best we can do here is to ask the current value for a given address. + aFTPProxy = KProtocolManager::proxyForUrl( + QUrl(QStringLiteral("ftp://ftp.libreoffice.org"))); + break; + default: // No proxy is used + break; + } + if (!aFTPProxy.isEmpty()) + { + QUrl aProxy(aFTPProxy); + OUString sProxy = fromQStringToOUString(aProxy.host()); + return css::beans::Optional<css::uno::Any>(true, uno::Any(sProxy)); + } + } + else if (id == u"ooInetFTPProxyPort") + { + QString aFTPProxy; + switch (KProtocolManager::proxyType()) + { + case KProtocolManager::ManualProxy: // Proxies are manually configured + aFTPProxy = KProtocolManager::proxyFor(QStringLiteral("FTP")); + break; + case KProtocolManager::PACProxy: // A proxy configuration URL has been given + case KProtocolManager::WPADProxy: // A proxy should be automatically discovered + case KProtocolManager::EnvVarProxy: // Proxy values set through environment variables + // In such cases, the proxy address is not stored in KDE, but determined dynamically. + // The proxy address may depend on the requested address, on the time of the day, on the speed of the wind... + // The best we can do here is to ask the current value for a given address. + aFTPProxy = KProtocolManager::proxyForUrl( + QUrl(QStringLiteral("ftp://ftp.libreoffice.org"))); + break; + default: // No proxy is used + break; + } + if (!aFTPProxy.isEmpty()) + { + QUrl aProxy(aFTPProxy); + sal_Int32 nPort = aProxy.port(); + return css::beans::Optional<css::uno::Any>(true, uno::Any(nPort)); + } + } + else if (id == u"ooInetHTTPProxyName") + { + QString aHTTPProxy; + switch (KProtocolManager::proxyType()) + { + case KProtocolManager::ManualProxy: // Proxies are manually configured + aHTTPProxy = KProtocolManager::proxyFor(QStringLiteral("HTTP")); + break; + case KProtocolManager::PACProxy: // A proxy configuration URL has been given + case KProtocolManager::WPADProxy: // A proxy should be automatically discovered + case KProtocolManager::EnvVarProxy: // Proxy values set through environment variables + // In such cases, the proxy address is not stored in KDE, but determined dynamically. + // The proxy address may depend on the requested address, on the time of the day, on the speed of the wind... + // The best we can do here is to ask the current value for a given address. + aHTTPProxy = KProtocolManager::proxyForUrl( + QUrl(QStringLiteral("http://www.libreoffice.org"))); + break; + default: // No proxy is used + break; + } + if (!aHTTPProxy.isEmpty()) + { + QUrl aProxy(aHTTPProxy); + OUString sProxy = fromQStringToOUString(aProxy.host()); + return css::beans::Optional<css::uno::Any>(true, uno::Any(sProxy)); + } + } + else if (id == u"ooInetHTTPProxyPort") + { + QString aHTTPProxy; + switch (KProtocolManager::proxyType()) + { + case KProtocolManager::ManualProxy: // Proxies are manually configured + aHTTPProxy = KProtocolManager::proxyFor(QStringLiteral("HTTP")); + break; + case KProtocolManager::PACProxy: // A proxy configuration URL has been given + case KProtocolManager::WPADProxy: // A proxy should be automatically discovered + case KProtocolManager::EnvVarProxy: // Proxy values set through environment variables + // In such cases, the proxy address is not stored in KDE, but determined dynamically. + // The proxy address may depend on the requested address, on the time of the day, on the speed of the wind... + // The best we can do here is to ask the current value for a given address. + aHTTPProxy = KProtocolManager::proxyForUrl( + QUrl(QStringLiteral("http://www.libreoffice.org"))); + break; + default: // No proxy is used + break; + } + if (!aHTTPProxy.isEmpty()) + { + QUrl aProxy(aHTTPProxy); + sal_Int32 nPort = aProxy.port(); + return css::beans::Optional<css::uno::Any>(true, uno::Any(nPort)); + } + } + else if (id == u"ooInetHTTPSProxyName") + { + QString aHTTPSProxy; + switch (KProtocolManager::proxyType()) + { + case KProtocolManager::ManualProxy: // Proxies are manually configured + aHTTPSProxy = KProtocolManager::proxyFor(QStringLiteral("HTTPS")); + break; + case KProtocolManager::PACProxy: // A proxy configuration URL has been given + case KProtocolManager::WPADProxy: // A proxy should be automatically discovered + case KProtocolManager::EnvVarProxy: // Proxy values set through environment variables + // In such cases, the proxy address is not stored in KDE, but determined dynamically. + // The proxy address may depend on the requested address, on the time of the day, on the speed of the wind... + // The best we can do here is to ask the current value for a given address. + aHTTPSProxy = KProtocolManager::proxyForUrl( + QUrl(QStringLiteral("https://www.libreoffice.org"))); + break; + default: // No proxy is used + break; + } + if (!aHTTPSProxy.isEmpty()) + { + QUrl aProxy(aHTTPSProxy); + OUString sProxy = fromQStringToOUString(aProxy.host()); + return css::beans::Optional<css::uno::Any>(true, uno::Any(sProxy)); + } + } + else if (id == u"ooInetHTTPSProxyPort") + { + QString aHTTPSProxy; + switch (KProtocolManager::proxyType()) + { + case KProtocolManager::ManualProxy: // Proxies are manually configured + aHTTPSProxy = KProtocolManager::proxyFor(QStringLiteral("HTTPS")); + break; + case KProtocolManager::PACProxy: // A proxy configuration URL has been given + case KProtocolManager::WPADProxy: // A proxy should be automatically discovered + case KProtocolManager::EnvVarProxy: // Proxy values set through environment variables + // In such cases, the proxy address is not stored in KDE, but determined dynamically. + // The proxy address may depend on the requested address, on the time of the day, on the speed of the wind... + // The best we can do here is to ask the current value for a given address. + aHTTPSProxy = KProtocolManager::proxyForUrl( + QUrl(QStringLiteral("https://www.libreoffice.org"))); + break; + default: // No proxy is used + break; + } + if (!aHTTPSProxy.isEmpty()) + { + QUrl aProxy(aHTTPSProxy); + sal_Int32 nPort = aProxy.port(); + return css::beans::Optional<css::uno::Any>(true, uno::Any(nPort)); + } + } + else if (id == u"ooInetNoProxy") + { + QString aNoProxyFor; + switch (KProtocolManager::proxyType()) + { + case KProtocolManager::ManualProxy: // Proxies are manually configured + case KProtocolManager::PACProxy: // A proxy configuration URL has been given + case KProtocolManager::WPADProxy: // A proxy should be automatically discovered + case KProtocolManager::EnvVarProxy: // Proxy values set through environment variables + aNoProxyFor = KProtocolManager::noProxyFor(); + break; + default: // No proxy is used + break; + } + if (!aNoProxyFor.isEmpty()) + { + OUString sNoProxyFor; + + aNoProxyFor = aNoProxyFor.replace(QLatin1Char(','), QLatin1Char(';')); + sNoProxyFor = fromQStringToOUString(aNoProxyFor); + return css::beans::Optional<css::uno::Any>(true, uno::Any(sNoProxyFor)); + } + } + else if (id == u"ooInetProxyType") + { + sal_Int32 nProxyType; + switch (KProtocolManager::proxyType()) + { + case KProtocolManager::ManualProxy: // Proxies are manually configured + case KProtocolManager::PACProxy: // A proxy configuration URL has been given + case KProtocolManager::WPADProxy: // A proxy should be automatically discovered + case KProtocolManager::EnvVarProxy: // Proxy values set through environment variables + nProxyType = 1; + break; + default: // No proxy is used + nProxyType = 0; + } + return css::beans::Optional<css::uno::Any>(true, uno::Any(nProxyType)); + } + else + { + OSL_ASSERT(false); // this cannot happen + } + return css::beans::Optional<css::uno::Any>(); +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/shell/source/backends/kf5be/kf5access.hxx b/shell/source/backends/kf5be/kf5access.hxx new file mode 100644 index 000000000..765d9c706 --- /dev/null +++ b/shell/source/backends/kf5be/kf5access.hxx @@ -0,0 +1,41 @@ +/* -*- 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 . + */ + +#ifndef INCLUDED_SHELL_SOURCE_BACKENDS_KF5BE_KF5ACCESS_HXX +#define INCLUDED_SHELL_SOURCE_BACKENDS_KF5BE_KF5ACCESS_HXX + +#include <sal/config.h> + +#include <string_view> + +#include <com/sun/star/beans/Optional.hpp> + +namespace com::sun::star::uno +{ +class Any; +} + +namespace kf5access +{ +css::beans::Optional<css::uno::Any> getValue(std::u16string_view id); +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/shell/source/backends/kf5be/kf5backend.cxx b/shell/source/backends/kf5be/kf5backend.cxx new file mode 100644 index 000000000..7137a9999 --- /dev/null +++ b/shell/source/backends/kf5be/kf5backend.cxx @@ -0,0 +1,260 @@ +/* -*- 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 <memory> + +#include <QtWidgets/QApplication> + +#include <com/sun/star/beans/Optional.hpp> +#include <com/sun/star/beans/UnknownPropertyException.hpp> +#include <com/sun/star/beans/XPropertyChangeListener.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/beans/XPropertySetInfo.hpp> +#include <com/sun/star/beans/XVetoableChangeListener.hpp> +#include <com/sun/star/lang/IllegalArgumentException.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/uno/Any.hxx> +#include <com/sun/star/uno/Reference.hxx> +#include <com/sun/star/uno/Sequence.hxx> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <com/sun/star/uno/XCurrentContext.hpp> +#include <cppuhelper/implbase.hxx> +#include <cppuhelper/weak.hxx> +#include <rtl/ustring.hxx> +#include <sal/types.h> +#include <uno/current_context.hxx> +#include <vcl/svapp.hxx> + +#include <osl/process.h> +#include <osl/thread.h> + +#include "kf5access.hxx" + +namespace +{ +class Service : public cppu::WeakImplHelper<css::lang::XServiceInfo, css::beans::XPropertySet> +{ +public: + Service(); + +private: + // noncopyable until we have good reasons... + Service(const Service&) = delete; + Service& operator=(const Service&) = delete; + + virtual ~Service() override {} + + virtual OUString SAL_CALL getImplementationName() override + { + return "com.sun.star.comp.configuration.backend.KF5Backend"; + } + + virtual sal_Bool SAL_CALL supportsService(OUString const& ServiceName) override + { + return ServiceName == getSupportedServiceNames()[0]; + } + + virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override + { + return { "com.sun.star.configuration.backend.KF5Backend" }; + } + + virtual css::uno::Reference<css::beans::XPropertySetInfo> SAL_CALL getPropertySetInfo() override + { + return css::uno::Reference<css::beans::XPropertySetInfo>(); + } + + virtual void SAL_CALL setPropertyValue(OUString const&, css::uno::Any const&) override; + + virtual css::uno::Any SAL_CALL getPropertyValue(OUString const& PropertyName) override; + + virtual void SAL_CALL addPropertyChangeListener( + OUString const&, css::uno::Reference<css::beans::XPropertyChangeListener> const&) override + { + } + + virtual void SAL_CALL removePropertyChangeListener( + OUString const&, css::uno::Reference<css::beans::XPropertyChangeListener> const&) override + { + } + + virtual void SAL_CALL addVetoableChangeListener( + OUString const&, css::uno::Reference<css::beans::XVetoableChangeListener> const&) override + { + } + + virtual void SAL_CALL removeVetoableChangeListener( + OUString const&, css::uno::Reference<css::beans::XVetoableChangeListener> const&) override + { + } + + std::map<OUString, css::beans::Optional<css::uno::Any>> m_KDESettings; +}; + +OString getDisplayArg() +{ + OUString aParam; + const sal_uInt32 nParams = osl_getCommandArgCount(); + for (sal_uInt32 nIdx = 0; nIdx < nParams; ++nIdx) + { + osl_getCommandArg(nIdx, &aParam.pData); + if (aParam != "-display") + continue; + + ++nIdx; + osl_getCommandArg(nIdx, &aParam.pData); + return OUStringToOString(aParam, osl_getThreadTextEncoding()); + } + return {}; +} + +OString getExecutable() +{ + OUString aParam, aBin; + osl_getExecutableFile(&aParam.pData); + osl_getSystemPathFromFileURL(aParam.pData, &aBin.pData); + return OUStringToOString(aBin, osl_getThreadTextEncoding()); +} + +void readKDESettings(std::map<OUString, css::beans::Optional<css::uno::Any>>& rSettings) +{ + const std::vector<OUString> aKeys + = { "EnableATToolSupport", "ExternalMailer", "SourceViewFontHeight", + "SourceViewFontName", "WorkPathVariable", "ooInetFTPProxyName", + "ooInetFTPProxyPort", "ooInetHTTPProxyName", "ooInetHTTPProxyPort", + "ooInetHTTPSProxyName", "ooInetHTTPSProxyPort", "ooInetNoProxy", + "ooInetProxyType" }; + + for (const OUString& aKey : aKeys) + { + css::beans::Optional<css::uno::Any> aValue = kf5access::getValue(aKey); + std::pair<OUString, css::beans::Optional<css::uno::Any>> elem + = std::make_pair(aKey, aValue); + rSettings.insert(elem); + } +} + +// init the QApplication when we load the kf5backend into a non-Qt vclplug (e.g. gtk3_kde5) +// TODO: use a helper process to read these values without linking to Qt directly? +// TODO: share this code somehow with Qt5Instance.cxx? +void initQApp(std::map<OUString, css::beans::Optional<css::uno::Any>>& rSettings) +{ + const auto aDisplay = getDisplayArg(); + int nFakeArgc = aDisplay.isEmpty() ? 2 : 3; + char** pFakeArgv = new char*[nFakeArgc]; + + pFakeArgv[0] = strdup(getExecutable().getStr()); + pFakeArgv[1] = strdup("--nocrashhandler"); + if (!aDisplay.isEmpty()) + pFakeArgv[2] = strdup(aDisplay.getStr()); + + char* session_manager = nullptr; + if (auto* session_manager_env = getenv("SESSION_MANAGER")) + { + session_manager = strdup(session_manager_env); + unsetenv("SESSION_MANAGER"); + } + + { + // rhbz#2047319 drop the SolarMutex during the execution of QApplication::init() + // https://invent.kde.org/qt/qt/qtwayland/-/merge_requests/24#note_383915 + SolarMutexReleaser aReleaser; // rhbz#2047319 drop the SolarMutex during the execution + + std::unique_ptr<QApplication> app(new QApplication(nFakeArgc, pFakeArgv)); + QObject::connect(app.get(), &QObject::destroyed, app.get(), [nFakeArgc, pFakeArgv]() { + for (int i = 0; i < nFakeArgc; ++i) + free(pFakeArgv[i]); + delete[] pFakeArgv; + }); + + readKDESettings(rSettings); + } + + if (session_manager != nullptr) + { + // coverity[tainted_string] - trusted source for setenv + setenv("SESSION_MANAGER", session_manager, 1); + free(session_manager); + } +} + +Service::Service() +{ + css::uno::Reference<css::uno::XCurrentContext> context(css::uno::getCurrentContext()); + if (!context.is()) + return; + + OUString desktop; + context->getValueByName("system.desktop-environment") >>= desktop; + + if (desktop == "PLASMA5") + { + if (!qApp) // no qt event loop yet + { + // so we start one and read KDE settings + initQApp(m_KDESettings); + } + else // someone else (most likely kde/qt vclplug) has started qt event loop + // all that is left to do is to read KDE settings + readKDESettings(m_KDESettings); + } +} + +void Service::setPropertyValue(OUString const&, css::uno::Any const&) +{ + throw css::lang::IllegalArgumentException("setPropertyValue not supported", + static_cast<cppu::OWeakObject*>(this), -1); +} + +css::uno::Any Service::getPropertyValue(OUString const& PropertyName) +{ + if (PropertyName == "EnableATToolSupport" || PropertyName == "ExternalMailer" + || PropertyName == "SourceViewFontHeight" || PropertyName == "SourceViewFontName" + || PropertyName == "WorkPathVariable" || PropertyName == "ooInetFTPProxyName" + || PropertyName == "ooInetFTPProxyPort" || PropertyName == "ooInetHTTPProxyName" + || PropertyName == "ooInetHTTPProxyPort" || PropertyName == "ooInetHTTPSProxyName" + || PropertyName == "ooInetHTTPSProxyPort" || PropertyName == "ooInetNoProxy" + || PropertyName == "ooInetProxyType") + { + std::map<OUString, css::beans::Optional<css::uno::Any>>::iterator it + = m_KDESettings.find(PropertyName); + if (it != m_KDESettings.end()) + return css::uno::Any(it->second); + else + return css::uno::Any(css::beans::Optional<css::uno::Any>()); + } + else if (PropertyName == "givenname" || PropertyName == "sn" + || PropertyName == "TemplatePathVariable") + { + return css::uno::Any(css::beans::Optional<css::uno::Any>()); + //TODO: obtain values from KDE? + } + throw css::beans::UnknownPropertyException(PropertyName, static_cast<cppu::OWeakObject*>(this)); +} + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface* +shell_kf5desktop_get_implementation(css::uno::XComponentContext*, + css::uno::Sequence<css::uno::Any> const&) +{ + return cppu::acquire(new Service()); +} +} +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/shell/source/backends/kf5be/kf5be1.component b/shell/source/backends/kf5be/kf5be1.component new file mode 100644 index 000000000..dd893bcb6 --- /dev/null +++ b/shell/source/backends/kf5be/kf5be1.component @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + * 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 . + --> + +<component loader="com.sun.star.loader.SharedLibrary" environment="@CPPU_ENV@" + xmlns="http://openoffice.org/2010/uno-components"> + <implementation name="com.sun.star.comp.configuration.backend.KF5Backend" + constructor="shell_kf5desktop_get_implementation"> + <service name="com.sun.star.configuration.backend.KF5Backend"/> + </implementation> +</component> diff --git a/shell/source/backends/localebe/localebackend.cxx b/shell/source/backends/localebe/localebackend.cxx new file mode 100644 index 000000000..558926d8f --- /dev/null +++ b/shell/source/backends/localebe/localebackend.cxx @@ -0,0 +1,333 @@ +/* -*- 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 <sal/log.hxx> + +#include <cassert> +#include <limits> + +#include "localebackend.hxx" +#include <com/sun/star/beans/Optional.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <cppuhelper/supportsservice.hxx> +#include <rtl/character.hxx> +#include <o3tl/char16_t2wchar_t.hxx> +#include <i18nlangtag/languagetag.hxx> +#include <i18nlangtag/mslangid.hxx> + +#ifdef _WIN32 +#if !defined WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +#endif +#include <windows.h> + +static css::beans::Optional<css::uno::Any> ImplGetLocale(LCID lcid) +{ + WCHAR buffer[8]; + PWSTR cp = buffer; + + cp += GetLocaleInfoW( lcid, LOCALE_SISO639LANGNAME, buffer, 4 ); + if( cp > buffer ) + { + if( 0 < GetLocaleInfoW( lcid, LOCALE_SISO3166CTRYNAME, cp, buffer + 8 - cp) ) + // #i50822# minus character must be written before cp + *(cp - 1) = '-'; + + return {true, css::uno::Any(OUString(o3tl::toU(buffer)))}; + } + + return {false, {}}; +} + +#elif defined(MACOSX) + +#include <rtl/ustrbuf.hxx> +#include <locale.h> +#include <string.h> + +#include <premac.h> +#include <CoreServices/CoreServices.h> +#include <CoreFoundation/CoreFoundation.h> +#include <postmac.h> + +namespace /* private */ +{ + + void OUStringBufferAppendCFString(OUStringBuffer& buffer, const CFStringRef s) + { + CFIndex lstr = CFStringGetLength(s); + for (CFIndex i = 0; i < lstr; i++) + buffer.append(sal_Unicode(CFStringGetCharacterAtIndex(s, i))); + } + + template <typename T> + class CFGuard + { + public: + explicit CFGuard(T& rT) : rT_(rT) {} + ~CFGuard() { if (rT_) CFRelease(rT_); } + private: + T& rT_; + }; + + typedef CFGuard<CFArrayRef> CFArrayGuard; + typedef CFGuard<CFStringRef> CFStringGuard; + typedef CFGuard<CFTypeRef> CFTypeRefGuard; + + /* For more information on the Apple locale concept please refer to + http://developer.apple.com/documentation/CoreFoundation/Conceptual/CFLocales/Articles/CFLocaleConcepts.html + According to this documentation a locale identifier has the format: language[_country][_variant]* + e.g. es_ES_PREEURO -> spain prior Euro support + Note: The calling code should be able to handle locales with only language information e.g. 'en' for certain + UI languages just the language code will be returned. + */ + + CFStringRef ImplGetAppPreference(const char* pref) + { + CFStringRef csPref = CFStringCreateWithCString(nullptr, pref, kCFStringEncodingASCII); + CFStringGuard csRefGuard(csPref); + + CFTypeRef ref = CFPreferencesCopyAppValue(csPref, kCFPreferencesCurrentApplication); + CFTypeRefGuard refGuard(ref); + + if (ref == nullptr) + return nullptr; + + CFStringRef sref = (CFGetTypeID(ref) == CFArrayGetTypeID()) ? static_cast<CFStringRef>(CFArrayGetValueAtIndex(static_cast<CFArrayRef>(ref), 0)) : static_cast<CFStringRef>(ref); + + // NOTE: this API is only available with macOS >=10.3. We need to use it because + // Apple used non-ISO values on systems <10.2 like "German" for instance but didn't + // upgrade those values during upgrade to newer macOS versions. See also #i54337# + return CFLocaleCreateCanonicalLocaleIdentifierFromString(kCFAllocatorDefault, sref); + } + + css::beans::Optional<css::uno::Any> ImplGetLocale(const char* pref) + { + CFStringRef sref = ImplGetAppPreference(pref); + CFStringGuard srefGuard(sref); + + OUStringBuffer aLocaleBuffer; + aLocaleBuffer.append("en-US"); // initialize with fallback value + + if (sref != nullptr) + { + // split the string into substrings; the first two (if there are two) substrings + // are language and country + CFArrayRef subs = CFStringCreateArrayBySeparatingStrings(nullptr, sref, CFSTR("_")); + CFArrayGuard subsGuard(subs); + + if (subs != nullptr) + { + aLocaleBuffer.setLength(0); // clear buffer which still contains fallback value + + CFStringRef lang = static_cast<CFStringRef>(CFArrayGetValueAtIndex(subs, 0)); + OUStringBufferAppendCFString(aLocaleBuffer, lang); + + // country also available? Assumption: if the array contains more than one + // value the second value is always the country! + if (CFArrayGetCount(subs) > 1) + { + aLocaleBuffer.append("-"); + CFStringRef country = static_cast<CFStringRef>(CFArrayGetValueAtIndex(subs, 1)); + OUStringBufferAppendCFString(aLocaleBuffer, country); + } + } + } + return {true, css::uno::Any(aLocaleBuffer.makeStringAndClear())}; + } + +} // namespace /* private */ + +#else + +#include <rtl/ustrbuf.hxx> +#include <cstdlib> +#include <cstring> + +static css::beans::Optional<css::uno::Any> ImplGetLocale(char const * category) +{ + const char *locale = std::getenv("LC_ALL"); + if (locale == nullptr || *locale == '\0') { + locale = std::getenv(category); + if (locale == nullptr || *locale == '\0') { + locale = std::getenv("LANG"); + } + } + + // Return "en-US" for C locales + if( (locale == nullptr) || *locale == '\0' || std::strcmp(locale, "C") == 0 + || std::strcmp(locale, "POSIX") == 0 ) + return {true, css::uno::Any(OUString("en-US"))}; + + + const char *cp; + const char *uscore = nullptr; + const char *end = nullptr; + + // locale string have the format lang[_ctry][.encoding][@modifier] + // Let LanguageTag handle all conversion, but do a sanity and length check + // first. + // For the fallback we are only interested in the first two items, so we + // handle '.' and '@' as string end for that. + for (cp = locale; *cp; cp++) + { + if (*cp == '_' && !uscore) + uscore = cp; + if ((*cp == '.' || *cp == '@') && !end) + end = cp; + if (!rtl::isAscii(static_cast<unsigned char>(*cp))) { + SAL_INFO("shell", "locale env var with non-ASCII content"); + return {false, {}}; + } + } + assert(cp >= locale); + if (cp - locale > std::numeric_limits<sal_Int32>::max()) { + SAL_INFO("shell", "locale env var content too long"); + return {false, {}}; + } + + // This is a tad awkward... but the easiest way to obtain what we're + // actually interested in. For example this also converts + // "ca_ES.UTF-8@valencia" to "ca-ES-valencia". + const OString aLocaleStr(locale); + const LanguageType nLang = MsLangId::convertUnxByteStringToLanguage( aLocaleStr); + if (nLang != LANGUAGE_DONTKNOW) + { + const OUString aLangTagStr( LanguageTag::convertToBcp47( nLang)); + return {true, css::uno::Any(aLangTagStr)}; + } + + // As a fallback, strip encoding and modifier and return just a + // language-country combination and let the caller handle unknowns. + OUStringBuffer aLocaleBuffer; + if (!end) + end = cp; + if( uscore != nullptr ) + { + aLocaleBuffer.appendAscii(locale, uscore++ - locale); + aLocaleBuffer.append("-"); + aLocaleBuffer.appendAscii(uscore, end - uscore); + } + else + { + aLocaleBuffer.appendAscii(locale, end - locale); + } + + return {true, css::uno::Any(aLocaleBuffer.makeStringAndClear())}; +} + +#endif + + +LocaleBackend::LocaleBackend() +{ +} + + +LocaleBackend::~LocaleBackend() +{ +} + + + +css::beans::Optional<css::uno::Any> LocaleBackend::getLocale() +{ +#if defined(_WIN32) + return ImplGetLocale( GetUserDefaultLCID() ); +#elif defined (MACOSX) + return ImplGetLocale("AppleLocale"); +#else + return ImplGetLocale("LC_CTYPE"); +#endif +} + + +css::beans::Optional<css::uno::Any> LocaleBackend::getUILocale() +{ +#if defined(_WIN32) + return ImplGetLocale( MAKELCID(GetUserDefaultUILanguage(), SORT_DEFAULT) ); +#elif defined(MACOSX) + return ImplGetLocale("AppleLanguages"); +#else + return ImplGetLocale("LC_MESSAGES"); +#endif +} + + +css::beans::Optional<css::uno::Any> LocaleBackend::getSystemLocale() +{ +// note: the implementation differs from getLocale() only on Windows +#if defined(_WIN32) + return ImplGetLocale( GetSystemDefaultLCID() ); +#else + return getLocale(); +#endif +} + + +void LocaleBackend::setPropertyValue( + OUString const &, css::uno::Any const &) +{ + throw css::lang::IllegalArgumentException( + "setPropertyValue not supported", + static_cast< cppu::OWeakObject * >(this), -1); +} + +css::uno::Any LocaleBackend::getPropertyValue( + OUString const & PropertyName) +{ + if ( PropertyName == "Locale" ) { + return css::uno::Any(getLocale()); + } else if (PropertyName == "SystemLocale") + { + return css::uno::Any(getSystemLocale()); + } else if (PropertyName == "UILocale") + { + return css::uno::Any(getUILocale()); + } else { + throw css::beans::UnknownPropertyException( + PropertyName, static_cast< cppu::OWeakObject * >(this)); + } +} + + +OUString SAL_CALL LocaleBackend::getImplementationName() +{ + return "com.sun.star.comp.configuration.backend.LocaleBackend" ; +} + +sal_Bool SAL_CALL LocaleBackend::supportsService(const OUString& aServiceName) +{ + return cppu::supportsService(this, aServiceName); +} + +uno::Sequence<OUString> SAL_CALL LocaleBackend::getSupportedServiceNames() +{ + return { "com.sun.star.configuration.backend.LocaleBackend" }; +} + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface* +shell_LocaleBackend_get_implementation( + css::uno::XComponentContext* , css::uno::Sequence<css::uno::Any> const&) +{ + return cppu::acquire(new LocaleBackend()); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/shell/source/backends/localebe/localebackend.hxx b/shell/source/backends/localebe/localebackend.hxx new file mode 100644 index 000000000..e2e4a0b36 --- /dev/null +++ b/shell/source/backends/localebe/localebackend.hxx @@ -0,0 +1,106 @@ +/* -*- 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 . + */ + +#ifndef INCLUDED_SHELL_SOURCE_BACKENDS_LOCALEBE_LOCALEBACKEND_HXX +#define INCLUDED_SHELL_SOURCE_BACKENDS_LOCALEBE_LOCALEBACKEND_HXX + +#include <sal/config.h> + +#include <com/sun/star/beans/Optional.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <cppuhelper/implbase.hxx> + + +namespace uno = css::uno ; +namespace lang = css::lang ; + +class LocaleBackend final : public ::cppu::WeakImplHelper < + css::beans::XPropertySet, + lang::XServiceInfo > +{ + + public: + + // XServiceInfo + virtual OUString SAL_CALL + getImplementationName( ) override ; + + virtual sal_Bool SAL_CALL + supportsService( const OUString& aServiceName ) override ; + + virtual uno::Sequence<OUString> SAL_CALL + getSupportedServiceNames( ) override ; + + // XPropertySet + virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL + getPropertySetInfo() override + { return css::uno::Reference< css::beans::XPropertySetInfo >(); } + + virtual void SAL_CALL setPropertyValue( + OUString const &, css::uno::Any const &) override; + + virtual css::uno::Any SAL_CALL getPropertyValue( + OUString const & PropertyName) override; + + virtual void SAL_CALL addPropertyChangeListener( + OUString const &, + css::uno::Reference< css::beans::XPropertyChangeListener > const &) override + {} + + virtual void SAL_CALL removePropertyChangeListener( + OUString const &, + css::uno::Reference< css::beans::XPropertyChangeListener > const &) override + {} + + virtual void SAL_CALL addVetoableChangeListener( + OUString const &, + css::uno::Reference< css::beans::XVetoableChangeListener > const &) override + {} + + virtual void SAL_CALL removeVetoableChangeListener( + OUString const &, + css::uno::Reference< css::beans::XVetoableChangeListener > const &) override + {} + + /** + Service constructor from a service factory. + + @param xContext component context + */ + LocaleBackend(); + + /** Destructor */ + virtual ~LocaleBackend() override ; + + private: + // Returns the user locale + static css::beans::Optional<css::uno::Any> getLocale(); + + // Returns the user UI locale + static css::beans::Optional<css::uno::Any> getUILocale(); + + // Returns the system default locale + static css::beans::Optional<css::uno::Any> getSystemLocale(); +} ; + + +#endif // INCLUDED_SHELL_SOURCE_BACKENDS_LOCALEBE_LOCALEBACKEND_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/shell/source/backends/localebe/localebe1.component b/shell/source/backends/localebe/localebe1.component new file mode 100644 index 000000000..f19a3f9e8 --- /dev/null +++ b/shell/source/backends/localebe/localebe1.component @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + * 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 . + --> + +<component loader="com.sun.star.loader.SharedLibrary" environment="@CPPU_ENV@" + xmlns="http://openoffice.org/2010/uno-components"> + <implementation name="com.sun.star.comp.configuration.backend.LocaleBackend" + constructor="shell_LocaleBackend_get_implementation"> + <service name="com.sun.star.configuration.backend.LocaleBackend"/> + </implementation> +</component> diff --git a/shell/source/backends/macbe/macbackend.hxx b/shell/source/backends/macbe/macbackend.hxx new file mode 100644 index 000000000..9a19a3002 --- /dev/null +++ b/shell/source/backends/macbe/macbackend.hxx @@ -0,0 +1,90 @@ +/* -*- 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 . + */ + +#ifndef INCLUDED_SHELL_SOURCE_BACKENDS_MACBE_MACBACKEND_HXX +#define INCLUDED_SHELL_SOURCE_BACKENDS_MACBE_MACBACKEND_HXX + +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <cppuhelper/implbase.hxx> +#include <rtl/string.hxx> + +// FIXME: stdio.h only for debugging... +#include <stdio.h> + +namespace uno = css::uno; +namespace lang = css::lang; + +class MacOSXBackend : public ::cppu::WeakImplHelper <css::beans::XPropertySet, lang::XServiceInfo > +{ + +public: + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName() override; + + virtual sal_Bool SAL_CALL supportsService(const OUString& aServiceName) override; + + virtual uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override; + + // XPropertySet + virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL + getPropertySetInfo() override + { return css::uno::Reference< css::beans::XPropertySetInfo >(); } + + virtual void SAL_CALL setPropertyValue( + OUString const &, css::uno::Any const &) override; + + virtual css::uno::Any SAL_CALL getPropertyValue( + OUString const & PropertyName) override; + + virtual void SAL_CALL addPropertyChangeListener( + OUString const &, + css::uno::Reference< css::beans::XPropertyChangeListener > const &) override + {} + + virtual void SAL_CALL removePropertyChangeListener( + OUString const &, + css::uno::Reference< css::beans::XPropertyChangeListener > const &) override + {} + + virtual void SAL_CALL addVetoableChangeListener( + OUString const &, + css::uno::Reference< css::beans::XVetoableChangeListener > const &) override + {} + + virtual void SAL_CALL removeVetoableChangeListener( + OUString const &, + css::uno::Reference< css::beans::XVetoableChangeListener > const &) override + {} + + /** + Service constructor from a service factory. + + @param xContext component context + */ + MacOSXBackend(); + + /** Destructor */ + virtual ~MacOSXBackend() override; +}; + +#endif // INCLUDED_SHELL_SOURCE_BACKENDS_MACBE_MACBACKEND_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/shell/source/backends/macbe/macbackend.mm b/shell/source/backends/macbe/macbackend.mm new file mode 100644 index 000000000..cb35a4b9d --- /dev/null +++ b/shell/source/backends/macbe/macbackend.mm @@ -0,0 +1,395 @@ +/* -*- 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 . + */ + + +// For MAXHOSTNAMELEN constant +#include <sys/param.h> + +#include <premac.h> +#include <SystemConfiguration/SystemConfiguration.h> +#include <Foundation/NSPathUtilities.h> +#include <postmac.h> + +#include "macbackend.hxx" + +#include <com/sun/star/beans/Optional.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <cppuhelper/supportsservice.hxx> +#include <rtl/ustrbuf.hxx> +#include <sal/log.hxx> +#include <osl/diagnose.h> +#include <osl/file.h> + +#define SPACE ' ' +#define SEMI_COLON ';' + +namespace +{ + +typedef enum { + sHTTP, + sHTTPS, + sFTP +} ServiceType; + +/* + * Returns current proxy settings for selected service type (HTTP or + * FTP) as a C string (in the buffer specified by host and hostSize) + * and a port number. + */ + +bool GetProxySetting(ServiceType sType, char *host, size_t hostSize, UInt16 *port) +{ + bool result; + CFDictionaryRef proxyDict; + CFNumberRef enableNum; + int enable; + CFStringRef hostStr; + CFNumberRef portNum; + int portInt; + + proxyDict = SCDynamicStoreCopyProxies(nullptr); + + if (!proxyDict) + return false; + + CFStringRef proxiesEnable; + CFStringRef proxiesProxy; + CFStringRef proxiesPort; + + switch ( sType ) + { + case sHTTP : proxiesEnable = kSCPropNetProxiesHTTPEnable; + proxiesProxy = kSCPropNetProxiesHTTPProxy; + proxiesPort = kSCPropNetProxiesHTTPPort; + break; + case sHTTPS: proxiesEnable = kSCPropNetProxiesHTTPSEnable; + proxiesProxy = kSCPropNetProxiesHTTPSProxy; + proxiesPort = kSCPropNetProxiesHTTPSPort; + break; + default: proxiesEnable = kSCPropNetProxiesFTPEnable; + proxiesProxy = kSCPropNetProxiesFTPProxy; + proxiesPort = kSCPropNetProxiesFTPPort; + break; + } + // Proxy enabled? + enableNum = static_cast<CFNumberRef>(CFDictionaryGetValue( proxyDict, + proxiesEnable )); + + result = (enableNum != nullptr) && (CFGetTypeID(enableNum) == CFNumberGetTypeID()); + + if (result) + result = CFNumberGetValue(enableNum, kCFNumberIntType, &enable) && (enable != 0); + + // Proxy enabled -> get hostname + if (result) + { + hostStr = static_cast<CFStringRef>(CFDictionaryGetValue( proxyDict, + proxiesProxy )); + + result = (hostStr != nullptr) && (CFGetTypeID(hostStr) == CFStringGetTypeID()); + } + + if (result) + result = CFStringGetCString(hostStr, host, static_cast<CFIndex>(hostSize), kCFStringEncodingASCII); + + // Get proxy port + if (result) + { + portNum = static_cast<CFNumberRef>(CFDictionaryGetValue( proxyDict, + proxiesPort )); + + result = (portNum != nullptr) && (CFGetTypeID(portNum) == CFNumberGetTypeID()); + } + else + { + CFRelease(proxyDict); + return false; + } + + if (result) + result = CFNumberGetValue(portNum, kCFNumberIntType, &portInt); + + if (result) + *port = static_cast<UInt16>(portInt); + + if (proxyDict) + CFRelease(proxyDict); + + if (!result) + { + *host = 0; + *port = 0; + } + + return result; +} + +} // unnamed namespace + +MacOSXBackend::MacOSXBackend() +{ +} + +MacOSXBackend::~MacOSXBackend(void) +{ +} + +static OUString CFStringToOUString(const CFStringRef sOrig) { + CFRetain(sOrig); + + CFIndex nStringLen = CFStringGetLength(sOrig)+1; + + // Allocate a c string buffer + char sBuffer[nStringLen]; + + CFStringGetCString(sOrig, sBuffer, nStringLen, kCFStringEncodingASCII); + + CFRelease(sOrig); + + return OUString::createFromAscii(sBuffer); +} + +static OUString GetOUString( NSString* pStr ) +{ + if( ! pStr ) + return OUString(); + int nLen = [pStr length]; + if( nLen == 0 ) + return OUString(); + + OUStringBuffer aBuf( nLen+1 ); + aBuf.setLength( nLen ); + [pStr getCharacters: + reinterpret_cast<unichar *>(const_cast<sal_Unicode*>(aBuf.getStr()))]; + return aBuf.makeStringAndClear(); +} + +void MacOSXBackend::setPropertyValue( + OUString const &, css::uno::Any const &) +{ + throw css::lang::IllegalArgumentException( + "setPropertyValue not supported", + static_cast< cppu::OWeakObject * >(this), -1); +} + +css::uno::Any MacOSXBackend::getPropertyValue( + OUString const & PropertyName) +{ + if ( PropertyName == "WorkPathVariable" ) + { + OUString aDocDir; + NSArray* pPaths = NSSearchPathForDirectoriesInDomains( NSDocumentDirectory, NSUserDomainMask, true ); + if( pPaths && [pPaths count] > 0 ) + { + aDocDir = GetOUString( [pPaths objectAtIndex: 0] ); + + OUString aDocURL; + if( aDocDir.getLength() > 0 && + osl_getFileURLFromSystemPath( aDocDir.pData, &aDocURL.pData ) == osl_File_E_None ) + { + return css::uno::Any( + css::beans::Optional< css::uno::Any >( + true, css::uno::Any( aDocURL ) ) ); + } + else + { + SAL_WARN("shell", "user documents list contains empty file path or conversion failed" ); + } + } + else + { + SAL_WARN("shell", "Got nil or empty list of user document directories" ); + } + return css::uno::Any(css::beans::Optional< css::uno::Any >()); + } else if ( PropertyName == "ooInetFTPProxyName" ) + { + char host[MAXHOSTNAMELEN]; + UInt16 port; + bool retVal; + + retVal = GetProxySetting(sFTP, host, 100, &port); + + if (retVal) + { + auto const Server = OUString::createFromAscii( host ); + if( Server.getLength() > 0 ) + { + return css::uno::Any( + css::beans::Optional< css::uno::Any >( + true, uno::Any( Server ) ) ); + } + } + return css::uno::Any(css::beans::Optional< css::uno::Any >()); + } else if ( PropertyName == "ooInetFTPProxyPort" ) + { + char host[MAXHOSTNAMELEN]; + UInt16 port; + bool retVal; + + retVal = GetProxySetting(sFTP, host, 100, &port); + + if (retVal && port > 0) + { + return css::uno::Any( + css::beans::Optional< css::uno::Any >( + true, uno::Any( sal_Int32(port) ) ) ); + } + return css::uno::Any(css::beans::Optional< css::uno::Any >()); + } else if ( PropertyName == "ooInetHTTPProxyName" ) + { + char host[MAXHOSTNAMELEN]; + UInt16 port; + bool retVal; + + retVal = GetProxySetting(sHTTP, host, 100, &port); + + if (retVal) + { + auto const Server = OUString::createFromAscii( host ); + if( Server.getLength() > 0 ) + { + return css::uno::Any( + css::beans::Optional< css::uno::Any >( + true, uno::Any( Server ) ) ); + } + } + return css::uno::Any(css::beans::Optional< css::uno::Any >()); + } else if ( PropertyName == "ooInetHTTPProxyPort" ) + { + char host[MAXHOSTNAMELEN]; + UInt16 port; + bool retVal; + + retVal = GetProxySetting(sHTTP, host, 100, &port); + + if (retVal && port > 0) + { + return css::uno::Any( + css::beans::Optional< css::uno::Any >( + true, uno::Any( sal_Int32(port) ) ) ); + } + return css::uno::Any(css::beans::Optional< css::uno::Any >()); + } else if ( PropertyName == "ooInetHTTPSProxyName" ) + { + char host[MAXHOSTNAMELEN]; + UInt16 port; + bool retVal; + + retVal = GetProxySetting(sHTTPS, host, 100, &port); + + if (retVal) + { + auto const Server = OUString::createFromAscii( host ); + if( Server.getLength() > 0 ) + { + return css::uno::Any( + css::beans::Optional< css::uno::Any >( + true, uno::Any( Server ) ) ); + } + } + return css::uno::Any(css::beans::Optional< css::uno::Any >()); + } else if ( PropertyName == "ooInetHTTPSProxyPort" ) + { + char host[MAXHOSTNAMELEN]; + UInt16 port; + bool retVal; + + retVal = GetProxySetting(sHTTPS, host, 100, &port); + + if (retVal && port > 0) + { + return css::uno::Any( + css::beans::Optional< css::uno::Any >( + true, uno::Any( sal_Int32(port) ) ) ); + } + return css::uno::Any(css::beans::Optional< css::uno::Any >()); + } else if ( PropertyName == "ooInetProxyType" ) + { + // override default for ProxyType, which is "0" meaning "No proxies". + return css::uno::Any( + css::beans::Optional< css::uno::Any >( + true, uno::Any( sal_Int32(1) ) ) ); + } else if ( PropertyName == "ooInetNoProxy" ) + { + OUString aProxyBypassList; + + CFArrayRef rExceptionsList; + CFDictionaryRef rProxyDict = SCDynamicStoreCopyProxies(nullptr); + + if (!rProxyDict) + rExceptionsList = nullptr; + else + rExceptionsList = static_cast<CFArrayRef>(CFDictionaryGetValue(rProxyDict, kSCPropNetProxiesExceptionsList)); + + if (rExceptionsList) + { + for (CFIndex idx = 0; idx < CFArrayGetCount(rExceptionsList); idx++) + { + CFStringRef rException = static_cast<CFStringRef>(CFArrayGetValueAtIndex(rExceptionsList, idx)); + + if (idx>0) + aProxyBypassList += ";"; + + aProxyBypassList += CFStringToOUString(rException); + } + } + + if (rProxyDict) + CFRelease(rProxyDict); + + // fill proxy bypass list + if( aProxyBypassList.getLength() > 0 ) + { + return css::uno::Any( + css::beans::Optional< css::uno::Any >( + true, + uno::Any( aProxyBypassList.replace( SPACE, SEMI_COLON ) ) ) ); + } + return css::uno::Any(css::beans::Optional< css::uno::Any >()); + } else { + throw css::beans::UnknownPropertyException( + PropertyName, static_cast< cppu::OWeakObject * >(this)); + } +} + +OUString SAL_CALL MacOSXBackend::getImplementationName(void) +{ + return "com.sun.star.comp.configuration.backend.MacOSXBackend"; +} + +sal_Bool SAL_CALL MacOSXBackend::supportsService(const OUString& aServiceName) +{ + return cppu::supportsService(this, aServiceName); +} + +uno::Sequence<OUString> SAL_CALL MacOSXBackend::getSupportedServiceNames(void) +{ + return { "com.sun.star.configuration.backend.MacOSXBackend" }; +} + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface* +shell_MacOSXBackend_get_implementation( + css::uno::XComponentContext* , css::uno::Sequence<css::uno::Any> const&) +{ + return cppu::acquire(new MacOSXBackend()); +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/shell/source/backends/macbe/macbe1.component b/shell/source/backends/macbe/macbe1.component new file mode 100644 index 000000000..8b42dc2e4 --- /dev/null +++ b/shell/source/backends/macbe/macbe1.component @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + * 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 . + --> + +<component loader="com.sun.star.loader.SharedLibrary" environment="@CPPU_ENV@" + xmlns="http://openoffice.org/2010/uno-components"> + <implementation name="com.sun.star.comp.configuration.backend.MacOSXBackend" + constructor="shell_MacOSXBackend_get_implementation"> + <service name="com.sun.star.configuration.backend.MacOSXBackend"/> + </implementation> +</component> diff --git a/shell/source/backends/wininetbe/wininetbackend.cxx b/shell/source/backends/wininetbe/wininetbackend.cxx new file mode 100644 index 000000000..71de3b135 --- /dev/null +++ b/shell/source/backends/wininetbe/wininetbackend.cxx @@ -0,0 +1,363 @@ +/* -*- 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 <cstddef> +#include <string_view> + +#include <cppuhelper/supportsservice.hxx> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <o3tl/string_view.hxx> +#include <rtl/ustrbuf.hxx> +#include <sal/log.hxx> + +#include "wininetbackend.hxx" + +#if !defined WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +#endif +#include <windows.h> +#include <wininet.h> +#include <sal/alloca.h> + +#define WININET_DLL_NAME L"wininet.dll" +#define EQUAL_SIGN '=' +#define COLON ':' +#define SPACE ' ' +#define SEMI_COLON ';' + +namespace { + +struct Library { + HMODULE module; + + explicit Library(HMODULE theModule): module(theModule) {} + + ~Library() { if (module) FreeLibrary(module); } +}; + +struct ProxyEntry +{ + OUString Server; + OUString Port; +}; + + ProxyEntry ReadProxyEntry(std::u16string_view aProxy, std::size_t& i) + { + ProxyEntry aProxyEntry; + + aProxyEntry.Server = o3tl::getToken( aProxy, COLON, i ); + if ( i != std::u16string_view::npos ) + aProxyEntry.Port = o3tl::getToken( aProxy, COLON, i ); + + return aProxyEntry; + } + + ProxyEntry FindProxyEntry(std::u16string_view aProxyList, std::u16string_view aType) + { + std::size_t nIndex = 0; + + do + { + // get the next token, e.g. ftp=server:port + std::u16string_view nextToken = o3tl::getToken( aProxyList, SPACE, nIndex ); + + // split the next token again into the parts separated + // through '=', e.g. ftp=server:port -> ftp and server:port + std::size_t i = 0; + if( nextToken.find( EQUAL_SIGN ) != std::u16string_view::npos ) + { + if( aType == o3tl::getToken( nextToken, EQUAL_SIGN, i ) ) + return ReadProxyEntry(nextToken, i); + } + else if( aType.empty()) + return ReadProxyEntry(nextToken, i); + + } while ( nIndex != std::u16string_view::npos ); + + return ProxyEntry(); + } + +} // unnamed namespace + +WinInetBackend::WinInetBackend() +{ + Library hWinInetDll( LoadLibraryW( WININET_DLL_NAME ) ); + if( hWinInetDll.module ) + { + typedef BOOL ( WINAPI *InternetQueryOption_Proc_T )( HINTERNET, DWORD, LPVOID, LPDWORD ); + + InternetQueryOption_Proc_T lpfnInternetQueryOption = + reinterpret_cast< InternetQueryOption_Proc_T >( + GetProcAddress( hWinInetDll.module, "InternetQueryOptionW" ) ); + if (lpfnInternetQueryOption) + { + // Some Windows versions would fail the InternetQueryOption call + // with ERROR_OUTOFMEMORY when the initial dwLength were zero (and + // are apparently fine with the initial sizeof (INTERNET_PROXY_INFO) + // and need no reallocation), while other versions fail with + // ERROR_INSUFFICIENT_BUFFER upon that initial dwLength and need a + // reallocation: + INTERNET_PROXY_INFO pi; + LPINTERNET_PROXY_INFO lpi = π + DWORD dwLength = sizeof (pi); + bool ok = lpfnInternetQueryOption( + nullptr, + INTERNET_OPTION_PROXY, + lpi, + &dwLength ); + if (!ok) + { + DWORD err = GetLastError(); + if (err == ERROR_INSUFFICIENT_BUFFER) + { + // allocate sufficient space on the stack + // insufficient space on the stack results + // in a stack overflow exception, we assume + // this never happens, because of the relatively + // small amount of memory we need + // alloca is nice because it is fast and we don't + // have to free the allocated memory, it will be + // automatically done + lpi = static_cast< LPINTERNET_PROXY_INFO >( + alloca( dwLength ) ); + ok = lpfnInternetQueryOption( + nullptr, + INTERNET_OPTION_PROXY, + lpi, + &dwLength ); + if (!ok) + { + err = GetLastError(); + } + } + if (!ok) + { + SAL_WARN( + "shell", + "InternetQueryOption INTERNET_OPTION_PROXY" + " GetLastError=" << err); + return; + } + } + + // if a proxy is disabled, InternetQueryOption returns + // an empty proxy list, so we don't have to check if + // proxy is enabled or not + + // We use InternetQueryOptionW (see https://msdn.microsoft.com/en-us/library/aa385101); + // it fills INTERNET_PROXY_INFO struct which is defined in WinInet.h to have LPCTSTR + // (i.e., the UNICODE-dependent generic string type expanding to const wchar_t* when + // UNICODE is defined, and InternetQueryOption macro expands to InternetQueryOptionW). + // Thus, it's natural to expect that W version would return wide strings. But it's not + // true. The W version still returns const char* in INTERNET_PROXY_INFO. + OUString aProxyList = OUString::createFromAscii( lpi->lpszProxy ); + OUString aProxyBypassList = OUString::createFromAscii( lpi->lpszProxyBypass ); + + // override default for ProxyType, which is "0" meaning "No proxies". + valueProxyType_.IsPresent = true; + valueProxyType_.Value <<= sal_Int32(1); + + // fill proxy bypass list + if( aProxyBypassList.getLength() > 0 ) + { + OUStringBuffer aReverseList; + sal_Int32 nIndex = 0; + do + { + OUString aToken = aProxyBypassList.getToken( 0, SPACE, nIndex ); + if ( aProxyList.indexOf( aToken ) == -1 ) + { + if ( aReverseList.getLength() ) + { + aReverseList.insert( 0, sal_Unicode( SEMI_COLON ) ); + aReverseList.insert( 0, aToken ); + } + else + aReverseList = aToken; + } + } + while ( nIndex >= 0 ); + + aProxyBypassList = aReverseList.makeStringAndClear(); + + valueNoProxy_.IsPresent = true; + valueNoProxy_.Value <<= aProxyBypassList.replace( SPACE, SEMI_COLON ); + } + + if( aProxyList.getLength() > 0 ) + { + + // this implementation follows the algorithm + // of the internet explorer + // if there are type-dependent proxy settings + // and type independent proxy settings in the + // registry the internet explorer chooses the + // type independent proxy for all settings + // e.g. imagine the following registry entry + // ftp=server:port;http=server:port;server:port + // the last token server:port is type independent + // so the ie chooses this proxy server + + // if there is no port specified for a type independent + // server the ie uses the port of an http server if + // there is one and it has a port + + + ProxyEntry aTypeIndepProxy = FindProxyEntry( aProxyList, u""); + ProxyEntry aHttpProxy = FindProxyEntry( aProxyList, u"http" ); + ProxyEntry aHttpsProxy = FindProxyEntry( aProxyList, u"https" ); + + ProxyEntry aFtpProxy = FindProxyEntry( aProxyList, u"ftp" ); + + if( aTypeIndepProxy.Server.getLength() ) + { + aHttpProxy.Server = aTypeIndepProxy.Server; + aHttpsProxy.Server = aTypeIndepProxy.Server; + aFtpProxy.Server = aTypeIndepProxy.Server; + + if( aTypeIndepProxy.Port.getLength() ) + { + aHttpProxy.Port = aTypeIndepProxy.Port; + aHttpsProxy.Port = aTypeIndepProxy.Port; + aFtpProxy.Port = aTypeIndepProxy.Port; + } + else + { + aFtpProxy.Port = aHttpProxy.Port; + aHttpsProxy.Port = aHttpProxy.Port; + } + } + + // http proxy name + if( aHttpProxy.Server.getLength() > 0 ) + { + valueHttpProxyName_.IsPresent = true; + valueHttpProxyName_.Value <<= aHttpProxy.Server; + } + + // http proxy port + if( aHttpProxy.Port.getLength() > 0 ) + { + valueHttpProxyPort_.IsPresent = true; + valueHttpProxyPort_.Value <<= aHttpProxy.Port.toInt32(); + } + + // https proxy name + if( aHttpsProxy.Server.getLength() > 0 ) + { + valueHttpsProxyName_.IsPresent = true; + valueHttpsProxyName_.Value <<= aHttpsProxy.Server; + } + + // https proxy port + if( aHttpsProxy.Port.getLength() > 0 ) + { + valueHttpsProxyPort_.IsPresent = true; + valueHttpsProxyPort_.Value <<= aHttpsProxy.Port.toInt32(); + } + + // ftp proxy name + if( aFtpProxy.Server.getLength() > 0 ) + { + valueFtpProxyName_.IsPresent = true; + valueFtpProxyName_.Value <<= aFtpProxy.Server; + } + + // ftp proxy port + if( aFtpProxy.Port.getLength() > 0 ) + { + valueFtpProxyPort_.IsPresent = true; + valueFtpProxyPort_.Value <<= aFtpProxy.Port.toInt32(); + } + } + } + } +} + +WinInetBackend::~WinInetBackend() +{ +} + +void WinInetBackend::setPropertyValue( + OUString const &, css::uno::Any const &) +{ + throw css::lang::IllegalArgumentException( + "setPropertyValue not supported", + static_cast< cppu::OWeakObject * >(this), -1); +} + +css::uno::Any WinInetBackend::getPropertyValue( + OUString const & PropertyName) +{ + if ( PropertyName == "ooInetFTPProxyName" ) + { + return css::uno::Any(valueFtpProxyName_); + } else if ( PropertyName == "ooInetFTPProxyPort" ) + { + return css::uno::Any(valueFtpProxyPort_); + } else if ( PropertyName == "ooInetHTTPProxyName" ) + { + return css::uno::Any(valueHttpProxyName_); + } else if ( PropertyName == "ooInetHTTPProxyPort" ) + { + return css::uno::Any(valueHttpProxyPort_); + } else if ( PropertyName == "ooInetHTTPSProxyName" ) + { + return css::uno::Any(valueHttpsProxyName_); + } else if ( PropertyName == "ooInetHTTPSProxyPort" ) + { + return css::uno::Any(valueHttpsProxyPort_); + } else if ( PropertyName == "ooInetNoProxy" ) + { + return css::uno::Any(valueNoProxy_); + } else if ( PropertyName == "ooInetProxyType" ) + { + return css::uno::Any(valueProxyType_); + } else { + throw css::beans::UnknownPropertyException( + PropertyName, static_cast< cppu::OWeakObject * >(this)); + } +} + +OUString SAL_CALL WinInetBackend::getImplementationName() +{ + return "com.sun.star.comp.configuration.backend.WinInetBackend" ; +} + +sal_Bool SAL_CALL WinInetBackend::supportsService(const OUString& aServiceName) +{ + return cppu::supportsService(this, aServiceName); +} + +uno::Sequence<OUString> SAL_CALL WinInetBackend::getSupportedServiceNames() +{ + return { "com.sun.star.configuration.backend.WinInetBackend" }; +} + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface* +shell_WinInetBackend_get_implementation( + css::uno::XComponentContext* , css::uno::Sequence<css::uno::Any> const&) +{ + return cppu::acquire(new WinInetBackend); +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/shell/source/backends/wininetbe/wininetbackend.hxx b/shell/source/backends/wininetbe/wininetbackend.hxx new file mode 100644 index 000000000..1b5f4ecbf --- /dev/null +++ b/shell/source/backends/wininetbe/wininetbackend.hxx @@ -0,0 +1,110 @@ +/* -*- 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 . + */ + +#ifndef INCLUDED_SHELL_SOURCE_BACKENDS_WININETBE_WININETBACKEND_HXX +#define INCLUDED_SHELL_SOURCE_BACKENDS_WININETBE_WININETBACKEND_HXX + +#include <com/sun/star/beans/Optional.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <cppuhelper/implbase.hxx> + +namespace uno = css::uno ; +namespace lang = css::lang ; + +class WinInetBackend : public ::cppu::WeakImplHelper < + css::beans::XPropertySet, + lang::XServiceInfo > { + + public: + + // XServiceInfo + virtual OUString SAL_CALL + getImplementationName( ) override; + + virtual sal_Bool SAL_CALL + supportsService( const OUString& aServiceName ) override; + + virtual uno::Sequence<OUString> SAL_CALL + getSupportedServiceNames( ) override; + + // XPropertySet + virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL + getPropertySetInfo() override + { return css::uno::Reference< css::beans::XPropertySetInfo >(); } + + virtual void SAL_CALL setPropertyValue( + OUString const &, css::uno::Any const &) override; + + virtual css::uno::Any SAL_CALL getPropertyValue( + OUString const & PropertyName) override; + + virtual void SAL_CALL addPropertyChangeListener( + OUString const &, + css::uno::Reference< css::beans::XPropertyChangeListener > const &) override + {} + + virtual void SAL_CALL removePropertyChangeListener( + OUString const &, + css::uno::Reference< css::beans::XPropertyChangeListener > const &) override + {} + + virtual void SAL_CALL addVetoableChangeListener( + OUString const &, + css::uno::Reference< css::beans::XVetoableChangeListener > const &) override + {} + + virtual void SAL_CALL removeVetoableChangeListener( + OUString const &, + css::uno::Reference< css::beans::XVetoableChangeListener > const &) override + {} + + /** + Service constructor from a service factory. + + @param xContext component context + */ + WinInetBackend(); + + /** Destructor */ + ~WinInetBackend() override; + + private: + css::beans::Optional< css::uno::Any > + valueProxyType_; + css::beans::Optional< css::uno::Any > + valueNoProxy_; + css::beans::Optional< css::uno::Any > + valueHttpProxyName_; + css::beans::Optional< css::uno::Any > + valueHttpProxyPort_; + css::beans::Optional< css::uno::Any > + valueHttpsProxyName_; + css::beans::Optional< css::uno::Any > + valueHttpsProxyPort_; + css::beans::Optional< css::uno::Any > + valueFtpProxyName_; + css::beans::Optional< css::uno::Any > + valueFtpProxyPort_; +} ; + + +#endif // INCLUDED_SHELL_SOURCE_BACKENDS_WININETBE_WININETBACKEND_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/shell/source/backends/wininetbe/wininetbe1.component b/shell/source/backends/wininetbe/wininetbe1.component new file mode 100644 index 000000000..1acdee781 --- /dev/null +++ b/shell/source/backends/wininetbe/wininetbe1.component @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + * 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 . + --> + +<component loader="com.sun.star.loader.SharedLibrary" environment="@CPPU_ENV@" + xmlns="http://openoffice.org/2010/uno-components"> + <implementation name="com.sun.star.comp.configuration.backend.WinInetBackend" + constructor="shell_WinInetBackend_get_implementation"> + <service name="com.sun.star.configuration.backend.WinInetBackend"/> + </implementation> +</component> |