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