LCOV - code coverage report
Current view: top level - usr/local/src/libreoffice/desktop/source/deployment/registry/package - dp_package.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 276 654 42.2 %
Date: 2013-07-09 Functions: 36 48 75.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10