/* -*- 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include 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(&seq))) { int relative = 0; int len = seq.getLength(); seq.realloc(len + 1); seq[len] = 0; p = reinterpret_cast(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(*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(true, css::uno::Any(url)) : css::beans::Optional(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 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: */