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