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