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

Generated by: LCOV version 1.10