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