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 : : //TODO: Large parts of this file were copied from dp_component.cxx; those parts
31 : : // should be consolidated.
32 : :
33 : : #include "dp_configuration.hrc"
34 : : #include "dp_backend.h"
35 : : #if !defined(ANDROID) && !defined(IOS)
36 : : #include "dp_persmap.h"
37 : : #endif
38 : : #include "dp_ucb.h"
39 : : #include "rtl/string.hxx"
40 : : #include "rtl/ustrbuf.hxx"
41 : : #include "rtl/uri.hxx"
42 : : #include "rtl/memory.h"
43 : : #include "osl/file.hxx"
44 : : #include "cppuhelper/exc_hlp.hxx"
45 : : #include "ucbhelper/content.hxx"
46 : : #include "unotools/ucbhelper.hxx"
47 : : #include "comphelper/anytostring.hxx"
48 : : #include "comphelper/servicedecl.hxx"
49 : : #include "xmlscript/xml_helper.hxx"
50 : : #include "svl/inettype.hxx"
51 : : #include "com/sun/star/configuration/Update.hpp"
52 : : #include "com/sun/star/ucb/NameClash.hpp"
53 : : #include "com/sun/star/io/XActiveDataSink.hpp"
54 : : #include "com/sun/star/lang/WrappedTargetRuntimeException.hpp"
55 : : #include "com/sun/star/util/XRefreshable.hpp"
56 : : #include <list>
57 : : #include <memory>
58 : :
59 : : #include "dp_configurationbackenddb.hxx"
60 : :
61 : : using namespace ::dp_misc;
62 : : using namespace ::com::sun::star;
63 : : using namespace ::com::sun::star::uno;
64 : : using namespace ::com::sun::star::ucb;
65 : : using ::rtl::OUString;
66 : :
67 : : namespace dp_registry {
68 : : namespace backend {
69 : : namespace configuration {
70 : : namespace {
71 : :
72 : : typedef ::std::list<OUString> t_stringlist;
73 : :
74 : : //==============================================================================
75 [ + - ][ + - ]: 380 : class BackendImpl : public ::dp_registry::backend::PackageRegistryBackend
[ + - ][ - + ]
76 : : {
77 [ - + ]: 7688 : class PackageImpl : public ::dp_registry::backend::Package
78 : : {
79 : : BackendImpl * getMyBackend() const ;
80 : :
81 : : const bool m_isSchema;
82 : :
83 : : // Package
84 : : virtual beans::Optional< beans::Ambiguous<sal_Bool> > isRegistered_(
85 : : ::osl::ResettableMutexGuard & guard,
86 : : ::rtl::Reference<AbortChannel> const & abortChannel,
87 : : Reference<XCommandEnvironment> const & xCmdEnv );
88 : : virtual void processPackage_(
89 : : ::osl::ResettableMutexGuard & guard,
90 : : bool registerPackage,
91 : : bool startup,
92 : : ::rtl::Reference<AbortChannel> const & abortChannel,
93 : : Reference<XCommandEnvironment> const & xCmdEnv );
94 : :
95 : : public:
96 : 3844 : inline PackageImpl(
97 : : ::rtl::Reference<PackageRegistryBackend> const & myBackend,
98 : : OUString const & url, OUString const & name,
99 : : Reference<deployment::XPackageTypeInfo> const & xPackageType,
100 : : bool isSchema, bool bRemoved, OUString const & identifier)
101 : : : Package( myBackend, url, name, name /* display-name */,
102 : : xPackageType, bRemoved, identifier),
103 : 3844 : m_isSchema( isSchema )
104 : 3844 : {}
105 : : };
106 : : friend class PackageImpl;
107 : :
108 : : t_stringlist m_xcs_files;
109 : : t_stringlist m_xcu_files;
110 : 1922 : t_stringlist & getFiles( bool xcs ) {
111 [ + + ]: 1922 : return xcs ? m_xcs_files : m_xcu_files;
112 : : }
113 : :
114 : : bool m_configmgrini_inited;
115 : : bool m_configmgrini_modified;
116 : : std::auto_ptr<ConfigurationBackendDb> m_backendDb;
117 : :
118 : : // PackageRegistryBackend
119 : : virtual Reference<deployment::XPackage> bindPackage_(
120 : : OUString const & url, OUString const & mediaType, sal_Bool bRemoved,
121 : : OUString const & identifier,
122 : : Reference<XCommandEnvironment> const & xCmdEnv );
123 : : #if !defined(ANDROID) && !defined(IOS)
124 : : // for backwards compatibility - nil if no (compatible) back-compat db present
125 : : ::std::auto_ptr<PersistentMap> m_registeredPackages;
126 : : #endif
127 : : virtual void SAL_CALL disposing();
128 : :
129 : : const Reference<deployment::XPackageTypeInfo> m_xConfDataTypeInfo;
130 : : const Reference<deployment::XPackageTypeInfo> m_xConfSchemaTypeInfo;
131 : : Sequence< Reference<deployment::XPackageTypeInfo> > m_typeInfos;
132 : :
133 : : void configmgrini_verify_init(
134 : : Reference<XCommandEnvironment> const & xCmdEnv );
135 : : void configmgrini_flush( Reference<XCommandEnvironment> const & xCmdEnv );
136 : :
137 : : /* The paramter isURL is false in the case of adding the conf:ini-entry
138 : : value from the backend db. This entry already contains the path as it
139 : : is used in the configmgr.ini.
140 : : */
141 : : bool addToConfigmgrIni( bool isSchema, bool isURL, OUString const & url,
142 : : Reference<XCommandEnvironment> const & xCmdEnv );
143 : : bool removeFromConfigmgrIni( bool isSchema, OUString const & url,
144 : : Reference<XCommandEnvironment> const & xCmdEnv );
145 : :
146 : : void addDataToDb(OUString const & url, ConfigurationBackendDb::Data const & data);
147 : : ::boost::optional<ConfigurationBackendDb::Data> readDataFromDb(OUString const & url);
148 : : void revokeEntryFromDb(OUString const & url);
149 : : bool hasActiveEntry(OUString const & url);
150 : : bool activateEntry(OUString const & url);
151 : :
152 : : public:
153 : : BackendImpl( Sequence<Any> const & args,
154 : : Reference<XComponentContext> const & xComponentContext );
155 : :
156 : : // XPackageRegistry
157 : : virtual Sequence< Reference<deployment::XPackageTypeInfo> > SAL_CALL
158 : : getSupportedPackageTypes() throw (RuntimeException);
159 : : virtual void SAL_CALL packageRemoved(OUString const & url, OUString const & mediaType)
160 : : throw (deployment::DeploymentException,
161 : : uno::RuntimeException);
162 : :
163 : : using PackageRegistryBackend::disposing;
164 : : };
165 : :
166 : : //______________________________________________________________________________
167 : 380 : void BackendImpl::disposing()
168 : : {
169 : : try {
170 [ + - ]: 380 : configmgrini_flush( Reference<XCommandEnvironment>() );
171 : :
172 [ + - ]: 380 : PackageRegistryBackend::disposing();
173 : : }
174 : 0 : catch (const RuntimeException &) {
175 : 0 : throw;
176 : : }
177 [ # # # ]: 0 : catch (const Exception &) {
178 [ # # ]: 0 : Any exc( ::cppu::getCaughtException() );
179 : : throw lang::WrappedTargetRuntimeException(
180 : : OUSTR("caught unexpected exception while disposing..."),
181 [ # # # # : 0 : static_cast<OWeakObject *>(this), exc );
# # ]
182 : : }
183 : 380 : }
184 : :
185 : : //______________________________________________________________________________
186 : 380 : BackendImpl::BackendImpl(
187 : : Sequence<Any> const & args,
188 : : Reference<XComponentContext> const & xComponentContext )
189 : : : PackageRegistryBackend( args, xComponentContext ),
190 : : m_configmgrini_inited( false ),
191 : : m_configmgrini_modified( false ),
192 : : m_xConfDataTypeInfo( new Package::TypeInfo(
193 : : OUSTR("application/"
194 : : "vnd.sun.star.configuration-data"),
195 : : OUSTR("*.xcu"),
196 : : getResourceString(RID_STR_CONF_DATA),
197 [ + - ]: 380 : RID_IMG_CONF_XML ) ),
198 : : m_xConfSchemaTypeInfo( new Package::TypeInfo(
199 : : OUSTR("application/"
200 : : "vnd.sun.star.configuration-schema"),
201 : : OUSTR("*.xcs"),
202 : : getResourceString(RID_STR_CONF_SCHEMA),
203 [ + - ]: 380 : RID_IMG_CONF_XML ) ),
204 [ + - ][ + - ]: 1140 : m_typeInfos( 2 )
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
205 : : {
206 [ + - ][ + - ]: 380 : m_typeInfos[ 0 ] = m_xConfDataTypeInfo;
207 [ + - ][ + - ]: 380 : m_typeInfos[ 1 ] = m_xConfSchemaTypeInfo;
208 : :
209 : 380 : const Reference<XCommandEnvironment> xCmdEnv;
210 : :
211 [ + - ]: 380 : if (transientMode())
212 : : {
213 : : // TODO
214 : : }
215 : : else
216 : : {
217 [ + - ][ + - ]: 380 : OUString dbFile = makeURL(getCachePath(), OUSTR("backenddb.xml"));
218 : : m_backendDb.reset(
219 [ + - ][ + - ]: 380 : new ConfigurationBackendDb(getComponentContext(), dbFile));
220 : : //clean up data folders which are no longer used.
221 : : //This must not be done in the same process where the help files
222 : : //are still registers. Only after revoking and restarting OOo the folders
223 : : //can be removed. This works now, because the extension manager is a singleton
224 : : //and the backends are only create once per process.
225 [ + - ]: 380 : ::std::list<OUString> folders = m_backendDb->getAllDataUrls();
226 [ + - ]: 380 : deleteUnusedFolders(OUString(), folders);
227 : :
228 [ + - ]: 380 : configmgrini_verify_init( xCmdEnv );
229 : :
230 : : #if !defined(ANDROID) && !defined(IOS)
231 : : SAL_WNODEPRECATED_DECLARATIONS_PUSH
232 : 380 : ::std::auto_ptr<PersistentMap> pMap;
233 : : SAL_WNODEPRECATED_DECLARATIONS_POP
234 [ + - ][ + - ]: 380 : rtl::OUString aCompatURL( makeURL( getCachePath(), OUSTR("registered_packages.db") ) );
235 : :
236 : : // Don't create it if it doesn't exist already
237 [ + - ][ - + ]: 380 : if ( ::utl::UCBContentHelper::Exists( expandUnoRcUrl( aCompatURL ) ) )
[ + - ]
238 : : {
239 : : try
240 : : {
241 : : SAL_WNODEPRECATED_DECLARATIONS_PUSH
242 [ # # ][ # # ]: 0 : pMap = ::std::auto_ptr<PersistentMap>( new PersistentMap( aCompatURL ) );
[ # # ]
243 : : SAL_WNODEPRECATED_DECLARATIONS_POP
244 : : }
245 [ # # # # ]: 0 : catch (const Exception &e)
246 : : {
247 : 0 : rtl::OUStringBuffer aStr( "Exception loading legacy package database: '" );
248 [ # # ]: 0 : aStr.append( e.Message );
249 [ # # ]: 0 : aStr.append( "' - ignoring file, please remove it.\n" );
250 [ # # ]: 0 : dp_misc::writeConsole( aStr.getStr() );
251 : : }
252 : : }
253 [ + - ]: 380 : m_registeredPackages = pMap;
254 : : #endif
255 : 380 : }
256 : 380 : }
257 : :
258 : 1922 : void BackendImpl::addDataToDb(
259 : : OUString const & url, ConfigurationBackendDb::Data const & data)
260 : : {
261 [ + - ]: 1922 : if (m_backendDb.get())
262 : 1922 : m_backendDb->addEntry(url, data);
263 : 1922 : }
264 : :
265 : 0 : ::boost::optional<ConfigurationBackendDb::Data> BackendImpl::readDataFromDb(
266 : : OUString const & url)
267 : : {
268 : 0 : ::boost::optional<ConfigurationBackendDb::Data> data;
269 [ # # ]: 0 : if (m_backendDb.get())
270 [ # # ][ # # ]: 0 : data = m_backendDb->getEntry(url);
[ # # ]
271 : 0 : return data;
272 : : }
273 : :
274 : 0 : void BackendImpl::revokeEntryFromDb(OUString const & url)
275 : : {
276 [ # # ]: 0 : if (m_backendDb.get())
277 : 0 : m_backendDb->revokeEntry(url);
278 : 0 : }
279 : :
280 : 10096 : bool BackendImpl::hasActiveEntry(OUString const & url)
281 : : {
282 [ + - ]: 10096 : if (m_backendDb.get())
283 : 10096 : return m_backendDb->hasActiveEntry(url);
284 : 10096 : return false;
285 : : }
286 : :
287 : 1922 : bool BackendImpl::activateEntry(OUString const & url)
288 : : {
289 [ + - ]: 1922 : if (m_backendDb.get())
290 : 1922 : return m_backendDb->activateEntry(url);
291 : 1922 : return false;
292 : : }
293 : :
294 : :
295 : :
296 : : // XPackageRegistry
297 : : //______________________________________________________________________________
298 : : Sequence< Reference<deployment::XPackageTypeInfo> >
299 : 380 : BackendImpl::getSupportedPackageTypes() throw (RuntimeException)
300 : : {
301 : 380 : return m_typeInfos;
302 : : }
303 : 0 : void BackendImpl::packageRemoved(OUString const & url, OUString const & /*mediaType*/)
304 : : throw (deployment::DeploymentException,
305 : : uno::RuntimeException)
306 : : {
307 [ # # ]: 0 : if (m_backendDb.get())
308 : 0 : m_backendDb->removeEntry(url);
309 : 0 : }
310 : :
311 : : // PackageRegistryBackend
312 : : //______________________________________________________________________________
313 : 3844 : Reference<deployment::XPackage> BackendImpl::bindPackage_(
314 : : OUString const & url, OUString const & mediaType_,
315 : : sal_Bool bRemoved, OUString const & identifier,
316 : : Reference<XCommandEnvironment> const & xCmdEnv )
317 : : {
318 : 3844 : OUString mediaType( mediaType_ );
319 [ - + ]: 3844 : if (mediaType.isEmpty())
320 : : {
321 : : // detect media-type:
322 [ # # ]: 0 : ::ucbhelper::Content ucbContent;
323 [ # # ][ # # ]: 0 : if (create_ucb_content( &ucbContent, url, xCmdEnv ))
324 : : {
325 [ # # ]: 0 : const OUString title( StrTitle::getTitle( ucbContent ) );
326 [ # # ]: 0 : if (title.endsWithIgnoreAsciiCaseAsciiL(
327 : : RTL_CONSTASCII_STRINGPARAM(".xcu") )) {
328 [ # # ]: 0 : mediaType = OUSTR("application/"
329 : 0 : "vnd.sun.star.configuration-data");
330 : : }
331 [ # # ]: 0 : if (title.endsWithIgnoreAsciiCaseAsciiL(
332 : : RTL_CONSTASCII_STRINGPARAM(".xcs") )) {
333 [ # # ]: 0 : mediaType = OUSTR("application/"
334 : 0 : "vnd.sun.star.configuration-schema");
335 : 0 : }
336 : : }
337 [ # # ]: 0 : if (mediaType.isEmpty())
338 : : throw lang::IllegalArgumentException(
339 [ # # ]: 0 : StrCannotDetectMediaType::get() + url,
340 [ # # ][ # # ]: 0 : static_cast<OWeakObject *>(this), static_cast<sal_Int16>(-1) );
[ # # ]
341 : : }
342 : :
343 [ + - ][ + - ]: 3844 : String type, subType;
344 [ + - ]: 3844 : INetContentTypeParameterList params;
345 [ + - ][ + - ]: 3844 : if (INetContentTypes::parse( mediaType, type, subType, ¶ms ))
[ + - ][ + - ]
346 : : {
347 [ + - ][ + - ]: 3844 : if (type.EqualsIgnoreCaseAscii("application"))
348 : : {
349 : 3844 : OUString name;
350 [ + - ]: 3844 : if (!bRemoved)
351 : : {
352 [ + - ]: 3844 : ::ucbhelper::Content ucbContent( url, xCmdEnv );
353 [ + - ][ + - ]: 3844 : name = StrTitle::getTitle( ucbContent );
354 : : }
355 : :
356 [ + - ]: 3844 : ::ucbhelper::Content ucbContent( url, xCmdEnv );
357 [ + + ]: 3844 : if (subType.EqualsIgnoreCaseAscii(
358 [ + - ]: 3844 : "vnd.sun.star.configuration-data"))
359 : : {
360 : : return new PackageImpl(
361 : : this, url, name, m_xConfDataTypeInfo, false /* data file */,
362 [ + - ][ + - ]: 3100 : bRemoved, identifier);
[ + - ]
363 : : }
364 [ + - ]: 744 : else if (subType.EqualsIgnoreCaseAscii(
365 [ + - ]: 744 : "vnd.sun.star.configuration-schema")) {
366 : : return new PackageImpl(
367 : : this, url, name, m_xConfSchemaTypeInfo, true /* schema file */,
368 [ + - ][ + - ]: 744 : bRemoved, identifier);
[ + - ]
369 [ + - ][ + - ]: 3844 : }
[ - + ]
370 : : }
371 : : }
372 : : throw lang::IllegalArgumentException(
373 [ # # ]: 0 : StrUnsupportedMediaType::get() + mediaType,
374 : : static_cast<OWeakObject *>(this),
375 [ + - ][ # # ]: 3844 : static_cast<sal_Int16>(-1) );
[ # # ][ + - ]
[ + - ]
376 : : }
377 : :
378 : :
379 : : //______________________________________________________________________________
380 : 2302 : void BackendImpl::configmgrini_verify_init(
381 : : Reference<XCommandEnvironment> const & xCmdEnv )
382 : : {
383 [ + - ]: 2302 : if (transientMode())
384 : 2302 : return;
385 [ + - ]: 2302 : const ::osl::MutexGuard guard( getMutex() );
386 [ + + ]: 2302 : if (! m_configmgrini_inited)
387 : : {
388 : : // common rc:
389 [ + - ]: 380 : ::ucbhelper::Content ucb_content;
390 [ + - + + ]: 760 : if (create_ucb_content(
391 : : &ucb_content,
392 : 380 : makeURL( getCachePath(), OUSTR("configmgr.ini") ),
393 [ + - + - ]: 1140 : xCmdEnv, false /* no throw */ ))
394 : : {
395 : 62 : OUString line;
396 [ + - + - ]: 124 : if (readLine( &line, OUSTR("SCHEMA="), ucb_content,
397 [ + - ]: 124 : RTL_TEXTENCODING_UTF8 ))
398 : : {
399 : 62 : sal_Int32 index = RTL_CONSTASCII_LENGTH("SCHEMA=");
400 [ + + ]: 372 : do {
401 : 372 : OUString token( line.getToken( 0, ' ', index ).trim() );
402 [ + - ]: 372 : if (!token.isEmpty()) {
403 : : //The file may not exist anymore if a shared or bundled
404 : : //extension was removed, but it can still be in the configmgrini.
405 : : //After running XExtensionManager::synchronize, the configmgrini is
406 : : //cleaned up
407 [ + - ]: 372 : m_xcs_files.push_back( token );
408 : 372 : }
409 : : }
410 : : while (index >= 0);
411 : : }
412 [ + - + - ]: 124 : if (readLine( &line, OUSTR("DATA="), ucb_content,
413 [ + - ]: 124 : RTL_TEXTENCODING_UTF8 )) {
414 : 62 : sal_Int32 index = RTL_CONSTASCII_LENGTH("DATA=");
415 [ + + ]: 1550 : do {
416 : 1550 : OUString token( line.getToken( 0, ' ', index ).trim() );
417 [ + - ]: 1550 : if (!token.isEmpty())
418 : : {
419 [ - + ]: 1550 : if (token[ 0 ] == '?')
420 : 0 : token = token.copy( 1 );
421 : : //The file may not exist anymore if a shared or bundled
422 : : //extension was removed, but it can still be in the configmgrini.
423 : : //After running XExtensionManager::synchronize, the configmgrini is
424 : : //cleaned up
425 [ + - ]: 1550 : m_xcu_files.push_back( token );
426 : 1550 : }
427 : : }
428 : : while (index >= 0);
429 : 62 : }
430 : : }
431 : 380 : m_configmgrini_modified = false;
432 [ + - ]: 380 : m_configmgrini_inited = true;
433 [ + - ]: 2302 : }
434 : : }
435 : :
436 : : //______________________________________________________________________________
437 : 2302 : void BackendImpl::configmgrini_flush(
438 : : Reference<XCommandEnvironment> const & xCmdEnv )
439 : : {
440 [ + - ]: 2302 : if (transientMode())
441 : : return;
442 [ + - ][ + + ]: 2302 : if (!m_configmgrini_inited || !m_configmgrini_modified)
443 : : return;
444 : :
445 : 1922 : ::rtl::OStringBuffer buf;
446 [ + - ]: 1922 : if (! m_xcs_files.empty())
447 : : {
448 : 1922 : t_stringlist::const_iterator iPos( m_xcs_files.begin() );
449 : 1922 : t_stringlist::const_iterator const iEnd( m_xcs_files.end() );
450 [ + - ]: 1922 : buf.append( RTL_CONSTASCII_STRINGPARAM("SCHEMA=") );
451 [ + + ]: 9362 : while (iPos != iEnd) {
452 : : // encoded ASCII file-urls:
453 : : const ::rtl::OString item(
454 [ + - ]: 7440 : ::rtl::OUStringToOString( *iPos, RTL_TEXTENCODING_ASCII_US ) );
455 [ + - ]: 7440 : buf.append( item );
456 : 7440 : ++iPos;
457 [ + + ]: 7440 : if (iPos != iEnd)
458 [ + - ]: 5518 : buf.append( ' ' );
459 : 7440 : }
460 [ + - ]: 1922 : buf.append(LF);
461 : : }
462 [ + + ]: 1922 : if (! m_xcu_files.empty())
463 : : {
464 : 1860 : t_stringlist::const_iterator iPos( m_xcu_files.begin() );
465 : 1860 : t_stringlist::const_iterator const iEnd( m_xcu_files.end() );
466 [ + - ]: 1860 : buf.append( RTL_CONSTASCII_STRINGPARAM("DATA=") );
467 [ + + ]: 25172 : while (iPos != iEnd) {
468 : : // encoded ASCII file-urls:
469 : : const ::rtl::OString item(
470 [ + - ]: 23312 : ::rtl::OUStringToOString( *iPos, RTL_TEXTENCODING_ASCII_US ) );
471 [ + - ]: 23312 : buf.append( item );
472 : 23312 : ++iPos;
473 [ + + ]: 23312 : if (iPos != iEnd)
474 [ + - ]: 21452 : buf.append( ' ' );
475 : 23312 : }
476 [ + - ]: 1860 : buf.append(LF);
477 : : }
478 : :
479 : : // write configmgr.ini:
480 : : const Reference<io::XInputStream> xData(
481 : : ::xmlscript::createInputStream(
482 : : ::rtl::ByteSequence(
483 : 1922 : reinterpret_cast<sal_Int8 const *>(buf.getStr()),
484 [ + - ][ + - ]: 3844 : buf.getLength() ) ) );
485 : : ::ucbhelper::Content ucb_content(
486 [ + - ][ + - ]: 1922 : makeURL( getCachePath(), OUSTR("configmgr.ini") ), xCmdEnv );
[ + - ]
487 [ + - ]: 1922 : ucb_content.writeStream( xData, true /* replace existing */ );
488 : :
489 [ + - ]: 2302 : m_configmgrini_modified = false;
490 : : }
491 : :
492 : : //______________________________________________________________________________
493 : 1922 : bool BackendImpl::addToConfigmgrIni( bool isSchema, bool isURL, OUString const & url_,
494 : : Reference<XCommandEnvironment> const & xCmdEnv )
495 : : {
496 [ + - ][ + - ]: 1922 : const OUString rcterm( isURL ? dp_misc::makeRcTerm(url_) : url_ );
497 [ + - ]: 1922 : const ::osl::MutexGuard guard( getMutex() );
498 [ + - ]: 1922 : configmgrini_verify_init( xCmdEnv );
499 : 1922 : t_stringlist & rSet = getFiles(isSchema);
500 [ + - ][ + - ]: 1922 : if (::std::find( rSet.begin(), rSet.end(), rcterm ) == rSet.end()) {
501 [ + - ]: 1922 : rSet.push_front( rcterm ); // prepend to list, thus overriding
502 : : // write immediately:
503 : 1922 : m_configmgrini_modified = true;
504 [ + - ]: 1922 : configmgrini_flush( xCmdEnv );
505 : 1922 : return true;
506 : : }
507 : : else
508 [ + - ]: 1922 : return false;
509 : : }
510 : :
511 : : //______________________________________________________________________________
512 : 0 : bool BackendImpl::removeFromConfigmgrIni(
513 : : bool isSchema, OUString const & url_,
514 : : Reference<XCommandEnvironment> const & xCmdEnv )
515 : : {
516 [ # # ]: 0 : const OUString rcterm( dp_misc::makeRcTerm(url_) );
517 [ # # ]: 0 : const ::osl::MutexGuard guard( getMutex() );
518 [ # # ]: 0 : configmgrini_verify_init( xCmdEnv );
519 : 0 : t_stringlist & rSet = getFiles(isSchema);
520 [ # # ]: 0 : t_stringlist::iterator i(std::find(rSet.begin(), rSet.end(), rcterm));
521 [ # # ][ # # ]: 0 : if (i == rSet.end() && !isSchema)
[ # # ][ # # ]
522 : : {
523 : : //in case the xcu contained %origin% then the configmr.ini contains the
524 : : //url to the file in the user installation (e.g. $BUNDLED_EXTENSIONS_USER)
525 : : //However, m_url (getURL()) contains the URL for the file in the actual
526 : : //extension installatation.
527 [ # # ]: 0 : ::boost::optional<ConfigurationBackendDb::Data> data = readDataFromDb(url_);
528 [ # # ][ # # ]: 0 : if (data)
529 [ # # ][ # # ]: 0 : i = std::find(rSet.begin(), rSet.end(), data->iniEntry);
[ # # ]
530 : : }
531 [ # # ]: 0 : if (i == rSet.end()) {
532 : 0 : return false;
533 : : }
534 [ # # ]: 0 : rSet.erase(i);
535 : : // write immediately:
536 : 0 : m_configmgrini_modified = true;
537 [ # # ]: 0 : configmgrini_flush( xCmdEnv );
538 [ # # ]: 0 : return true;
539 : : }
540 : :
541 : :
542 : : // Package
543 : : //______________________________________________________________________________
544 : :
545 : 13940 : BackendImpl * BackendImpl::PackageImpl::getMyBackend() const
546 : : {
547 : 13940 : BackendImpl * pBackend = static_cast<BackendImpl *>(m_myBackend.get());
548 [ - + ]: 13940 : if (NULL == pBackend)
549 : : {
550 : : //May throw a DisposedException
551 : 0 : check();
552 : : //We should never get here...
553 : : throw RuntimeException(
554 : : OUSTR("Failed to get the BackendImpl"),
555 [ # # ][ # # ]: 0 : static_cast<OWeakObject*>(const_cast<PackageImpl *>(this)));
[ # # ]
556 : : }
557 : 13940 : return pBackend;
558 : : }
559 : :
560 : : beans::Optional< beans::Ambiguous<sal_Bool> >
561 : 10096 : BackendImpl::PackageImpl::isRegistered_(
562 : : ::osl::ResettableMutexGuard &,
563 : : ::rtl::Reference<AbortChannel> const &,
564 : : Reference<XCommandEnvironment> const & )
565 : : {
566 [ + - ]: 10096 : BackendImpl * that = getMyBackend();
567 [ + - ]: 10096 : const rtl::OUString url(getURL());
568 : :
569 : 10096 : bool bReg = false;
570 [ + - ][ + - ]: 10096 : if (that->hasActiveEntry(getURL()))
[ + + ]
571 : 4330 : bReg = true;
572 : : #if !defined(ANDROID) && !defined(IOS)
573 [ + + ][ - + ]: 10096 : if (!bReg && that->m_registeredPackages.get())
[ - + ]
574 : : {
575 : : // fallback for user extension registered in berkeley DB
576 : : bReg = that->m_registeredPackages->has(
577 [ # # ][ # # ]: 0 : rtl::OUStringToOString( url, RTL_TEXTENCODING_UTF8 ));
578 : : }
579 : : #endif
580 : : return beans::Optional< beans::Ambiguous<sal_Bool> >(
581 : 10096 : true, beans::Ambiguous<sal_Bool>( bReg, false ) );
582 : : }
583 : :
584 : : //------------------------------------------------------------------------------
585 : 434 : OUString encodeForXml( OUString const & text )
586 : : {
587 : : // encode conforming xml:
588 : 434 : sal_Int32 len = text.getLength();
589 : 434 : ::rtl::OUStringBuffer buf;
590 [ + + ]: 30876 : for ( sal_Int32 pos = 0; pos < len; ++pos )
591 : : {
592 : 30442 : sal_Unicode c = text[ pos ];
593 [ - - - - : 30442 : switch (c) {
- + ]
594 : : case '<':
595 [ # # ]: 0 : buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("<") );
596 : 0 : break;
597 : : case '>':
598 [ # # ]: 0 : buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(">") );
599 : 0 : break;
600 : : case '&':
601 [ # # ]: 0 : buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("&") );
602 : 0 : break;
603 : : case '\'':
604 [ # # ]: 0 : buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("'") );
605 : 0 : break;
606 : : case '\"':
607 [ # # ]: 0 : buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(""") );
608 : 0 : break;
609 : : default:
610 [ + - ]: 30442 : buf.append( c );
611 : 30442 : break;
612 : : }
613 : : }
614 [ + - ]: 434 : return buf.makeStringAndClear();
615 : : }
616 : :
617 : : //______________________________________________________________________________
618 : 1550 : OUString replaceOrigin(
619 : : OUString const & url, OUString const & destFolder, Reference< XCommandEnvironment > const & xCmdEnv, bool & out_replaced)
620 : : {
621 : : // looking for %origin%:
622 [ + - ]: 1550 : ::ucbhelper::Content ucb_content( url, xCmdEnv );
623 [ + - ]: 1550 : ::rtl::ByteSequence bytes( readFile( ucb_content ) );
624 : 1550 : ::rtl::ByteSequence filtered( bytes.getLength() * 2,
625 [ + - ]: 1550 : ::rtl::BYTESEQ_NODEFAULT );
626 : 1550 : bool use_filtered = false;
627 : 1550 : ::rtl::OString origin;
628 : : sal_Char const * pBytes = reinterpret_cast<sal_Char const *>(
629 : 1550 : bytes.getConstArray());
630 : 1550 : sal_Size nBytes = bytes.getLength();
631 : 1550 : sal_Int32 write_pos = 0;
632 [ + - ]: 5766 : while (nBytes > 0)
633 : : {
634 : 5766 : sal_Int32 index = rtl_str_indexOfChar_WithLength( pBytes, nBytes, '%' );
635 [ + + ]: 5766 : if (index < 0) {
636 [ + + ]: 1550 : if (! use_filtered) // opt
637 : 1116 : break;
638 : 434 : index = nBytes;
639 : : }
640 : :
641 [ - + ]: 4650 : if ((write_pos + index) > filtered.getLength())
642 [ # # ]: 0 : filtered.realloc( (filtered.getLength() + index) * 2 );
643 [ + - ][ + - ]: 4650 : rtl_copyMemory( filtered.getArray() + write_pos, pBytes, index );
644 : 4650 : write_pos += index;
645 : 4650 : pBytes += index;
646 : 4650 : nBytes -= index;
647 [ + + ]: 4650 : if (nBytes == 0)
648 : 434 : break;
649 : :
650 : : // consume %:
651 : 4216 : ++pBytes;
652 : 4216 : --nBytes;
653 : 4216 : sal_Char const * pAdd = "%";
654 : 4216 : sal_Int32 nAdd = 1;
655 [ + - ][ - + ]: 4216 : if (nBytes > 1 && pBytes[ 0 ] == '%')
656 : : {
657 : : // %% => %
658 : 0 : ++pBytes;
659 : 0 : --nBytes;
660 : 0 : use_filtered = true;
661 : : }
662 [ + + ]: 4216 : else if (rtl_str_shortenedCompare_WithLength(
663 : : pBytes, nBytes,
664 : : RTL_CONSTASCII_STRINGPARAM("origin%"),
665 : 4216 : RTL_CONSTASCII_LENGTH("origin%")) == 0)
666 : : {
667 [ + + ]: 1860 : if (origin.isEmpty()) {
668 : : // encode only once
669 : : origin = ::rtl::OUStringToOString(
670 : : encodeForXml( url.copy( 0, url.lastIndexOf( '/' ) ) ),
671 : : // xxx todo: encode always for UTF-8? => lookup doc-header?
672 [ + - ][ + - ]: 434 : RTL_TEXTENCODING_UTF8 );
673 : : }
674 : 1860 : pAdd = origin.getStr();
675 : 1860 : nAdd = origin.getLength();
676 : 1860 : pBytes += RTL_CONSTASCII_LENGTH("origin%");
677 : 1860 : nBytes -= RTL_CONSTASCII_LENGTH("origin%");
678 : 1860 : use_filtered = true;
679 : : }
680 [ - + ]: 4216 : if ((write_pos + nAdd) > filtered.getLength())
681 [ # # ]: 0 : filtered.realloc( (filtered.getLength() + nAdd) * 2 );
682 [ + - ][ + - ]: 4216 : rtl_copyMemory( filtered.getArray() + write_pos, pAdd, nAdd );
683 : 4216 : write_pos += nAdd;
684 : : }
685 [ + + ]: 1550 : if (!use_filtered)
686 : 1116 : return url;
687 [ + - ]: 434 : if (write_pos < filtered.getLength())
688 [ + - ]: 434 : filtered.realloc( write_pos );
689 : 434 : rtl::OUString newUrl(url);
690 [ + - ]: 434 : if (!destFolder.isEmpty())
691 : : {
692 : : //get the file name of the xcu and add it to the url of the temporary folder
693 : 434 : sal_Int32 i = url.lastIndexOf('/');
694 : 434 : newUrl = destFolder + url.copy(i);
695 : : }
696 : :
697 : : ucbhelper::Content(newUrl, xCmdEnv).writeStream(
698 [ + - ][ + - ]: 434 : xmlscript::createInputStream(filtered), true);
[ + - ][ + - ]
699 : 434 : out_replaced = true;
700 [ + - ]: 1550 : return newUrl;
701 : : }
702 : :
703 : : //______________________________________________________________________________
704 : 1922 : void BackendImpl::PackageImpl::processPackage_(
705 : : ::osl::ResettableMutexGuard &,
706 : : bool doRegisterPackage,
707 : : bool startup,
708 : : ::rtl::Reference<AbortChannel> const &,
709 : : Reference<XCommandEnvironment> const & xCmdEnv )
710 : : {
711 [ + - ]: 1922 : BackendImpl * that = getMyBackend();
712 [ + - ]: 1922 : OUString url( getURL() );
713 : :
714 [ + - ]: 1922 : if (doRegisterPackage)
715 : : {
716 [ + - ][ + - ]: 1922 : if (getMyBackend()->activateEntry(getURL()))
[ + - ][ - + ]
717 : : {
718 [ # # ]: 0 : ::boost::optional<ConfigurationBackendDb::Data> data = that->readDataFromDb(url);
719 : : OSL_ASSERT(data);
720 [ # # ][ # # ]: 0 : that->addToConfigmgrIni( m_isSchema, false, data->iniEntry, xCmdEnv );
[ # # ]
721 : : }
722 : : else
723 : : {
724 : 1922 : ConfigurationBackendDb::Data data;
725 [ + + ]: 1922 : if (!m_isSchema)
726 : : {
727 [ + - ]: 1550 : const OUString sModFolder = that->createFolder(OUString(), xCmdEnv);
728 : 1550 : bool out_replaced = false;
729 [ + - ]: 1550 : url = replaceOrigin(url, sModFolder, xCmdEnv, out_replaced);
730 [ + + ]: 1550 : if (out_replaced)
731 : 434 : data.dataUrl = sModFolder;
732 : : else
733 [ + - ]: 1550 : deleteTempFolder(sModFolder);
734 : : }
735 : : //No need for live-deployment for bundled extension, because OOo
736 : : //restarts after installation
737 [ - + ][ # # ]: 1922 : if (that->m_eContext != CONTEXT_BUNDLED
738 : 0 : && !startup)
739 : : {
740 [ # # ]: 0 : if (m_isSchema)
741 : : {
742 : : com::sun::star::configuration::Update::get(
743 [ # # ][ # # ]: 0 : that->m_xComponentContext)->insertExtensionXcsFile(
744 [ # # ][ # # ]: 0 : that->m_eContext == CONTEXT_SHARED, expandUnoRcUrl(url));
745 : : }
746 : : else
747 : : {
748 : : com::sun::star::configuration::Update::get(
749 [ # # ][ # # ]: 0 : that->m_xComponentContext)->insertExtensionXcuFile(
750 [ # # ][ # # ]: 0 : that->m_eContext == CONTEXT_SHARED, expandUnoRcUrl(url));
751 : : }
752 : : }
753 [ + - ]: 1922 : that->addToConfigmgrIni( m_isSchema, true, url, xCmdEnv );
754 [ + - ]: 1922 : data.iniEntry = dp_misc::makeRcTerm(url);
755 [ + - ][ + - ]: 1922 : that->addDataToDb(getURL(), data);
756 : : }
757 : : }
758 : : else // revoke
759 : : {
760 : : #if !defined(ANDROID) && !defined(IOS)
761 [ # # ]: 0 : if (!that->removeFromConfigmgrIni(m_isSchema, url, xCmdEnv) &&
[ # # # # ]
[ # # ]
762 : 0 : that->m_registeredPackages.get()) {
763 : : // Obsolete package database handling - should be removed for LibreOffice 4.0
764 : : t_string2string_map entries(
765 [ # # ]: 0 : that->m_registeredPackages->getEntries());
766 [ # # ][ # # ]: 0 : for (t_string2string_map::iterator i(entries.begin());
767 [ # # ]: 0 : i != entries.end(); ++i)
768 : : {
769 : : //If the xcu file was installed before the configmgr was chaned
770 : : //to use the configmgr.ini, one needed to rebuild to whole directory
771 : : //structur containing the xcu, xcs files from all extensions. Now,
772 : : //we just add all other xcu/xcs files to the configmgr.ini instead of
773 : : //rebuilding the directory structure.
774 : : rtl::OUString url2(
775 [ # # ][ # # ]: 0 : rtl::OStringToOUString(i->first, RTL_TEXTENCODING_UTF8));
776 [ # # ]: 0 : if (url2 != url) {
777 [ # # ]: 0 : bool schema = i->second.equalsIgnoreAsciiCase(
778 : 0 : "vnd.sun.star.configuration-schema");
779 : 0 : OUString url_replaced(url2);
780 : 0 : ConfigurationBackendDb::Data data;
781 [ # # ]: 0 : if (!schema)
782 : : {
783 [ # # ]: 0 : const OUString sModFolder = that->createFolder(OUString(), xCmdEnv);
784 : 0 : bool out_replaced = false;
785 : : url_replaced = replaceOrigin(
786 [ # # ]: 0 : url2, sModFolder, xCmdEnv, out_replaced);
787 [ # # ]: 0 : if (out_replaced)
788 : 0 : data.dataUrl = sModFolder;
789 : : else
790 [ # # ]: 0 : deleteTempFolder(sModFolder);
791 : : }
792 [ # # ]: 0 : that->addToConfigmgrIni(schema, true, url_replaced, xCmdEnv);
793 [ # # ]: 0 : data.iniEntry = dp_misc::makeRcTerm(url_replaced);
794 [ # # ]: 0 : that->addDataToDb(url2, data);
795 : : }
796 [ # # ][ # # ]: 0 : that->m_registeredPackages->erase(i->first);
797 : 0 : }
798 : : try
799 : : {
800 : : ::ucbhelper::Content(
801 : 0 : makeURL( that->getCachePath(), OUSTR("registry") ),
802 : : xCmdEnv ).executeCommand(
803 [ # # ][ # # ]: 0 : OUSTR("delete"), Any( true /* delete physically */ ) );
[ # # # # ]
[ # # ][ # # ]
[ # # ][ # # ]
804 : : }
805 [ # # ]: 0 : catch(const Exception&)
806 : : {
807 : : OSL_ASSERT(0);
808 [ # # ]: 0 : }
809 : : }
810 : : #endif
811 [ # # ]: 0 : ::boost::optional<ConfigurationBackendDb::Data> data = that->readDataFromDb(url);
812 : : //If an xcu file was life deployed then always a data entry is written.
813 : : //If the xcu file was already in the configmr.ini then there is also
814 : : //a data entry
815 [ # # ][ # # ]: 0 : if (!m_isSchema && data)
[ # # ][ # # ]
816 : : {
817 : : com::sun::star::configuration::Update::get(
818 [ # # ][ # # ]: 0 : that->m_xComponentContext)->removeExtensionXcuFile(expandUnoRcTerm(data->iniEntry));
[ # # ][ # # ]
[ # # ]
819 : : }
820 [ # # ][ # # ]: 0 : that->revokeEntryFromDb(url);
821 : 1922 : }
822 : 1922 : }
823 : :
824 : : } // anon namespace
825 : :
826 : : namespace sdecl = comphelper::service_decl;
827 : 124 : sdecl::class_<BackendImpl, sdecl::with_args<true> > serviceBI;
828 : 124 : extern sdecl::ServiceDecl const serviceDecl(
829 : : serviceBI,
830 : : "com.sun.star.comp.deployment.configuration.PackageRegistryBackend",
831 : : BACKEND_SERVICE_NAME );
832 : :
833 : : } // namespace configuration
834 : : } // namespace backend
835 [ + - ][ + - ]: 372 : } // namespace dp_registry
836 : :
837 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|