1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 29 // MARKER(update_precomp.py): autogen include statement, do not remove 30 #include "precompiled_xmlhelp.hxx" 31 32 #include <string.h> 33 #include <rtl/ustrbuf.hxx> 34 #ifndef _VOS_DIAGNOSE_HXX_ 35 #include <vos/diagnose.hxx> 36 #endif 37 #include "tvread.hxx" 38 #include <expat.h> 39 #include <osl/file.hxx> 40 #include <com/sun/star/frame/XConfigManager.hpp> 41 #include <com/sun/star/beans/PropertyValue.hpp> 42 43 #include <comphelper/processfactory.hxx> 44 #include <com/sun/star/beans/XPropertySet.hpp> 45 #include "com/sun/star/deployment/thePackageManagerFactory.hpp" 46 #include <com/sun/star/util/XMacroExpander.hpp> 47 #include <com/sun/star/uri/XUriReferenceFactory.hpp> 48 #include <com/sun/star/uri/XVndSunStarExpandUrl.hpp> 49 #include <comphelper/locale.hxx> 50 51 namespace treeview { 52 53 54 class TVDom 55 { 56 friend class TVChildTarget; 57 friend class TVRead; 58 59 public: 60 61 TVDom( TVDom* arent = 0 ) 62 : kind( other ), 63 parent( arent ), 64 childs( 0 ) 65 { 66 } 67 68 ~TVDom() 69 { 70 for( unsigned i = 0; i < childs.size(); ++i ) 71 delete childs[i]; 72 } 73 74 75 TVDom* newChild() 76 { 77 childs.push_back( new TVDom( this ) ); 78 return childs.back(); 79 } 80 81 82 TVDom* getParent() const 83 { 84 if( parent ) 85 return parent; 86 else 87 return const_cast<TVDom*>(this); // I am my own parent, if I am the root 88 } 89 90 enum Kind { 91 tree_view, 92 tree_node, 93 tree_leaf, 94 other 95 }; 96 97 bool isLeaf() const { return kind == TVDom::tree_leaf; } 98 void setKind( Kind ind ) { kind = ind; } 99 Kind getKind( ) const { return kind; } 100 101 102 void setApplication( const char* appl ) 103 { 104 application = rtl::OUString( (sal_Char*)(appl), 105 strlen( appl ), 106 RTL_TEXTENCODING_UTF8 ); 107 } 108 109 void setTitle( const char* itle ) 110 { 111 title += rtl::OUString( (sal_Char*)(itle), 112 strlen( itle ), 113 RTL_TEXTENCODING_UTF8 ); 114 } 115 116 void setTitle( const XML_Char* itle,int len ) 117 { 118 title += rtl::OUString( (sal_Char*)(itle), 119 len, 120 RTL_TEXTENCODING_UTF8 ); 121 } 122 123 void setId( const char* d ) 124 { 125 id = rtl::OUString( (sal_Char*)(d), 126 strlen( d ), 127 RTL_TEXTENCODING_UTF8 ); 128 } 129 130 void setAnchor( const char* nchor ) 131 { 132 anchor = rtl::OUString( (sal_Char*)(nchor), 133 strlen( nchor ), 134 RTL_TEXTENCODING_UTF8 ); 135 } 136 137 rtl::OUString getTargetURL() 138 { 139 if( ! targetURL.getLength() ) 140 { 141 sal_Int32 len; 142 for ( const TVDom* p = this;; p = p->parent ) 143 { 144 len = p->application.getLength(); 145 if ( len != 0 ) 146 break; 147 } 148 149 rtl::OUStringBuffer strBuff( 22 + len + id.getLength() ); 150 strBuff.appendAscii( 151 "vnd.sun.star.help://" 152 ).append(id); 153 154 targetURL = strBuff.makeStringAndClear(); 155 } 156 157 return targetURL; 158 } 159 160 private: 161 162 Kind kind; 163 rtl::OUString application; 164 rtl::OUString title; 165 rtl::OUString id; 166 rtl::OUString anchor; 167 rtl::OUString targetURL; 168 169 TVDom *parent; 170 std::vector< TVDom* > childs; 171 }; 172 173 } 174 175 176 177 using namespace treeview; 178 using namespace com::sun::star; 179 using namespace com::sun::star::uno; 180 using namespace com::sun::star::beans; 181 using namespace com::sun::star::lang; 182 using namespace com::sun::star::util; 183 using namespace com::sun::star::frame; 184 using namespace com::sun::star::container; 185 using namespace com::sun::star::deployment; 186 187 188 ConfigData::ConfigData() 189 : prodName( rtl::OUString::createFromAscii( "%PRODUCTNAME" ) ), 190 prodVersion( rtl::OUString::createFromAscii( "%PRODUCTVERSION" ) ), 191 vendName( rtl::OUString::createFromAscii( "%VENDORNAME" ) ), 192 vendVersion( rtl::OUString::createFromAscii( "%VENDORVERSION" ) ), 193 vendShort( rtl::OUString::createFromAscii( "%VENDORSHORT" ) ) 194 { 195 } 196 197 void SAL_CALL ConfigData::replaceName( rtl::OUString& oustring ) const 198 { 199 sal_Int32 idx = -1,k = 0,off; 200 bool cap = false; 201 rtl::OUStringBuffer aStrBuf( 0 ); 202 203 while( ( idx = oustring.indexOf( sal_Unicode('%'),++idx ) ) != -1 ) 204 { 205 if( oustring.indexOf( prodName,idx ) == idx ) 206 off = PRODUCTNAME; 207 else if( oustring.indexOf( prodVersion,idx ) == idx ) 208 off = PRODUCTVERSION; 209 else if( oustring.indexOf( vendName,idx ) == idx ) 210 off = VENDORNAME; 211 else if( oustring.indexOf( vendVersion,idx ) == idx ) 212 off = VENDORVERSION; 213 else if( oustring.indexOf( vendShort,idx ) == idx ) 214 off = VENDORSHORT; 215 else 216 off = -1; 217 218 if( off != -1 ) 219 { 220 if( ! cap ) 221 { 222 cap = true; 223 aStrBuf.ensureCapacity( 256 ); 224 } 225 226 aStrBuf.append( &oustring.getStr()[k],idx - k ); 227 aStrBuf.append( m_vReplacement[off] ); 228 k = idx + m_vAdd[off]; 229 } 230 } 231 232 if( cap ) 233 { 234 if( k < oustring.getLength() ) 235 aStrBuf.append( &oustring.getStr()[k],oustring.getLength()-k ); 236 oustring = aStrBuf.makeStringAndClear(); 237 } 238 } 239 240 241 242 243 ////////////////////////////////////////////////////////////////////////// 244 // XInterface 245 ////////////////////////////////////////////////////////////////////////// 246 247 248 void SAL_CALL 249 TVBase::acquire( 250 void ) 251 throw() 252 { 253 OWeakObject::acquire(); 254 } 255 256 257 void SAL_CALL 258 TVBase::release( 259 void ) 260 throw() 261 { 262 OWeakObject::release(); 263 } 264 265 266 Any SAL_CALL 267 TVBase::queryInterface( 268 const Type& rType ) 269 throw( RuntimeException ) 270 { 271 Any aRet = cppu::queryInterface( rType, 272 SAL_STATIC_CAST( XTypeProvider*, this ), 273 SAL_STATIC_CAST( XNameAccess*, this ), 274 SAL_STATIC_CAST( XHierarchicalNameAccess*, this ), 275 SAL_STATIC_CAST( XChangesNotifier*, this ), 276 SAL_STATIC_CAST( XComponent*, this ) ); 277 278 return aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType ); 279 } 280 281 282 //////////////////////////////////////////////////////////////////////////////// 283 // 284 // XTypeProvider methods. 285 286 XTYPEPROVIDER_IMPL_5( TVBase, 287 XTypeProvider, 288 XNameAccess, 289 XHierarchicalNameAccess, 290 XChangesNotifier, 291 XComponent ); 292 293 294 295 296 297 298 // TVRead 299 300 301 TVRead::TVRead( const ConfigData& configData,TVDom* tvDom ) 302 { 303 if( ! tvDom ) 304 return; 305 306 Title = tvDom->title; 307 configData.replaceName( Title ); 308 if( tvDom->isLeaf() ) 309 { 310 TargetURL = ( tvDom->getTargetURL() + configData.appendix ); 311 if( tvDom->anchor.getLength() ) 312 TargetURL += ( rtl::OUString::createFromAscii( "#" ) + 313 tvDom->anchor ); 314 } 315 else 316 Children = new TVChildTarget( configData,tvDom ); 317 } 318 319 320 321 TVRead::~TVRead() 322 { 323 } 324 325 326 327 328 329 330 // XNameAccess 331 332 Any SAL_CALL 333 TVRead::getByName( const rtl::OUString& aName ) 334 throw( NoSuchElementException, 335 WrappedTargetException, 336 RuntimeException ) 337 { 338 bool found( true ); 339 Any aAny; 340 if( aName.compareToAscii( "Title" ) == 0 ) 341 aAny <<= Title; 342 else if( aName.compareToAscii( "TargetURL" ) == 0 ) 343 aAny <<= TargetURL; 344 else if( aName.compareToAscii( "Children" ) == 0 ) 345 { 346 cppu::OWeakObject* p = Children.get(); 347 aAny <<= Reference< XInterface >( p ); 348 } 349 else 350 found = false; 351 352 if( found ) 353 return aAny; 354 355 throw NoSuchElementException(); 356 } 357 358 359 360 361 Sequence< rtl::OUString > SAL_CALL 362 TVRead::getElementNames( ) 363 throw( RuntimeException ) 364 { 365 Sequence< rtl::OUString > seq( 3 ); 366 367 seq[0] = rtl::OUString::createFromAscii( "Title" ); 368 seq[1] = rtl::OUString::createFromAscii( "TargetURL" ); 369 seq[2] = rtl::OUString::createFromAscii( "Children" ); 370 371 return seq; 372 } 373 374 375 376 sal_Bool SAL_CALL 377 TVRead::hasByName( const rtl::OUString& aName ) 378 throw( RuntimeException ) 379 { 380 if( aName.compareToAscii( "Title" ) == 0 || 381 aName.compareToAscii( "TargetURL" ) == 0 || 382 aName.compareToAscii( "Children" ) == 0 ) 383 return true; 384 385 return false; 386 } 387 388 389 // XHierarchicalNameAccess 390 391 Any SAL_CALL 392 TVRead::getByHierarchicalName( const rtl::OUString& aName ) 393 throw( NoSuchElementException, 394 RuntimeException ) 395 { 396 sal_Int32 idx; 397 rtl::OUString name( aName ); 398 399 if( ( idx = name.indexOf( sal_Unicode( '/' ) ) ) != -1 && 400 name.copy( 0,idx ).compareToAscii( "Children" ) == 0 ) 401 return Children->getByHierarchicalName( name.copy( 1 + idx ) ); 402 403 return getByName( name ); 404 } 405 406 407 408 409 sal_Bool SAL_CALL 410 TVRead::hasByHierarchicalName( const rtl::OUString& aName ) 411 throw( RuntimeException ) 412 { 413 sal_Int32 idx; 414 rtl::OUString name( aName ); 415 416 if( ( idx = name.indexOf( sal_Unicode( '/' ) ) ) != -1 && 417 name.copy( 0,idx ).compareToAscii( "Children" ) == 0 ) 418 return Children->hasByHierarchicalName( name.copy( 1 + idx ) ); 419 420 return hasByName( name ); 421 } 422 423 424 425 /**************************************************************************/ 426 /* */ 427 /* TVChildTarget */ 428 /* */ 429 /**************************************************************************/ 430 431 432 433 434 extern "C" void start_handler(void *userData, 435 const XML_Char *name, 436 const XML_Char **atts) 437 { 438 TVDom::Kind kind; 439 440 if( strcmp( name,"help_section" ) == 0 || 441 strcmp( name,"node" ) == 0 ) 442 kind = TVDom::tree_node; 443 else if( strcmp( name,"topic" ) == 0 ) 444 kind = TVDom::tree_leaf; 445 else 446 return; 447 448 TVDom **tvDom = static_cast< TVDom** >( userData ); 449 TVDom *p; 450 p = *tvDom; 451 452 *tvDom = p->newChild(); 453 p = *tvDom; 454 455 p->setKind( kind ); 456 while( *atts ) 457 { 458 if( strcmp( *atts,"application" ) == 0 ) 459 p->setApplication( *(atts+1) ); 460 else if( strcmp( *atts,"title" ) == 0 ) 461 p->setTitle( *(atts+1) ); 462 else if( strcmp( *atts,"id" ) == 0 ) 463 p->setId( *(atts+1) ); 464 else if( strcmp( *atts,"anchor" ) == 0 ) 465 p->setAnchor( *(atts+1) ); 466 467 atts+=2; 468 } 469 } 470 471 472 extern "C" void end_handler(void *userData, 473 const XML_Char *name ) 474 { 475 (void)name; 476 477 TVDom **tvDom = static_cast< TVDom** >( userData ); 478 *tvDom = (*tvDom)->getParent(); 479 } 480 481 482 extern "C" void data_handler( void *userData, 483 const XML_Char *s, 484 int len) 485 { 486 TVDom **tvDom = static_cast< TVDom** >( userData ); 487 if( (*tvDom)->isLeaf() ) 488 (*tvDom)->setTitle( s,len ); 489 } 490 491 492 493 TVChildTarget::TVChildTarget( const ConfigData& configData,TVDom* tvDom ) 494 { 495 Elements.resize( tvDom->childs.size() ); 496 for( unsigned i = 0; i < Elements.size(); ++i ) 497 Elements[i] = new TVRead( configData,tvDom->childs[i] ); 498 } 499 500 501 502 503 504 TVChildTarget::TVChildTarget( const Reference< XMultiServiceFactory >& xMSF ) 505 { 506 ConfigData configData = init( xMSF ); 507 508 if( ! configData.locale.getLength() || 509 ! configData.system.getLength() ) 510 return; 511 512 sal_uInt64 ret,len = 0; 513 int j = configData.vFileURL.size(); 514 515 TVDom tvDom; 516 TVDom* pTVDom = &tvDom; 517 518 while( j ) 519 { 520 len = configData.vFileLen[--j]; 521 char* s = new char[ int(len) ]; // the buffer to hold the installed files 522 osl::File aFile( configData.vFileURL[j] ); 523 aFile.open( OpenFlag_Read ); 524 aFile.read( s,len,ret ); 525 aFile.close(); 526 527 XML_Parser parser = XML_ParserCreate( 0 ); 528 XML_SetElementHandler( parser, 529 start_handler, 530 end_handler ); 531 XML_SetCharacterDataHandler( parser, 532 data_handler); 533 XML_SetUserData( parser,&pTVDom ); // does not return this 534 535 int parsed = XML_Parse( parser,s,int( len ),j==0 ); 536 (void)parsed; 537 OSL_ENSURE( parsed, "TVChildTarget::TVChildTarget(): Tree file parsing failed" ); 538 539 XML_ParserFree( parser ); 540 delete[] s; 541 } 542 543 // now TVDom holds the relevant information 544 545 Elements.resize( tvDom.childs.size() ); 546 for( unsigned i = 0; i < Elements.size(); ++i ) 547 Elements[i] = new TVRead( configData,tvDom.childs[i] ); 548 } 549 550 551 TVChildTarget::~TVChildTarget() 552 { 553 } 554 555 556 557 Any SAL_CALL 558 TVChildTarget::getByName( const rtl::OUString& aName ) 559 throw( NoSuchElementException, 560 WrappedTargetException, 561 RuntimeException ) 562 { 563 rtl::OUString num( aName.getStr()+2,aName.getLength()-4 ); 564 sal_Int32 idx = num.toInt32() - 1; 565 if( idx < 0 || Elements.size() <= sal_uInt32( idx ) ) 566 throw NoSuchElementException(); 567 568 Any aAny; 569 cppu::OWeakObject* p = Elements[idx].get(); 570 aAny <<= Reference< XInterface >( p ); 571 return aAny; 572 } 573 574 575 576 577 Sequence< rtl::OUString > SAL_CALL 578 TVChildTarget::getElementNames( ) 579 throw( RuntimeException ) 580 { 581 Sequence< rtl::OUString > seq( Elements.size() ); 582 for( unsigned i = 0; i < Elements.size(); ++i ) 583 seq[i] = rtl::OUString::valueOf( sal_Int32( 1+i ) ); 584 585 return seq; 586 } 587 588 589 590 sal_Bool SAL_CALL 591 TVChildTarget::hasByName( const rtl::OUString& aName ) 592 throw( RuntimeException ) 593 { 594 rtl::OUString num( aName.getStr()+2,aName.getLength()-4 ); 595 sal_Int32 idx = num.toInt32() - 1; 596 if( idx < 0 || Elements.size() <= sal_uInt32( idx ) ) 597 return false; 598 599 return true; 600 } 601 602 603 604 // XHierarchicalNameAccess 605 606 Any SAL_CALL 607 TVChildTarget::getByHierarchicalName( const rtl::OUString& aName ) 608 throw( NoSuchElementException, 609 RuntimeException ) 610 { 611 sal_Int32 idx; 612 rtl::OUString name( aName ); 613 614 if( ( idx = name.indexOf( sal_Unicode( '/' ) ) ) != -1 ) 615 { 616 rtl::OUString num( name.getStr()+2,idx-4 ); 617 sal_Int32 pref = num.toInt32() - 1; 618 619 if( pref < 0 || Elements.size() <= sal_uInt32( pref ) ) 620 throw NoSuchElementException(); 621 622 return Elements[pref]->getByHierarchicalName( name.copy( 1 + idx ) ); 623 } 624 else 625 return getByName( name ); 626 } 627 628 629 630 sal_Bool SAL_CALL 631 TVChildTarget::hasByHierarchicalName( const rtl::OUString& aName ) 632 throw( RuntimeException ) 633 { 634 sal_Int32 idx; 635 rtl::OUString name( aName ); 636 637 if( ( idx = name.indexOf( sal_Unicode( '/' ) ) ) != -1 ) 638 { 639 rtl::OUString num( name.getStr()+2,idx-4 ); 640 sal_Int32 pref = num.toInt32() - 1; 641 if( pref < 0 || Elements.size() <= sal_uInt32( pref ) ) 642 return false; 643 644 return Elements[pref]->hasByHierarchicalName( name.copy( 1 + idx ) ); 645 } 646 else 647 return hasByName( name ); 648 } 649 650 651 652 653 654 655 ConfigData TVChildTarget::init( const Reference< XMultiServiceFactory >& xSMgr ) 656 { 657 ConfigData configData; 658 Reference< XMultiServiceFactory > sProvider( getConfiguration(xSMgr) ); 659 660 /**********************************************************************/ 661 /* reading Office.Common */ 662 /**********************************************************************/ 663 664 Reference< XHierarchicalNameAccess > xHierAccess( getHierAccess( sProvider, 665 "org.openoffice.Office.Common" ) ); 666 rtl::OUString system( getKey( xHierAccess,"Help/System" ) ); 667 sal_Bool showBasic( getBooleanKey(xHierAccess,"Help/ShowBasic") ); 668 rtl::OUString instPath( getKey( xHierAccess,"Path/Current/Help" ) ); 669 if( ! instPath.getLength() ) 670 // try to determine path from default 671 instPath = rtl::OUString::createFromAscii( "$(instpath)/help" ); 672 673 // replace anything like $(instpath); 674 subst( xSMgr,instPath ); 675 676 /**********************************************************************/ 677 /* reading setup */ 678 /**********************************************************************/ 679 680 xHierAccess = getHierAccess( sProvider, 681 "org.openoffice.Setup" ); 682 683 rtl::OUString productName( getKey( xHierAccess,"Product/ooName" ) ); 684 rtl::OUString setupversion( getKey( xHierAccess,"Product/ooSetupVersion" ) ); 685 rtl::OUString setupextension; 686 687 try 688 { 689 uno::Reference< lang::XMultiServiceFactory > xConfigProvider( 690 xSMgr ->createInstance(::rtl::OUString::createFromAscii("com.sun.star.configuration.ConfigurationProvider")), uno::UNO_QUERY_THROW); 691 692 uno::Sequence < uno::Any > lParams(1); 693 beans::PropertyValue aParam ; 694 aParam.Name = ::rtl::OUString::createFromAscii("nodepath"); 695 aParam.Value <<= ::rtl::OUString::createFromAscii("/org.openoffice.Setup/Product"); 696 lParams[0] = uno::makeAny(aParam); 697 698 // open it 699 uno::Reference< uno::XInterface > xCFG( xConfigProvider->createInstanceWithArguments( 700 ::rtl::OUString::createFromAscii("com.sun.star.configuration.ConfigurationAccess"), 701 lParams) ); 702 703 uno::Reference< container::XNameAccess > xDirectAccess(xCFG, uno::UNO_QUERY); 704 uno::Any aRet = xDirectAccess->getByName(::rtl::OUString::createFromAscii("ooSetupExtension")); 705 706 aRet >>= setupextension; 707 } 708 catch ( uno::Exception& ) 709 { 710 } 711 712 rtl::OUString productVersion( setupversion + 713 rtl::OUString::createFromAscii( " " ) + 714 setupextension ); 715 rtl::OUString locale( getKey( xHierAccess,"L10N/ooLocale" ) ); 716 717 718 // Determine fileurl from url and locale 719 rtl::OUString url; 720 osl::FileBase::RC errFile = osl::FileBase::getFileURLFromSystemPath( instPath,url ); 721 if( errFile != osl::FileBase::E_None ) return configData; 722 if( url.lastIndexOf( sal_Unicode( '/' ) ) != url.getLength() - 1 ) 723 url += rtl::OUString::createFromAscii( "/" ); 724 rtl::OUString ret; 725 sal_Int32 idx; 726 osl::DirectoryItem aDirItem; 727 if( osl::FileBase::E_None == osl::DirectoryItem::get( url + locale,aDirItem ) ) 728 ret = locale; 729 else if( ( ( idx = locale.indexOf( '-' ) ) != -1 || 730 ( idx = locale.indexOf( '_' ) ) != -1 ) && 731 osl::FileBase::E_None == osl::DirectoryItem::get( url + locale.copy( 0,idx ), 732 aDirItem ) ) 733 ret = locale.copy( 0,idx ); 734 else 735 { 736 locale = rtl::OUString::createFromAscii( "en-US" ); 737 ret = rtl::OUString::createFromAscii("en"); 738 } 739 url = url + ret; 740 741 // first of all, try do determine whether there are any *.tree files present 742 743 // Start with extensions to set them at the end of the list 744 TreeFileIterator aTreeIt( locale ); 745 rtl::OUString aTreeFile; 746 sal_Int32 nFileSize; 747 while( (aTreeFile = aTreeIt.nextTreeFile( nFileSize ) ).getLength() > 0 ) 748 { 749 configData.vFileLen.push_back( nFileSize ); 750 configData.vFileURL.push_back( aTreeFile ); 751 } 752 753 osl::Directory aDirectory( url ); 754 osl::FileStatus aFileStatus( FileStatusMask_FileName | FileStatusMask_FileSize | FileStatusMask_FileURL ); 755 if( osl::Directory::E_None == aDirectory.open() ) 756 { 757 int idx_ = 0; 758 rtl::OUString aFileUrl, aFileName; 759 while( aDirectory.getNextItem( aDirItem ) == osl::FileBase::E_None && 760 aDirItem.getFileStatus( aFileStatus ) == osl::FileBase::E_None && 761 aFileStatus.isValid( FileStatusMask_FileURL ) && 762 aFileStatus.isValid( FileStatusMask_FileName ) ) 763 { 764 aFileUrl = aFileStatus.getFileURL(); 765 aFileName = aFileStatus.getFileName(); 766 idx_ = aFileName.lastIndexOf( sal_Unicode( '.' ) ); 767 if( idx_ == -1 ) 768 continue; 769 770 const sal_Unicode* str = aFileName.getStr(); 771 772 if( aFileName.getLength() == idx_ + 5 && 773 ( str[idx_ + 1] == 't' || str[idx_ + 1] == 'T' ) && 774 ( str[idx_ + 2] == 'r' || str[idx_ + 2] == 'R' ) && 775 ( str[idx_ + 3] == 'e' || str[idx_ + 3] == 'E' ) && 776 ( str[idx_ + 4] == 'e' || str[idx_ + 4] == 'E' ) ) 777 { 778 OSL_ENSURE( aFileStatus.isValid( FileStatusMask_FileSize ), 779 "invalid file size" ); 780 781 rtl::OUString baseName = aFileName.copy(0,idx_).toAsciiLowerCase(); 782 if(! showBasic && baseName.compareToAscii("sbasic") == 0 ) 783 continue; 784 785 configData.vFileLen.push_back( aFileStatus.getFileSize() ); 786 configData.vFileURL.push_back( aFileUrl ); 787 } 788 } 789 aDirectory.close(); 790 } 791 792 configData.m_vAdd[0] = 12; 793 configData.m_vAdd[1] = 15; 794 configData.m_vAdd[2] = 11; 795 configData.m_vAdd[3] = 14; 796 configData.m_vAdd[4] = 12; 797 configData.m_vReplacement[0] = productName; 798 configData.m_vReplacement[1] = productVersion; 799 // m_vReplacement[2...4] (vendorName/-Version/-Short) are empty strings 800 801 configData.system = system; 802 configData.locale = locale; 803 configData.appendix = 804 rtl::OUString::createFromAscii( "?Language=" ) + 805 configData.locale + 806 rtl::OUString::createFromAscii( "&System=" ) + 807 configData.system + 808 rtl::OUString::createFromAscii( "&UseDB=no" ) ; 809 810 return configData; 811 } 812 813 814 815 816 817 818 819 820 821 Reference< XMultiServiceFactory > 822 TVChildTarget::getConfiguration(const Reference< XMultiServiceFactory >& m_xSMgr) const 823 { 824 Reference< XMultiServiceFactory > sProvider; 825 if( m_xSMgr.is() ) 826 { 827 try 828 { 829 rtl::OUString sProviderService = 830 rtl::OUString::createFromAscii( "com.sun.star.configuration.ConfigurationProvider" ); 831 sProvider = 832 Reference< XMultiServiceFactory >( 833 m_xSMgr->createInstance( sProviderService ), 834 UNO_QUERY ); 835 } 836 catch( const com::sun::star::uno::Exception& ) 837 { 838 OSL_ENSURE( sProvider.is(),"cant instantiate configuration" ); 839 } 840 } 841 842 return sProvider; 843 } 844 845 846 847 Reference< XHierarchicalNameAccess > 848 TVChildTarget::getHierAccess( const Reference< XMultiServiceFactory >& sProvider, 849 const char* file ) const 850 { 851 Reference< XHierarchicalNameAccess > xHierAccess; 852 853 if( sProvider.is() ) 854 { 855 Sequence< Any > seq(1); 856 rtl::OUString sReaderService = 857 rtl::OUString::createFromAscii( "com.sun.star.configuration.ConfigurationAccess" ); 858 859 seq[0] <<= rtl::OUString::createFromAscii( file ); 860 861 try 862 { 863 xHierAccess = 864 Reference< XHierarchicalNameAccess > 865 ( sProvider->createInstanceWithArguments( sReaderService,seq ), 866 UNO_QUERY ); 867 } 868 catch( const com::sun::star::uno::Exception& ) 869 { 870 } 871 } 872 873 return xHierAccess; 874 } 875 876 877 878 rtl::OUString 879 TVChildTarget::getKey( const Reference< XHierarchicalNameAccess >& xHierAccess, 880 const char* key ) const 881 { 882 rtl::OUString instPath; 883 if( xHierAccess.is() ) 884 { 885 Any aAny; 886 try 887 { 888 aAny = 889 xHierAccess->getByHierarchicalName( rtl::OUString::createFromAscii( key ) ); 890 } 891 catch( const com::sun::star::container::NoSuchElementException& ) 892 { 893 } 894 aAny >>= instPath; 895 } 896 return instPath; 897 } 898 899 900 sal_Bool 901 TVChildTarget::getBooleanKey(const Reference< 902 XHierarchicalNameAccess >& xHierAccess, 903 const char* key) const 904 { 905 sal_Bool ret = sal_False; 906 if( xHierAccess.is() ) 907 { 908 Any aAny; 909 try 910 { 911 aAny = 912 xHierAccess->getByHierarchicalName( 913 rtl::OUString::createFromAscii(key)); 914 } 915 catch( const com::sun::star::container::NoSuchElementException& ) 916 { 917 } 918 aAny >>= ret; 919 } 920 return ret; 921 } 922 923 924 void TVChildTarget::subst( const Reference< XMultiServiceFactory >& m_xSMgr, 925 rtl::OUString& instpath ) const 926 { 927 Reference< XConfigManager > xCfgMgr; 928 if( m_xSMgr.is() ) 929 { 930 try 931 { 932 xCfgMgr = 933 Reference< XConfigManager >( 934 m_xSMgr->createInstance( rtl::OUString::createFromAscii( "com.sun.star.config.SpecialConfigManager" ) ), 935 UNO_QUERY ); 936 } 937 catch( const com::sun::star::uno::Exception& ) 938 { 939 OSL_ENSURE( xCfgMgr.is()," cant instantiate the special config manager " ); 940 } 941 } 942 943 OSL_ENSURE( xCfgMgr.is(), "specialconfigmanager not found\n" ); 944 945 if( xCfgMgr.is() ) 946 instpath = xCfgMgr->substituteVariables( instpath ); 947 } 948 949 950 //=================================================================== 951 // class ExtensionIteratorBase 952 953 static rtl::OUString aSlash( rtl::OUString::createFromAscii( "/" ) ); 954 static rtl::OUString aHelpFilesBaseName( rtl::OUString::createFromAscii( "help" ) ); 955 static rtl::OUString aHelpMediaType( rtl::OUString::createFromAscii( "application/vnd.sun.star.help" ) ); 956 957 ExtensionIteratorBase::ExtensionIteratorBase( const rtl::OUString& aLanguage ) 958 : m_eState( USER_EXTENSIONS ) 959 , m_aLanguage( aLanguage ) 960 { 961 init(); 962 } 963 964 void ExtensionIteratorBase::init() 965 { 966 Reference< XMultiServiceFactory > xFactory = comphelper::getProcessServiceFactory(); 967 Reference< XPropertySet > xProps( xFactory, UNO_QUERY ); 968 OSL_ASSERT( xProps.is() ); 969 if (xProps.is()) 970 { 971 xProps->getPropertyValue( 972 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("DefaultContext") ) ) >>= m_xContext; 973 OSL_ASSERT( m_xContext.is() ); 974 } 975 if( !m_xContext.is() ) 976 { 977 throw RuntimeException( 978 ::rtl::OUString::createFromAscii( "ExtensionIteratorBase::init(), no XComponentContext" ), 979 Reference< XInterface >() ); 980 } 981 982 Reference< XMultiComponentFactory > xSMgr( m_xContext->getServiceManager(), UNO_QUERY ); 983 m_xSFA = Reference< ucb::XSimpleFileAccess >( 984 xSMgr->createInstanceWithContext( rtl::OUString::createFromAscii( "com.sun.star.ucb.SimpleFileAccess" ), 985 m_xContext ), UNO_QUERY_THROW ); 986 987 m_bUserPackagesLoaded = false; 988 m_bSharedPackagesLoaded = false; 989 m_bBundledPackagesLoaded = false; 990 m_iUserPackage = 0; 991 m_iSharedPackage = 0; 992 m_iBundledPackage = 0; 993 } 994 995 Reference< deployment::XPackage > ExtensionIteratorBase::implGetHelpPackageFromPackage 996 ( Reference< deployment::XPackage > xPackage, Reference< deployment::XPackage >& o_xParentPackageBundle ) 997 { 998 o_xParentPackageBundle.clear(); 999 1000 Reference< deployment::XPackage > xHelpPackage; 1001 if( !xPackage.is() ) 1002 return xHelpPackage; 1003 1004 // Check if parent package is registered 1005 beans::Optional< beans::Ambiguous<sal_Bool> > option( xPackage->isRegistered 1006 ( Reference<task::XAbortChannel>(), Reference<ucb::XCommandEnvironment>() ) ); 1007 bool bRegistered = false; 1008 if( option.IsPresent ) 1009 { 1010 beans::Ambiguous<sal_Bool> const & reg = option.Value; 1011 if( !reg.IsAmbiguous && reg.Value ) 1012 bRegistered = true; 1013 } 1014 if( !bRegistered ) 1015 return xHelpPackage; 1016 1017 if( xPackage->isBundle() ) 1018 { 1019 Sequence< Reference< deployment::XPackage > > aPkgSeq = xPackage->getBundle 1020 ( Reference<task::XAbortChannel>(), Reference<ucb::XCommandEnvironment>() ); 1021 sal_Int32 nPkgCount = aPkgSeq.getLength(); 1022 const Reference< deployment::XPackage >* pSeq = aPkgSeq.getConstArray(); 1023 for( sal_Int32 iPkg = 0 ; iPkg < nPkgCount ; ++iPkg ) 1024 { 1025 const Reference< deployment::XPackage > xSubPkg = pSeq[ iPkg ]; 1026 const Reference< deployment::XPackageTypeInfo > xPackageTypeInfo = xSubPkg->getPackageType(); 1027 rtl::OUString aMediaType = xPackageTypeInfo->getMediaType(); 1028 if( aMediaType.equals( aHelpMediaType ) ) 1029 { 1030 xHelpPackage = xSubPkg; 1031 o_xParentPackageBundle = xPackage; 1032 break; 1033 } 1034 } 1035 } 1036 else 1037 { 1038 const Reference< deployment::XPackageTypeInfo > xPackageTypeInfo = xPackage->getPackageType(); 1039 rtl::OUString aMediaType = xPackageTypeInfo->getMediaType(); 1040 if( aMediaType.equals( aHelpMediaType ) ) 1041 xHelpPackage = xPackage; 1042 } 1043 1044 return xHelpPackage; 1045 } 1046 1047 Reference< deployment::XPackage > ExtensionIteratorBase::implGetNextUserHelpPackage 1048 ( Reference< deployment::XPackage >& o_xParentPackageBundle ) 1049 { 1050 Reference< deployment::XPackage > xHelpPackage; 1051 1052 if( !m_bUserPackagesLoaded ) 1053 { 1054 Reference< XPackageManager > xUserManager = 1055 thePackageManagerFactory::get( m_xContext )->getPackageManager( rtl::OUString::createFromAscii("user") ); 1056 m_aUserPackagesSeq = xUserManager->getDeployedPackages 1057 ( Reference< task::XAbortChannel >(), Reference< ucb::XCommandEnvironment >() ); 1058 1059 m_bUserPackagesLoaded = true; 1060 } 1061 1062 if( m_iUserPackage == m_aUserPackagesSeq.getLength() ) 1063 { 1064 m_eState = SHARED_EXTENSIONS; // Later: SHARED_MODULE 1065 } 1066 else 1067 { 1068 const Reference< deployment::XPackage >* pUserPackages = m_aUserPackagesSeq.getConstArray(); 1069 Reference< deployment::XPackage > xPackage = pUserPackages[ m_iUserPackage++ ]; 1070 VOS_ENSURE( xPackage.is(), "ExtensionIteratorBase::implGetNextUserHelpPackage(): Invalid package" ); 1071 xHelpPackage = implGetHelpPackageFromPackage( xPackage, o_xParentPackageBundle ); 1072 } 1073 1074 return xHelpPackage; 1075 } 1076 1077 Reference< deployment::XPackage > ExtensionIteratorBase::implGetNextSharedHelpPackage 1078 ( Reference< deployment::XPackage >& o_xParentPackageBundle ) 1079 { 1080 Reference< deployment::XPackage > xHelpPackage; 1081 1082 if( !m_bSharedPackagesLoaded ) 1083 { 1084 Reference< XPackageManager > xSharedManager = 1085 thePackageManagerFactory::get( m_xContext )->getPackageManager( rtl::OUString::createFromAscii("shared") ); 1086 m_aSharedPackagesSeq = xSharedManager->getDeployedPackages 1087 ( Reference< task::XAbortChannel >(), Reference< ucb::XCommandEnvironment >() ); 1088 1089 m_bSharedPackagesLoaded = true; 1090 } 1091 1092 if( m_iSharedPackage == m_aSharedPackagesSeq.getLength() ) 1093 { 1094 m_eState = BUNDLED_EXTENSIONS; 1095 } 1096 else 1097 { 1098 const Reference< deployment::XPackage >* pSharedPackages = m_aSharedPackagesSeq.getConstArray(); 1099 Reference< deployment::XPackage > xPackage = pSharedPackages[ m_iSharedPackage++ ]; 1100 VOS_ENSURE( xPackage.is(), "ExtensionIteratorBase::implGetNextSharedHelpPackage(): Invalid package" ); 1101 xHelpPackage = implGetHelpPackageFromPackage( xPackage, o_xParentPackageBundle ); 1102 } 1103 1104 return xHelpPackage; 1105 } 1106 1107 Reference< deployment::XPackage > ExtensionIteratorBase::implGetNextBundledHelpPackage 1108 ( Reference< deployment::XPackage >& o_xParentPackageBundle ) 1109 { 1110 Reference< deployment::XPackage > xHelpPackage; 1111 1112 if( !m_bBundledPackagesLoaded ) 1113 { 1114 Reference< XPackageManager > xBundledManager = 1115 thePackageManagerFactory::get( m_xContext )->getPackageManager( rtl::OUString::createFromAscii("bundled") ); 1116 m_aBundledPackagesSeq = xBundledManager->getDeployedPackages 1117 ( Reference< task::XAbortChannel >(), Reference< ucb::XCommandEnvironment >() ); 1118 1119 m_bBundledPackagesLoaded = true; 1120 } 1121 1122 if( m_iBundledPackage == m_aBundledPackagesSeq.getLength() ) 1123 { 1124 m_eState = END_REACHED; 1125 } 1126 else 1127 { 1128 const Reference< deployment::XPackage >* pBundledPackages = m_aBundledPackagesSeq.getConstArray(); 1129 Reference< deployment::XPackage > xPackage = pBundledPackages[ m_iBundledPackage++ ]; 1130 VOS_ENSURE( xPackage.is(), "ExtensionIteratorBase::implGetNextBundledHelpPackage(): Invalid package" ); 1131 xHelpPackage = implGetHelpPackageFromPackage( xPackage, o_xParentPackageBundle ); 1132 } 1133 1134 return xHelpPackage; 1135 } 1136 1137 inline bool isLetter( sal_Unicode c ) 1138 { 1139 bool bLetter = ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')); 1140 return bLetter; 1141 } 1142 1143 void ExtensionIteratorBase::implGetLanguageVectorFromPackage( ::std::vector< ::rtl::OUString > &rv, 1144 com::sun::star::uno::Reference< com::sun::star::deployment::XPackage > xPackage ) 1145 { 1146 rv.clear(); 1147 rtl::OUString aExtensionPath = xPackage->getURL(); 1148 Sequence< rtl::OUString > aEntrySeq = m_xSFA->getFolderContents( aExtensionPath, true ); 1149 1150 const rtl::OUString* pSeq = aEntrySeq.getConstArray(); 1151 sal_Int32 nCount = aEntrySeq.getLength(); 1152 for( sal_Int32 i = 0 ; i < nCount ; ++i ) 1153 { 1154 rtl::OUString aEntry = pSeq[i]; 1155 if( m_xSFA->isFolder( aEntry ) ) 1156 { 1157 sal_Int32 nLastSlash = aEntry.lastIndexOf( '/' ); 1158 if( nLastSlash != -1 ) 1159 { 1160 rtl::OUString aPureEntry = aEntry.copy( nLastSlash + 1 ); 1161 1162 // Check language sceme 1163 int nLen = aPureEntry.getLength(); 1164 const sal_Unicode* pc = aPureEntry.getStr(); 1165 bool bStartCanBeLanguage = ( nLen >= 2 && isLetter( pc[0] ) && isLetter( pc[1] ) ); 1166 bool bIsLanguage = bStartCanBeLanguage && 1167 ( nLen == 2 || (nLen == 5 && pc[2] == '-' && isLetter( pc[3] ) && isLetter( pc[4] )) ); 1168 if( bIsLanguage ) 1169 rv.push_back( aPureEntry ); 1170 } 1171 } 1172 } 1173 } 1174 1175 1176 //=================================================================== 1177 // class TreeFileIterator 1178 1179 rtl::OUString TreeFileIterator::nextTreeFile( sal_Int32& rnFileSize ) 1180 { 1181 rtl::OUString aRetFile; 1182 1183 while( !aRetFile.getLength() && m_eState != END_REACHED ) 1184 { 1185 switch( m_eState ) 1186 { 1187 case USER_EXTENSIONS: 1188 { 1189 Reference< deployment::XPackage > xParentPackageBundle; 1190 Reference< deployment::XPackage > xHelpPackage = implGetNextUserHelpPackage( xParentPackageBundle ); 1191 if( !xHelpPackage.is() ) 1192 break; 1193 1194 aRetFile = implGetTreeFileFromPackage( rnFileSize, xHelpPackage ); 1195 break; 1196 } 1197 1198 case SHARED_EXTENSIONS: 1199 { 1200 Reference< deployment::XPackage > xParentPackageBundle; 1201 Reference< deployment::XPackage > xHelpPackage = implGetNextSharedHelpPackage( xParentPackageBundle ); 1202 if( !xHelpPackage.is() ) 1203 break; 1204 1205 aRetFile = implGetTreeFileFromPackage( rnFileSize, xHelpPackage ); 1206 break; 1207 } 1208 case BUNDLED_EXTENSIONS: 1209 { 1210 Reference< deployment::XPackage > xParentPackageBundle; 1211 Reference< deployment::XPackage > xHelpPackage = implGetNextBundledHelpPackage( xParentPackageBundle ); 1212 if( !xHelpPackage.is() ) 1213 break; 1214 1215 aRetFile = implGetTreeFileFromPackage( rnFileSize, xHelpPackage ); 1216 break; 1217 } 1218 1219 case END_REACHED: 1220 VOS_ENSURE( false, "DataBaseIterator::nextTreeFile(): Invalid case END_REACHED" ); 1221 break; 1222 } 1223 } 1224 1225 return aRetFile; 1226 } 1227 1228 rtl::OUString TreeFileIterator::expandURL( const rtl::OUString& aURL ) 1229 { 1230 static Reference< util::XMacroExpander > xMacroExpander; 1231 static Reference< uri::XUriReferenceFactory > xFac; 1232 1233 osl::MutexGuard aGuard( m_aMutex ); 1234 1235 if( !xMacroExpander.is() || !xFac.is() ) 1236 { 1237 Reference< XMultiComponentFactory > xSMgr( m_xContext->getServiceManager(), UNO_QUERY ); 1238 1239 xFac = Reference< uri::XUriReferenceFactory >( 1240 xSMgr->createInstanceWithContext( rtl::OUString::createFromAscii( 1241 "com.sun.star.uri.UriReferenceFactory"), m_xContext ) , UNO_QUERY ); 1242 if( !xFac.is() ) 1243 { 1244 throw RuntimeException( 1245 ::rtl::OUString::createFromAscii( "Databases::expand(), could not instatiate UriReferenceFactory." ), 1246 Reference< XInterface >() ); 1247 } 1248 1249 xMacroExpander = Reference< util::XMacroExpander >( 1250 m_xContext->getValueByName( 1251 ::rtl::OUString::createFromAscii( "/singletons/com.sun.star.util.theMacroExpander" ) ), 1252 UNO_QUERY_THROW ); 1253 } 1254 1255 rtl::OUString aRetURL = aURL; 1256 if( xMacroExpander.is() ) 1257 { 1258 Reference< uri::XUriReference > uriRef; 1259 for (;;) 1260 { 1261 uriRef = Reference< uri::XUriReference >( xFac->parse( aRetURL ), UNO_QUERY ); 1262 if ( uriRef.is() ) 1263 { 1264 Reference < uri::XVndSunStarExpandUrl > sxUri( uriRef, UNO_QUERY ); 1265 if( !sxUri.is() ) 1266 break; 1267 1268 aRetURL = sxUri->expand( xMacroExpander ); 1269 } 1270 } 1271 } 1272 return aRetURL; 1273 } 1274 1275 rtl::OUString TreeFileIterator::implGetTreeFileFromPackage 1276 ( sal_Int32& rnFileSize, Reference< deployment::XPackage > xPackage ) 1277 { 1278 rtl::OUString aRetFile; 1279 rtl::OUString aLanguage = m_aLanguage; 1280 for( sal_Int32 iPass = 0 ; iPass < 2 ; ++iPass ) 1281 { 1282 rtl::OUStringBuffer aStrBuf; 1283 aStrBuf.append( xPackage->getURL() ); 1284 aStrBuf.append( aSlash ); 1285 aStrBuf.append( aLanguage ); 1286 aStrBuf.append( aSlash ); 1287 aStrBuf.append( aHelpFilesBaseName ); 1288 aStrBuf.appendAscii( ".tree" ); 1289 1290 aRetFile = expandURL( aStrBuf.makeStringAndClear() ); 1291 if( iPass == 0 ) 1292 { 1293 if( m_xSFA->exists( aRetFile ) ) 1294 break; 1295 1296 ::std::vector< ::rtl::OUString > av; 1297 implGetLanguageVectorFromPackage( av, xPackage ); 1298 ::std::vector< ::rtl::OUString >::const_iterator pFound = av.end(); 1299 try 1300 { 1301 pFound = ::comphelper::Locale::getFallback( av, m_aLanguage ); 1302 } 1303 catch( ::comphelper::Locale::MalFormedLocaleException& ) 1304 {} 1305 if( pFound != av.end() ) 1306 aLanguage = *pFound; 1307 } 1308 } 1309 1310 rnFileSize = 0; 1311 if( m_xSFA->exists( aRetFile ) ) 1312 rnFileSize = m_xSFA->getSize( aRetFile ); 1313 else 1314 aRetFile = rtl::OUString(); 1315 1316 return aRetFile; 1317 } 1318 1319 1320 1321