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