LCOV - code coverage report
Current view: top level - desktop/source/deployment/registry/configuration - dp_configuration.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 46 348 13.2 %
Date: 2015-06-13 12:38:46 Functions: 8 27 29.6 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : //TODO: Large parts of this file were copied from dp_component.cxx; those parts
      21             : // should be consolidated.
      22             : 
      23             : #include <config_features.h>
      24             : 
      25             : #include "dp_configuration.hrc"
      26             : #include "dp_backend.h"
      27             : #if HAVE_FEATURE_EXTENSIONS
      28             : #include "dp_persmap.h"
      29             : #endif
      30             : #include "dp_ucb.h"
      31             : #include <rtl/string.hxx>
      32             : #include <rtl/ustrbuf.hxx>
      33             : #include <rtl/uri.hxx>
      34             : #include <osl/file.hxx>
      35             : #include <cppuhelper/exc_hlp.hxx>
      36             : #include <ucbhelper/content.hxx>
      37             : #include <unotools/ucbhelper.hxx>
      38             : #include <comphelper/anytostring.hxx>
      39             : #include <comphelper/servicedecl.hxx>
      40             : #include <xmlscript/xml_helper.hxx>
      41             : #include <svl/inettype.hxx>
      42             : #include <com/sun/star/configuration/Update.hpp>
      43             : #include <com/sun/star/ucb/NameClash.hpp>
      44             : #include <com/sun/star/io/XActiveDataSink.hpp>
      45             : #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
      46             : #include <com/sun/star/util/XRefreshable.hpp>
      47             : #include <list>
      48             : #include <memory>
      49             : #include <utility>
      50             : 
      51             : #include "dp_configurationbackenddb.hxx"
      52             : 
      53             : using namespace ::dp_misc;
      54             : using namespace ::com::sun::star;
      55             : using namespace ::com::sun::star::uno;
      56             : using namespace ::com::sun::star::ucb;
      57             : 
      58             : namespace dp_registry {
      59             : namespace backend {
      60             : namespace configuration {
      61             : namespace {
      62             : 
      63             : typedef ::std::list<OUString> t_stringlist;
      64             : 
      65             : 
      66         392 : class BackendImpl : public ::dp_registry::backend::PackageRegistryBackend
      67             : {
      68           0 :     class PackageImpl : public ::dp_registry::backend::Package
      69             :     {
      70             :         BackendImpl * getMyBackend() const ;
      71             : 
      72             :         const bool m_isSchema;
      73             : 
      74             :         // Package
      75             :         virtual beans::Optional< beans::Ambiguous<sal_Bool> > isRegistered_(
      76             :             ::osl::ResettableMutexGuard & guard,
      77             :             ::rtl::Reference<AbortChannel> const & abortChannel,
      78             :             Reference<XCommandEnvironment> const & xCmdEnv ) SAL_OVERRIDE;
      79             :         virtual void processPackage_(
      80             :             ::osl::ResettableMutexGuard & guard,
      81             :             bool registerPackage,
      82             :             bool startup,
      83             :             ::rtl::Reference<AbortChannel> const & abortChannel,
      84             :             Reference<XCommandEnvironment> const & xCmdEnv ) SAL_OVERRIDE;
      85             : 
      86             :     public:
      87           0 :         inline PackageImpl(
      88             :             ::rtl::Reference<PackageRegistryBackend> const & myBackend,
      89             :             OUString const & url, OUString const & name,
      90             :             Reference<deployment::XPackageTypeInfo> const & xPackageType,
      91             :             bool isSchema, bool bRemoved, OUString const & identifier)
      92             :             : Package( myBackend, url, name, name /* display-name */,
      93             :                        xPackageType, bRemoved, identifier),
      94           0 :               m_isSchema( isSchema )
      95           0 :             {}
      96             :     };
      97             :     friend class PackageImpl;
      98             : 
      99             :     t_stringlist m_xcs_files;
     100             :     t_stringlist m_xcu_files;
     101           0 :     t_stringlist & getFiles( bool xcs ) {
     102           0 :         return xcs ? m_xcs_files : m_xcu_files;
     103             :     }
     104             : 
     105             :     bool m_configmgrini_inited;
     106             :     bool m_configmgrini_modified;
     107             :     std::unique_ptr<ConfigurationBackendDb> m_backendDb;
     108             : 
     109             :     // PackageRegistryBackend
     110             :     virtual Reference<deployment::XPackage> bindPackage_(
     111             :         OUString const & url, OUString const & mediaType, bool bRemoved,
     112             :         OUString const & identifier,
     113             :         Reference<XCommandEnvironment> const & xCmdEnv ) SAL_OVERRIDE;
     114             : 
     115             : #if HAVE_FEATURE_EXTENSIONS
     116             :     // for backwards compatibility - nil if no (compatible) back-compat db present
     117             :     ::std::unique_ptr<PersistentMap> m_registeredPackages;
     118             : #endif
     119             : 
     120             :     virtual void SAL_CALL disposing() SAL_OVERRIDE;
     121             : 
     122             :     const Reference<deployment::XPackageTypeInfo> m_xConfDataTypeInfo;
     123             :     const Reference<deployment::XPackageTypeInfo> m_xConfSchemaTypeInfo;
     124             :     Sequence< Reference<deployment::XPackageTypeInfo> > m_typeInfos;
     125             : 
     126             :     void configmgrini_verify_init(
     127             :         Reference<XCommandEnvironment> const & xCmdEnv );
     128             :     void configmgrini_flush( Reference<XCommandEnvironment> const & xCmdEnv );
     129             : 
     130             :     /* The parameter isURL is false in the case of adding the conf:ini-entry
     131             :        value from the backend db. This entry already contains the path as it
     132             :        is used in the configmgr.ini.
     133             :      */
     134             :     bool addToConfigmgrIni( bool isSchema, bool isURL, OUString const & url,
     135             :                      Reference<XCommandEnvironment> const & xCmdEnv );
     136             :     bool removeFromConfigmgrIni( bool isSchema, OUString const & url,
     137             :                           Reference<XCommandEnvironment> const & xCmdEnv );
     138             : 
     139             :     void addDataToDb(OUString const & url, ConfigurationBackendDb::Data const & data);
     140             :     ::boost::optional<ConfigurationBackendDb::Data> readDataFromDb(OUString const & url);
     141             :     void revokeEntryFromDb(OUString const & url);
     142             :     bool hasActiveEntry(OUString const & url);
     143             :     bool activateEntry(OUString const & url);
     144             : 
     145             : public:
     146             :     BackendImpl( Sequence<Any> const & args,
     147             :                  Reference<XComponentContext> const & xComponentContext );
     148             : 
     149             :     // XPackageRegistry
     150             :     virtual Sequence< Reference<deployment::XPackageTypeInfo> > SAL_CALL
     151             :     getSupportedPackageTypes() throw (RuntimeException, std::exception) SAL_OVERRIDE;
     152             :     virtual void SAL_CALL packageRemoved(OUString const & url, OUString const & mediaType)
     153             :         throw (deployment::DeploymentException,
     154             :                uno::RuntimeException, std::exception) SAL_OVERRIDE;
     155             : 
     156             :     using PackageRegistryBackend::disposing;
     157             : };
     158             : 
     159             : 
     160         392 : void BackendImpl::disposing()
     161             : {
     162             :     try {
     163         392 :         configmgrini_flush( Reference<XCommandEnvironment>() );
     164             : 
     165         392 :         PackageRegistryBackend::disposing();
     166             :     }
     167           0 :     catch (const RuntimeException &) {
     168           0 :         throw;
     169             :     }
     170           0 :     catch (const Exception &) {
     171           0 :         Any exc( ::cppu::getCaughtException() );
     172             :         throw lang::WrappedTargetRuntimeException(
     173             :             "caught unexpected exception while disposing...",
     174           0 :             static_cast<OWeakObject *>(this), exc );
     175             :     }
     176         392 : }
     177             : 
     178             : 
     179         392 : BackendImpl::BackendImpl(
     180             :     Sequence<Any> const & args,
     181             :     Reference<XComponentContext> const & xComponentContext )
     182             :     : PackageRegistryBackend( args, xComponentContext ),
     183             :       m_configmgrini_inited( false ),
     184             :       m_configmgrini_modified( false ),
     185             :       m_xConfDataTypeInfo( new Package::TypeInfo(
     186             :                                "application/vnd.sun.star.configuration-data",
     187             :                                "*.xcu",
     188             :                                getResourceString(RID_STR_CONF_DATA),
     189         392 :                                RID_IMG_CONF_XML ) ),
     190             :       m_xConfSchemaTypeInfo( new Package::TypeInfo(
     191             :                                  "application/vnd.sun.star.configuration-schema",
     192             :                                  "*.xcs",
     193             :                                  getResourceString(RID_STR_CONF_SCHEMA),
     194         392 :                                  RID_IMG_CONF_XML ) ),
     195        1176 :       m_typeInfos( 2 )
     196             : {
     197         392 :     m_typeInfos[ 0 ] = m_xConfDataTypeInfo;
     198         392 :     m_typeInfos[ 1 ] = m_xConfSchemaTypeInfo;
     199             : 
     200         392 :     const Reference<XCommandEnvironment> xCmdEnv;
     201             : 
     202         392 :     if (transientMode())
     203             :     {
     204             :         // TODO
     205             :     }
     206             :     else
     207             :     {
     208         392 :         OUString dbFile = makeURL(getCachePath(), "backenddb.xml");
     209             :         m_backendDb.reset(
     210         392 :             new ConfigurationBackendDb(getComponentContext(), dbFile));
     211             :         //clean up data folders which are no longer used.
     212             :         //This must not be done in the same process where the help files
     213             :         //are still registers. Only after revoking and restarting OOo the folders
     214             :         //can be removed. This works now, because the extension manager is a singleton
     215             :         //and the backends are only create once per process.
     216         784 :         ::std::list<OUString> folders = m_backendDb->getAllDataUrls();
     217         392 :         deleteUnusedFolders(OUString(), folders);
     218             : 
     219         392 :         configmgrini_verify_init( xCmdEnv );
     220             : 
     221             : #if HAVE_FEATURE_EXTENSIONS
     222         784 :         ::std::unique_ptr<PersistentMap> pMap;
     223         784 :         OUString aCompatURL( makeURL( getCachePath(), "registered_packages.pmap" ) );
     224             : 
     225             :         // Don't create it if it doesn't exist already
     226         392 :         if ( ::utl::UCBContentHelper::Exists( expandUnoRcUrl( aCompatURL ) ) )
     227             :         {
     228             :             try
     229             :             {
     230           0 :                 pMap.reset( new PersistentMap( aCompatURL, false ) );
     231             :             }
     232           0 :             catch (const Exception &e)
     233             :             {
     234           0 :                 OUStringBuffer aStr( "Exception loading legacy package database: '" );
     235           0 :                 aStr.append( e.Message );
     236           0 :                 aStr.append( "' - ignoring file, please remove it.\n" );
     237           0 :                 dp_misc::writeConsole( aStr.getStr() );
     238             :             }
     239             :         }
     240         784 :         m_registeredPackages = std::move(pMap);
     241             : #endif
     242         392 :      }
     243         392 : }
     244             : 
     245           0 : void BackendImpl::addDataToDb(
     246             :     OUString const & url, ConfigurationBackendDb::Data const & data)
     247             : {
     248           0 :     if (m_backendDb.get())
     249           0 :         m_backendDb->addEntry(url, data);
     250           0 : }
     251             : 
     252           0 : ::boost::optional<ConfigurationBackendDb::Data> BackendImpl::readDataFromDb(
     253             :     OUString const & url)
     254             : {
     255           0 :     ::boost::optional<ConfigurationBackendDb::Data> data;
     256           0 :     if (m_backendDb.get())
     257           0 :         data = m_backendDb->getEntry(url);
     258           0 :     return data;
     259             : }
     260             : 
     261           0 : void BackendImpl::revokeEntryFromDb(OUString const & url)
     262             : {
     263           0 :     if (m_backendDb.get())
     264           0 :         m_backendDb->revokeEntry(url);
     265           0 : }
     266             : 
     267           0 : bool BackendImpl::hasActiveEntry(OUString const & url)
     268             : {
     269           0 :     if (m_backendDb.get())
     270           0 :         return m_backendDb->hasActiveEntry(url);
     271           0 :     return false;
     272             : }
     273             : 
     274           0 : bool BackendImpl::activateEntry(OUString const & url)
     275             : {
     276           0 :     if (m_backendDb.get())
     277           0 :         return m_backendDb->activateEntry(url);
     278           0 :     return false;
     279             : }
     280             : 
     281             : 
     282             : 
     283             : // XPackageRegistry
     284             : 
     285             : Sequence< Reference<deployment::XPackageTypeInfo> >
     286         392 : BackendImpl::getSupportedPackageTypes() throw (RuntimeException, std::exception)
     287             : {
     288         392 :     return m_typeInfos;
     289             : }
     290           0 : void BackendImpl::packageRemoved(OUString const & url, OUString const & /*mediaType*/)
     291             :         throw (deployment::DeploymentException,
     292             :                uno::RuntimeException, std::exception)
     293             : {
     294           0 :     if (m_backendDb.get())
     295           0 :         m_backendDb->removeEntry(url);
     296           0 : }
     297             : 
     298             : // PackageRegistryBackend
     299             : 
     300           0 : Reference<deployment::XPackage> BackendImpl::bindPackage_(
     301             :     OUString const & url, OUString const & mediaType_,
     302             :     bool bRemoved, OUString const & identifier,
     303             :     Reference<XCommandEnvironment> const & xCmdEnv )
     304             : {
     305           0 :     OUString mediaType( mediaType_ );
     306           0 :     if (mediaType.isEmpty())
     307             :     {
     308             :         // detect media-type:
     309           0 :         ::ucbhelper::Content ucbContent;
     310           0 :         if (create_ucb_content( &ucbContent, url, xCmdEnv ))
     311             :         {
     312           0 :             const OUString title( StrTitle::getTitle( ucbContent ) );
     313           0 :             if (title.endsWithIgnoreAsciiCase( ".xcu" )) {
     314           0 :                 mediaType = "application/vnd.sun.star.configuration-data";
     315             :             }
     316           0 :             if (title.endsWithIgnoreAsciiCase( ".xcs" )) {
     317           0 :                 mediaType = "application/vnd.sun.star.configuration-schema";
     318           0 :             }
     319             :         }
     320           0 :         if (mediaType.isEmpty())
     321             :             throw lang::IllegalArgumentException(
     322           0 :                 StrCannotDetectMediaType::get() + url,
     323           0 :                 static_cast<OWeakObject *>(this), static_cast<sal_Int16>(-1) );
     324             :     }
     325             : 
     326           0 :     OUString type, subType;
     327           0 :     INetContentTypeParameterList params;
     328           0 :     if (INetContentTypes::parse( mediaType, type, subType, &params ))
     329             :     {
     330           0 :         if (type.equalsIgnoreAsciiCase("application"))
     331             :         {
     332           0 :             OUString name;
     333           0 :             if (!bRemoved)
     334             :             {
     335           0 :                 ::ucbhelper::Content ucbContent( url, xCmdEnv, m_xComponentContext );
     336           0 :                 name = StrTitle::getTitle( ucbContent );
     337             :             }
     338             : 
     339           0 :             ::ucbhelper::Content ucbContent( url, xCmdEnv, m_xComponentContext );
     340           0 :             if (subType.equalsIgnoreAsciiCase( "vnd.sun.star.configuration-data"))
     341             :             {
     342             :                 return new PackageImpl(
     343             :                     this, url, name, m_xConfDataTypeInfo, false /* data file */,
     344           0 :                     bRemoved, identifier);
     345             :             }
     346           0 :             else if (subType.equalsIgnoreAsciiCase( "vnd.sun.star.configuration-schema")) {
     347             :                 return new PackageImpl(
     348             :                     this, url, name, m_xConfSchemaTypeInfo, true /* schema file */,
     349           0 :                     bRemoved, identifier);
     350           0 :             }
     351             :         }
     352             :     }
     353             :     throw lang::IllegalArgumentException(
     354           0 :         StrUnsupportedMediaType::get() + mediaType,
     355             :         static_cast<OWeakObject *>(this),
     356           0 :         static_cast<sal_Int16>(-1) );
     357             : }
     358             : 
     359             : 
     360             : 
     361         392 : void BackendImpl::configmgrini_verify_init(
     362             :     Reference<XCommandEnvironment> const & xCmdEnv )
     363             : {
     364         392 :     if (transientMode())
     365         392 :         return;
     366         392 :     const ::osl::MutexGuard guard( getMutex() );
     367         392 :     if (! m_configmgrini_inited)
     368             :     {
     369             :         // common rc:
     370         392 :         ::ucbhelper::Content ucb_content;
     371         784 :         if (create_ucb_content(
     372             :                 &ucb_content,
     373         392 :                 makeURL( getCachePath(), "configmgr.ini" ),
     374        1176 :                 xCmdEnv, false /* no throw */ ))
     375             :         {
     376           0 :             OUString line;
     377           0 :             if (readLine( &line, "SCHEMA=", ucb_content,
     378           0 :                           RTL_TEXTENCODING_UTF8 ))
     379             :             {
     380           0 :                 sal_Int32 index = RTL_CONSTASCII_LENGTH("SCHEMA=");
     381           0 :                 do {
     382           0 :                     OUString token( line.getToken( 0, ' ', index ).trim() );
     383           0 :                     if (!token.isEmpty()) {
     384             :                         //The  file may not exist anymore if a shared or bundled
     385             :                         //extension was removed, but it can still be in the configmgrini.
     386             :                         //After running XExtensionManager::synchronize, the configmgrini is
     387             :                         //cleaned up
     388           0 :                         m_xcs_files.push_back( token );
     389           0 :                     }
     390             :                 }
     391           0 :                 while (index >= 0);
     392             :             }
     393           0 :             if (readLine( &line, "DATA=", ucb_content,
     394           0 :                           RTL_TEXTENCODING_UTF8 )) {
     395           0 :                 sal_Int32 index = RTL_CONSTASCII_LENGTH("DATA=");
     396           0 :                 do {
     397           0 :                     OUString token( line.getToken( 0, ' ', index ).trim() );
     398           0 :                     if (!token.isEmpty())
     399             :                     {
     400           0 :                         if (token[ 0 ] == '?')
     401           0 :                             token = token.copy( 1 );
     402             :                         //The  file may not exist anymore if a shared or bundled
     403             :                         //extension was removed, but it can still be in the configmgrini.
     404             :                         //After running XExtensionManager::synchronize, the configmgrini is
     405             :                         //cleaned up
     406           0 :                         m_xcu_files.push_back( token );
     407           0 :                     }
     408             :                 }
     409           0 :                 while (index >= 0);
     410           0 :             }
     411             :         }
     412         392 :         m_configmgrini_modified = false;
     413         392 :         m_configmgrini_inited = true;
     414         392 :     }
     415             : }
     416             : 
     417             : 
     418         392 : void BackendImpl::configmgrini_flush(
     419             :     Reference<XCommandEnvironment> const & xCmdEnv )
     420             : {
     421         392 :     if (transientMode())
     422         392 :         return;
     423         392 :     if (!m_configmgrini_inited || !m_configmgrini_modified)
     424         392 :         return;
     425             : 
     426           0 :     OStringBuffer buf;
     427           0 :     if (! m_xcs_files.empty())
     428             :     {
     429           0 :         t_stringlist::const_iterator iPos( m_xcs_files.begin() );
     430           0 :         t_stringlist::const_iterator const iEnd( m_xcs_files.end() );
     431           0 :         buf.append( "SCHEMA=" );
     432           0 :         while (iPos != iEnd) {
     433             :             // encoded ASCII file-urls:
     434             :             const OString item(
     435           0 :                 OUStringToOString( *iPos, RTL_TEXTENCODING_ASCII_US ) );
     436           0 :             buf.append( item );
     437           0 :             ++iPos;
     438           0 :             if (iPos != iEnd)
     439           0 :                 buf.append( ' ' );
     440           0 :         }
     441           0 :         buf.append(LF);
     442             :     }
     443           0 :     if (! m_xcu_files.empty())
     444             :     {
     445           0 :         t_stringlist::const_iterator iPos( m_xcu_files.begin() );
     446           0 :         t_stringlist::const_iterator const iEnd( m_xcu_files.end() );
     447           0 :         buf.append( "DATA=" );
     448           0 :         while (iPos != iEnd) {
     449             :             // encoded ASCII file-urls:
     450             :             const OString item(
     451           0 :                 OUStringToOString( *iPos, RTL_TEXTENCODING_ASCII_US ) );
     452           0 :             buf.append( item );
     453           0 :             ++iPos;
     454           0 :             if (iPos != iEnd)
     455           0 :                 buf.append( ' ' );
     456           0 :         }
     457           0 :         buf.append(LF);
     458             :     }
     459             : 
     460             :     // write configmgr.ini:
     461             :     const Reference<io::XInputStream> xData(
     462             :         ::xmlscript::createInputStream(
     463             :             ::rtl::ByteSequence(
     464           0 :                 reinterpret_cast<sal_Int8 const *>(buf.getStr()),
     465           0 :                 buf.getLength() ) ) );
     466             :     ::ucbhelper::Content ucb_content(
     467           0 :         makeURL( getCachePath(), "configmgr.ini" ), xCmdEnv, m_xComponentContext );
     468           0 :     ucb_content.writeStream( xData, true /* replace existing */ );
     469             : 
     470           0 :     m_configmgrini_modified = false;
     471             : }
     472             : 
     473             : 
     474           0 : bool BackendImpl::addToConfigmgrIni( bool isSchema, bool isURL, OUString const & url_,
     475             :                               Reference<XCommandEnvironment> const & xCmdEnv )
     476             : {
     477           0 :     const OUString rcterm( isURL ? dp_misc::makeRcTerm(url_) : url_ );
     478           0 :     const ::osl::MutexGuard guard( getMutex() );
     479           0 :     configmgrini_verify_init( xCmdEnv );
     480           0 :     t_stringlist & rSet = getFiles(isSchema);
     481           0 :     if (::std::find( rSet.begin(), rSet.end(), rcterm ) == rSet.end()) {
     482           0 :         rSet.push_front( rcterm ); // prepend to list, thus overriding
     483             :         // write immediately:
     484           0 :         m_configmgrini_modified = true;
     485           0 :         configmgrini_flush( xCmdEnv );
     486           0 :         return true;
     487             :     }
     488             :     else
     489           0 :         return false;
     490             : }
     491             : 
     492             : 
     493           0 : bool BackendImpl::removeFromConfigmgrIni(
     494             :     bool isSchema, OUString const & url_,
     495             :     Reference<XCommandEnvironment> const & xCmdEnv )
     496             : {
     497           0 :     const OUString rcterm( dp_misc::makeRcTerm(url_) );
     498           0 :     const ::osl::MutexGuard guard( getMutex() );
     499           0 :     configmgrini_verify_init( xCmdEnv );
     500           0 :     t_stringlist & rSet = getFiles(isSchema);
     501           0 :     t_stringlist::iterator i(std::find(rSet.begin(), rSet.end(), rcterm));
     502           0 :     if (i == rSet.end() && !isSchema)
     503             :     {
     504             :         //in case the xcu contained %origin% then the configmr.ini contains the
     505             :         //url to the file in the user installation (e.g. $BUNDLED_EXTENSIONS_USER)
     506             :         //However, m_url (getURL()) contains the URL for the file in the actual
     507             :         //extension installatation.
     508           0 :         ::boost::optional<ConfigurationBackendDb::Data> data = readDataFromDb(url_);
     509           0 :         if (data)
     510           0 :             i = std::find(rSet.begin(), rSet.end(), data->iniEntry);
     511             :     }
     512           0 :     if (i == rSet.end()) {
     513           0 :         return false;
     514             :     }
     515           0 :     rSet.erase(i);
     516             :     // write immediately:
     517           0 :     m_configmgrini_modified = true;
     518           0 :     configmgrini_flush( xCmdEnv );
     519           0 :     return true;
     520             : }
     521             : 
     522             : 
     523             : // Package
     524             : 
     525             : 
     526           0 : BackendImpl * BackendImpl::PackageImpl::getMyBackend() const
     527             : {
     528           0 :     BackendImpl * pBackend = static_cast<BackendImpl *>(m_myBackend.get());
     529           0 :     if (NULL == pBackend)
     530             :     {
     531             :         //May throw a DisposedException
     532           0 :         check();
     533             :         //We should never get here...
     534             :         throw RuntimeException(
     535             :             "Failed to get the BackendImpl",
     536           0 :             static_cast<OWeakObject*>(const_cast<PackageImpl *>(this)));
     537             :     }
     538           0 :     return pBackend;
     539             : }
     540             : 
     541             : beans::Optional< beans::Ambiguous<sal_Bool> >
     542           0 : BackendImpl::PackageImpl::isRegistered_(
     543             :     ::osl::ResettableMutexGuard &,
     544             :     ::rtl::Reference<AbortChannel> const &,
     545             :     Reference<XCommandEnvironment> const & )
     546             : {
     547           0 :     BackendImpl * that = getMyBackend();
     548             : 
     549           0 :     bool bReg = false;
     550           0 :     if (that->hasActiveEntry(getURL()))
     551           0 :         bReg = true;
     552             : 
     553             : #if HAVE_FEATURE_EXTENSIONS
     554           0 :     const OUString url(getURL());
     555           0 :     if (!bReg && that->m_registeredPackages.get())
     556             :     {
     557             :         // fallback for user extension registered in berkeley DB
     558             :         bReg = that->m_registeredPackages->has(
     559           0 :             OUStringToOString( url, RTL_TEXTENCODING_UTF8 ));
     560             :     }
     561             : #endif
     562             :     return beans::Optional< beans::Ambiguous<sal_Bool> >(
     563           0 :         true, beans::Ambiguous<sal_Bool>( bReg, false ) );
     564             : }
     565             : 
     566             : 
     567           0 : OUString encodeForXml( OUString const & text )
     568             : {
     569             :     // encode conforming xml:
     570           0 :     sal_Int32 len = text.getLength();
     571           0 :     OUStringBuffer buf;
     572           0 :     for ( sal_Int32 pos = 0; pos < len; ++pos )
     573             :     {
     574           0 :         sal_Unicode c = text[ pos ];
     575           0 :         switch (c) {
     576             :         case '<':
     577           0 :             buf.appendAscii( "&lt;" );
     578           0 :             break;
     579             :         case '>':
     580           0 :             buf.appendAscii( "&gt;" );
     581           0 :             break;
     582             :         case '&':
     583           0 :             buf.appendAscii( "&amp;" );
     584           0 :             break;
     585             :         case '\'':
     586           0 :             buf.appendAscii( "&apos;" );
     587           0 :             break;
     588             :         case '\"':
     589           0 :             buf.appendAscii( "&quot;" );
     590           0 :             break;
     591             :         default:
     592           0 :             buf.append( c );
     593           0 :             break;
     594             :         }
     595             :     }
     596           0 :     return buf.makeStringAndClear();
     597             : }
     598             : 
     599             : 
     600           0 : OUString replaceOrigin(
     601             :     OUString const & url, OUString const & destFolder, Reference< XCommandEnvironment > const & xCmdEnv, Reference< XComponentContext > const & xContext, bool & out_replaced)
     602             : {
     603             :     // looking for %origin%:
     604           0 :     ::ucbhelper::Content ucb_content( url, xCmdEnv, xContext );
     605           0 :     ::rtl::ByteSequence bytes( readFile( ucb_content ) );
     606           0 :     ::rtl::ByteSequence filtered( bytes.getLength() * 2,
     607           0 :                                   ::rtl::BYTESEQ_NODEFAULT );
     608           0 :     bool use_filtered = false;
     609           0 :     OString origin;
     610             :     sal_Char const * pBytes = reinterpret_cast<sal_Char const *>(
     611           0 :         bytes.getConstArray());
     612           0 :     sal_Size nBytes = bytes.getLength();
     613           0 :     sal_Int32 write_pos = 0;
     614           0 :     while (nBytes > 0)
     615             :     {
     616           0 :         sal_Int32 index = rtl_str_indexOfChar_WithLength( pBytes, nBytes, '%' );
     617           0 :         if (index < 0) {
     618           0 :             if (! use_filtered) // opt
     619           0 :                 break;
     620           0 :             index = nBytes;
     621             :         }
     622             : 
     623           0 :         if ((write_pos + index) > filtered.getLength())
     624           0 :             filtered.realloc( (filtered.getLength() + index) * 2 );
     625           0 :         memcpy( filtered.getArray() + write_pos, pBytes, index );
     626           0 :         write_pos += index;
     627           0 :         pBytes += index;
     628           0 :         nBytes -= index;
     629           0 :         if (nBytes == 0)
     630           0 :             break;
     631             : 
     632             :         // consume %:
     633           0 :         ++pBytes;
     634           0 :         --nBytes;
     635           0 :         sal_Char const * pAdd = "%";
     636           0 :         sal_Int32 nAdd = 1;
     637           0 :         if (nBytes > 1 && pBytes[ 0 ] == '%')
     638             :         {
     639             :             // %% => %
     640           0 :             ++pBytes;
     641           0 :             --nBytes;
     642           0 :             use_filtered = true;
     643             :         }
     644           0 :         else if (rtl_str_shortenedCompare_WithLength(
     645             :                      pBytes, nBytes,
     646             :                      "origin%",
     647             :                      RTL_CONSTASCII_LENGTH("origin%"),
     648           0 :                      RTL_CONSTASCII_LENGTH("origin%")) == 0)
     649             :         {
     650           0 :             if (origin.isEmpty()) {
     651             :                 // encode only once
     652           0 :                 origin = OUStringToOString(
     653             :                     encodeForXml( url.copy( 0, url.lastIndexOf( '/' ) ) ),
     654             :                     // xxx todo: encode always for UTF-8? => lookup doc-header?
     655           0 :                     RTL_TEXTENCODING_UTF8 );
     656             :             }
     657           0 :             pAdd = origin.getStr();
     658           0 :             nAdd = origin.getLength();
     659           0 :             pBytes += RTL_CONSTASCII_LENGTH("origin%");
     660           0 :             nBytes -= RTL_CONSTASCII_LENGTH("origin%");
     661           0 :             use_filtered = true;
     662             :         }
     663           0 :         if ((write_pos + nAdd) > filtered.getLength())
     664           0 :             filtered.realloc( (filtered.getLength() + nAdd) * 2 );
     665           0 :         memcpy( filtered.getArray() + write_pos, pAdd, nAdd );
     666           0 :         write_pos += nAdd;
     667             :     }
     668           0 :     if (!use_filtered)
     669           0 :         return url;
     670           0 :     if (write_pos < filtered.getLength())
     671           0 :         filtered.realloc( write_pos );
     672           0 :     OUString newUrl(url);
     673           0 :     if (!destFolder.isEmpty())
     674             :     {
     675             :         //get the file name of the xcu and add it to the url of the temporary folder
     676           0 :         sal_Int32 i = url.lastIndexOf('/');
     677           0 :         newUrl = destFolder + url.copy(i);
     678             :     }
     679             : 
     680             :     ucbhelper::Content(newUrl, xCmdEnv, xContext).writeStream(
     681           0 :         xmlscript::createInputStream(filtered), true);
     682           0 :     out_replaced = true;
     683           0 :     return newUrl;
     684             : }
     685             : 
     686             : 
     687           0 : void BackendImpl::PackageImpl::processPackage_(
     688             :     ::osl::ResettableMutexGuard &,
     689             :     bool doRegisterPackage,
     690             :     bool startup,
     691             :     ::rtl::Reference<AbortChannel> const &,
     692             :     Reference<XCommandEnvironment> const & xCmdEnv )
     693             : {
     694           0 :     BackendImpl * that = getMyBackend();
     695           0 :     OUString url( getURL() );
     696             : 
     697           0 :     if (doRegisterPackage)
     698             :     {
     699           0 :         if (getMyBackend()->activateEntry(getURL()))
     700             :         {
     701           0 :             ::boost::optional<ConfigurationBackendDb::Data> data = that->readDataFromDb(url);
     702             :             OSL_ASSERT(data);
     703           0 :             that->addToConfigmgrIni( m_isSchema, false, data->iniEntry, xCmdEnv );
     704             :         }
     705             :         else
     706             :         {
     707           0 :             ConfigurationBackendDb::Data data;
     708           0 :             if (!m_isSchema)
     709             :             {
     710           0 :                 const OUString sModFolder = that->createFolder(OUString(), xCmdEnv);
     711           0 :                 bool out_replaced = false;
     712           0 :                 url = replaceOrigin(url, sModFolder, xCmdEnv, that->getComponentContext(), out_replaced);
     713           0 :                 if (out_replaced)
     714           0 :                     data.dataUrl = sModFolder;
     715             :                 else
     716           0 :                     deleteTempFolder(sModFolder);
     717             :             }
     718             :             //No need for live-deployment for bundled extension, because OOo
     719             :             //restarts after installation
     720           0 :             if (that->m_eContext != CONTEXT_BUNDLED
     721           0 :                 && !startup)
     722             :             {
     723           0 :                 if (m_isSchema)
     724             :                 {
     725             :                     com::sun::star::configuration::Update::get(
     726           0 :                         that->m_xComponentContext)->insertExtensionXcsFile(
     727           0 :                             that->m_eContext == CONTEXT_SHARED, expandUnoRcUrl(url));
     728             :                 }
     729             :                 else
     730             :                 {
     731             :                     com::sun::star::configuration::Update::get(
     732           0 :                         that->m_xComponentContext)->insertExtensionXcuFile(
     733           0 :                             that->m_eContext == CONTEXT_SHARED, expandUnoRcUrl(url));
     734             :                 }
     735             :             }
     736           0 :             that->addToConfigmgrIni( m_isSchema, true, url, xCmdEnv );
     737           0 :             data.iniEntry = dp_misc::makeRcTerm(url);
     738           0 :             that->addDataToDb(getURL(), data);
     739             :         }
     740             :     }
     741             :     else // revoke
     742             :     {
     743             : #if HAVE_FEATURE_EXTENSIONS
     744           0 :         if (!that->removeFromConfigmgrIni(m_isSchema, url, xCmdEnv) &&
     745           0 :             that->m_registeredPackages.get()) {
     746             :             // Obsolete package database handling - should be removed for LibreOffice 4.0
     747             :             t_string2string_map entries(
     748           0 :                 that->m_registeredPackages->getEntries());
     749           0 :             for (t_string2string_map::iterator i(entries.begin());
     750           0 :                  i != entries.end(); ++i)
     751             :             {
     752             :                 //If the xcu file was installed before the configmgr was chaned
     753             :                 //to use the configmgr.ini, one needed to rebuild to whole directory
     754             :                 //structure containing the xcu, xcs files from all extensions. Now,
     755             :                 //we just add all other xcu/xcs files to the configmgr.ini instead of
     756             :                 //rebuilding the directory structure.
     757             :                 OUString url2(
     758           0 :                     OStringToOUString(i->first, RTL_TEXTENCODING_UTF8));
     759           0 :                 if (url2 != url) {
     760           0 :                    bool schema = i->second.equalsIgnoreAsciiCase(
     761           0 :                        "vnd.sun.star.configuration-schema");
     762           0 :                    OUString url_replaced(url2);
     763           0 :                    ConfigurationBackendDb::Data data;
     764           0 :                    if (!schema)
     765             :                    {
     766           0 :                        const OUString sModFolder = that->createFolder(OUString(), xCmdEnv);
     767           0 :                        bool out_replaced = false;
     768           0 :                        url_replaced = replaceOrigin(
     769           0 :                            url2, sModFolder, xCmdEnv, that->getComponentContext(), out_replaced);
     770           0 :                        if (out_replaced)
     771           0 :                            data.dataUrl = sModFolder;
     772             :                        else
     773           0 :                            deleteTempFolder(sModFolder);
     774             :                    }
     775           0 :                    that->addToConfigmgrIni(schema, true, url_replaced, xCmdEnv);
     776           0 :                    data.iniEntry = dp_misc::makeRcTerm(url_replaced);
     777           0 :                    that->addDataToDb(url2, data);
     778             :                 }
     779           0 :                 that->m_registeredPackages->erase(i->first);
     780           0 :             }
     781             :             try
     782             :             {
     783             :                 ::ucbhelper::Content(
     784           0 :                     makeURL( that->getCachePath(), "registry" ),
     785           0 :                     xCmdEnv, that->getComponentContext() ).executeCommand(
     786           0 :                         "delete", Any( true /* delete physically */ ) );
     787             :             }
     788           0 :             catch(const Exception&)
     789             :             {
     790             :                 OSL_ASSERT(false);
     791           0 :             }
     792             :         }
     793             : #endif
     794           0 :         ::boost::optional<ConfigurationBackendDb::Data> data = that->readDataFromDb(url);
     795             :         //If an xcu file was life deployed then always a data entry is written.
     796             :         //If the xcu file was already in the configmr.ini then there is also
     797             :         //a data entry
     798           0 :         if (!m_isSchema && data)
     799             :         {
     800             :             com::sun::star::configuration::Update::get(
     801           0 :                 that->m_xComponentContext)->removeExtensionXcuFile(expandUnoRcTerm(data->iniEntry));
     802             :         }
     803           0 :         that->revokeEntryFromDb(url);
     804           0 :     }
     805           0 : }
     806             : 
     807             : } // anon namespace
     808             : 
     809             : namespace sdecl = comphelper::service_decl;
     810         111 : sdecl::class_<BackendImpl, sdecl::with_args<true> > serviceBI;
     811         111 : extern sdecl::ServiceDecl const serviceDecl(
     812             :     serviceBI,
     813             :     "com.sun.star.comp.deployment.configuration.PackageRegistryBackend",
     814             :     BACKEND_SERVICE_NAME );
     815             : 
     816             : } // namespace configuration
     817             : } // namespace backend
     818         333 : } // namespace dp_registry
     819             : 
     820             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11