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

Generated by: LCOV version 1.11