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