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_xmlhelp.hxx" 30 #include "db.hxx" 31 #ifndef _VOS_DIAGNOSE_HXX_ 32 #include <vos/diagnose.hxx> 33 #endif 34 #include <osl/thread.h> 35 #include <rtl/uri.hxx> 36 #include <osl/file.hxx> 37 #include <rtl/memory.h> 38 #include <com/sun/star/lang/Locale.hpp> 39 #include <rtl/ustrbuf.hxx> 40 #include "inputstream.hxx" 41 #include <algorithm> 42 #include <string.h> 43 44 // Extensible help 45 #include "com/sun/star/deployment/ExtensionManager.hpp" 46 #include "com/sun/star/deployment/thePackageManagerFactory.hpp" 47 #include <comphelper/processfactory.hxx> 48 #include <com/sun/star/beans/XPropertySet.hpp> 49 #include <com/sun/star/uno/XComponentContext.hpp> 50 #include <com/sun/star/ucb/XCommandEnvironment.hpp> 51 #include <com/sun/star/beans/Optional.hpp> 52 #include <com/sun/star/beans/PropertyValue.hpp> 53 #include <com/sun/star/beans/NamedValue.hpp> 54 #include <com/sun/star/frame/XConfigManager.hpp> 55 #include <com/sun/star/util/XMacroExpander.hpp> 56 #include <com/sun/star/uri/XUriReferenceFactory.hpp> 57 #include <com/sun/star/uri/XVndSunStarExpandUrl.hpp> 58 #include <com/sun/star/script/XInvocation.hpp> 59 #include <comphelper/locale.hxx> 60 61 #include <com/sun/star/awt/XToolkit.hpp> 62 #include <com/sun/star/awt/XExtendedToolkit.hpp> 63 #include <com/sun/star/awt/XWindowPeer.hpp> 64 #include <com/sun/star/awt/XVclWindowPeer.hpp> 65 #include <com/sun/star/awt/XTopWindow.hpp> 66 67 #include <l10ntools/compilehelp.hxx> 68 #include <comphelper/storagehelper.hxx> 69 70 #include "databases.hxx" 71 #include "urlparameter.hxx" 72 73 using namespace chelp; 74 using namespace berkeleydbproxy; 75 using namespace com::sun::star; 76 using namespace com::sun::star::uno; 77 using namespace com::sun::star::io; 78 using namespace com::sun::star::container; 79 using namespace com::sun::star::i18n; 80 using namespace com::sun::star::lang; 81 using namespace com::sun::star::deployment; 82 using namespace com::sun::star::beans; 83 84 85 static rtl::OUString aSlash( rtl::OUString::createFromAscii( "/" ) ); 86 static rtl::OUString aHelpFilesBaseName( rtl::OUString::createFromAscii( "help" ) ); 87 static rtl::OUString aHelpMediaType( rtl::OUString::createFromAscii( "application/vnd.sun.star.help" ) ); 88 89 rtl::OUString Databases::expandURL( const rtl::OUString& aURL ) 90 { 91 osl::MutexGuard aGuard( m_aMutex ); 92 rtl::OUString aRetURL = expandURL( aURL, m_xContext ); 93 return aRetURL; 94 } 95 96 rtl::OUString Databases::expandURL( const rtl::OUString& aURL, Reference< uno::XComponentContext > xContext ) 97 { 98 static Reference< util::XMacroExpander > xMacroExpander; 99 static Reference< uri::XUriReferenceFactory > xFac; 100 101 if( !xContext.is() ) 102 return rtl::OUString(); 103 104 if( !xMacroExpander.is() || !xFac.is() ) 105 { 106 Reference< XMultiComponentFactory > xSMgr( xContext->getServiceManager(), UNO_QUERY ); 107 108 xFac = Reference< uri::XUriReferenceFactory >( 109 xSMgr->createInstanceWithContext( rtl::OUString::createFromAscii( 110 "com.sun.star.uri.UriReferenceFactory"), xContext ) , UNO_QUERY ); 111 if( !xFac.is() ) 112 { 113 throw RuntimeException( 114 ::rtl::OUString::createFromAscii( "Databases::expand(), could not instatiate UriReferenceFactory." ), 115 Reference< XInterface >() ); 116 } 117 118 xMacroExpander = Reference< util::XMacroExpander >( 119 xContext->getValueByName( 120 ::rtl::OUString::createFromAscii( "/singletons/com.sun.star.util.theMacroExpander" ) ), 121 UNO_QUERY_THROW ); 122 } 123 124 rtl::OUString aRetURL = aURL; 125 if( xMacroExpander.is() ) 126 { 127 Reference< uri::XUriReference > uriRef; 128 for (;;) 129 { 130 uriRef = Reference< uri::XUriReference >( xFac->parse( aRetURL ), UNO_QUERY ); 131 if ( uriRef.is() ) 132 { 133 Reference < uri::XVndSunStarExpandUrl > sxUri( uriRef, UNO_QUERY ); 134 if( !sxUri.is() ) 135 break; 136 137 aRetURL = sxUri->expand( xMacroExpander ); 138 } 139 } 140 } 141 return aRetURL; 142 } 143 144 Databases::Databases( sal_Bool showBasic, 145 const rtl::OUString& instPath, 146 const com::sun::star::uno::Sequence< rtl::OUString >& imagesZipPaths, 147 const rtl::OUString& productName, 148 const rtl::OUString& productVersion, 149 const rtl::OUString& styleSheet, 150 Reference< uno::XComponentContext > xContext ) 151 : m_xContext( xContext ), 152 m_bShowBasic(showBasic), 153 m_nErrorDocLength( 0 ), 154 m_pErrorDoc( 0 ), 155 m_nCustomCSSDocLength( 0 ), 156 m_pCustomCSSDoc( 0 ), 157 m_aCSS(styleSheet.toAsciiLowerCase()), 158 newProdName(rtl::OUString::createFromAscii( "$[officename]" ) ), 159 newProdVersion(rtl::OUString::createFromAscii( "$[officeversion]" ) ), 160 prodName( rtl::OUString::createFromAscii( "%PRODUCTNAME" ) ), 161 prodVersion( rtl::OUString::createFromAscii( "%PRODUCTVERSION" ) ), 162 vendName( rtl::OUString::createFromAscii( "%VENDORNAME" ) ), 163 vendVersion( rtl::OUString::createFromAscii( "%VENDORVERSION" ) ), 164 vendShort( rtl::OUString::createFromAscii( "%VENDORSHORT" ) ), 165 m_aImagesZipPaths( imagesZipPaths ), 166 m_nSymbolsStyle( 0 ) 167 { 168 m_xSMgr = Reference< XMultiComponentFactory >( m_xContext->getServiceManager(), UNO_QUERY ); 169 170 m_vAdd[0] = 12; 171 m_vAdd[1] = 15; 172 m_vAdd[2] = 11; 173 m_vAdd[3] = 14; 174 m_vAdd[4] = 12; 175 m_vAdd[5] = 13; 176 m_vAdd[6] = 16; 177 178 m_vReplacement[0] = productName; 179 m_vReplacement[1] = productVersion; 180 // m_vReplacement[2...4] (vendorName/-Version/-Short) are empty strings 181 m_vReplacement[5] = productName; 182 m_vReplacement[6] = productVersion; 183 184 setInstallPath( instPath ); 185 186 m_xSFA = Reference< ucb::XSimpleFileAccess >( 187 m_xSMgr->createInstanceWithContext( rtl::OUString::createFromAscii( "com.sun.star.ucb.SimpleFileAccess" ), 188 m_xContext ), UNO_QUERY_THROW ); 189 } 190 191 Databases::~Databases() 192 { 193 // release stylesheet 194 195 delete[] m_pCustomCSSDoc; 196 197 // release errorDocument 198 199 delete[] m_pErrorDoc; 200 201 // unload the databases 202 203 { 204 // DatabasesTable 205 DatabasesTable::iterator it = m_aDatabases.begin(); 206 while( it != m_aDatabases.end() ) 207 { 208 if( it->second ) 209 it->second->close( 0 ); 210 delete it->second; 211 ++it; 212 } 213 } 214 215 { 216 // ModInfoTable 217 218 ModInfoTable::iterator it = m_aModInfo.begin(); 219 while( it != m_aModInfo.end() ) 220 { 221 delete it->second; 222 ++it; 223 } 224 } 225 226 { 227 // KeywordInfoTable 228 229 KeywordInfoTable::iterator it = m_aKeywordInfo.begin(); 230 while( it != m_aKeywordInfo.end() ) 231 { 232 delete it->second; 233 ++it; 234 } 235 } 236 } 237 238 static bool impl_getZipFile( 239 Sequence< rtl::OUString > & rImagesZipPaths, 240 const rtl::OUString & rZipName, 241 rtl::OUString & rFileName ) 242 { 243 const rtl::OUString *pPathArray = rImagesZipPaths.getArray(); 244 for ( int i = 0; i < rImagesZipPaths.getLength(); ++i ) 245 { 246 rFileName = pPathArray[ i ]; 247 if ( rFileName.getLength() ) 248 { 249 if ( 1 + rFileName.lastIndexOf( '/' ) != rFileName.getLength() ) 250 { 251 rFileName += rtl::OUString::createFromAscii( "/" ); 252 } 253 rFileName += rZipName; 254 255 // test existence 256 osl::DirectoryItem aDirItem; 257 if ( osl::DirectoryItem::get( rFileName, aDirItem ) == osl::FileBase::E_None ) 258 return true; 259 } 260 } 261 return false; 262 } 263 264 rtl::OString Databases::getImagesZipFileURL() 265 { 266 //sal_Int16 nSymbolsStyle = SvtMiscOptions().GetCurrentSymbolsStyle(); 267 sal_Int16 nSymbolsStyle = 0; 268 try 269 { 270 uno::Reference< lang::XMultiServiceFactory > xConfigProvider( 271 m_xSMgr ->createInstanceWithContext(::rtl::OUString::createFromAscii("com.sun.star.configuration.ConfigurationProvider"), m_xContext), uno::UNO_QUERY_THROW); 272 273 // set root path 274 uno::Sequence < uno::Any > lParams(1); 275 beans::PropertyValue aParam ; 276 aParam.Name = ::rtl::OUString::createFromAscii("nodepath"); 277 aParam.Value <<= ::rtl::OUString::createFromAscii("org.openoffice.Office.Common"); 278 lParams[0] = uno::makeAny(aParam); 279 280 // open it 281 uno::Reference< uno::XInterface > xCFG( xConfigProvider->createInstanceWithArguments( 282 ::rtl::OUString::createFromAscii("com.sun.star.configuration.ConfigurationAccess"), 283 lParams) ); 284 285 bool bChanged = false; 286 uno::Reference< container::XHierarchicalNameAccess > xAccess(xCFG, uno::UNO_QUERY_THROW); 287 uno::Any aResult = xAccess->getByHierarchicalName(::rtl::OUString::createFromAscii("Misc/SymbolSet")); 288 if ( (aResult >>= nSymbolsStyle) && m_nSymbolsStyle != nSymbolsStyle ) 289 { 290 m_nSymbolsStyle = nSymbolsStyle; 291 bChanged = true; 292 } 293 294 if ( !m_aImagesZipFileURL.getLength() || bChanged ) 295 { 296 rtl::OUString aImageZip, aSymbolsStyleName; 297 aResult = xAccess->getByHierarchicalName(::rtl::OUString::createFromAscii("Misc/SymbolStyle")); 298 aResult >>= aSymbolsStyleName; 299 300 bool bFound = false; 301 if ( aSymbolsStyleName.getLength() != 0 ) 302 { 303 rtl::OUString aZipName = rtl::OUString::createFromAscii( "images_" ); 304 aZipName += aSymbolsStyleName; 305 aZipName += rtl::OUString::createFromAscii( ".zip" ); 306 307 bFound = impl_getZipFile( m_aImagesZipPaths, aZipName, aImageZip ); 308 } 309 310 if ( ! bFound ) 311 bFound = impl_getZipFile( m_aImagesZipPaths, rtl::OUString::createFromAscii( "images.zip" ), aImageZip ); 312 313 if ( ! bFound ) 314 aImageZip = rtl::OUString(); 315 316 m_aImagesZipFileURL = rtl::OUStringToOString( 317 rtl::Uri::encode( 318 aImageZip, 319 rtl_UriCharClassPchar, 320 rtl_UriEncodeIgnoreEscapes, 321 RTL_TEXTENCODING_UTF8 ), RTL_TEXTENCODING_UTF8 ); 322 } 323 } 324 catch ( NoSuchElementException const & ) 325 { 326 } 327 328 return m_aImagesZipFileURL; 329 } 330 331 void Databases::replaceName( rtl::OUString& oustring ) const 332 { 333 sal_Int32 idx = -1,idx1 = -1,idx2 = -1,k = 0,off; 334 bool cap = false; 335 rtl::OUStringBuffer aStrBuf( 0 ); 336 337 while( true ) 338 { 339 ++idx; 340 idx1 = oustring.indexOf( sal_Unicode('%'),idx); 341 idx2 = oustring.indexOf( sal_Unicode('$'),idx); 342 343 if(idx1 == -1 && idx2 == -1) 344 break; 345 346 if(idx1 == -1) 347 idx = idx2; 348 else if(idx2 == -1) 349 idx = idx1; 350 else { 351 // no index is zero 352 if(idx1 < idx2) 353 idx = idx1; 354 else if(idx2 < idx1 ) 355 idx = idx2; 356 } 357 358 if( oustring.indexOf( prodName,idx ) == idx ) 359 off = PRODUCTNAME; 360 else if( oustring.indexOf( prodVersion,idx ) == idx ) 361 off = PRODUCTVERSION; 362 else if( oustring.indexOf( vendName,idx ) == idx ) 363 off = VENDORNAME; 364 else if( oustring.indexOf( vendVersion,idx ) == idx ) 365 off = VENDORVERSION; 366 else if( oustring.indexOf( vendShort,idx ) == idx ) 367 off = VENDORSHORT; 368 else if( oustring.indexOf( newProdName,idx ) == idx ) 369 off = NEWPRODUCTNAME; 370 else if( oustring.indexOf( newProdVersion,idx ) == idx ) 371 off = NEWPRODUCTVERSION; 372 else 373 off = -1; 374 375 if( off != -1 ) 376 { 377 if( ! cap ) 378 { 379 cap = true; 380 aStrBuf.ensureCapacity( 256 ); 381 } 382 383 aStrBuf.append( &oustring.getStr()[k],idx - k ); 384 aStrBuf.append( m_vReplacement[off] ); 385 k = idx + m_vAdd[off]; 386 } 387 } 388 389 if( cap ) 390 { 391 if( k < oustring.getLength() ) 392 aStrBuf.append( &oustring.getStr()[k],oustring.getLength()-k ); 393 oustring = aStrBuf.makeStringAndClear(); 394 } 395 } 396 397 398 399 400 rtl::OUString Databases::getInstallPathAsSystemPath() 401 { 402 osl::MutexGuard aGuard( m_aMutex ); 403 404 if( ! m_aInstallDirectoryAsSystemPath.getLength() ) 405 { 406 #ifdef DBG_UTIL 407 bool bla = 408 osl::FileBase::E_None == 409 osl::FileBase::getSystemPathFromFileURL( m_aInstallDirectory,m_aInstallDirectoryAsSystemPath ); 410 VOS_ENSURE( bla,"HelpProvider, no installpath" ); 411 #else 412 osl::FileBase::getSystemPathFromFileURL( m_aInstallDirectory,m_aInstallDirectoryAsSystemPath ); 413 #endif 414 } 415 416 return m_aInstallDirectoryAsSystemPath; 417 } 418 419 rtl::OUString Databases::getInstallPathAsURL() 420 { 421 osl::MutexGuard aGuard( m_aMutex ); 422 423 return m_aInstallDirectory; 424 } 425 426 427 const std::vector< rtl::OUString >& Databases::getModuleList( const rtl::OUString& Language ) 428 { 429 if( m_avModules.size() == 0 ) 430 { 431 rtl::OUString fileName,dirName = getInstallPathAsURL() + processLang( Language ); 432 osl::Directory dirFile( dirName ); 433 434 osl::DirectoryItem aDirItem; 435 osl::FileStatus aStatus( FileStatusMask_FileName ); 436 437 sal_Int32 idx; 438 439 if( osl::FileBase::E_None != dirFile.open() ) 440 return m_avModules; 441 442 while( dirFile.getNextItem( aDirItem ) == osl::FileBase::E_None && 443 aDirItem.getFileStatus( aStatus ) == osl::FileBase::E_None ) 444 { 445 if( ! aStatus.isValid( FileStatusMask_FileName ) ) 446 continue; 447 448 fileName = aStatus.getFileName(); 449 450 // Check, whether fileName is of the form *.cfg 451 idx = fileName.lastIndexOf( sal_Unicode( '.' ) ); 452 453 if( idx == -1 ) 454 continue; 455 456 const sal_Unicode* str = fileName.getStr(); 457 458 if( fileName.getLength() == idx + 4 && 459 ( str[idx + 1] == 'c' || str[idx + 1] == 'C' ) && 460 ( str[idx + 2] == 'f' || str[idx + 2] == 'F' ) && 461 ( str[idx + 3] == 'g' || str[idx + 3] == 'G' ) && 462 ( fileName = fileName.copy(0,idx).toAsciiLowerCase() ).compareToAscii( "picture" ) != 0 ) { 463 if(! m_bShowBasic && fileName.compareToAscii("sbasic") == 0 ) 464 continue; 465 m_avModules.push_back( fileName ); 466 } 467 } 468 } 469 return m_avModules; 470 } 471 472 473 474 StaticModuleInformation* Databases::getStaticInformationForModule( const rtl::OUString& Module, 475 const rtl::OUString& Language ) 476 { 477 osl::MutexGuard aGuard( m_aMutex ); 478 479 rtl::OUString key = processLang(Language) + rtl::OUString::createFromAscii( "/" ) + Module; 480 481 std::pair< ModInfoTable::iterator,bool > aPair = 482 m_aModInfo.insert( ModInfoTable::value_type( key,0 ) ); 483 484 ModInfoTable::iterator it = aPair.first; 485 486 if( aPair.second && ! it->second ) 487 { 488 osl::File cfgFile( getInstallPathAsURL() + 489 key + 490 rtl::OUString::createFromAscii( ".cfg" ) ); 491 492 if( osl::FileBase::E_None != cfgFile.open( OpenFlag_Read ) ) 493 it->second = 0; 494 else 495 { 496 sal_uInt32 pos = 0; 497 sal_uInt64 nRead; 498 sal_Char buffer[2048]; 499 sal_Unicode lineBuffer[1028]; 500 rtl::OUString fileContent; 501 502 while( osl::FileBase::E_None == cfgFile.read( &buffer,2048,nRead ) && nRead ) 503 fileContent += rtl::OUString( buffer,sal_Int32( nRead ),RTL_TEXTENCODING_UTF8 ); 504 505 cfgFile.close(); 506 507 const sal_Unicode* str = fileContent.getStr(); 508 rtl::OUString current,lang_,program,startid,title,heading,fulltext; 509 rtl::OUString order = rtl::OUString::createFromAscii( "1" ); 510 511 for( sal_Int32 i = 0;i < fileContent.getLength();i++ ) 512 { 513 sal_Unicode ch = str[ i ]; 514 if( ch == sal_Unicode( '\n' ) || ch == sal_Unicode( '\r' ) ) 515 { 516 if( pos ) 517 { 518 current = rtl::OUString( lineBuffer,pos ); 519 520 if( current.compareToAscii( "Title",5 ) == 0 ) 521 { 522 title = current.copy( current.indexOf(sal_Unicode( '=' ) ) + 1 ); 523 } 524 else if( current.compareToAscii( "Start",5 ) == 0 ) 525 { 526 startid = current.copy( current.indexOf('=') + 1 ); 527 } 528 else if( current.compareToAscii( "Language",8 ) == 0 ) 529 { 530 lang_ = current.copy( current.indexOf('=') + 1 ); 531 } 532 else if( current.compareToAscii( "Program",7 ) == 0 ) 533 { 534 program = current.copy( current.indexOf('=') + 1 ); 535 } 536 else if( current.compareToAscii( "Heading",7 ) == 0 ) 537 { 538 heading = current.copy( current.indexOf('=') + 1 ); 539 } 540 else if( current.compareToAscii( "FullText",8 ) == 0 ) 541 { 542 fulltext = current.copy( current.indexOf('=') + 1 ); 543 } 544 else if( current.compareToAscii( "Order",5 ) == 0 ) 545 { 546 order = current.copy( current.indexOf('=') + 1 ); 547 } 548 } 549 pos = 0; 550 } 551 else 552 lineBuffer[ pos++ ] = ch; 553 } 554 replaceName( title ); 555 it->second = new StaticModuleInformation( title, 556 startid, 557 program, 558 heading, 559 fulltext, 560 order ); 561 } 562 } 563 564 return it->second; 565 } 566 567 568 569 570 rtl::OUString Databases::processLang( const rtl::OUString& Language ) 571 { 572 osl::MutexGuard aGuard( m_aMutex ); 573 574 rtl::OUString ret; 575 LangSetTable::iterator it = m_aLangSet.find( Language ); 576 577 if( it == m_aLangSet.end() ) 578 { 579 sal_Int32 idx; 580 osl::DirectoryItem aDirItem; 581 582 if( osl::FileBase::E_None == osl::DirectoryItem::get( getInstallPathAsURL() + Language,aDirItem ) ) 583 { 584 ret = Language; 585 m_aLangSet[ Language ] = ret; 586 } 587 else if( ( ( idx = Language.indexOf( '-' ) ) != -1 || 588 ( idx = Language.indexOf( '_' ) ) != -1 ) && 589 osl::FileBase::E_None == osl::DirectoryItem::get( getInstallPathAsURL() + Language.copy( 0,idx ), 590 aDirItem ) ) 591 { 592 ret = Language.copy( 0,idx ); 593 m_aLangSet[ Language ] = ret; 594 } 595 } 596 else 597 ret = it->second; 598 599 return ret; 600 } 601 602 603 rtl::OUString Databases::country( const rtl::OUString& Language ) 604 { 605 sal_Int32 idx; 606 if( ( idx = Language.indexOf( '-' ) ) != -1 || 607 ( idx = Language.indexOf( '_' ) ) != -1 ) 608 return Language.copy( 1+idx ); 609 610 return rtl::OUString(); 611 } 612 613 614 615 Db* Databases::getBerkeley( const rtl::OUString& Database, 616 const rtl::OUString& Language, bool helpText, 617 const rtl::OUString* pExtensionPath ) 618 { 619 if( ! Database.getLength() || ! Language.getLength() ) 620 return 0; 621 622 osl::MutexGuard aGuard( m_aMutex ); 623 624 625 rtl::OUString aFileExt( rtl::OUString::createFromAscii( helpText ? ".ht" : ".db" ) ); 626 rtl::OUString dbFileName = aSlash + Database + aFileExt; 627 rtl::OUString key; 628 if( pExtensionPath == NULL ) 629 key = processLang( Language ) + dbFileName; 630 else 631 key = *pExtensionPath + Language + dbFileName; // make unique, don't change language 632 633 std::pair< DatabasesTable::iterator,bool > aPair = 634 m_aDatabases.insert( DatabasesTable::value_type( key,0 ) ); 635 636 DatabasesTable::iterator it = aPair.first; 637 638 if( aPair.second && ! it->second ) 639 { 640 Db* table = new Db(); 641 642 rtl::OUString fileURL; 643 if( pExtensionPath ) 644 fileURL = expandURL(*pExtensionPath) + Language + dbFileName; 645 else 646 fileURL = getInstallPathAsURL() + key; 647 648 rtl::OUString fileNameDBHelp( fileURL ); 649 //Extensions always use the new format 650 if( pExtensionPath != NULL ) 651 fileNameDBHelp += rtl::OUString::createFromAscii( "_" ); 652 //SimpleFileAccess takes file URLs as arguments!!! Using filenames works accidentally but 653 //fails for example when using long path names on Windows (starting with \\?\) 654 if( m_xSFA->exists( fileNameDBHelp ) ) 655 { 656 DBHelp* pDBHelp = new DBHelp( fileNameDBHelp, m_xSFA ); 657 table->setDBHelp( pDBHelp ); 658 659 #ifdef TEST_DBHELP 660 bool bSuccess; 661 bool bOldDbAccess = false; 662 bSuccess = pDBHelp->testAgainstDb( fileURL, bOldDbAccess ); 663 664 bOldDbAccess = true; 665 bSuccess = pDBHelp->testAgainstDb( fileURL, bOldDbAccess ); 666 #endif 667 } 668 else if( table->open( 0,fileURL, DB_BTREE,DB_RDONLY,0644 ) ) 669 { 670 table->close( 0 ); 671 delete table; 672 table = 0; 673 } 674 675 it->second = table; 676 } 677 678 return it->second; 679 } 680 681 Reference< XCollator > 682 Databases::getCollator( const rtl::OUString& Language, 683 const rtl::OUString& System ) 684 { 685 (void)System; 686 687 rtl::OUString key = Language; 688 689 osl::MutexGuard aGuard( m_aMutex ); 690 691 CollatorTable::iterator it = 692 m_aCollatorTable.insert( CollatorTable::value_type( key,0 ) ).first; 693 694 if( ! it->second.is() ) 695 { 696 it->second = 697 Reference< XCollator > ( 698 m_xSMgr->createInstanceWithContext( rtl::OUString::createFromAscii( "com.sun.star.i18n.Collator" ), 699 m_xContext ), UNO_QUERY ); 700 rtl::OUString langStr = processLang(Language); 701 rtl::OUString countryStr = country(Language); 702 if( !countryStr.getLength() ) 703 { 704 if( langStr.compareToAscii("de") == 0 ) 705 countryStr = rtl::OUString::createFromAscii("DE"); 706 else if( langStr.compareToAscii("en") == 0 ) 707 countryStr = rtl::OUString::createFromAscii("US"); 708 else if( langStr.compareToAscii("es") == 0 ) 709 countryStr = rtl::OUString::createFromAscii("ES"); 710 else if( langStr.compareToAscii("it") == 0 ) 711 countryStr = rtl::OUString::createFromAscii("IT"); 712 else if( langStr.compareToAscii("fr") == 0 ) 713 countryStr = rtl::OUString::createFromAscii("FR"); 714 else if( langStr.compareToAscii("sv") == 0 ) 715 countryStr = rtl::OUString::createFromAscii("SE"); 716 else if( langStr.compareToAscii("ja") == 0 ) 717 countryStr = rtl::OUString::createFromAscii("JP"); 718 else if( langStr.compareToAscii("ko") == 0 ) 719 countryStr = rtl::OUString::createFromAscii("KR"); 720 } 721 it->second->loadDefaultCollator( Locale( langStr, 722 countryStr, 723 rtl::OUString() ), 724 0 ); 725 } 726 727 return it->second; 728 } 729 730 731 732 namespace chelp { 733 734 struct KeywordElementComparator 735 { 736 KeywordElementComparator( const Reference< XCollator >& xCollator ) 737 : m_xCollator( xCollator ) 738 { } 739 740 bool operator()( const KeywordInfo::KeywordElement& la, 741 const KeywordInfo::KeywordElement& ra ) const 742 { 743 const rtl::OUString& l = la.key; 744 const rtl::OUString& r = ra.key; 745 746 bool ret; 747 748 if( m_xCollator.is() ) 749 { 750 sal_Int32 l1 = l.indexOf( sal_Unicode( ';' ) ); 751 sal_Int32 l3 = ( l1 == -1 ? l.getLength() : l1 ); 752 753 sal_Int32 r1 = r.indexOf( sal_Unicode( ';' ) ); 754 sal_Int32 r3 = ( r1 == -1 ? r.getLength() : r1 ); 755 756 sal_Int32 c1 = m_xCollator->compareSubstring( l,0,l3,r,0,r3 ); 757 758 if( c1 == +1 ) 759 ret = false; 760 else if( c1 == 0 ) 761 { 762 sal_Int32 l2 = l.getLength() - l1 - 1; 763 sal_Int32 r2 = r.getLength() - r1 - 1; 764 ret = ( m_xCollator->compareSubstring( l,1+l1,l2,r,1+r1,r2 ) < 0 ); 765 } 766 else 767 ret = true; 768 } 769 else 770 ret = bool( l < r ); 771 772 return ret; 773 } 774 775 Reference< XCollator > m_xCollator; 776 }; // end struct KeywordElementComparator 777 778 } 779 780 781 782 KeywordInfo::KeywordElement::KeywordElement( Databases *pDatabases, 783 Db* pDb, 784 rtl::OUString& ky, 785 rtl::OUString& data ) 786 : key( ky ) 787 { 788 pDatabases->replaceName( key ); 789 init( pDatabases,pDb,data ); 790 } 791 792 793 794 void KeywordInfo::KeywordElement::init( Databases *pDatabases,Db* pDb,const rtl::OUString& ids ) 795 { 796 const sal_Unicode* idstr = ids.getStr(); 797 std::vector< rtl::OUString > id,anchor; 798 int idx = -1,k; 799 while( ( idx = ids.indexOf( ';',k = ++idx ) ) != -1 ) 800 { 801 int h = ids.indexOf( sal_Unicode( '#' ),k ); 802 if( h < idx ) 803 { 804 // found an anchor 805 id.push_back( rtl::OUString( &idstr[k],h-k ) ); 806 anchor.push_back( rtl::OUString( &idstr[h+1],idx-h-1 ) ); 807 } 808 else 809 { 810 id.push_back( rtl::OUString( &idstr[k],idx-k ) ); 811 anchor.push_back( rtl::OUString() ); 812 } 813 } 814 815 listId.realloc( id.size() ); 816 listAnchor.realloc( id.size() ); 817 listTitle.realloc( id.size() ); 818 819 int nSize = 0; 820 const sal_Char* pData = NULL; 821 const sal_Char pEmpty[] = ""; 822 823 for( sal_uInt32 i = 0; i < id.size(); ++i ) 824 { 825 listId[i] = id[i]; 826 listAnchor[i] = anchor[i]; 827 828 nSize = 0; 829 pData = pEmpty; 830 if( pDb ) 831 { 832 rtl::OString idi( id[i].getStr(),id[i].getLength(),RTL_TEXTENCODING_UTF8 ); 833 DBHelp* pDBHelp = pDb->getDBHelp(); 834 if( pDBHelp != NULL ) 835 { 836 DBData aDBData; 837 bool bSuccess = pDBHelp->getValueForKey( idi, aDBData ); 838 if( bSuccess ) 839 { 840 nSize = aDBData.getSize(); 841 pData = aDBData.getData(); 842 } 843 } 844 else 845 { 846 Dbt key_( static_cast< void* >( const_cast< sal_Char* >( idi.getStr() ) ), 847 idi.getLength() ); 848 Dbt data; 849 pDb->get( 0,&key_,&data,0 ); 850 nSize = data.get_size(); 851 pData = static_cast<sal_Char*>( data.get_data() ); 852 } 853 } 854 855 DbtToStringConverter converter( pData, nSize ); 856 857 rtl::OUString title = converter.getTitle(); 858 pDatabases->replaceName( title ); 859 listTitle[i] = title; 860 } 861 } 862 863 864 865 KeywordInfo::KeywordInfo( const std::vector< KeywordElement >& aVec ) 866 : listKey( aVec.size() ), 867 listId( aVec.size() ), 868 listAnchor( aVec.size() ), 869 listTitle( aVec.size() ) 870 { 871 for( unsigned int i = 0; i < aVec.size(); ++i ) 872 { 873 listKey[i] = aVec[i].key; 874 listId[i] = aVec[i].listId; 875 listAnchor[i] = aVec[i].listAnchor; 876 listTitle[i] = aVec[i].listTitle; 877 } 878 } 879 880 bool Databases::checkModuleMatchForExtension 881 ( const rtl::OUString& Database, const rtl::OUString& doclist ) 882 { 883 bool bBelongsToDatabase = true; 884 885 // Analyse doclist string to find module assignments 886 bool bFoundAtLeastOneModule = false; 887 bool bModuleMatch = false; 888 sal_Int32 nLen = doclist.getLength(); 889 sal_Int32 nLastFound = doclist.lastIndexOf( sal_Unicode(';') ); 890 if( nLastFound == -1 ) 891 nLastFound = nLen; 892 const sal_Unicode* pStr = doclist.getStr(); 893 sal_Int32 nFound = doclist.lastIndexOf( sal_Unicode('_') ); 894 while( nFound != -1 ) 895 { 896 // Simple optimization, stop if '_' is followed by "id" 897 if( nLen - nFound > 2 ) 898 { 899 if( pStr[ nFound + 1 ] == sal_Unicode('i') && 900 pStr[ nFound + 2 ] == sal_Unicode('d') ) 901 break; 902 } 903 904 rtl::OUString aModule = doclist.copy( nFound + 1, nLastFound - nFound - 1 ); 905 std::vector< rtl::OUString >::iterator result = std::find( m_avModules.begin(), m_avModules.end(), aModule ); 906 if( result != m_avModules.end() ) 907 { 908 bFoundAtLeastOneModule = true; 909 if( Database == aModule ) 910 { 911 bModuleMatch = true; 912 break; 913 } 914 } 915 916 nLastFound = nFound; 917 if( nLastFound == 0 ) 918 break; 919 nFound = doclist.lastIndexOf( sal_Unicode('_'), nLastFound - 1 ); 920 } 921 922 if( bFoundAtLeastOneModule && !bModuleMatch ) 923 bBelongsToDatabase = false; 924 925 return bBelongsToDatabase; 926 } 927 928 929 KeywordInfo* Databases::getKeyword( const rtl::OUString& Database, 930 const rtl::OUString& Language ) 931 { 932 osl::MutexGuard aGuard( m_aMutex ); 933 934 rtl::OUString key = processLang(Language) + rtl::OUString::createFromAscii( "/" ) + Database; 935 936 std::pair< KeywordInfoTable::iterator,bool > aPair = 937 m_aKeywordInfo.insert( KeywordInfoTable::value_type( key,0 ) ); 938 939 KeywordInfoTable::iterator it = aPair.first; 940 941 if( aPair.second && ! it->second ) 942 { 943 std::vector<KeywordInfo::KeywordElement> aVector; 944 945 KeyDataBaseFileIterator aDbFileIt( m_xContext, *this, Database, Language ); 946 rtl::OUString fileURL; 947 bool bExtension = false; 948 while( (fileURL = aDbFileIt.nextDbFile( bExtension )).getLength() > 0 ) 949 { 950 Db table; 951 952 rtl::OUString fileNameDBHelp( fileURL ); 953 if( bExtension ) 954 fileNameDBHelp += rtl::OUString::createFromAscii( "_" ); 955 if( m_xSFA->exists( fileNameDBHelp ) ) 956 { 957 DBHelp aDBHelp( fileNameDBHelp, m_xSFA ); 958 959 DBData aKey; 960 DBData aValue; 961 if( aDBHelp.startIteration() ) 962 { 963 Db* idmap = getBerkeley( Database,Language ); 964 965 DBHelp* pDBHelp = idmap->getDBHelp(); 966 if( pDBHelp != NULL ) 967 { 968 bool bOptimizeForPerformance = true; 969 pDBHelp->releaseHashMap(); 970 pDBHelp->createHashMap( bOptimizeForPerformance ); 971 } 972 973 while( aDBHelp.getNextKeyAndValue( aKey, aValue ) ) 974 { 975 rtl::OUString keyword( aKey.getData(), aKey.getSize(), 976 RTL_TEXTENCODING_UTF8 ); 977 rtl::OUString doclist( aValue.getData(), aValue.getSize(), 978 RTL_TEXTENCODING_UTF8 ); 979 980 bool bBelongsToDatabase = true; 981 if( bExtension ) 982 bBelongsToDatabase = checkModuleMatchForExtension( Database, doclist ); 983 984 if( !bBelongsToDatabase ) 985 continue; 986 987 aVector.push_back( KeywordInfo::KeywordElement( this, 988 idmap, 989 keyword, 990 doclist ) ); 991 } 992 aDBHelp.stopIteration(); 993 994 if( pDBHelp != NULL ) 995 pDBHelp->releaseHashMap(); 996 } 997 998 #ifdef TEST_DBHELP 999 bool bSuccess; 1000 bool bOldDbAccess = false; 1001 bSuccess = aDBHelp.testAgainstDb( fileURL, bOldDbAccess ); 1002 1003 bOldDbAccess = true; 1004 bSuccess = aDBHelp.testAgainstDb( fileURL, bOldDbAccess ); 1005 1006 int nDummy = 0; 1007 #endif 1008 } 1009 1010 else if( 0 == table.open( 0,fileURL,DB_BTREE,DB_RDONLY,0644 ) ) 1011 { 1012 Db* idmap = getBerkeley( Database,Language ); 1013 1014 bool first = true; 1015 1016 Dbc* cursor = 0; 1017 table.cursor( 0,&cursor,0 ); 1018 Dbt key_,data; 1019 key_.set_flags( DB_DBT_MALLOC ); // Initially the cursor must allocate the necessary memory 1020 data.set_flags( DB_DBT_MALLOC ); 1021 while( cursor && DB_NOTFOUND != cursor->get( &key_,&data,DB_NEXT ) ) 1022 { 1023 rtl::OUString keyword( static_cast<sal_Char*>(key_.get_data()), 1024 key_.get_size(), 1025 RTL_TEXTENCODING_UTF8 ); 1026 rtl::OUString doclist( static_cast<sal_Char*>(data.get_data()), 1027 data.get_size(), 1028 RTL_TEXTENCODING_UTF8 ); 1029 1030 bool bBelongsToDatabase = true; 1031 if( bExtension ) 1032 bBelongsToDatabase = checkModuleMatchForExtension( Database, doclist ); 1033 1034 if( !bBelongsToDatabase ) 1035 continue; 1036 1037 aVector.push_back( KeywordInfo::KeywordElement( this, 1038 idmap, 1039 keyword, 1040 doclist ) ); 1041 if( first ) 1042 { 1043 key_.set_flags( DB_DBT_REALLOC ); 1044 data.set_flags( DB_DBT_REALLOC ); 1045 first = false; 1046 } 1047 } 1048 1049 if( cursor ) cursor->close(); 1050 } 1051 table.close( 0 ); 1052 } 1053 1054 // sorting 1055 Reference< XCollator > xCollator = getCollator( Language,rtl::OUString()); 1056 KeywordElementComparator aComparator( xCollator ); 1057 std::sort(aVector.begin(),aVector.end(),aComparator); 1058 1059 KeywordInfo* pInfo = it->second = new KeywordInfo( aVector ); 1060 (void)pInfo; 1061 } 1062 1063 return it->second; 1064 } 1065 1066 Reference< XHierarchicalNameAccess > Databases::jarFile( const rtl::OUString& jar, 1067 const rtl::OUString& Language ) 1068 { 1069 if( ! jar.getLength() || 1070 ! Language.getLength() ) 1071 { 1072 return Reference< XHierarchicalNameAccess >( 0 ); 1073 } 1074 rtl::OUString key = processLang(Language) + aSlash + jar; 1075 1076 osl::MutexGuard aGuard( m_aMutex ); 1077 1078 ZipFileTable::iterator it = 1079 m_aZipFileTable.insert( ZipFileTable::value_type( key,Reference< XHierarchicalNameAccess >(0) ) ).first; 1080 1081 if( ! it->second.is() ) 1082 { 1083 rtl::OUString zipFile; 1084 try 1085 { 1086 // Extension jar file? Search for ? 1087 sal_Int32 nQuestionMark1 = jar.indexOf( sal_Unicode('?') ); 1088 sal_Int32 nQuestionMark2 = jar.lastIndexOf( sal_Unicode('?') ); 1089 if( nQuestionMark1 != -1 && nQuestionMark2 != -1 && nQuestionMark1 != nQuestionMark2 ) 1090 { 1091 ::rtl::OUString aExtensionPath = jar.copy( nQuestionMark1 + 1, nQuestionMark2 - nQuestionMark1 - 1 ); 1092 ::rtl::OUString aPureJar = jar.copy( nQuestionMark2 + 1 ); 1093 1094 rtl::OUStringBuffer aStrBuf; 1095 aStrBuf.append( aExtensionPath ); 1096 aStrBuf.append( aSlash ); 1097 aStrBuf.append( aPureJar ); 1098 1099 zipFile = expandURL( aStrBuf.makeStringAndClear() ); 1100 } 1101 else 1102 { 1103 zipFile = getInstallPathAsURL() + key; 1104 } 1105 1106 Sequence< Any > aArguments( 2 ); 1107 1108 XInputStream_impl* p = new XInputStream_impl( zipFile ); 1109 if( p->CtorSuccess() ) 1110 { 1111 Reference< XInputStream > xInputStream( p ); 1112 aArguments[ 0 ] <<= xInputStream; 1113 } 1114 else 1115 { 1116 delete p; 1117 aArguments[ 0 ] <<= zipFile; 1118 } 1119 1120 // let ZipPackage be used ( no manifest.xml is required ) 1121 beans::NamedValue aArg; 1122 aArg.Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "StorageFormat" ) ); 1123 aArg.Value <<= ZIP_STORAGE_FORMAT_STRING; 1124 aArguments[ 1 ] <<= aArg; 1125 1126 Reference< XInterface > xIfc 1127 = m_xSMgr->createInstanceWithArgumentsAndContext( 1128 rtl::OUString::createFromAscii( 1129 "com.sun.star.packages.comp.ZipPackage" ), 1130 aArguments, m_xContext ); 1131 1132 if ( xIfc.is() ) 1133 { 1134 it->second = Reference< XHierarchicalNameAccess >( xIfc, UNO_QUERY ); 1135 1136 VOS_ENSURE( it->second.is(), 1137 "ContentProvider::createPackage - " 1138 "Got no hierarchical name access!" ); 1139 1140 } 1141 } 1142 catch ( RuntimeException & ) 1143 { 1144 } 1145 catch ( Exception & ) 1146 { 1147 } 1148 } 1149 1150 return it->second; 1151 } 1152 1153 Reference< XHierarchicalNameAccess > Databases::findJarFileForPath 1154 ( const rtl::OUString& jar, const rtl::OUString& Language, 1155 const rtl::OUString& path, rtl::OUString* o_pExtensionPath, 1156 rtl::OUString* o_pExtensionRegistryPath ) 1157 { 1158 Reference< XHierarchicalNameAccess > xNA; 1159 if( ! jar.getLength() || 1160 ! Language.getLength() ) 1161 { 1162 return xNA; 1163 } 1164 1165 JarFileIterator aJarFileIt( m_xContext, *this, jar, Language ); 1166 Reference< XHierarchicalNameAccess > xTestNA; 1167 Reference< deployment::XPackage > xParentPackageBundle; 1168 while( (xTestNA = aJarFileIt.nextJarFile( xParentPackageBundle, o_pExtensionPath, o_pExtensionRegistryPath )).is() ) 1169 { 1170 if( xTestNA.is() && xTestNA->hasByHierarchicalName( path ) ) 1171 { 1172 bool bSuccess = true; 1173 if( xParentPackageBundle.is() ) 1174 { 1175 rtl::OUString aIdentifierInPath; 1176 sal_Int32 nFindSlash = path.indexOf( '/' ); 1177 if( nFindSlash != -1 ) 1178 aIdentifierInPath = path.copy( 0, nFindSlash ); 1179 1180 beans::Optional<rtl::OUString> aIdentifierOptional = xParentPackageBundle->getIdentifier(); 1181 if( aIdentifierInPath.getLength() && aIdentifierOptional.IsPresent ) 1182 { 1183 rtl::OUString aUnencodedIdentifier = aIdentifierOptional.Value; 1184 rtl::OUString aIdentifier = rtl::Uri::encode( aUnencodedIdentifier, 1185 rtl_UriCharClassPchar, rtl_UriEncodeIgnoreEscapes, RTL_TEXTENCODING_UTF8 ); 1186 1187 if( !aIdentifierInPath.equals( aIdentifier ) ) 1188 { 1189 // path does not start with extension identifier -> ignore 1190 bSuccess = false; 1191 } 1192 } 1193 else 1194 { 1195 // No identifier -> ignore 1196 bSuccess = false; 1197 } 1198 } 1199 1200 if( bSuccess ) 1201 { 1202 xNA = xTestNA; 1203 break; 1204 } 1205 } 1206 } 1207 1208 return xNA; 1209 } 1210 1211 void Databases::popupDocument( URLParameter* urlPar,char **buffer,int *byteCount ) 1212 { 1213 const char* pop1 = 1214 " <html> " 1215 " <head> " 1216 " <help:css-file-link xmlns:help=\"http://openoffice.org/2000/help\"/> " 1217 " </head> " 1218 " <body> " 1219 " <help:popup-cut Id=\""; 1220 const sal_Int32 l1 = strlen( pop1 ); 1221 1222 const char* pop3 = "\" Eid=\""; 1223 const sal_Int32 l3 = strlen( pop3 ); 1224 1225 const char* pop5 = 1226 "\" xmlns:help=\"http://openoffice.org/2000/help\"></help:popup-cut> " 1227 " </body> " 1228 " </html>"; 1229 const sal_Int32 l5 = strlen( pop5 ); 1230 sal_Int32 l2,l4; 1231 1232 rtl::OUString val = urlPar->get_id(); 1233 rtl::OString pop2O( val.getStr(),l2 = val.getLength(),RTL_TEXTENCODING_UTF8 ); 1234 const char* pop2 = pop2O.getStr(); 1235 1236 val = urlPar->get_eid(); 1237 rtl::OString pop4O( val.getStr(),l4 = val.getLength(),RTL_TEXTENCODING_UTF8 ); 1238 const char* pop4 = pop4O.getStr(); 1239 1240 (*byteCount) = l1 + l2 + l3 + l4 + l5; 1241 1242 *buffer = new char[ 1+*byteCount ]; 1243 1244 rtl_copyMemory( *buffer,pop1,l1 ); 1245 rtl_copyMemory( *buffer+l1,pop2,l2 ); 1246 rtl_copyMemory( *buffer+(l1+l2),pop3,l3 ); 1247 rtl_copyMemory( *buffer+(l1+l2+l3),pop4,l4 ); 1248 rtl_copyMemory( *buffer+(l1+l2+l3+l4),pop5,l5 ); 1249 (*buffer)[*byteCount] = 0; 1250 } 1251 1252 1253 void Databases::changeCSS(const rtl::OUString& newStyleSheet) 1254 { 1255 m_aCSS = newStyleSheet.toAsciiLowerCase(); 1256 delete[] m_pCustomCSSDoc, m_pCustomCSSDoc = 0,m_nCustomCSSDocLength = 0; 1257 } 1258 1259 1260 1261 void Databases::cascadingStylesheet( const rtl::OUString& Language, 1262 char** buffer, 1263 int* byteCount ) 1264 { 1265 if( ! m_pCustomCSSDoc ) 1266 { 1267 int retry = 2; 1268 bool error = true; 1269 rtl::OUString fileURL; 1270 1271 sal_Bool bHighContrastMode = sal_False; 1272 rtl::OUString aCSS( m_aCSS ); 1273 if ( aCSS.compareToAscii( "default" ) == 0 ) 1274 { 1275 // #i50760: "default" needs to adapt HC mode 1276 uno::Reference< awt::XToolkit > xToolkit = uno::Reference< awt::XToolkit >( 1277 ::comphelper::getProcessServiceFactory()->createInstance( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.awt.Toolkit" ) ) ), uno::UNO_QUERY ); 1278 if ( xToolkit.is() ) 1279 { 1280 uno::Reference< awt::XExtendedToolkit > xExtToolkit( xToolkit, uno::UNO_QUERY ); 1281 if ( xExtToolkit.is() ) 1282 { 1283 uno::Reference< awt::XTopWindow > xTopWindow = xExtToolkit->getActiveTopWindow(); 1284 if ( xTopWindow.is() ) 1285 { 1286 uno::Reference< awt::XVclWindowPeer > xVclWindowPeer( xTopWindow, uno::UNO_QUERY ); 1287 if ( xVclWindowPeer.is() ) 1288 { 1289 uno::Any aHCMode = xVclWindowPeer->getProperty( rtl::OUString::createFromAscii( "HighContrastMode" ) ); 1290 if ( ( aHCMode >>= bHighContrastMode ) && bHighContrastMode ) 1291 aCSS = rtl::OUString::createFromAscii( "highcontrastblack" ); 1292 } 1293 } 1294 } 1295 } 1296 } 1297 1298 while( error && retry ) 1299 { 1300 1301 if( retry == 2 ) 1302 fileURL = 1303 getInstallPathAsURL() + 1304 processLang( Language ) + 1305 rtl::OUString::createFromAscii( "/" ) + 1306 aCSS + 1307 rtl::OUString::createFromAscii( ".css" ); 1308 else if( retry == 1 ) 1309 fileURL = 1310 getInstallPathAsURL() + 1311 aCSS + 1312 rtl::OUString::createFromAscii( ".css" ); 1313 1314 osl::DirectoryItem aDirItem; 1315 osl::File aFile( fileURL ); 1316 osl::FileStatus aStatus( FileStatusMask_FileSize ); 1317 1318 if( osl::FileBase::E_None == osl::DirectoryItem::get( fileURL,aDirItem ) && 1319 osl::FileBase::E_None == aFile.open( OpenFlag_Read ) && 1320 osl::FileBase::E_None == aDirItem.getFileStatus( aStatus ) ) 1321 { 1322 m_nCustomCSSDocLength = int( aStatus.getFileSize() ); 1323 m_pCustomCSSDoc = new char[ 1 + m_nCustomCSSDocLength ]; 1324 m_pCustomCSSDoc[ m_nCustomCSSDocLength ] = 0; 1325 sal_uInt64 a = m_nCustomCSSDocLength,b = m_nCustomCSSDocLength; 1326 aFile.read( m_pCustomCSSDoc,a,b ); 1327 aFile.close(); 1328 error = false; 1329 } 1330 1331 --retry; 1332 if ( !retry && error && bHighContrastMode ) 1333 { 1334 // fall back to default css 1335 aCSS = rtl::OUString::createFromAscii( "default" ); 1336 retry = 2; 1337 bHighContrastMode = sal_False; 1338 } 1339 } 1340 1341 if( error ) 1342 { 1343 m_nCustomCSSDocLength = 0; 1344 m_pCustomCSSDoc = new char[ 1 ]; // Initialize with 1 to avoid gcc compiler warning 1345 } 1346 } 1347 1348 *byteCount = m_nCustomCSSDocLength; 1349 *buffer = new char[ 1 + *byteCount ]; 1350 (*buffer)[*byteCount] = 0; 1351 rtl_copyMemory( *buffer,m_pCustomCSSDoc,m_nCustomCSSDocLength ); 1352 1353 } 1354 1355 1356 void Databases::setActiveText( const rtl::OUString& Module, 1357 const rtl::OUString& Language, 1358 const rtl::OUString& Id, 1359 char** buffer, 1360 int* byteCount ) 1361 { 1362 DataBaseIterator aDbIt( m_xContext, *this, Module, Language, true ); 1363 1364 // #i84550 Cache information about failed ids 1365 rtl::OString id( Id.getStr(),Id.getLength(),RTL_TEXTENCODING_UTF8 ); 1366 EmptyActiveTextSet::iterator it = m_aEmptyActiveTextSet.find( id ); 1367 bool bFoundAsEmpty = ( it != m_aEmptyActiveTextSet.end() ); 1368 Dbt data; 1369 DBData aDBData; 1370 1371 int nSize = 0; 1372 const sal_Char* pData = NULL; 1373 1374 bool bSuccess = false; 1375 if( !bFoundAsEmpty ) 1376 { 1377 Db* db; 1378 Dbt key( static_cast< void* >( const_cast< sal_Char* >( id.getStr() ) ),id.getLength() ); 1379 while( !bSuccess && (db = aDbIt.nextDb()) != NULL ) 1380 { 1381 DBHelp* pDBHelp = db->getDBHelp(); 1382 if( pDBHelp != NULL ) 1383 { 1384 bSuccess = pDBHelp->getValueForKey( id, aDBData ); 1385 nSize = aDBData.getSize(); 1386 pData = aDBData.getData(); 1387 } 1388 else 1389 { 1390 int err = db->get( 0, &key, &data, 0 ); 1391 if( err == 0 ) 1392 { 1393 bSuccess = true; 1394 nSize = data.get_size(); 1395 pData = static_cast<sal_Char*>( data.get_data() ); 1396 } 1397 } 1398 } 1399 } 1400 1401 if( bSuccess ) 1402 { 1403 // ensure existence of tmp after for 1404 rtl::OString tmp; 1405 for( int i = 0; i < nSize; ++i ) 1406 if( pData[i] == '%' || pData[i] == '$' ) 1407 { 1408 // need of replacement 1409 rtl::OUString temp = rtl::OUString( pData, nSize, RTL_TEXTENCODING_UTF8 ); 1410 replaceName( temp ); 1411 tmp = rtl::OString( temp.getStr(), 1412 temp.getLength(), 1413 RTL_TEXTENCODING_UTF8 ); 1414 nSize = tmp.getLength(); 1415 pData = tmp.getStr(); 1416 break; 1417 } 1418 1419 *byteCount = nSize; 1420 *buffer = new char[ 1 + nSize ]; 1421 (*buffer)[nSize] = 0; 1422 rtl_copyMemory( *buffer, pData, nSize ); 1423 } 1424 else 1425 { 1426 *byteCount = 0; 1427 *buffer = new char[1]; // Initialize with 1 to avoid compiler warnings 1428 if( !bFoundAsEmpty ) 1429 m_aEmptyActiveTextSet.insert( id ); 1430 } 1431 } 1432 1433 1434 void Databases::setInstallPath( const rtl::OUString& aInstDir ) 1435 { 1436 osl::MutexGuard aGuard( m_aMutex ); 1437 1438 osl::FileBase::getFileURLFromSystemPath( aInstDir,m_aInstallDirectory ); 1439 //TODO: check returned error code 1440 1441 if( m_aInstallDirectory.lastIndexOf( sal_Unicode( '/' ) ) != m_aInstallDirectory.getLength() - 1 ) 1442 m_aInstallDirectory += rtl::OUString::createFromAscii( "/" ); 1443 1444 m_aInstallDirectoryWithoutEncoding = rtl::Uri::decode( m_aInstallDirectory, 1445 rtl_UriDecodeWithCharset, 1446 RTL_TEXTENCODING_UTF8 ); 1447 } 1448 1449 1450 //=================================================================== 1451 // class ExtensionIteratorBase 1452 1453 ExtensionHelpExistanceMap ExtensionIteratorBase::aHelpExistanceMap; 1454 1455 ExtensionIteratorBase::ExtensionIteratorBase( Reference< XComponentContext > xContext, 1456 Databases& rDatabases, const rtl::OUString& aInitialModule, const rtl::OUString& aLanguage ) 1457 : m_xContext( xContext ) 1458 , m_rDatabases( rDatabases ) 1459 , m_eState( INITIAL_MODULE ) 1460 , m_aInitialModule( aInitialModule ) 1461 , m_aLanguage( aLanguage ) 1462 { 1463 init(); 1464 } 1465 1466 ExtensionIteratorBase::ExtensionIteratorBase( Databases& rDatabases, 1467 const rtl::OUString& aInitialModule, const rtl::OUString& aLanguage ) 1468 : m_rDatabases( rDatabases ) 1469 , m_eState( INITIAL_MODULE ) 1470 , m_aInitialModule( aInitialModule ) 1471 , m_aLanguage( aLanguage ) 1472 { 1473 init(); 1474 } 1475 1476 void ExtensionIteratorBase::init() 1477 { 1478 if( !m_xContext.is() ) 1479 { 1480 Reference< XMultiServiceFactory > xFactory = comphelper::getProcessServiceFactory(); 1481 Reference< XPropertySet > xProps( xFactory, UNO_QUERY ); 1482 OSL_ASSERT( xProps.is() ); 1483 if (xProps.is()) 1484 { 1485 xProps->getPropertyValue( 1486 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("DefaultContext") ) ) >>= m_xContext; 1487 OSL_ASSERT( m_xContext.is() ); 1488 } 1489 } 1490 if( !m_xContext.is() ) 1491 { 1492 throw RuntimeException( 1493 ::rtl::OUString::createFromAscii( "ExtensionIteratorBase::init(), no XComponentContext" ), 1494 Reference< XInterface >() ); 1495 } 1496 1497 Reference< XMultiComponentFactory > xSMgr( m_xContext->getServiceManager(), UNO_QUERY ); 1498 m_xSFA = Reference< ucb::XSimpleFileAccess >( 1499 xSMgr->createInstanceWithContext( rtl::OUString::createFromAscii( "com.sun.star.ucb.SimpleFileAccess" ), 1500 m_xContext ), UNO_QUERY_THROW ); 1501 1502 m_bUserPackagesLoaded = false; 1503 m_bSharedPackagesLoaded = false; 1504 m_bBundledPackagesLoaded = false; 1505 m_iUserPackage = 0; 1506 m_iSharedPackage = 0; 1507 m_iBundledPackage = 0; 1508 } 1509 1510 Reference< deployment::XPackage > ExtensionIteratorBase::implGetHelpPackageFromPackage 1511 ( Reference< deployment::XPackage > xPackage, Reference< deployment::XPackage >& o_xParentPackageBundle ) 1512 { 1513 o_xParentPackageBundle.clear(); 1514 1515 Reference< deployment::XPackage > xHelpPackage; 1516 if( !xPackage.is() ) 1517 return xHelpPackage; 1518 1519 // #i84550 Cache information about help content in extension 1520 rtl::OUString aExtensionPath = xPackage->getURL(); 1521 ExtensionHelpExistanceMap::iterator it = aHelpExistanceMap.find( aExtensionPath ); 1522 bool bFound = ( it != aHelpExistanceMap.end() ); 1523 bool bHasHelp = bFound ? it->second : false; 1524 if( bFound && !bHasHelp ) 1525 return xHelpPackage; 1526 1527 // Check if parent package is registered 1528 beans::Optional< beans::Ambiguous<sal_Bool> > option( xPackage->isRegistered 1529 ( Reference<task::XAbortChannel>(), Reference<ucb::XCommandEnvironment>() ) ); 1530 bool bRegistered = false; 1531 if( option.IsPresent ) 1532 { 1533 beans::Ambiguous<sal_Bool> const & reg = option.Value; 1534 if( !reg.IsAmbiguous && reg.Value ) 1535 bRegistered = true; 1536 } 1537 if( bRegistered ) 1538 { 1539 if( xPackage->isBundle() ) 1540 { 1541 Sequence< Reference< deployment::XPackage > > aPkgSeq = xPackage->getBundle 1542 ( Reference<task::XAbortChannel>(), Reference<ucb::XCommandEnvironment>() ); 1543 sal_Int32 nPkgCount = aPkgSeq.getLength(); 1544 const Reference< deployment::XPackage >* pSeq = aPkgSeq.getConstArray(); 1545 for( sal_Int32 iPkg = 0 ; iPkg < nPkgCount ; ++iPkg ) 1546 { 1547 const Reference< deployment::XPackage > xSubPkg = pSeq[ iPkg ]; 1548 const Reference< deployment::XPackageTypeInfo > xPackageTypeInfo = xSubPkg->getPackageType(); 1549 rtl::OUString aMediaType = xPackageTypeInfo->getMediaType(); 1550 if( aMediaType.equals( aHelpMediaType ) ) 1551 { 1552 xHelpPackage = xSubPkg; 1553 o_xParentPackageBundle = xPackage; 1554 break; 1555 } 1556 } 1557 } 1558 else 1559 { 1560 const Reference< deployment::XPackageTypeInfo > xPackageTypeInfo = xPackage->getPackageType(); 1561 rtl::OUString aMediaType = xPackageTypeInfo->getMediaType(); 1562 if( aMediaType.equals( aHelpMediaType ) ) 1563 xHelpPackage = xPackage; 1564 } 1565 } 1566 1567 if( !bFound ) 1568 aHelpExistanceMap[ aExtensionPath ] = xHelpPackage.is(); 1569 1570 return xHelpPackage; 1571 } 1572 1573 Reference< deployment::XPackage > ExtensionIteratorBase::implGetNextUserHelpPackage 1574 ( Reference< deployment::XPackage >& o_xParentPackageBundle ) 1575 { 1576 Reference< deployment::XPackage > xHelpPackage; 1577 1578 if( !m_bUserPackagesLoaded ) 1579 { 1580 Reference< XExtensionManager > xExtensionManager = ExtensionManager::get(m_xContext); 1581 m_aUserPackagesSeq = xExtensionManager->getDeployedExtensions 1582 ( rtl::OUString::createFromAscii("user"), Reference< task::XAbortChannel >(), Reference< ucb::XCommandEnvironment >() ); 1583 m_bUserPackagesLoaded = true; 1584 } 1585 1586 if( m_iUserPackage == m_aUserPackagesSeq.getLength() ) 1587 { 1588 m_eState = SHARED_EXTENSIONS; // Later: SHARED_MODULE 1589 } 1590 else 1591 { 1592 const Reference< deployment::XPackage >* pUserPackages = m_aUserPackagesSeq.getConstArray(); 1593 Reference< deployment::XPackage > xPackage = pUserPackages[ m_iUserPackage++ ]; 1594 VOS_ENSURE( xPackage.is(), "ExtensionIteratorBase::implGetNextUserHelpPackage(): Invalid package" ); 1595 xHelpPackage = implGetHelpPackageFromPackage( xPackage, o_xParentPackageBundle ); 1596 } 1597 1598 return xHelpPackage; 1599 } 1600 1601 Reference< deployment::XPackage > ExtensionIteratorBase::implGetNextSharedHelpPackage 1602 ( Reference< deployment::XPackage >& o_xParentPackageBundle ) 1603 { 1604 Reference< deployment::XPackage > xHelpPackage; 1605 1606 if( !m_bSharedPackagesLoaded ) 1607 { 1608 Reference< XExtensionManager > xExtensionManager = ExtensionManager::get(m_xContext); 1609 m_aSharedPackagesSeq = xExtensionManager->getDeployedExtensions 1610 ( rtl::OUString::createFromAscii("shared"), Reference< task::XAbortChannel >(), Reference< ucb::XCommandEnvironment >() ); 1611 m_bSharedPackagesLoaded = true; 1612 } 1613 1614 if( m_iSharedPackage == m_aSharedPackagesSeq.getLength() ) 1615 { 1616 m_eState = BUNDLED_EXTENSIONS; 1617 } 1618 else 1619 { 1620 const Reference< deployment::XPackage >* pSharedPackages = m_aSharedPackagesSeq.getConstArray(); 1621 Reference< deployment::XPackage > xPackage = pSharedPackages[ m_iSharedPackage++ ]; 1622 VOS_ENSURE( xPackage.is(), "ExtensionIteratorBase::implGetNextSharedHelpPackage(): Invalid package" ); 1623 xHelpPackage = implGetHelpPackageFromPackage( xPackage, o_xParentPackageBundle ); 1624 } 1625 1626 return xHelpPackage; 1627 } 1628 1629 Reference< deployment::XPackage > ExtensionIteratorBase::implGetNextBundledHelpPackage 1630 ( Reference< deployment::XPackage >& o_xParentPackageBundle ) 1631 { 1632 Reference< deployment::XPackage > xHelpPackage; 1633 1634 if( !m_bBundledPackagesLoaded ) 1635 { 1636 Reference< XExtensionManager > xExtensionManager = ExtensionManager::get(m_xContext); 1637 m_aBundledPackagesSeq = xExtensionManager->getDeployedExtensions 1638 ( rtl::OUString::createFromAscii("bundled"), Reference< task::XAbortChannel >(), Reference< ucb::XCommandEnvironment >() ); 1639 m_bBundledPackagesLoaded = true; 1640 } 1641 1642 if( m_iBundledPackage == m_aBundledPackagesSeq.getLength() ) 1643 { 1644 m_eState = END_REACHED; 1645 } 1646 else 1647 { 1648 const Reference< deployment::XPackage >* pBundledPackages = 1649 m_aBundledPackagesSeq.getConstArray(); 1650 Reference< deployment::XPackage > xPackage = pBundledPackages[ m_iBundledPackage++ ]; 1651 VOS_ENSURE( xPackage.is(), "ExtensionIteratorBase::implGetNextBundledHelpPackage(): Invalid package" ); 1652 xHelpPackage = implGetHelpPackageFromPackage( xPackage, o_xParentPackageBundle ); 1653 } 1654 1655 return xHelpPackage; 1656 } 1657 1658 rtl::OUString ExtensionIteratorBase::implGetFileFromPackage( 1659 const rtl::OUString& rFileExtension, Reference< deployment::XPackage > xPackage ) 1660 { 1661 // No extension -> search for pure language folder 1662 bool bLangFolderOnly = (rFileExtension.getLength() == 0); 1663 1664 rtl::OUString aFile; 1665 rtl::OUString aLanguage = m_aLanguage; 1666 for( sal_Int32 iPass = 0 ; iPass < 2 ; ++iPass ) 1667 { 1668 rtl::OUStringBuffer aStrBuf; 1669 aStrBuf.append( xPackage->getRegistrationDataURL().Value); 1670 aStrBuf.append( aSlash ); 1671 aStrBuf.append( aLanguage ); 1672 if( !bLangFolderOnly ) 1673 { 1674 aStrBuf.append( aSlash ); 1675 aStrBuf.append( aHelpFilesBaseName ); 1676 aStrBuf.append( rFileExtension ); 1677 } 1678 1679 aFile = m_rDatabases.expandURL( aStrBuf.makeStringAndClear() ); 1680 if( iPass == 0 ) 1681 { 1682 if( m_xSFA->exists( aFile ) ) 1683 break; 1684 1685 ::std::vector< ::rtl::OUString > av; 1686 implGetLanguageVectorFromPackage( av, xPackage ); 1687 ::std::vector< ::rtl::OUString >::const_iterator pFound = av.end(); 1688 try 1689 { 1690 pFound = ::comphelper::Locale::getFallback( av, m_aLanguage ); 1691 } 1692 catch( ::comphelper::Locale::MalFormedLocaleException& ) 1693 {} 1694 if( pFound != av.end() ) 1695 aLanguage = *pFound; 1696 } 1697 } 1698 return aFile; 1699 } 1700 1701 inline bool isLetter( sal_Unicode c ) 1702 { 1703 bool bLetter = ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')); 1704 return bLetter; 1705 } 1706 1707 void ExtensionIteratorBase::implGetLanguageVectorFromPackage( ::std::vector< ::rtl::OUString > &rv, 1708 com::sun::star::uno::Reference< com::sun::star::deployment::XPackage > xPackage ) 1709 { 1710 rv.clear(); 1711 rtl::OUString aExtensionPath = xPackage->getURL(); 1712 Sequence< rtl::OUString > aEntrySeq = m_xSFA->getFolderContents( aExtensionPath, true ); 1713 1714 const rtl::OUString* pSeq = aEntrySeq.getConstArray(); 1715 sal_Int32 nCount = aEntrySeq.getLength(); 1716 for( sal_Int32 i = 0 ; i < nCount ; ++i ) 1717 { 1718 rtl::OUString aEntry = pSeq[i]; 1719 if( m_xSFA->isFolder( aEntry ) ) 1720 { 1721 sal_Int32 nLastSlash = aEntry.lastIndexOf( '/' ); 1722 if( nLastSlash != -1 ) 1723 { 1724 rtl::OUString aPureEntry = aEntry.copy( nLastSlash + 1 ); 1725 1726 // Check language sceme 1727 int nLen = aPureEntry.getLength(); 1728 const sal_Unicode* pc = aPureEntry.getStr(); 1729 bool bStartCanBeLanguage = ( nLen >= 2 && isLetter( pc[0] ) && isLetter( pc[1] ) ); 1730 bool bIsLanguage = bStartCanBeLanguage && 1731 ( nLen == 2 || (nLen == 5 && pc[2] == '-' && isLetter( pc[3] ) && isLetter( pc[4] )) ); 1732 if( bIsLanguage ) 1733 rv.push_back( aPureEntry ); 1734 } 1735 } 1736 } 1737 } 1738 1739 1740 //=================================================================== 1741 // class DataBaseIterator 1742 1743 Db* DataBaseIterator::nextDb( rtl::OUString* o_pExtensionPath, rtl::OUString* o_pExtensionRegistryPath ) 1744 { 1745 Db* pRetDb = NULL; 1746 1747 while( !pRetDb && m_eState != END_REACHED ) 1748 { 1749 switch( m_eState ) 1750 { 1751 case INITIAL_MODULE: 1752 pRetDb = m_rDatabases.getBerkeley( m_aInitialModule, m_aLanguage, m_bHelpText ); 1753 m_eState = USER_EXTENSIONS; // Later: SHARED_MODULE 1754 break; 1755 1756 // Later: 1757 //case SHARED_MODULE 1758 //... 1759 1760 case USER_EXTENSIONS: 1761 { 1762 Reference< deployment::XPackage > xParentPackageBundle; 1763 Reference< deployment::XPackage > xHelpPackage = implGetNextUserHelpPackage( xParentPackageBundle ); 1764 if( !xHelpPackage.is() ) 1765 break; 1766 pRetDb = implGetDbFromPackage( xHelpPackage, o_pExtensionPath, o_pExtensionRegistryPath ); 1767 break; 1768 } 1769 1770 case SHARED_EXTENSIONS: 1771 { 1772 Reference< deployment::XPackage > xParentPackageBundle; 1773 Reference< deployment::XPackage > xHelpPackage = implGetNextSharedHelpPackage( xParentPackageBundle ); 1774 if( !xHelpPackage.is() ) 1775 break; 1776 1777 pRetDb = implGetDbFromPackage( xHelpPackage, o_pExtensionPath, o_pExtensionRegistryPath ); 1778 break; 1779 } 1780 1781 case BUNDLED_EXTENSIONS: 1782 { 1783 Reference< deployment::XPackage > xParentPackageBundle; 1784 Reference< deployment::XPackage > xHelpPackage = implGetNextBundledHelpPackage( xParentPackageBundle ); 1785 if( !xHelpPackage.is() ) 1786 break; 1787 1788 pRetDb = implGetDbFromPackage( xHelpPackage, o_pExtensionPath, o_pExtensionRegistryPath ); 1789 break; 1790 } 1791 1792 case END_REACHED: 1793 VOS_ENSURE( false, "DataBaseIterator::nextDb(): Invalid case END_REACHED" ); 1794 break; 1795 } 1796 } 1797 1798 return pRetDb; 1799 } 1800 1801 Db* DataBaseIterator::implGetDbFromPackage( Reference< deployment::XPackage > xPackage, 1802 rtl::OUString* o_pExtensionPath, rtl::OUString* o_pExtensionRegistryPath ) 1803 { 1804 1805 beans::Optional< ::rtl::OUString> optRegData; 1806 try 1807 { 1808 optRegData = xPackage->getRegistrationDataURL(); 1809 } 1810 catch ( deployment::ExtensionRemovedException&) 1811 { 1812 return NULL; 1813 } 1814 1815 Db* pRetDb = NULL; 1816 if (optRegData.IsPresent && optRegData.Value.getLength() > 0) 1817 { 1818 rtl::OUString aRegDataUrl(optRegData.Value); 1819 aRegDataUrl += aSlash; 1820 1821 rtl::OUString aUsedLanguage = m_aLanguage; 1822 pRetDb = m_rDatabases.getBerkeley( 1823 aHelpFilesBaseName, aUsedLanguage, m_bHelpText, &aRegDataUrl); 1824 1825 // Language fallback 1826 if( !pRetDb ) 1827 { 1828 ::std::vector< ::rtl::OUString > av; 1829 implGetLanguageVectorFromPackage( av, xPackage ); 1830 ::std::vector< ::rtl::OUString >::const_iterator pFound = av.end(); 1831 try 1832 { 1833 pFound = ::comphelper::Locale::getFallback( av, m_aLanguage ); 1834 } 1835 catch( ::comphelper::Locale::MalFormedLocaleException& ) 1836 {} 1837 if( pFound != av.end() ) 1838 { 1839 aUsedLanguage = *pFound; 1840 pRetDb = m_rDatabases.getBerkeley( 1841 aHelpFilesBaseName, aUsedLanguage, m_bHelpText, &aRegDataUrl); 1842 } 1843 } 1844 1845 if( o_pExtensionPath ) 1846 *o_pExtensionPath = aRegDataUrl + aUsedLanguage; 1847 1848 if( o_pExtensionRegistryPath ) 1849 *o_pExtensionRegistryPath = xPackage->getURL() + aSlash + aUsedLanguage; 1850 } 1851 1852 return pRetDb; 1853 } 1854 1855 1856 //=================================================================== 1857 // class KeyDataBaseFileIterator 1858 1859 //returns a file URL 1860 rtl::OUString KeyDataBaseFileIterator::nextDbFile( bool& o_rbExtension ) 1861 { 1862 rtl::OUString aRetFile; 1863 1864 while( !aRetFile.getLength() && m_eState != END_REACHED ) 1865 { 1866 switch( m_eState ) 1867 { 1868 case INITIAL_MODULE: 1869 aRetFile = 1870 m_rDatabases.getInstallPathAsURL() + 1871 m_rDatabases.processLang( m_aLanguage ) + aSlash + m_aInitialModule + 1872 rtl::OUString::createFromAscii( ".key" ); 1873 1874 o_rbExtension = false; 1875 1876 m_eState = USER_EXTENSIONS; // Later: SHARED_MODULE 1877 break; 1878 1879 // Later: 1880 //case SHARED_MODULE 1881 //... 1882 1883 case USER_EXTENSIONS: 1884 { 1885 Reference< deployment::XPackage > xParentPackageBundle; 1886 Reference< deployment::XPackage > xHelpPackage = implGetNextUserHelpPackage( xParentPackageBundle ); 1887 if( !xHelpPackage.is() ) 1888 break; 1889 1890 aRetFile = implGetDbFileFromPackage( xHelpPackage ); 1891 o_rbExtension = true; 1892 break; 1893 } 1894 1895 case SHARED_EXTENSIONS: 1896 { 1897 Reference< deployment::XPackage > xParentPackageBundle; 1898 Reference< deployment::XPackage > xHelpPackage = implGetNextSharedHelpPackage( xParentPackageBundle ); 1899 if( !xHelpPackage.is() ) 1900 break; 1901 1902 aRetFile = implGetDbFileFromPackage( xHelpPackage ); 1903 o_rbExtension = true; 1904 break; 1905 } 1906 1907 case BUNDLED_EXTENSIONS: 1908 { 1909 Reference< deployment::XPackage > xParentPackageBundle; 1910 Reference< deployment::XPackage > xHelpPackage = implGetNextBundledHelpPackage( xParentPackageBundle ); 1911 if( !xHelpPackage.is() ) 1912 break; 1913 1914 aRetFile = implGetDbFileFromPackage( xHelpPackage ); 1915 o_rbExtension = true; 1916 break; 1917 } 1918 1919 case END_REACHED: 1920 VOS_ENSURE( false, "DataBaseIterator::nextDbFile(): Invalid case END_REACHED" ); 1921 break; 1922 } 1923 } 1924 1925 return aRetFile; 1926 } 1927 1928 //Returns a file URL, that does not contain macros 1929 rtl::OUString KeyDataBaseFileIterator::implGetDbFileFromPackage 1930 ( Reference< deployment::XPackage > xPackage ) 1931 { 1932 rtl::OUString aExpandedURL = 1933 implGetFileFromPackage( rtl::OUString::createFromAscii( ".key" ), xPackage ); 1934 1935 return aExpandedURL; 1936 } 1937 1938 1939 //=================================================================== 1940 // class JarFileIterator 1941 1942 Reference< XHierarchicalNameAccess > JarFileIterator::nextJarFile 1943 ( Reference< deployment::XPackage >& o_xParentPackageBundle, 1944 rtl::OUString* o_pExtensionPath, rtl::OUString* o_pExtensionRegistryPath ) 1945 { 1946 Reference< XHierarchicalNameAccess > xNA; 1947 1948 while( !xNA.is() && m_eState != END_REACHED ) 1949 { 1950 switch( m_eState ) 1951 { 1952 case INITIAL_MODULE: 1953 xNA = m_rDatabases.jarFile( m_aInitialModule, m_aLanguage ); 1954 m_eState = USER_EXTENSIONS; // Later: SHARED_MODULE 1955 break; 1956 1957 // Later: 1958 //case SHARED_MODULE 1959 //... 1960 1961 case USER_EXTENSIONS: 1962 { 1963 Reference< deployment::XPackage > xHelpPackage = implGetNextUserHelpPackage( o_xParentPackageBundle ); 1964 if( !xHelpPackage.is() ) 1965 break; 1966 1967 xNA = implGetJarFromPackage( xHelpPackage, o_pExtensionPath, o_pExtensionRegistryPath ); 1968 break; 1969 } 1970 1971 case SHARED_EXTENSIONS: 1972 { 1973 Reference< deployment::XPackage > xHelpPackage = implGetNextSharedHelpPackage( o_xParentPackageBundle ); 1974 if( !xHelpPackage.is() ) 1975 break; 1976 1977 xNA = implGetJarFromPackage( xHelpPackage, o_pExtensionPath, o_pExtensionRegistryPath ); 1978 break; 1979 } 1980 1981 case BUNDLED_EXTENSIONS: 1982 { 1983 Reference< deployment::XPackage > xHelpPackage = implGetNextBundledHelpPackage( o_xParentPackageBundle ); 1984 if( !xHelpPackage.is() ) 1985 break; 1986 1987 xNA = implGetJarFromPackage( xHelpPackage, o_pExtensionPath, o_pExtensionRegistryPath ); 1988 break; 1989 } 1990 1991 case END_REACHED: 1992 VOS_ENSURE( false, "JarFileIterator::nextJarFile(): Invalid case END_REACHED" ); 1993 break; 1994 } 1995 } 1996 1997 return xNA; 1998 } 1999 2000 Reference< XHierarchicalNameAccess > JarFileIterator::implGetJarFromPackage 2001 ( Reference< deployment::XPackage > xPackage, rtl::OUString* o_pExtensionPath, rtl::OUString* o_pExtensionRegistryPath ) 2002 { 2003 Reference< XHierarchicalNameAccess > xNA; 2004 2005 rtl::OUString zipFile = 2006 implGetFileFromPackage( rtl::OUString::createFromAscii( ".jar" ), xPackage ); 2007 2008 try 2009 { 2010 Sequence< Any > aArguments( 2 ); 2011 aArguments[ 0 ] <<= zipFile; 2012 2013 // let ZipPackage be used ( no manifest.xml is required ) 2014 beans::NamedValue aArg; 2015 aArg.Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "StorageFormat" ) ); 2016 aArg.Value <<= ZIP_STORAGE_FORMAT_STRING; 2017 aArguments[ 1 ] <<= aArg; 2018 2019 Reference< XMultiComponentFactory >xSMgr( m_xContext->getServiceManager(), UNO_QUERY ); 2020 Reference< XInterface > xIfc 2021 = xSMgr->createInstanceWithArgumentsAndContext( 2022 rtl::OUString::createFromAscii( 2023 "com.sun.star.packages.comp.ZipPackage" ), 2024 aArguments, m_xContext ); 2025 2026 if ( xIfc.is() ) 2027 { 2028 xNA = Reference< XHierarchicalNameAccess >( xIfc, UNO_QUERY ); 2029 2030 VOS_ENSURE( xNA.is(), 2031 "JarFileIterator::implGetJarFromPackage() - " 2032 "Got no hierarchical name access!" ); 2033 } 2034 } 2035 catch ( RuntimeException & ) 2036 {} 2037 catch ( Exception & ) 2038 {} 2039 2040 if( xNA.is() && o_pExtensionPath != NULL ) 2041 { 2042 // Extract path including language from file name 2043 sal_Int32 nLastSlash = zipFile.lastIndexOf( '/' ); 2044 if( nLastSlash != -1 ) 2045 *o_pExtensionPath = zipFile.copy( 0, nLastSlash ); 2046 2047 if( o_pExtensionRegistryPath != NULL ) 2048 { 2049 rtl::OUString& rPath = *o_pExtensionPath; 2050 sal_Int32 nLastSlashInPath = rPath.lastIndexOf( '/', rPath.getLength() - 1 ); 2051 2052 *o_pExtensionRegistryPath = xPackage->getURL(); 2053 *o_pExtensionRegistryPath += rPath.copy( nLastSlashInPath); 2054 } 2055 } 2056 2057 return xNA; 2058 } 2059 2060 2061 //=================================================================== 2062 // class IndexFolderIterator 2063 2064 rtl::OUString IndexFolderIterator::nextIndexFolder( bool& o_rbExtension, bool& o_rbTemporary ) 2065 { 2066 rtl::OUString aIndexFolder; 2067 2068 while( !aIndexFolder.getLength() && m_eState != END_REACHED ) 2069 { 2070 switch( m_eState ) 2071 { 2072 case INITIAL_MODULE: 2073 aIndexFolder = 2074 m_rDatabases.getInstallPathAsURL() + 2075 m_rDatabases.processLang( m_aLanguage ) + aSlash + m_aInitialModule + 2076 rtl::OUString::createFromAscii( ".idxl" ); 2077 2078 o_rbTemporary = false; 2079 o_rbExtension = false; 2080 2081 m_eState = USER_EXTENSIONS; // Later: SHARED_MODULE 2082 break; 2083 2084 // Later: 2085 //case SHARED_MODULE 2086 //... 2087 2088 case USER_EXTENSIONS: 2089 { 2090 Reference< deployment::XPackage > xParentPackageBundle; 2091 Reference< deployment::XPackage > xHelpPackage = implGetNextUserHelpPackage( xParentPackageBundle ); 2092 if( !xHelpPackage.is() ) 2093 break; 2094 2095 aIndexFolder = implGetIndexFolderFromPackage( o_rbTemporary, xHelpPackage ); 2096 o_rbExtension = true; 2097 break; 2098 } 2099 2100 case SHARED_EXTENSIONS: 2101 { 2102 Reference< deployment::XPackage > xParentPackageBundle; 2103 Reference< deployment::XPackage > xHelpPackage = implGetNextSharedHelpPackage( xParentPackageBundle ); 2104 if( !xHelpPackage.is() ) 2105 break; 2106 2107 aIndexFolder = implGetIndexFolderFromPackage( o_rbTemporary, xHelpPackage ); 2108 o_rbExtension = true; 2109 break; 2110 } 2111 2112 case BUNDLED_EXTENSIONS: 2113 { 2114 Reference< deployment::XPackage > xParentPackageBundle; 2115 Reference< deployment::XPackage > xHelpPackage = implGetNextBundledHelpPackage( xParentPackageBundle ); 2116 if( !xHelpPackage.is() ) 2117 break; 2118 2119 aIndexFolder = implGetIndexFolderFromPackage( o_rbTemporary, xHelpPackage ); 2120 o_rbExtension = true; 2121 break; 2122 } 2123 2124 case END_REACHED: 2125 VOS_ENSURE( false, "IndexFolderIterator::nextIndexFolder(): Invalid case END_REACHED" ); 2126 break; 2127 } 2128 } 2129 2130 return aIndexFolder; 2131 } 2132 2133 rtl::OUString IndexFolderIterator::implGetIndexFolderFromPackage( bool& o_rbTemporary, Reference< deployment::XPackage > xPackage ) 2134 { 2135 rtl::OUString aIndexFolder = 2136 implGetFileFromPackage( rtl::OUString::createFromAscii( ".idxl" ), xPackage ); 2137 2138 o_rbTemporary = false; 2139 if( !m_xSFA->isFolder( aIndexFolder ) ) 2140 { 2141 // i98680: Missing index? Try to generate now 2142 rtl::OUString aLangURL = implGetFileFromPackage( rtl::OUString(), xPackage ); 2143 if( m_xSFA->isFolder( aLangURL ) ) 2144 { 2145 // Test write access (shared extension may be read only) 2146 bool bIsWriteAccess = false; 2147 try 2148 { 2149 rtl::OUString aCreateTestFolder = aLangURL + rtl::OUString::createFromAscii( "CreateTestFolder" ); 2150 m_xSFA->createFolder( aCreateTestFolder ); 2151 if( m_xSFA->isFolder( aCreateTestFolder ) ) 2152 bIsWriteAccess = true; 2153 2154 m_xSFA->kill( aCreateTestFolder ); 2155 } 2156 catch (Exception &) 2157 {} 2158 2159 // TEST 2160 //bIsWriteAccess = false; 2161 2162 Reference< script::XInvocation > xInvocation; 2163 Reference< XMultiComponentFactory >xSMgr( m_xContext->getServiceManager(), UNO_QUERY ); 2164 try 2165 { 2166 xInvocation = Reference< script::XInvocation >( 2167 m_xContext->getServiceManager()->createInstanceWithContext( rtl::OUString::createFromAscii( 2168 "com.sun.star.help.HelpIndexer" ), m_xContext ) , UNO_QUERY ); 2169 2170 if( xInvocation.is() ) 2171 { 2172 Sequence<uno::Any> aParamsSeq( bIsWriteAccess ? 6 : 8 ); 2173 2174 aParamsSeq[0] = uno::makeAny( rtl::OUString::createFromAscii( "-lang" ) ); 2175 2176 rtl::OUString aLang; 2177 sal_Int32 nLastSlash = aLangURL.lastIndexOf( '/' ); 2178 if( nLastSlash != -1 ) 2179 aLang = aLangURL.copy( nLastSlash + 1 ); 2180 else 2181 aLang = rtl::OUString::createFromAscii( "en" ); 2182 aParamsSeq[1] = uno::makeAny( aLang ); 2183 2184 aParamsSeq[2] = uno::makeAny( rtl::OUString::createFromAscii( "-mod" ) ); 2185 aParamsSeq[3] = uno::makeAny( rtl::OUString::createFromAscii( "help" ) ); 2186 2187 rtl::OUString aZipDir = aLangURL; 2188 if( !bIsWriteAccess ) 2189 { 2190 rtl::OUString aTempFileURL; 2191 ::osl::FileBase::RC eErr = ::osl::File::createTempFile( 0, 0, &aTempFileURL ); 2192 if( eErr == ::osl::FileBase::E_None ) 2193 { 2194 rtl::OUString aTempDirURL = aTempFileURL; 2195 try 2196 { 2197 m_xSFA->kill( aTempDirURL ); 2198 } 2199 catch (Exception &) 2200 {} 2201 m_xSFA->createFolder( aTempDirURL ); 2202 2203 aZipDir = aTempDirURL; 2204 o_rbTemporary = true; 2205 } 2206 } 2207 2208 aParamsSeq[4] = uno::makeAny( rtl::OUString::createFromAscii( "-zipdir" ) ); 2209 rtl::OUString aSystemPath; 2210 osl::FileBase::getSystemPathFromFileURL( aZipDir, aSystemPath ); 2211 aParamsSeq[5] = uno::makeAny( aSystemPath ); 2212 2213 if( !bIsWriteAccess ) 2214 { 2215 aParamsSeq[6] = uno::makeAny( rtl::OUString::createFromAscii( "-srcdir" ) ); 2216 rtl::OUString aSrcDirVal; 2217 osl::FileBase::getSystemPathFromFileURL( aLangURL, aSrcDirVal ); 2218 aParamsSeq[7] = uno::makeAny( aSrcDirVal ); 2219 } 2220 2221 Sequence< sal_Int16 > aOutParamIndex; 2222 Sequence< uno::Any > aOutParam; 2223 uno::Any aRet = xInvocation->invoke( rtl::OUString::createFromAscii( "createIndex" ), 2224 aParamsSeq, aOutParamIndex, aOutParam ); 2225 2226 if( bIsWriteAccess ) 2227 aIndexFolder = implGetFileFromPackage( rtl::OUString::createFromAscii( ".idxl" ), xPackage ); 2228 else 2229 aIndexFolder = aZipDir + rtl::OUString::createFromAscii( "/help.idxl" ); 2230 } 2231 } 2232 catch (Exception &) 2233 {} 2234 } 2235 } 2236 2237 return aIndexFolder; 2238 } 2239 2240 void IndexFolderIterator::deleteTempIndexFolder( const rtl::OUString& aIndexFolder ) 2241 { 2242 sal_Int32 nLastSlash = aIndexFolder.lastIndexOf( '/' ); 2243 if( nLastSlash != -1 ) 2244 { 2245 rtl::OUString aTmpFolder = aIndexFolder.copy( 0, nLastSlash ); 2246 try 2247 { 2248 m_xSFA->kill( aTmpFolder ); 2249 } 2250 catch (Exception &) 2251 {} 2252 } 2253 } 2254