LCOV - code coverage report
Current view: top level - desktop/source/deployment/registry/package - dp_package.cxx (source / functions) Hit Total Coverage
Test: commit 0e63ca4fde4e446f346e35849c756a30ca294aab Lines: 264 653 40.4 %
Date: 2014-04-11 Functions: 34 48 70.8 %
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             : #include "dp_package.hrc"
      22             : #include "dp_backend.h"
      23             : #include "dp_ucb.h"
      24             : #include "dp_interact.h"
      25             : #include "dp_dependencies.hxx"
      26             : #include "dp_platform.hxx"
      27             : #include "dp_descriptioninfoset.hxx"
      28             : #include "dp_identifier.hxx"
      29             : #include "rtl/uri.hxx"
      30             : #include "cppuhelper/exc_hlp.hxx"
      31             : #include "cppuhelper/implbase1.hxx"
      32             : #include "cppuhelper/supportsservice.hxx"
      33             : #include "ucbhelper/content.hxx"
      34             : #include "svl/inettype.hxx"
      35             : #include "comphelper/anytostring.hxx"
      36             : #include "comphelper/makesequence.hxx"
      37             : #include "comphelper/sequence.hxx"
      38             : #include "com/sun/star/lang/WrappedTargetException.hpp"
      39             : #include "com/sun/star/lang/XServiceInfo.hpp"
      40             : #include "com/sun/star/beans/UnknownPropertyException.hpp"
      41             : #include "com/sun/star/graphic/XGraphic.hpp"
      42             : #include "com/sun/star/graphic/GraphicProvider.hpp"
      43             : #include "com/sun/star/graphic/XGraphicProvider.hpp"
      44             : #include <com/sun/star/io/Pipe.hpp>
      45             : #include "com/sun/star/io/XOutputStream.hpp"
      46             : #include "com/sun/star/io/XInputStream.hpp"
      47             : #include "com/sun/star/task/InteractionClassification.hpp"
      48             : #include "com/sun/star/task/XInteractionApprove.hpp"
      49             : #include "com/sun/star/ucb/XInteractionReplaceExistingData.hpp"
      50             : #include "com/sun/star/ucb/NameClashResolveRequest.hpp"
      51             : #include "com/sun/star/ucb/XContentAccess.hpp"
      52             : #include "com/sun/star/ucb/NameClash.hpp"
      53             : #include "com/sun/star/ucb/UnsupportedCommandException.hpp"
      54             : #include "com/sun/star/sdbc/XResultSet.hpp"
      55             : #include "com/sun/star/sdbc/XRow.hpp"
      56             : #include "com/sun/star/packages/manifest/ManifestReader.hpp"
      57             : #include "com/sun/star/packages/manifest/ManifestWriter.hpp"
      58             : #include "com/sun/star/deployment/DependencyException.hpp"
      59             : #include "com/sun/star/deployment/LicenseException.hpp"
      60             : #include "com/sun/star/deployment/PlatformException.hpp"
      61             : #include "com/sun/star/deployment/Prerequisites.hpp"
      62             : #include "com/sun/star/xml/dom/XDocumentBuilder.hpp"
      63             : #include "com/sun/star/xml/xpath/XXPathAPI.hpp"
      64             : #include "com/sun/star/deployment/XPackageManager.hpp"
      65             : #include "boost/optional.hpp"
      66             : #include <vector>
      67             : #include <stdio.h>
      68             : 
      69             : #include "dp_extbackenddb.hxx"
      70             : using namespace ::dp_misc;
      71             : using namespace ::com::sun::star;
      72             : using namespace ::com::sun::star::uno;
      73             : 
      74             : 
      75             : namespace dp_registry {
      76             : namespace backend {
      77             : namespace bundle {
      78             : namespace {
      79             : 
      80             : typedef cppu::ImplInheritanceHelper1<PackageRegistryBackend,
      81             :                                      lang::XServiceInfo> ImplBaseT;
      82             : 
      83             : 
      84         490 : class BackendImpl : public ImplBaseT
      85             : {
      86          12 :     class PackageImpl : public ::dp_registry::backend::Package
      87             :     {
      88             :         BackendImpl * getMyBackend() const;
      89             :         /** constains the old tooltip description for the Extension Manager GUI in OOo v.2.x
      90             :             We keep it for backward compatibility.
      91             :         */
      92             :         OUString m_oldDescription;
      93             :         OUString m_url_expanded;
      94             :         const bool m_legacyBundle;
      95             :         Sequence< Reference<deployment::XPackage> > m_bundle;
      96             :         Sequence< Reference<deployment::XPackage> > * m_pBundle;
      97             : 
      98             :         ExtensionBackendDb::Data m_dbData;
      99             : 
     100             :         Reference<deployment::XPackage> bindBundleItem(
     101             :             OUString const & url, OUString const & mediaType,
     102             :             sal_Bool bRemoved, //that is, using data base information
     103             :             OUString const & identifier,
     104             :             Reference<ucb::XCommandEnvironment> const & xCmdEnv,
     105             :             bool notifyDetectionError = true );
     106             : 
     107             :         typedef ::std::vector< Reference<deployment::XPackage> > t_packagevec;
     108             :         void scanBundle(
     109             :             t_packagevec & bundle,
     110             :             ::rtl::Reference<AbortChannel> const & abortChannel,
     111             :             Reference<ucb::XCommandEnvironment> const & xCmdEnv );
     112             :         void scanLegacyBundle(
     113             :             t_packagevec & bundle,
     114             :             OUString const & url,
     115             :             ::rtl::Reference<AbortChannel> const & abortChannel,
     116             :             Reference<ucb::XCommandEnvironment> const & xCmdEnv,
     117             :             bool skip_registration = false );
     118             :         ::std::vector<Reference<deployment::XPackage> > getPackagesFromDb(
     119             :             Reference<ucb::XCommandEnvironment> const & xCmdEnv);
     120             :         bool checkPlatform(
     121             :             Reference<ucb::XCommandEnvironment > const &  environment);
     122             : 
     123             :         bool checkDependencies(
     124             :             Reference<ucb::XCommandEnvironment > const &
     125             :                 environment,
     126             :             DescriptionInfoset const & description);
     127             :             // throws css::uno::RuntimeException,
     128             :             // css::deployment::DeploymentException
     129             : 
     130             :         sal_Bool checkLicense(
     131             :             Reference< ucb::XCommandEnvironment > const & xCmdEnv,
     132             :             DescriptionInfoset const & description, bool bNoLicenseChecking)
     133             :                 throw (deployment::DeploymentException,
     134             :                        ucb::CommandFailedException,
     135             :                        ucb::CommandAbortedException,
     136             :                        RuntimeException);
     137             :         // @throws DeploymentException
     138             :         OUString getTextFromURL(
     139             :             const Reference< ucb::XCommandEnvironment >& xCmdEnv,
     140             :             const OUString& licenseUrl);
     141             : 
     142             :         DescriptionInfoset getDescriptionInfoset();
     143             : 
     144             :         // Package
     145             :         virtual beans::Optional< beans::Ambiguous<sal_Bool> > isRegistered_(
     146             :             ::osl::ResettableMutexGuard & guard,
     147             :             ::rtl::Reference<AbortChannel> const & abortChannel,
     148             :             Reference<ucb::XCommandEnvironment> const & xCmdEnv ) SAL_OVERRIDE;
     149             :         virtual void processPackage_(
     150             :             ::osl::ResettableMutexGuard & guard,
     151             :             bool registerPackage,
     152             :             bool startup,
     153             :             ::rtl::Reference<AbortChannel> const & abortChannel,
     154             :             Reference<ucb::XCommandEnvironment> const & xCmdEnv ) SAL_OVERRIDE;
     155             : 
     156             :         virtual void SAL_CALL disposing() SAL_OVERRIDE;
     157             : 
     158             : 
     159             : 
     160             :     public:
     161             :         PackageImpl(
     162             :             ::rtl::Reference<PackageRegistryBackend> const & myBackend,
     163             :             OUString const & url,
     164             :             OUString const & name,
     165             :             Reference<deployment::XPackageTypeInfo> const & xPackageType,
     166             :             bool legacyBundle,
     167             :             bool bRemoved,
     168             :             OUString const & identifier);
     169             : 
     170             :         // XPackage
     171             :         virtual sal_Bool SAL_CALL isBundle() throw (RuntimeException, std::exception) SAL_OVERRIDE;
     172             : 
     173             :         virtual Sequence< Reference<deployment::XPackage> > SAL_CALL getBundle(
     174             :             Reference<task::XAbortChannel> const & xAbortChannel,
     175             :             Reference<ucb::XCommandEnvironment> const & xCmdEnv )
     176             :             throw (deployment::DeploymentException,
     177             :                    ucb::CommandFailedException,
     178             :                    ucb::CommandAbortedException,
     179             :                    lang::IllegalArgumentException, RuntimeException, std::exception) SAL_OVERRIDE;
     180             :         virtual OUString SAL_CALL getDescription()
     181             :             throw (deployment::ExtensionRemovedException, RuntimeException, std::exception) SAL_OVERRIDE;
     182             : 
     183             :         virtual OUString SAL_CALL getLicenseText()
     184             :             throw (deployment::ExtensionRemovedException, RuntimeException, std::exception) SAL_OVERRIDE;
     185             : 
     186             :         virtual void SAL_CALL exportTo(
     187             :             OUString const & destFolderURL, OUString const & newTitle,
     188             :             sal_Int32 nameClashAction,
     189             :             Reference<ucb::XCommandEnvironment> const & xCmdEnv )
     190             :             throw (deployment::ExtensionRemovedException,
     191             :                    ucb::CommandFailedException,
     192             :                    ucb::CommandAbortedException,
     193             :                    RuntimeException, std::exception) SAL_OVERRIDE;
     194             : 
     195             :         virtual ::sal_Int32 SAL_CALL checkPrerequisites(
     196             :             const Reference< task::XAbortChannel >& xAbortChannel,
     197             :             const Reference< ucb::XCommandEnvironment >& xCmdEnv,
     198             :             sal_Bool noLicenseChecking)
     199             :             throw (deployment::ExtensionRemovedException,
     200             :                    deployment::DeploymentException,
     201             :                    ucb::CommandFailedException,
     202             :                    ucb::CommandAbortedException,
     203             :                    RuntimeException, std::exception) SAL_OVERRIDE;
     204             : 
     205             :         virtual sal_Bool SAL_CALL checkDependencies(
     206             :             const Reference< ucb::XCommandEnvironment >& xCmdEnv )
     207             :             throw (deployment::DeploymentException,
     208             :                    deployment::ExtensionRemovedException,
     209             :                    ucb::CommandFailedException,
     210             :                    RuntimeException, std::exception) SAL_OVERRIDE;
     211             : 
     212             :         virtual beans::Optional<OUString> SAL_CALL getIdentifier()
     213             :             throw (RuntimeException, std::exception) SAL_OVERRIDE;
     214             : 
     215             :         virtual OUString SAL_CALL getVersion()
     216             :             throw (deployment::ExtensionRemovedException, RuntimeException, std::exception) SAL_OVERRIDE;
     217             : 
     218             :         virtual Sequence<OUString> SAL_CALL getUpdateInformationURLs()
     219             :             throw (deployment::ExtensionRemovedException, RuntimeException, std::exception) SAL_OVERRIDE;
     220             : 
     221             :         virtual beans::StringPair SAL_CALL getPublisherInfo()
     222             :             throw (deployment::ExtensionRemovedException, RuntimeException, std::exception) SAL_OVERRIDE;
     223             : 
     224             :         virtual OUString SAL_CALL getDisplayName()
     225             :             throw (deployment::ExtensionRemovedException, RuntimeException, std::exception) SAL_OVERRIDE;
     226             : 
     227             :         virtual Reference< graphic::XGraphic > SAL_CALL
     228             :         getIcon( sal_Bool bHighContrast )
     229             :             throw (deployment::ExtensionRemovedException,
     230             :                    RuntimeException, std::exception) SAL_OVERRIDE;
     231             :     };
     232             :     friend class PackageImpl;
     233             : 
     234             :     Reference<deployment::XPackageRegistry> m_xRootRegistry;
     235             :     const Reference<deployment::XPackageTypeInfo> m_xBundleTypeInfo;
     236             :     const Reference<deployment::XPackageTypeInfo> m_xLegacyBundleTypeInfo;
     237             :     Sequence< Reference<deployment::XPackageTypeInfo> > m_typeInfos;
     238             : 
     239             :     std::auto_ptr<ExtensionBackendDb> m_backendDb;
     240             : 
     241             :     void addDataToDb(OUString const & url, ExtensionBackendDb::Data const & data);
     242             :     ExtensionBackendDb::Data readDataFromDb(OUString const & url);
     243             :     void revokeEntryFromDb(OUString const & url);
     244             : 
     245             :     // PackageRegistryBackend
     246             :     virtual Reference<deployment::XPackage> bindPackage_(
     247             :         OUString const & url, OUString const & mediaType,
     248             :         sal_Bool bRemoved, OUString const & identifier,
     249             :         Reference<ucb::XCommandEnvironment> const & xCmdEnv ) SAL_OVERRIDE;
     250             : 
     251             :     virtual void SAL_CALL disposing() SAL_OVERRIDE;
     252             : 
     253             : public:
     254             :     BackendImpl(
     255             :         Sequence<Any> const & args,
     256             :         Reference<XComponentContext> const & xComponentContext,
     257             :         Reference<deployment::XPackageRegistry> const & xRootRegistry );
     258             : 
     259             :     // XServiceInfo
     260             :     virtual OUString SAL_CALL getImplementationName() throw (RuntimeException, std::exception) SAL_OVERRIDE;
     261             :     virtual sal_Bool SAL_CALL supportsService( OUString const& name )
     262             :         throw (RuntimeException, std::exception) SAL_OVERRIDE;
     263             :     virtual Sequence<OUString> SAL_CALL getSupportedServiceNames()
     264             :         throw (RuntimeException, std::exception) SAL_OVERRIDE;
     265             : 
     266             :     // XPackageRegistry
     267             :     virtual Sequence< Reference<deployment::XPackageTypeInfo> > SAL_CALL
     268             :     getSupportedPackageTypes() throw (RuntimeException, std::exception) SAL_OVERRIDE;
     269             :     virtual void SAL_CALL packageRemoved(OUString const & url, OUString const & mediaType)
     270             :         throw (deployment::DeploymentException,
     271             :                uno::RuntimeException, std::exception) SAL_OVERRIDE;
     272             : 
     273             :     using ImplBaseT::disposing;
     274             : };
     275             : 
     276             : //Used to find a XPackage with a particular URL
     277           3 : class XPackage_eq : public std::unary_function<Reference<deployment::XPackage>, bool>
     278             : {
     279             :     OUString m_URL;
     280             : public:
     281           1 :     explicit XPackage_eq(const OUString & s) : m_URL(s) {}
     282           0 :     bool operator() (const Reference<deployment::XPackage> & p) const
     283             :     {
     284           0 :         return m_URL.equals(p->getURL());
     285             :     }
     286             : };
     287             : 
     288             : 
     289         245 : BackendImpl::BackendImpl(
     290             :     Sequence<Any> const & args,
     291             :     Reference<XComponentContext> const & xComponentContext,
     292             :     Reference<deployment::XPackageRegistry> const & xRootRegistry )
     293             :     : ImplBaseT( args, xComponentContext ),
     294             :       m_xRootRegistry( xRootRegistry ),
     295             :       m_xBundleTypeInfo( new Package::TypeInfo(
     296             :                              "application/vnd.sun.star.package-bundle",
     297             :                              "*.oxt;*.uno.pkg",
     298             :                              getResourceString(RID_STR_PACKAGE_BUNDLE),
     299         245 :                              RID_IMG_DEF_PACKAGE_BUNDLE ) ),
     300             :       m_xLegacyBundleTypeInfo( new Package::TypeInfo(
     301             :                                    "application/vnd.sun.star.legacy-package-bundle",
     302             :                                    "*.zip",
     303         245 :                                    m_xBundleTypeInfo->getShortDescription(),
     304         245 :                                    RID_IMG_DEF_PACKAGE_BUNDLE ) ),
     305         980 :     m_typeInfos(2)
     306             : {
     307         245 :     m_typeInfos[ 0 ] = m_xBundleTypeInfo;
     308         245 :     m_typeInfos[ 1 ] = m_xLegacyBundleTypeInfo;
     309             : 
     310         245 :     if (!transientMode())
     311             :     {
     312         245 :         OUString dbFile = makeURL(getCachePath(), getImplementationName());
     313         245 :         dbFile = makeURL(dbFile, "backenddb.xml");
     314             :         m_backendDb.reset(
     315         245 :             new ExtensionBackendDb(getComponentContext(), dbFile));
     316             :    }
     317         245 : }
     318             : 
     319             : 
     320         245 : void BackendImpl::disposing()
     321             : {
     322         245 :     m_xRootRegistry.clear();
     323         245 :     PackageRegistryBackend::disposing();
     324         245 : }
     325             : 
     326             : // XServiceInfo
     327         490 : OUString BackendImpl::getImplementationName() throw (RuntimeException, std::exception)
     328             : {
     329         490 :     return OUString("com.sun.star.comp.deployment.bundle.PackageRegistryBackend");
     330             : }
     331             : 
     332           0 : sal_Bool BackendImpl::supportsService(OUString const & ServiceName)
     333             :     throw (css::uno::RuntimeException, std::exception)
     334             : {
     335           0 :     return cppu::supportsService(this, ServiceName);
     336             : }
     337             : 
     338           0 : Sequence<OUString> BackendImpl::getSupportedServiceNames()
     339             :     throw (RuntimeException, std::exception)
     340             : {
     341             :     return comphelper::makeSequence(
     342           0 :         OUString(BACKEND_SERVICE_NAME) );
     343             : }
     344             : 
     345             : // XPackageRegistry
     346             : 
     347             : Sequence< Reference<deployment::XPackageTypeInfo> >
     348         245 : BackendImpl::getSupportedPackageTypes() throw (RuntimeException, std::exception)
     349             : {
     350         245 :     return m_typeInfos;
     351             : }
     352             : 
     353           3 : void BackendImpl::packageRemoved(OUString const & url, OUString const & /*mediaType*/)
     354             :         throw (deployment::DeploymentException,
     355             :                uno::RuntimeException, std::exception)
     356             : {
     357             :     //Notify the backend responsible for processing the different media
     358             :     //types that this extension was removed.
     359           3 :     ExtensionBackendDb::Data data = readDataFromDb(url);
     360           4 :     for (ExtensionBackendDb::Data::ITC_ITEMS i = data.items.begin(); i != data.items.end(); ++i)
     361             :     {
     362           1 :         m_xRootRegistry->packageRemoved(i->first, i->second);
     363             :     }
     364             : 
     365           3 :     if (m_backendDb.get())
     366           3 :         m_backendDb->removeEntry(url);
     367           3 : }
     368             : 
     369             : 
     370             : // PackageRegistryBackend
     371             : 
     372           6 : Reference<deployment::XPackage> BackendImpl::bindPackage_(
     373             :     OUString const & url, OUString const & mediaType_,
     374             :     sal_Bool bRemoved, OUString const & identifier,
     375             :     Reference<ucb::XCommandEnvironment> const & xCmdEnv )
     376             : {
     377           6 :     OUString mediaType( mediaType_ );
     378           6 :     if (mediaType.isEmpty())
     379             :     {
     380             :         // detect media-type:
     381           3 :         ::ucbhelper::Content ucbContent;
     382           3 :         if (create_ucb_content( &ucbContent, url, xCmdEnv ))
     383             :         {
     384           3 :             if (ucbContent.isFolder())
     385             :             {
     386             :                 //Every .oxt, uno.pkg file must contain a META-INF folder
     387           1 :                 ::ucbhelper::Content metaInfContent;
     388           2 :                 if (create_ucb_content(
     389             :                     &metaInfContent, makeURL( url, "META-INF" ),
     390           2 :                     xCmdEnv, false /* no throw */ ))
     391             :                 {
     392           1 :                      mediaType = "application/vnd.sun.star.package-bundle";
     393           1 :                 }
     394             :                 //No support of legacy bundles, because every folder could be one.
     395             :             }
     396             :             else
     397             :             {
     398           2 :                 const OUString title( StrTitle::getTitle( ucbContent ) );
     399           2 :                 if (title.endsWithIgnoreAsciiCase(".oxt") ||
     400           0 :                     title.endsWithIgnoreAsciiCase(".uno.pkg"))
     401           2 :                     mediaType = "application/vnd.sun.star.package-bundle";
     402           0 :                 else if (title.endsWithIgnoreAsciiCase(".zip"))
     403           0 :                     mediaType = "application/vnd.sun.star.legacy-package-bundle";
     404             :             }
     405             :         }
     406           3 :         if (mediaType.isEmpty())
     407             :             throw lang::IllegalArgumentException(
     408           0 :                 StrCannotDetectMediaType::get() + url,
     409           0 :                 static_cast<OWeakObject *>(this), static_cast<sal_Int16>(-1) );
     410             :     }
     411             : 
     412          12 :     OUString type, subType;
     413          12 :     INetContentTypeParameterList params;
     414           6 :     if (INetContentTypes::parse( mediaType, type, subType, &params ))
     415             :     {
     416           6 :         if (type.equalsIgnoreAsciiCase("application"))
     417             :         {
     418             : 
     419             :             //In case a XPackage is created for a removed extension, we cannot
     420             :             //obtain the name
     421           6 :             OUString name;
     422           6 :             if (!bRemoved)
     423             :             {
     424             :                 ::ucbhelper::Content ucbContent(
     425           6 :                     url, xCmdEnv, getComponentContext() );
     426           6 :                 name = StrTitle::getTitle( ucbContent );
     427             :             }
     428           6 :             if (subType.equalsIgnoreAsciiCase("vnd.sun.star.package-bundle"))
     429             :             {
     430             :                 return new PackageImpl(
     431             :                     this, url, name, m_xBundleTypeInfo, false, bRemoved,
     432           6 :                     identifier);
     433             :             }
     434           0 :             else if (subType.equalsIgnoreAsciiCase( "vnd.sun.star.legacy-package-bundle"))
     435             :             {
     436             :                 return new PackageImpl(
     437             :                     this, url, name, m_xLegacyBundleTypeInfo, true, bRemoved,
     438           0 :                     identifier);
     439           0 :             }
     440             :         }
     441             :     }
     442             :     throw lang::IllegalArgumentException(
     443           0 :         StrUnsupportedMediaType::get() + mediaType,
     444             :         static_cast<OWeakObject *>(this),
     445           6 :         static_cast<sal_Int16>(-1) );
     446             : }
     447             : 
     448           1 : void BackendImpl::addDataToDb(
     449             :     OUString const & url, ExtensionBackendDb::Data const & data)
     450             : {
     451           1 :     if (m_backendDb.get())
     452           1 :         m_backendDb->addEntry(url, data);
     453           1 : }
     454             : 
     455           3 : ExtensionBackendDb::Data BackendImpl::readDataFromDb(
     456             :     OUString const & url)
     457             : {
     458           3 :     ExtensionBackendDb::Data data;
     459           3 :     if (m_backendDb.get())
     460           3 :         data = m_backendDb->getEntry(url);
     461           3 :     return data;
     462             : }
     463             : 
     464           1 : void BackendImpl::revokeEntryFromDb(OUString const & url)
     465             : {
     466           1 :     if (m_backendDb.get())
     467           1 :         m_backendDb->revokeEntry(url);
     468           1 : }
     469             : 
     470             : 
     471             : 
     472           6 : BackendImpl::PackageImpl::PackageImpl(
     473             :     ::rtl::Reference<PackageRegistryBackend> const & myBackend,
     474             :     OUString const & url,
     475             :     OUString const & name,
     476             :     Reference<deployment::XPackageTypeInfo> const & xPackageType,
     477             :     bool legacyBundle, bool bRemoved, OUString const & identifier)
     478             :     : Package( myBackend, url, name, name /* display-name */,
     479             :                xPackageType, bRemoved, identifier),
     480             :       m_url_expanded( expandUnoRcUrl( url ) ),
     481             :       m_legacyBundle( legacyBundle ),
     482           6 :       m_pBundle( 0 )
     483             : {
     484           6 :     if (bRemoved)
     485           0 :         m_dbData = getMyBackend()->readDataFromDb(url);
     486           6 : }
     487             : 
     488           4 : BackendImpl * BackendImpl::PackageImpl::getMyBackend() const
     489             : {
     490           4 :     BackendImpl * pBackend = static_cast<BackendImpl *>(m_myBackend.get());
     491           4 :     if (NULL == pBackend)
     492             :     {
     493             :         //May throw a DisposedException
     494           0 :         check();
     495             :         //We should never get here...
     496             :         throw RuntimeException("Failed to get the BackendImpl",
     497           0 :             static_cast<OWeakObject*>(const_cast<PackageImpl *>(this)));
     498             :     }
     499           4 :     return pBackend;
     500             : }
     501             : 
     502           6 : void BackendImpl::PackageImpl::disposing()
     503             : {
     504           6 :     sal_Int32 len = m_bundle.getLength();
     505           6 :     Reference<deployment::XPackage> const * p = m_bundle.getConstArray();
     506           7 :     for ( sal_Int32 pos = 0; pos < len; ++pos )
     507           1 :         try_dispose( p[ pos ] );
     508           6 :     m_bundle.realloc( 0 );
     509             : 
     510           6 :     Package::disposing();
     511           6 : }
     512             : 
     513             : // Package
     514             : 
     515             : beans::Optional< beans::Ambiguous<sal_Bool> >
     516           4 : BackendImpl::PackageImpl::isRegistered_(
     517             :     ::osl::ResettableMutexGuard &,
     518             :     ::rtl::Reference<AbortChannel> const & abortChannel,
     519             :     Reference<ucb::XCommandEnvironment> const & xCmdEnv )
     520             : {
     521             :     //In case the object was created for a removed extension (m_bRemoved = true)
     522             :     //but the extension is not registered, then bundle will be empty. Then
     523             :     //the return value will be Optional<...>.IsPresent= false. Althoug this is
     524             :     //not true, this does not matter. Then registerPackage or revokePackage
     525             :     //would never be called for the items. But since the extension is removed
     526             :     //and not registered anyway, this does not matter.
     527             :     const Sequence< Reference<deployment::XPackage> > bundle(
     528           4 :         getBundle( abortChannel.get(), xCmdEnv ) );
     529             : 
     530           4 :     bool reg = false;
     531           4 :     bool present = false;
     532           4 :     bool ambig = false;
     533          12 :     for ( sal_Int32 pos = bundle.getLength(); pos--; )
     534             :     {
     535           4 :         Reference<deployment::XPackage> const & xPackage = bundle[ pos ];
     536             :         Reference<task::XAbortChannel> xSubAbortChannel(
     537           4 :             xPackage->createAbortChannel() );
     538           8 :         AbortChannel::Chain chain( abortChannel, xSubAbortChannel );
     539             :         beans::Optional< beans::Ambiguous<sal_Bool> > option(
     540           4 :             xPackage->isRegistered( xSubAbortChannel, xCmdEnv ) );
     541             : 
     542             :         //present = true if at least one bundle item has this value.
     543             :         //reg = true if all bundle items have an option value (option.IsPresent == 1)
     544             :         //and all have value of true (option.Value.Value == true)
     545             :         //If not, then the bundle has the status of not registered and ambiguous.
     546           4 :         if (option.IsPresent)
     547             :         {
     548           4 :             beans::Ambiguous<sal_Bool> const & status = option.Value;
     549           4 :             if (present)
     550             :             {
     551             :                 //we never come here in the first iteration
     552           0 :                 if (reg != (status.Value != sal_False)) {
     553             : 
     554           0 :                     ambig = true;
     555           0 :                     reg = false;
     556           0 :                     break;
     557             :                 }
     558             :             }
     559             :             else
     560             :             {
     561             :                 //we always come here in the first iteration
     562           4 :                 reg = status.Value;
     563           4 :                 present = true;
     564             :             }
     565             :         }
     566           4 :     }
     567             :     return beans::Optional< beans::Ambiguous<sal_Bool> >(
     568           4 :         present, beans::Ambiguous<sal_Bool>(reg, ambig) );
     569             : }
     570             : 
     571           0 : OUString BackendImpl::PackageImpl::getTextFromURL(
     572             :     const css::uno::Reference< css::ucb::XCommandEnvironment >& xCmdEnv,
     573             :     const OUString& licenseUrl)
     574             : {
     575             :     try
     576             :     {
     577             :         ::ucbhelper::Content descContent(
     578           0 :             licenseUrl, xCmdEnv, getMyBackend()->getComponentContext());
     579           0 :         ::rtl::ByteSequence seq = dp_misc::readFile(descContent);
     580             :         return OUString( reinterpret_cast<sal_Char const *>(
     581           0 :             seq.getConstArray()), seq.getLength(), RTL_TEXTENCODING_UTF8);
     582             :     }
     583           0 :     catch (const css::uno::Exception&)
     584             :     {
     585           0 :         Any exc( ::cppu::getCaughtException() );
     586             :             throw css::deployment::DeploymentException(
     587           0 :                 "Could not read file " + licenseUrl, 0, exc);
     588             :     }
     589             : 
     590             : }
     591             : 
     592          19 : DescriptionInfoset BackendImpl::PackageImpl::getDescriptionInfoset()
     593             : {
     594          19 :     return dp_misc::getDescriptionInfoset(m_url_expanded);
     595             : }
     596             : 
     597           2 : bool BackendImpl::PackageImpl::checkPlatform(
     598             :     css::uno::Reference< css::ucb::XCommandEnvironment > const &  environment)
     599             : {
     600           2 :     bool ret = false;
     601           2 :     DescriptionInfoset info(getDescriptionInfoset());
     602           4 :     Sequence<OUString> platforms(info.getSupportedPlaforms());
     603           2 :     if (hasValidPlatform(platforms))
     604             :     {
     605           2 :         ret = true;
     606             :     }
     607             :     else
     608             :     {
     609           0 :         ret = false;
     610             :         OUString msg(
     611           0 :             "unsupported platform");
     612             :         Any e(
     613             :             css::deployment::PlatformException(
     614           0 :                 msg, static_cast<OWeakObject *>(this), this));
     615           0 :         if (!interactContinuation(
     616           0 :                 e, cppu::UnoType< css::task::XInteractionApprove >::get(),
     617           0 :                 environment, NULL, NULL))
     618             :         {
     619             :             throw css::deployment::DeploymentException(
     620           0 :                 msg, static_cast<OWeakObject *>(this), e);
     621           0 :         }
     622             :     }
     623           4 :     return ret;
     624             : }
     625             : 
     626             : 
     627           2 : bool BackendImpl::PackageImpl::checkDependencies(
     628             :     css::uno::Reference< css::ucb::XCommandEnvironment > const & environment,
     629             :     DescriptionInfoset const & description)
     630             : {
     631             :     css::uno::Sequence< css::uno::Reference< css::xml::dom::XElement > >
     632           2 :         unsatisfied(dp_misc::Dependencies::check(description));
     633             : 
     634           2 :     if (unsatisfied.getLength() == 0) {
     635           2 :         return true;
     636             :     } else {
     637             :         OUString msg(
     638           0 :             "unsatisfied dependencies");
     639             :         Any e(
     640             :             css::deployment::DependencyException(
     641           0 :                 msg, static_cast<OWeakObject *>(this), unsatisfied));
     642           0 :         if (!interactContinuation(
     643           0 :                 e, cppu::UnoType< css::task::XInteractionApprove >::get(),
     644           0 :                 environment, NULL, NULL))
     645             :         {
     646             :             throw css::deployment::DeploymentException(
     647           0 :                 msg, static_cast<OWeakObject *>(this), e);
     648             :         }
     649           0 :         return false;
     650           2 :     }
     651             : }
     652             : 
     653           2 : sal_Bool BackendImpl::PackageImpl::checkLicense(
     654             :     css::uno::Reference< css::ucb::XCommandEnvironment > const & xCmdEnv,
     655             :     DescriptionInfoset const & info, bool alreadyInstalled)
     656             :         throw (css::deployment::DeploymentException,
     657             :             css::ucb::CommandFailedException,
     658             :             css::ucb::CommandAbortedException,
     659             :             css::uno::RuntimeException)
     660             : {
     661             :     try
     662             :     {
     663             :         ::boost::optional<SimpleLicenseAttributes> simplLicAttr
     664           2 :             = info.getSimpleLicenseAttributes();
     665           2 :        if (! simplLicAttr)
     666           2 :             return true;
     667           0 :         OUString sLic = info.getLocalizedLicenseURL();
     668             :         //If we do not get a localized licence then there is an error in the description.xml
     669             :         //This should be handled by using a validating parser. Therefore we assume that no
     670             :         //license is available.
     671           0 :         if (sLic.isEmpty())
     672             :             throw css::deployment::DeploymentException(
     673           0 :                 "Could not obtain path to license. Possible error in description.xml", 0, Any());
     674           0 :         OUString sHref = m_url_expanded + "/" + sLic;
     675           0 :            OUString sLicense = getTextFromURL(xCmdEnv, sHref);
     676             :         ////determine who has to agree to the license
     677             :         //check correct value for attribute
     678           0 :         if ( ! (simplLicAttr->acceptBy == "user" || simplLicAttr->acceptBy == "admin"))
     679             :             throw css::deployment::DeploymentException(
     680           0 :                 "Could not obtain attribute simple-lincense@accept-by or it has no valid value", 0, Any());
     681             : 
     682             : 
     683             :         //Only use interaction if there is no version of this extension already installed
     684             :         //and the suppress-on-update flag is not set for the new extension
     685             :         // alreadyInstalled | bSuppressOnUpdate | show license
     686             : 
     687             :         //      0     |      0            |     1
     688             :         //      0     |      1            |     1
     689             :         //      1     |      0            |     1
     690             :         //      1     |      1            |     0
     691             : 
     692           0 :         if ( !(alreadyInstalled && simplLicAttr->suppressOnUpdate))
     693             :         {
     694             :             css::deployment::LicenseException licExc(
     695           0 :                 OUString(), 0, getDisplayName(), sLicense,
     696           0 :                 simplLicAttr->acceptBy);
     697           0 :             bool approve = false;
     698           0 :             bool abort = false;
     699           0 :             if (! interactContinuation(
     700           0 :                 Any(licExc), cppu::UnoType<task::XInteractionApprove>::get(), xCmdEnv, &approve, &abort ))
     701             :                 throw css::deployment::DeploymentException(
     702           0 :                     "Could not interact with user.", 0, Any());
     703             : 
     704           0 :             if (approve == true)
     705           0 :                 return true;
     706             :             else
     707           0 :                 return false;
     708             :         }
     709           2 :         return true;
     710           0 :     } catch (const css::ucb::CommandFailedException&) {
     711           0 :         throw;
     712           0 :     } catch (const css::ucb::CommandAbortedException&) {
     713           0 :         throw;
     714           0 :     } catch (const css::deployment::DeploymentException&) {
     715           0 :         throw;
     716           0 :     } catch (const css::uno::RuntimeException&) {
     717           0 :         throw;
     718           0 :     } catch (const css::uno::Exception&) {
     719           0 :         Any anyExc = cppu::getCaughtException();
     720           0 :         throw css::deployment::DeploymentException("Unexpected exception", 0, anyExc);
     721             :     }
     722             : }
     723             : 
     724           2 : ::sal_Int32 BackendImpl::PackageImpl::checkPrerequisites(
     725             :         const css::uno::Reference< css::task::XAbortChannel >&,
     726             :         const css::uno::Reference< css::ucb::XCommandEnvironment >& xCmdEnv,
     727             :         sal_Bool alreadyInstalled)
     728             :         throw (css::deployment::DeploymentException,
     729             :                css::deployment::ExtensionRemovedException,
     730             :                css::ucb::CommandFailedException,
     731             :                css::ucb::CommandAbortedException,
     732             :                css::uno::RuntimeException, std::exception)
     733             : {
     734           2 :     if (m_bRemoved)
     735           0 :         throw deployment::ExtensionRemovedException();
     736           2 :     DescriptionInfoset info = getDescriptionInfoset();
     737           2 :     if (!info.hasDescription())
     738           0 :         return 0;
     739             : 
     740             :     //always return LICENSE as long as the user did not accept the license
     741             :     //so that XExtensonManager::checkPrerequisitesAndEnable will again
     742             :     //check the license
     743           2 :     if (!checkPlatform(xCmdEnv))
     744             :         return deployment::Prerequisites::PLATFORM |
     745           0 :             deployment::Prerequisites::LICENSE;
     746           2 :     else if(!checkDependencies(xCmdEnv, info))
     747             :         return deployment::Prerequisites::DEPENDENCIES |
     748           0 :             deployment::Prerequisites::LICENSE;
     749           2 :     else if(!checkLicense(xCmdEnv, info, alreadyInstalled))
     750           0 :         return deployment::Prerequisites::LICENSE;
     751             :     else
     752           2 :         return 0;
     753             : }
     754             : 
     755           0 : sal_Bool BackendImpl::PackageImpl::checkDependencies(
     756             :         const css::uno::Reference< css::ucb::XCommandEnvironment >& xCmdEnv )
     757             :         throw (deployment::DeploymentException,
     758             :                deployment::ExtensionRemovedException,
     759             :                ucb::CommandFailedException,
     760             :                RuntimeException, std::exception)
     761             : {
     762           0 :     if (m_bRemoved)
     763           0 :         throw deployment::ExtensionRemovedException();
     764           0 :     DescriptionInfoset info = getDescriptionInfoset();
     765           0 :     if (!info.hasDescription())
     766           0 :         return sal_True;
     767             : 
     768           0 :     return checkDependencies(xCmdEnv, info);
     769             : }
     770             : 
     771          11 : beans::Optional<OUString> BackendImpl::PackageImpl::getIdentifier()
     772             :     throw (RuntimeException, std::exception)
     773             : {
     774          11 :     OUString identifier;
     775          11 :     if (m_bRemoved)
     776           0 :         identifier = m_identifier;
     777             :     else
     778          22 :         identifier = dp_misc::generateIdentifier(
     779          11 :             getDescriptionInfoset().getIdentifier(), m_name);
     780             : 
     781             :     return beans::Optional<OUString>(
     782          11 :         true, identifier);
     783             : }
     784             : 
     785           1 : OUString BackendImpl::PackageImpl::getVersion()
     786             :     throw (deployment::ExtensionRemovedException, RuntimeException, std::exception)
     787             : {
     788           1 :     if (m_bRemoved)
     789           0 :         throw deployment::ExtensionRemovedException();
     790           1 :     return getDescriptionInfoset().getVersion();
     791             : }
     792             : 
     793           0 : Sequence<OUString> BackendImpl::PackageImpl::getUpdateInformationURLs()
     794             :     throw (deployment::ExtensionRemovedException, RuntimeException, std::exception)
     795             : {
     796           0 :     if (m_bRemoved)
     797           0 :         throw deployment::ExtensionRemovedException();
     798           0 :     return getDescriptionInfoset().getUpdateInformationUrls();
     799             : }
     800             : 
     801           0 : beans::StringPair BackendImpl::PackageImpl::getPublisherInfo()
     802             :     throw (deployment::ExtensionRemovedException, RuntimeException, std::exception)
     803             : {
     804           0 :     if (m_bRemoved)
     805           0 :         throw deployment::ExtensionRemovedException();
     806           0 :     ::std::pair< OUString, OUString > aInfo = getDescriptionInfoset().getLocalizedPublisherNameAndURL();
     807           0 :     beans::StringPair aStrPair( aInfo.first, aInfo.second );
     808           0 :     return aStrPair;
     809             : }
     810             : 
     811             : 
     812           0 : uno::Reference< graphic::XGraphic > BackendImpl::PackageImpl::getIcon( sal_Bool bHighContrast )
     813             :     throw (deployment::ExtensionRemovedException, RuntimeException, std::exception )
     814             : {
     815           0 :     if (m_bRemoved)
     816           0 :         throw deployment::ExtensionRemovedException();
     817             : 
     818           0 :     uno::Reference< graphic::XGraphic > xGraphic;
     819             : 
     820           0 :     OUString aIconURL = getDescriptionInfoset().getIconURL( bHighContrast );
     821           0 :     if ( !aIconURL.isEmpty() )
     822             :     {
     823           0 :         OUString aFullIconURL = m_url_expanded + "/" + aIconURL;
     824             : 
     825           0 :         uno::Reference< XComponentContext > xContext( getMyBackend()->getComponentContext() );
     826           0 :         uno::Reference< graphic::XGraphicProvider > xGraphProvider( graphic::GraphicProvider::create(xContext) );
     827             : 
     828           0 :             uno::Sequence< beans::PropertyValue > aMediaProps( 1 );
     829           0 :             aMediaProps[0].Name = "URL";
     830           0 :             aMediaProps[0].Value <<= aFullIconURL;
     831             : 
     832           0 :         xGraphic = xGraphProvider->queryGraphic( aMediaProps );
     833             :     }
     834             : 
     835           0 :     return xGraphic;
     836             : }
     837             : 
     838             : 
     839           2 : void BackendImpl::PackageImpl::processPackage_(
     840             :     ::osl::ResettableMutexGuard &,
     841             :     bool doRegisterPackage,
     842             :     bool startup,
     843             :     ::rtl::Reference<AbortChannel> const & abortChannel,
     844             :     Reference<ucb::XCommandEnvironment> const & xCmdEnv )
     845             : {
     846             :     const Sequence< Reference<deployment::XPackage> > bundle(
     847           2 :         getBundle( abortChannel.get(), xCmdEnv ) );
     848             : 
     849           2 :     if (doRegisterPackage)
     850             :     {
     851           1 :         ExtensionBackendDb::Data data;
     852           1 :         const sal_Int32 len = bundle.getLength();
     853           2 :         for ( sal_Int32 pos = 0; pos < len; ++pos )
     854             :         {
     855           1 :             checkAborted(abortChannel);
     856           1 :             Reference<deployment::XPackage> const & xPackage = bundle[ pos ];
     857             :             Reference<task::XAbortChannel> xSubAbortChannel(
     858           1 :                 xPackage->createAbortChannel() );
     859           2 :             AbortChannel::Chain chain( abortChannel, xSubAbortChannel );
     860             :             try {
     861           1 :                 xPackage->registerPackage( startup, xSubAbortChannel, xCmdEnv );
     862             :             }
     863           0 :             catch (const Exception &)
     864             :             {
     865             :                //We even try a rollback if the user cancelled the action (CommandAbortedException)
     866             :                 //in order to prevent invalid database entries.
     867           0 :                 Any exc( ::cppu::getCaughtException() );
     868             :                 // try to handle exception, notify:
     869           0 :                 bool approve = false, abort = false;
     870           0 :                 if (! interactContinuation(
     871             :                         Any( lang::WrappedTargetException(
     872             :                                  "bundle item registration error!",
     873             :                                  static_cast<OWeakObject *>(this), exc ) ),
     874           0 :                         cppu::UnoType<task::XInteractionApprove>::get(), xCmdEnv,
     875           0 :                         &approve, &abort )) {
     876             :                     OSL_ASSERT( !approve && !abort );
     877           0 :                     if (m_legacyBundle) // default for legacy packages: ignore
     878           0 :                         continue;
     879             :                     // no selection at all, so rethrow;
     880             :                     // no C++ rethrow after getCaughtException(),
     881             :                     // see cppuhelper/exc_hlp.hxx:
     882           0 :                     ::cppu::throwException(exc);
     883             :                 }
     884           0 :                 if (approve && !abort) // ignore error, just continue
     885           0 :                     continue;
     886             : 
     887             :                 {
     888           0 :                     ProgressLevel progress( xCmdEnv, "rollback..." );
     889             :                     // try rollback
     890           0 :                     for ( ; pos--; )
     891             :                     {
     892             :                         try {
     893           0 :                             bundle[ pos ]->revokePackage(
     894           0 :                                 startup, xSubAbortChannel, xCmdEnv );
     895             :                         }
     896           0 :                         catch (const Exception &)
     897             :                         {
     898             :                             OSL_FAIL( OUStringToOString(
     899             :                                             ::comphelper::anyToString(
     900             :                                                 ::cppu::getCaughtException() ),
     901             :                                             RTL_TEXTENCODING_UTF8 ).getStr() );
     902             :                             // ignore any errors of rollback
     903             :                         }
     904             :                     }
     905           0 :                     progress.update( "rollback finished." );
     906             :                 }
     907             : 
     908           0 :                 deployment::DeploymentException dpExc;
     909           0 :                 if (exc >>= dpExc) {
     910             :                     throw ucb::CommandFailedException(
     911           0 :                         dpExc.Message, dpExc.Context, dpExc.Cause );
     912             :                 }
     913             :                 else {
     914             :                     // rethrow CommandFailedException
     915           0 :                     ::cppu::throwException(exc);
     916           0 :                 }
     917           0 :             }
     918             :             data.items.push_back(
     919           1 :                 ::std::make_pair(xPackage->getURL(),
     920           2 :                                  xPackage->getPackageType()->getMediaType()));
     921           1 :         }
     922           1 :         getMyBackend()->addDataToDb(getURL(), data);
     923             :     }
     924             :     else
     925             :     {
     926             :         // revoke in reverse order:
     927           3 :         for ( sal_Int32 pos = bundle.getLength(); pos--; )
     928             :         {
     929           1 :             checkAborted(abortChannel);
     930           1 :             Reference<deployment::XPackage> const & xPackage = bundle[ pos ];
     931             :             Reference<task::XAbortChannel> xSubAbortChannel(
     932           1 :                 xPackage->createAbortChannel() );
     933           2 :             AbortChannel::Chain chain( abortChannel, xSubAbortChannel );
     934             :             try {
     935           1 :                 bundle[ pos ]->revokePackage(
     936           1 :                     startup, xSubAbortChannel, xCmdEnv );
     937             :             }
     938           0 :             catch (const RuntimeException &) {
     939           0 :                 throw;
     940             :             }
     941           0 :             catch (const ucb::CommandAbortedException &) {
     942           0 :                 throw;
     943             :             }
     944           0 :             catch (const Exception &) {
     945             :                 // CommandFailedException, DeploymentException:
     946           0 :                 Any exc( ::cppu::getCaughtException() );
     947             :                 // try to handle exception, notify:
     948           0 :                 bool approve = false, abort = false;
     949           0 :                 if (! interactContinuation(
     950             :                         Any( lang::WrappedTargetException(
     951             :                                  "bundle item revocation error!",
     952             :                                  static_cast<OWeakObject *>(this), exc ) ),
     953           0 :                         cppu::UnoType<task::XInteractionApprove>::get(), xCmdEnv,
     954           0 :                         &approve, &abort )) {
     955             :                     OSL_ASSERT( !approve && !abort );
     956           0 :                     if (m_legacyBundle) // default for legacy packages: ignore
     957           0 :                         continue;
     958             :                     // no selection at all, so rethrow
     959             :                     // no C++ rethrow after getCaughtException(),
     960             :                     // see cppuhelper/exc_hlp.hxx:
     961           0 :                     ::cppu::throwException(exc);
     962           0 :                 }
     963             :                 // ignore errors when revoking, although abort may have been
     964             :                 // selected
     965           0 :             }
     966           1 :         }
     967           1 :         getMyBackend()->revokeEntryFromDb(getURL());
     968           2 :     }
     969           2 : }
     970             : 
     971             : 
     972           0 : OUString BackendImpl::PackageImpl::getDescription()
     973             :     throw (deployment::ExtensionRemovedException, RuntimeException, std::exception)
     974             : {
     975           0 :     if (m_bRemoved)
     976           0 :         throw deployment::ExtensionRemovedException();
     977             : 
     978           0 :     const OUString sRelativeURL(getDescriptionInfoset().getLocalizedDescriptionURL());
     979           0 :     OUString sDescription;
     980           0 :     if (!sRelativeURL.isEmpty())
     981             :     {
     982           0 :         OUString sURL = m_url_expanded + "/" + sRelativeURL;
     983             : 
     984             :         try
     985             :         {
     986           0 :             sDescription = getTextFromURL( css::uno::Reference< css::ucb::XCommandEnvironment >(), sURL );
     987             :         }
     988           0 :         catch ( const css::deployment::DeploymentException& )
     989             :         {
     990             :             OSL_FAIL( OUStringToOString( ::comphelper::anyToString( ::cppu::getCaughtException() ), RTL_TEXTENCODING_UTF8 ).getStr() );
     991           0 :         }
     992             :     }
     993             : 
     994           0 :     if (!sDescription.isEmpty())
     995           0 :         return sDescription;
     996           0 :     return m_oldDescription;
     997             : }
     998             : 
     999             : 
    1000           0 : OUString BackendImpl::PackageImpl::getLicenseText()
    1001             :     throw (deployment::ExtensionRemovedException, RuntimeException, std::exception)
    1002             : {
    1003           0 :     if (m_bRemoved)
    1004           0 :         throw deployment::ExtensionRemovedException();
    1005             : 
    1006           0 :     OUString sLicense;
    1007           0 :     DescriptionInfoset aInfo = getDescriptionInfoset();
    1008             : 
    1009           0 :     ::boost::optional< SimpleLicenseAttributes > aSimplLicAttr = aInfo.getSimpleLicenseAttributes();
    1010           0 :     if ( aSimplLicAttr )
    1011             :     {
    1012           0 :         OUString aLicenseURL = aInfo.getLocalizedLicenseURL();
    1013             : 
    1014           0 :         if ( !aLicenseURL.isEmpty() )
    1015             :         {
    1016           0 :             OUString aFullURL = m_url_expanded + "/" + aLicenseURL;
    1017           0 :                sLicense = getTextFromURL( Reference< ucb::XCommandEnvironment >(), aFullURL);
    1018           0 :            }
    1019             :     }
    1020             : 
    1021           0 :      return sLicense;
    1022             : }
    1023             : 
    1024             : 
    1025           0 : void BackendImpl::PackageImpl::exportTo(
    1026             :     OUString const & destFolderURL, OUString const & newTitle,
    1027             :     sal_Int32 nameClashAction, Reference<ucb::XCommandEnvironment> const & xCmdEnv )
    1028             :     throw (ucb::CommandFailedException,
    1029             :            deployment::ExtensionRemovedException,
    1030             :            ucb::CommandAbortedException, RuntimeException, std::exception)
    1031             : {
    1032           0 :     if (m_bRemoved)
    1033           0 :         throw deployment::ExtensionRemovedException();
    1034             : 
    1035             :     ::ucbhelper::Content sourceContent(
    1036           0 :         m_url_expanded, xCmdEnv, getMyBackend()->getComponentContext() );
    1037           0 :     OUString title(newTitle);
    1038           0 :     if (title.isEmpty())
    1039           0 :         sourceContent.getPropertyValue( "Title" ) >>= title;
    1040             :     OUString destURL( makeURL( destFolderURL, ::rtl::Uri::encode(
    1041             :                                    title, rtl_UriCharClassPchar,
    1042             :                                    rtl_UriEncodeIgnoreEscapes,
    1043           0 :                                    RTL_TEXTENCODING_UTF8 ) ) );
    1044             : 
    1045           0 :     if (nameClashAction == ucb::NameClash::ASK)
    1046             :     {
    1047           0 :         if (create_ucb_content(
    1048             :                 0, destURL, xCmdEnv, false /* no throw */ )) {
    1049           0 :             bool replace = false, abort = false;
    1050           0 :             if (! interactContinuation(
    1051             :                     Any( ucb::NameClashResolveRequest(
    1052           0 :                              "file already exists: " + title,
    1053             :                              static_cast<OWeakObject *>(this),
    1054             :                              task::InteractionClassification_QUERY,
    1055             :                              destFolderURL, title, OUString() ) ),
    1056           0 :                     cppu::UnoType<ucb::XInteractionReplaceExistingData>::get(), xCmdEnv,
    1057           0 :                     &replace, &abort ) || !replace) {
    1058           0 :                 return;
    1059             :             }
    1060             :         }
    1061             :     }
    1062           0 :     else if (nameClashAction != ucb::NameClash::OVERWRITE) {
    1063             :         throw ucb::CommandFailedException("unsupported nameClashAction!",
    1064           0 :             static_cast<OWeakObject *>(this), Any() );
    1065             :     }
    1066           0 :     erase_path( destURL, xCmdEnv );
    1067             : 
    1068           0 :     OUStringBuffer buf;
    1069           0 :     buf.appendAscii( "vnd.sun.star.zip://" );
    1070             :     buf.append( ::rtl::Uri::encode( destURL,
    1071             :                                     rtl_UriCharClassRegName,
    1072             :                                     rtl_UriEncodeIgnoreEscapes,
    1073           0 :                                     RTL_TEXTENCODING_UTF8 ) );
    1074           0 :     buf.append( '/' );
    1075           0 :     OUString destFolder( buf.makeStringAndClear() );
    1076             : 
    1077             :     ::ucbhelper::Content destFolderContent(
    1078           0 :         destFolder, xCmdEnv, getMyBackend()->getComponentContext() );
    1079             :     {
    1080             :         // transfer every item of folder into zip:
    1081             :         Reference<sdbc::XResultSet> xResultSet(
    1082             :             sourceContent.createCursor(
    1083             :                 Sequence<OUString>(),
    1084           0 :                 ::ucbhelper::INCLUDE_FOLDERS_AND_DOCUMENTS ) );
    1085           0 :         ProgressLevel progress( xCmdEnv, OUString() );
    1086           0 :         while (xResultSet->next())
    1087             :         {
    1088             :             ::ucbhelper::Content subContent(
    1089             :                 Reference<ucb::XContentAccess>(
    1090           0 :                     xResultSet, UNO_QUERY_THROW )->queryContent(),
    1091           0 :                 xCmdEnv, getMyBackend()->getComponentContext() );
    1092           0 :             if (! destFolderContent.transferContent(
    1093             :                     subContent, ::ucbhelper::InsertOperation_COPY,
    1094           0 :                     OUString(), ucb::NameClash::OVERWRITE ))
    1095             :                 throw RuntimeException( "UCB transferContent() failed!",
    1096           0 :                                         static_cast<OWeakObject *>(this) );
    1097           0 :             progress.update( Any() ); // animating progress bar
    1098           0 :         }
    1099             :     }
    1100             : 
    1101             :     // assure META-INF folder:
    1102           0 :     ::ucbhelper::Content metainfFolderContent;
    1103             :     create_folder( &metainfFolderContent,
    1104           0 :                    makeURL( destFolderContent.getURL(), "META-INF" ),
    1105           0 :                    xCmdEnv );
    1106             : 
    1107           0 :     if (m_legacyBundle)
    1108             :     {
    1109             :         // easy to migrate legacy bundles to new format:
    1110             :         // just export them once using a .oxt name!
    1111             :         // set detected media-types of any bundle item:
    1112             : 
    1113             :         // collect all manifest entries:
    1114           0 :         Sequence< Reference<deployment::XPackage> > bundle;
    1115             :         try {
    1116           0 :             bundle = getBundle( Reference<task::XAbortChannel>(), xCmdEnv );
    1117             :         }
    1118             :         // xxx todo: think about exception specs:
    1119           0 :         catch (const deployment::DeploymentException &) {
    1120             :             OSL_FAIL( OUStringToOString(
    1121             :                             ::comphelper::anyToString(
    1122             :                                 ::cppu::getCaughtException() ),
    1123             :                             RTL_TEXTENCODING_UTF8 ).getStr() );
    1124             :         }
    1125           0 :         catch (const lang::IllegalArgumentException & exc) {
    1126             :             (void) exc;
    1127             :             OSL_FAIL( OUStringToOString(
    1128             :                             exc.Message, RTL_TEXTENCODING_UTF8 ).getStr() );
    1129             :         }
    1130             : 
    1131           0 :         ::std::vector< Sequence<beans::PropertyValue> > manifest;
    1132           0 :         manifest.reserve( bundle.getLength() );
    1133           0 :         sal_Int32 baseURLlen = m_url_expanded.getLength();
    1134           0 :         Reference<deployment::XPackage> const *pbundle = bundle.getConstArray();
    1135           0 :         const OUString strMediaType( "MediaType" );
    1136           0 :         const OUString strFullPath( "FullPath" );
    1137           0 :         const OUString strIsFolder( "IsFolder" );
    1138           0 :         for ( sal_Int32 pos = bundle.getLength(); pos--; )
    1139             :         {
    1140           0 :             Reference<deployment::XPackage> const & xPackage = pbundle[ pos ];
    1141           0 :             OUString url_( expandUnoRcUrl( xPackage->getURL() ) );
    1142             :             OSL_ASSERT( url_.getLength() >= baseURLlen );
    1143           0 :             OUString fullPath;
    1144           0 :             if (url_.getLength() > baseURLlen)
    1145           0 :                 fullPath = url_.copy( baseURLlen + 1 );
    1146             :             ::ucbhelper::Content ucbContent(
    1147           0 :                 url_, xCmdEnv, getMyBackend()->getComponentContext() );
    1148           0 :             if (ucbContent.getPropertyValue(strIsFolder).get<bool>())
    1149           0 :                 fullPath += "/";
    1150           0 :             Sequence<beans::PropertyValue> attribs( 2 );
    1151           0 :             beans::PropertyValue * pattribs = attribs.getArray();
    1152           0 :             pattribs[ 0 ].Name = strFullPath;
    1153           0 :             pattribs[ 0 ].Value <<= fullPath;
    1154           0 :             pattribs[ 1 ].Name = strMediaType;
    1155             :             const Reference<deployment::XPackageTypeInfo> xPackageType(
    1156           0 :                 xPackage->getPackageType() );
    1157           0 :             OUString mediaType;
    1158             :             OSL_ASSERT( xPackageType.is() );
    1159           0 :             if (xPackageType.is())
    1160           0 :                 mediaType = xPackageType->getMediaType();
    1161             :             else
    1162           0 :                 mediaType = "unknown";
    1163           0 :             pattribs[ 1 ].Value <<= mediaType;
    1164           0 :             manifest.push_back( attribs );
    1165           0 :         }
    1166             : 
    1167             :         // write into pipe:
    1168             :         Reference<XComponentContext> xContext(
    1169           0 :             getMyBackend()->getComponentContext() );
    1170             :         Reference<packages::manifest::XManifestWriter> xManifestWriter =
    1171           0 :             packages::manifest::ManifestWriter::create( xContext );
    1172           0 :         Reference<io::XOutputStream> xPipe( io::Pipe::create(xContext), UNO_QUERY_THROW );
    1173           0 :         xManifestWriter->writeManifestSequence(
    1174           0 :             xPipe, comphelper::containerToSequence(manifest) );
    1175             : 
    1176             :         // write buffered pipe data to content:
    1177             :         ::ucbhelper::Content manifestContent(
    1178           0 :             makeURL( metainfFolderContent.getURL(), "manifest.xml" ),
    1179           0 :             xCmdEnv, getMyBackend()->getComponentContext() );
    1180             :         manifestContent.writeStream(
    1181             :             Reference<io::XInputStream>( xPipe, UNO_QUERY_THROW ),
    1182           0 :             true /* replace existing */ );
    1183             :     }
    1184             :     else
    1185             :     {
    1186             :         // overwrite manifest.xml:
    1187           0 :         ::ucbhelper::Content manifestContent;
    1188           0 :         if ( ! create_ucb_content(
    1189             :             &manifestContent,
    1190             :             makeURL( m_url_expanded, "META-INF/manifest.xml" ),
    1191           0 :             xCmdEnv, false ) )
    1192             :         {
    1193             :             OSL_FAIL( "### missing META-INF/manifest.xml file!" );
    1194           0 :             return;
    1195             :         }
    1196             : 
    1197           0 :         if (! metainfFolderContent.transferContent(
    1198             :                 manifestContent, ::ucbhelper::InsertOperation_COPY,
    1199           0 :                 OUString(), ucb::NameClash::OVERWRITE ))
    1200             :             throw RuntimeException( "UCB transferContent() failed!",
    1201           0 :                                     static_cast<OWeakObject *>(this) );
    1202             :     }
    1203             : 
    1204             :     // xxx todo: maybe obsolete in the future
    1205             :     try {
    1206           0 :         destFolderContent.executeCommand( "flush", Any() );
    1207             :     }
    1208           0 :     catch (const ucb::UnsupportedCommandException &) {
    1209           0 :     }
    1210             : }
    1211             : 
    1212             : 
    1213           0 : sal_Bool BackendImpl::PackageImpl::isBundle() throw (RuntimeException, std::exception)
    1214             : {
    1215           0 :     return true;
    1216             : }
    1217             : 
    1218             : 
    1219           6 : Sequence< Reference<deployment::XPackage> > BackendImpl::PackageImpl::getBundle(
    1220             :     Reference<task::XAbortChannel> const & xAbortChannel,
    1221             :     Reference<ucb::XCommandEnvironment> const & xCmdEnv )
    1222             :     throw (deployment::DeploymentException,
    1223             :            ucb::CommandFailedException, ucb::CommandAbortedException,
    1224             :            lang::IllegalArgumentException, RuntimeException, std::exception)
    1225             : {
    1226           6 :     Sequence< Reference<deployment::XPackage> > * pBundle = m_pBundle;
    1227           6 :     if (pBundle == 0)
    1228             :     {
    1229           1 :         t_packagevec bundle;
    1230           1 :         if (m_bRemoved)
    1231             :         {
    1232           0 :             bundle = getPackagesFromDb(xCmdEnv);
    1233             :         }
    1234             :         else
    1235             :         {
    1236             :             try {
    1237           1 :                 if (m_legacyBundle)
    1238             :                 {
    1239             :                     // .zip legacy packages allow script.xlb, dialog.xlb in bundle
    1240             :                     // root folder:
    1241           0 :                     OUString mediaType;
    1242             :                     // probe for script.xlb:
    1243           0 :                     if (create_ucb_content(
    1244             :                             0, makeURL( m_url_expanded, "script.xlb" ),
    1245           0 :                             xCmdEnv, false /* no throw */ )) {
    1246           0 :                         mediaType = "application/vnd.sun.star.basic-library";
    1247             :                     }
    1248             :                     // probe for dialog.xlb:
    1249           0 :                     else if (create_ucb_content(
    1250             :                                  0, makeURL( m_url_expanded, "dialog.xlb" ),
    1251           0 :                                  xCmdEnv, false /* no throw */ ))
    1252           0 :                         mediaType = "application/vnd.sun.star.dialog-library";
    1253             : 
    1254           0 :                     if (!mediaType.isEmpty()) {
    1255             :                         const Reference<deployment::XPackage> xPackage(
    1256           0 :                             bindBundleItem( getURL(), mediaType, false, OUString(),
    1257           0 :                                             xCmdEnv ) );
    1258           0 :                         if (xPackage.is())
    1259           0 :                             bundle.push_back( xPackage );
    1260             :                         // continue scanning:
    1261             :                     }
    1262           0 :                     scanLegacyBundle( bundle, getURL(),
    1263           0 :                                       AbortChannel::get(xAbortChannel), xCmdEnv );
    1264             :                 }
    1265             :                 else
    1266             :                 {
    1267             :                     // .oxt:
    1268           1 :                     scanBundle( bundle, AbortChannel::get(xAbortChannel), xCmdEnv );
    1269             :                 }
    1270             : 
    1271             :             }
    1272           0 :             catch (const RuntimeException &) {
    1273           0 :                 throw;
    1274             :             }
    1275           0 :             catch (const ucb::CommandFailedException &) {
    1276           0 :                 throw;
    1277             :             }
    1278           0 :             catch (const ucb::CommandAbortedException &) {
    1279           0 :                 throw;
    1280             :             }
    1281           0 :             catch (const deployment::DeploymentException &) {
    1282           0 :                 throw;
    1283             :             }
    1284           0 :             catch (const Exception &) {
    1285           0 :                 Any exc( ::cppu::getCaughtException() );
    1286             :                 throw deployment::DeploymentException(
    1287           0 :                     "error scanning bundle: " + getURL(),
    1288           0 :                     static_cast<OWeakObject *>(this), exc );
    1289             :             }
    1290             :         }
    1291             : 
    1292             :         // sort: schema before config data, typelibs before components:
    1293           2 :         Sequence< Reference<deployment::XPackage> > ret( bundle.size() );
    1294           1 :         Reference<deployment::XPackage> * pret = ret.getArray();
    1295           1 :         sal_Int32 lower_end = 0;
    1296           1 :         sal_Int32 upper_end = ret.getLength();
    1297           1 :         t_packagevec::const_iterator iPos( bundle.begin() );
    1298           1 :         t_packagevec::const_iterator const iEnd( bundle.end() );
    1299           2 :         for ( ; iPos != iEnd; ++iPos )
    1300             :         {
    1301             :             const Reference<deployment::XPackageTypeInfo> xPackageType(
    1302           1 :                 (*iPos)->getPackageType() );
    1303             :             OSL_ASSERT( xPackageType.is() );
    1304           1 :             if (xPackageType.is())
    1305             :             {
    1306           1 :                 const OUString mediaType( xPackageType->getMediaType() );
    1307           1 :                 OUString type, subType;
    1308           1 :                 INetContentTypeParameterList params;
    1309           3 :                 if (INetContentTypes::parse( mediaType, type, subType, &params ) &&
    1310           3 :                     type.equalsIgnoreAsciiCase("application") &&
    1311           1 :                     (subType.equalsIgnoreAsciiCase( "vnd.sun.star.uno-component") ||
    1312           0 :                      subType.equalsIgnoreAsciiCase( "vnd.sun.star.configuration-data")))
    1313             :                 {
    1314           1 :                     --upper_end;
    1315           1 :                     pret[ upper_end ] = *iPos;
    1316           1 :                     continue;
    1317           0 :                 }
    1318             :             }
    1319           0 :             pret[ lower_end ] = *iPos;
    1320           0 :             ++lower_end;
    1321           0 :         }
    1322             :         OSL_ASSERT( lower_end == upper_end );
    1323             : 
    1324           2 :         const ::osl::MutexGuard guard( getMutex() );
    1325           1 :         pBundle = m_pBundle;
    1326           1 :         if (pBundle == 0) {
    1327           1 :             m_bundle = ret;
    1328           1 :             pBundle = &m_bundle;
    1329             :             OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
    1330           1 :             m_pBundle = pBundle;
    1331           1 :         }
    1332             :     }
    1333             :     else {
    1334             :         OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
    1335             :     }
    1336           6 :     return *pBundle;
    1337             : }
    1338             : 
    1339           2 : inline bool isBundle_( OUString const & mediaType )
    1340             : {
    1341             :     // xxx todo: additional parsing?
    1342           4 :     return !mediaType.isEmpty() &&
    1343           4 :         (mediaType.matchIgnoreAsciiCase( "application/vnd.sun.star.package-bundle") ||
    1344           4 :          mediaType.matchIgnoreAsciiCase( "application/vnd.sun.star.legacy-package-bundle"));
    1345             : }
    1346             : 
    1347             : 
    1348           1 : Reference<deployment::XPackage> BackendImpl::PackageImpl::bindBundleItem(
    1349             :     OUString const & url, OUString const & mediaType,
    1350             :     sal_Bool bRemoved, OUString const & identifier,
    1351             :     Reference<ucb::XCommandEnvironment> const & xCmdEnv,
    1352             :     bool notifyDetectionError )
    1353             : {
    1354             :     // ignore any nested bundles:
    1355           1 :     if (isBundle_(mediaType))
    1356           0 :         return Reference<deployment::XPackage>();
    1357             : 
    1358           1 :     Reference<deployment::XPackage>xPackage;
    1359             :     try {
    1360             :         try {
    1361           1 :             xPackage.set( getMyBackend()->m_xRootRegistry->bindPackage(
    1362           1 :                               url, mediaType, bRemoved, identifier, xCmdEnv ) );
    1363             :             OSL_ASSERT( xPackage.is() );
    1364           0 :         } catch (css::lang::IllegalArgumentException & e) {
    1365           0 :             css::uno::Any exc(cppu::getCaughtException());
    1366             :             throw css::lang::WrappedTargetException(
    1367           0 :                 "wrapped: " + e.Message, e.Context, exc);
    1368             :         }
    1369             :     }
    1370           0 :     catch (const RuntimeException &) {
    1371           0 :         throw;
    1372             :     }
    1373           0 :     catch (const ucb::CommandFailedException &) {
    1374             :         // ignore already handled error
    1375             :     }
    1376           0 :     catch (const Exception &) {
    1377           0 :         const Any exc( ::cppu::getCaughtException() );
    1378           0 :         if (notifyDetectionError ||
    1379             :             !exc.isExtractableTo(
    1380             :                 ::getCppuType( reinterpret_cast<
    1381           0 :                                lang::IllegalArgumentException const *>(0) ) ))
    1382             :         {
    1383             :             interactContinuation(
    1384             :                 Any( lang::WrappedTargetException("bundle item error!",
    1385             :                          static_cast<OWeakObject *>(this), exc ) ),
    1386           0 :                 cppu::UnoType<task::XInteractionApprove>::get(), xCmdEnv, 0, 0 );
    1387           0 :         }
    1388             :     }
    1389             : 
    1390           1 :     if (xPackage.is()) {
    1391             :         const Reference<deployment::XPackageTypeInfo> xPackageType(
    1392           1 :             xPackage->getPackageType() );
    1393             :         OSL_ASSERT( xPackageType.is() );
    1394             :         // ignore any nested bundles:
    1395           1 :         if (xPackageType.is() && isBundle_( xPackageType->getMediaType() ))
    1396           0 :             xPackage.clear();
    1397             :     }
    1398           1 :     return xPackage;
    1399             : }
    1400             : 
    1401             : 
    1402           1 : void BackendImpl::PackageImpl::scanBundle(
    1403             :     t_packagevec & bundle,
    1404             :     ::rtl::Reference<AbortChannel> const & abortChannel,
    1405             :     Reference<ucb::XCommandEnvironment> const & xCmdEnv )
    1406             : {
    1407             :     OSL_ASSERT( !m_legacyBundle );
    1408             : 
    1409           1 :     OUString mfUrl( makeURL( m_url_expanded, "META-INF/manifest.xml" ) );
    1410           2 :     ::ucbhelper::Content manifestContent;
    1411           1 :     if (! create_ucb_content(
    1412           1 :             &manifestContent, mfUrl, xCmdEnv, false /* no throw */ ))
    1413             :     {
    1414             :         SAL_WARN(
    1415             :             "desktop.deployment",
    1416             :             "cannot create UCB Content for <" << mfUrl << ">" );
    1417           1 :         return;
    1418             :     }
    1419             : 
    1420             : 
    1421           1 :     const LanguageTag& officeLocale = getOfficeLanguageTag();
    1422           2 :     const ::std::vector< OUString > officeFallbacks( officeLocale.getFallbackStrings( true));
    1423           1 :     const size_t nPenaltyMax = ::std::numeric_limits<size_t>::max();
    1424           1 :     size_t descrPenalty = nPenaltyMax;
    1425           2 :     OUString descrFile;
    1426             : 
    1427             :     const Reference<XComponentContext> xContext(
    1428           2 :         getMyBackend()->getComponentContext() );
    1429             :     Reference<packages::manifest::XManifestReader> xManifestReader =
    1430           2 :         packages::manifest::ManifestReader::create( xContext );
    1431             :     const Sequence< Sequence<beans::PropertyValue> > manifestSeq(
    1432           2 :         xManifestReader->readManifestSequence( manifestContent.openStream() ) );
    1433           2 :     const OUString packageRootURL( getURL() );
    1434           3 :     for ( sal_Int32 pos = manifestSeq.getLength(); pos--; )
    1435             :     {
    1436           2 :         OUString fullPath, mediaType;
    1437           1 :         Sequence<beans::PropertyValue> const & attribs = manifestSeq[ pos ];
    1438           4 :         for ( sal_Int32 i = attribs.getLength(); i--; )
    1439             :         {
    1440           2 :             if (!(fullPath.isEmpty() || mediaType.isEmpty()))
    1441           0 :                 break;
    1442           2 :             if ( attribs[i].Name == "FullPath" )
    1443           1 :                 attribs[i].Value >>= fullPath;
    1444           1 :             else if ( attribs[i].Name == "MediaType" )
    1445           1 :                 attribs[i].Value >>= mediaType;
    1446             :         }
    1447             : 
    1448           1 :         if ( fullPath.isEmpty() || mediaType.isEmpty() || mediaType == "text/xml" )// opt: exclude common text/xml
    1449           0 :             continue;
    1450             : 
    1451           2 :         OUString type, subType;
    1452           2 :         INetContentTypeParameterList params;
    1453           1 :         if (! INetContentTypes::parse( mediaType, type, subType, &params ))
    1454           0 :             continue;
    1455             : 
    1456           1 :         INetContentTypeParameter const * param = params.find("platform");
    1457           1 :         if (param != 0 && !platform_fits( param->m_sValue ))
    1458           0 :             continue;
    1459           2 :         const OUString url( makeURL( packageRootURL, fullPath ) );
    1460             : 
    1461             :         // check for bundle description:
    1462           2 :         if (type.equalsIgnoreAsciiCase("application") &&
    1463           1 :             subType.equalsIgnoreAsciiCase( "vnd.sun.star.package-bundle-description"))
    1464             :         {
    1465             :             // check locale:
    1466           0 :             param = params.find("locale");
    1467           0 :             if (param == 0) {
    1468           0 :                 if (descrFile.isEmpty())
    1469           0 :                     descrFile = url;
    1470             :             }
    1471             :             else {
    1472             :                 // match best locale:
    1473           0 :                 LanguageTag descrTag( param->m_sValue);
    1474           0 :                 if (officeLocale.getLanguage() == descrTag.getLanguage())
    1475             :                 {
    1476           0 :                     size_t nPenalty = nPenaltyMax;
    1477           0 :                     const ::std::vector< OUString > descrFallbacks( descrTag.getFallbackStrings( true));
    1478           0 :                     for (size_t o=0; o < officeFallbacks.size() && nPenalty == nPenaltyMax; ++o)
    1479             :                     {
    1480           0 :                         for (size_t d=0; d < descrFallbacks.size() && nPenalty == nPenaltyMax; ++d)
    1481             :                         {
    1482           0 :                             if (officeFallbacks[o] == descrFallbacks[d])
    1483             :                             {
    1484             :                                 // The last fallbacks are always language-only
    1485             :                                 // fallbacks, so we _will_ have _some_ match if
    1486             :                                 // we ever entered the overall if() condition.
    1487           0 :                                 nPenalty = o * 1000 + d;
    1488           0 :                                 if (descrPenalty > nPenalty)
    1489             :                                 {
    1490           0 :                                     descrPenalty = nPenalty;
    1491           0 :                                     descrFile = url;
    1492             :                                 }
    1493             :                             }
    1494             :                         }
    1495           0 :                     }
    1496           0 :                 }
    1497             :                 // TODO: we could break here if descrPenalty==0 for an exact
    1498             :                 // match of officeLocale, but the previous code didn't; are
    1499             :                 // there side effects?
    1500             :             }
    1501           0 :             continue;
    1502             :         }
    1503             : 
    1504           1 :         checkAborted( abortChannel );
    1505             : 
    1506             :         //We make sure that we only create one XPackage for a particular URL.
    1507             :         //Sometime programmers insert the same URL several times in the manifest
    1508             :         //which may lead to DisposedExceptions.
    1509           1 :         if (bundle.end() == std::find_if(bundle.begin(), bundle.end(), XPackage_eq(url)))
    1510             :         {
    1511             :             const Reference<deployment::XPackage> xPackage(
    1512           1 :                 bindBundleItem( url, mediaType, false, OUString(), xCmdEnv ) );
    1513           1 :             if (xPackage.is())
    1514           1 :                 bundle.push_back( xPackage );
    1515             :         }
    1516             :         else
    1517             :         {
    1518           0 :             fprintf(stderr, "manifest.xml contains a duplicate entry!\n");
    1519             :         }
    1520           1 :     }
    1521             : 
    1522           1 :     if (!descrFile.isEmpty())
    1523             :     {
    1524           0 :         ::ucbhelper::Content descrFileContent;
    1525           0 :         if (create_ucb_content( &descrFileContent, descrFile,
    1526             :                                 xCmdEnv, false /* no throw */ ))
    1527             :         {
    1528             :             // patch description:
    1529           0 :             ::rtl::ByteSequence bytes( readFile( descrFileContent ) );
    1530           0 :             OUStringBuffer buf;
    1531           0 :             if ( bytes.getLength() )
    1532             :             {
    1533             :                 buf.append( OUString( reinterpret_cast<sal_Char const *>(
    1534           0 :                                           bytes.getConstArray() ),
    1535           0 :                                       bytes.getLength(), RTL_TEXTENCODING_UTF8 ) );
    1536             :             }
    1537             :             else
    1538             :             {
    1539           0 :                 buf.append( Package::getDescription() );
    1540             :             }
    1541           0 :             m_oldDescription = buf.makeStringAndClear();
    1542           0 :         }
    1543           1 :     }
    1544             : }
    1545             : 
    1546             : 
    1547           0 : void BackendImpl::PackageImpl::scanLegacyBundle(
    1548             :     t_packagevec & bundle,
    1549             :     OUString const & url,
    1550             :     ::rtl::Reference<AbortChannel> const & abortChannel,
    1551             :     Reference<ucb::XCommandEnvironment> const & xCmdEnv,
    1552             :     bool skip_registration )
    1553             : {
    1554             :     ::ucbhelper::Content ucbContent(
    1555           0 :         url, xCmdEnv, getMyBackend()->getComponentContext() );
    1556             : 
    1557             :     // check for platform paths:
    1558           0 :     const OUString title( StrTitle::getTitle( ucbContent ) );
    1559           0 :     if (title.endsWithIgnoreAsciiCase( ".plt" ) &&
    1560           0 :         !platform_fits( title.copy( 0, title.getLength() - 4 ) )) {
    1561           0 :         return;
    1562             :     }
    1563           0 :     if (title.endsWithIgnoreAsciiCase("skip_registration") )
    1564           0 :         skip_registration = true;
    1565             : 
    1566           0 :     OUString ar [] = { OUString("Title"), OUString("IsFolder") };
    1567             :     Reference<sdbc::XResultSet> xResultSet(
    1568             :         ucbContent.createCursor(
    1569           0 :             Sequence<OUString>( ar, ARLEN(ar) ),
    1570           0 :             ::ucbhelper::INCLUDE_FOLDERS_AND_DOCUMENTS ) );
    1571           0 :     while (xResultSet->next())
    1572             :     {
    1573           0 :         checkAborted( abortChannel );
    1574             : 
    1575           0 :         const Reference<sdbc::XRow> xRow( xResultSet, UNO_QUERY_THROW );
    1576             :         const OUString title_enc( ::rtl::Uri::encode(
    1577           0 :                                       xRow->getString( 1 /* Title */ ),
    1578             :                                       rtl_UriCharClassPchar,
    1579             :                                       rtl_UriEncodeIgnoreEscapes,
    1580           0 :                                       RTL_TEXTENCODING_UTF8 ) );
    1581           0 :         const OUString path( makeURL( url, title_enc ) );
    1582             : 
    1583           0 :         OUString mediaType;
    1584             :         const Reference<deployment::XPackage> xPackage(
    1585             :             bindBundleItem( path, OUString() /* detect */, false, OUString(),
    1586           0 :                             xCmdEnv, false /* ignore detection errors */ ) );
    1587           0 :         if (xPackage.is()) {
    1588             :             const Reference<deployment::XPackageTypeInfo> xPackageType(
    1589           0 :                 xPackage->getPackageType() );
    1590             :             OSL_ASSERT( xPackageType.is() );
    1591           0 :             if (xPackageType.is())
    1592           0 :                 mediaType = xPackageType->getMediaType();
    1593             : 
    1594           0 :             if (skip_registration &&
    1595             :                 // xxx todo: additional parsing?
    1596           0 :                 mediaType.matchIgnoreAsciiCase("application/vnd.sun.star.uno-component"))
    1597           0 :                 continue;
    1598             : 
    1599           0 :             bundle.push_back( xPackage );
    1600             :         }
    1601             : 
    1602           0 :         if (mediaType.isEmpty() ||
    1603             :             // script.xlb, dialog.xlb can be met everywhere:
    1604           0 :             mediaType.matchIgnoreAsciiCase("application/vnd.sun.star.basic-library") ||
    1605           0 :             mediaType.matchIgnoreAsciiCase("application/vnd.sun.star.dialog-library"))
    1606             :         {
    1607           0 :             if (xRow->getBoolean( 2 /* IsFolder */ )) { // recurse into folder:
    1608             :                 scanLegacyBundle(
    1609           0 :                     bundle, path, abortChannel, xCmdEnv, skip_registration );
    1610             :             }
    1611             :         }
    1612           0 :     }
    1613             : }
    1614             : 
    1615           3 : OUString BackendImpl::PackageImpl::getDisplayName()
    1616             :     throw (deployment::ExtensionRemovedException, RuntimeException, std::exception)
    1617             : {
    1618           3 :     if (m_bRemoved)
    1619           0 :         throw deployment::ExtensionRemovedException();
    1620             : 
    1621           3 :     OUString sName = getDescriptionInfoset().getLocalizedDisplayName();
    1622           3 :     if (sName.isEmpty())
    1623           3 :         return m_displayName;
    1624             :     else
    1625           0 :         return sName;
    1626             : }
    1627             : 
    1628             : ::std::vector<Reference<deployment::XPackage> >
    1629           0 : BackendImpl::PackageImpl::getPackagesFromDb(
    1630             :     Reference<ucb::XCommandEnvironment> const & xCmdEnv)
    1631             : {
    1632           0 :     ::std::vector<Reference<deployment::XPackage> > retVector;
    1633             : 
    1634             :     typedef ::std::vector< ::std::pair<OUString, OUString> >::const_iterator ITC;
    1635           0 :     for (ITC i = m_dbData.items.begin(); i != m_dbData.items.end(); ++i)
    1636             :     {
    1637             :         Reference<deployment::XPackage> xExtension =
    1638           0 :             bindBundleItem(i->first, i->second, true, m_identifier, xCmdEnv);
    1639             :         OSL_ASSERT(xExtension.is());
    1640           0 :         if (xExtension.is())
    1641           0 :             retVector.push_back(xExtension);
    1642           0 :     }
    1643             : 
    1644           0 :     return retVector;
    1645             : }
    1646             : 
    1647             : } // anon namespace
    1648             : 
    1649             : 
    1650         245 : Reference<deployment::XPackageRegistry> create(
    1651             :     Reference<deployment::XPackageRegistry> const & xRootRegistry,
    1652             :     OUString const & context, OUString const & cachePath, bool readOnly,
    1653             :     Reference<XComponentContext> const & xComponentContext )
    1654             : {
    1655         245 :     Sequence<Any> args(cachePath.isEmpty() ? 1 : 3 );
    1656         245 :     args[ 0 ] <<= context;
    1657         245 :     if (!cachePath.isEmpty()) {
    1658         245 :         args[ 1 ] <<= cachePath;
    1659         245 :         args[ 2 ] <<= readOnly;
    1660             :     }
    1661         245 :     return new BackendImpl( args, xComponentContext, xRootRegistry );
    1662             : }
    1663             : 
    1664             : } // namespace bundle
    1665             : } // namespace backend
    1666             : } // namespace dp_registry
    1667             : 
    1668             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10