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

Generated by: LCOV version 1.10