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