1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_ucb.hxx" 30 #include <osl/security.hxx> 31 #include <osl/file.hxx> 32 #include <osl/socket.h> 33 #include <cppuhelper/factory.hxx> 34 #ifndef _COM_SUN_STAR_BEANS_PROPERTYATTRIBBUTE_HPP_ 35 #include <com/sun/star/beans/PropertyAttribute.hpp> 36 #endif 37 #include <com/sun/star/ucb/FileSystemNotation.hpp> 38 #include <com/sun/star/beans/PropertyState.hpp> 39 #include "filglob.hxx" 40 #include "filid.hxx" 41 #include "shell.hxx" 42 #include "bc.hxx" 43 #include "prov.hxx" 44 45 46 using namespace fileaccess; 47 using namespace com::sun::star; 48 using namespace com::sun::star::uno; 49 using namespace com::sun::star::lang; 50 using namespace com::sun::star::beans; 51 using namespace com::sun::star::ucb; 52 using namespace com::sun::star::container; 53 54 //========================================================================= 55 extern "C" void SAL_CALL component_getImplementationEnvironment( 56 const sal_Char ** ppEnvTypeName, uno_Environment ** ) 57 { 58 *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; 59 } 60 61 //========================================================================= 62 extern "C" void * SAL_CALL component_getFactory( 63 const sal_Char * pImplName, void * pServiceManager, void * ) 64 { 65 void * pRet = 0; 66 67 Reference< XMultiServiceFactory > xSMgr( 68 reinterpret_cast< XMultiServiceFactory * >( pServiceManager ) ); 69 Reference< XSingleServiceFactory > xFactory; 70 71 ////////////////////////////////////////////////////////////////////// 72 // File Content Provider. 73 ////////////////////////////////////////////////////////////////////// 74 75 if ( fileaccess::shell::getImplementationName_static(). 76 compareToAscii( pImplName ) == 0 ) 77 { 78 xFactory = FileProvider::createServiceFactory( xSMgr ); 79 } 80 81 ////////////////////////////////////////////////////////////////////// 82 83 if ( xFactory.is() ) 84 { 85 xFactory->acquire(); 86 pRet = xFactory.get(); 87 } 88 89 return pRet; 90 } 91 92 /****************************************************************************/ 93 /* */ 94 /* */ 95 /* FileProvider */ 96 /* */ 97 /* */ 98 /****************************************************************************/ 99 100 101 102 FileProvider::FileProvider( const Reference< XMultiServiceFactory >& xMultiServiceFactory ) 103 : m_xMultiServiceFactory( xMultiServiceFactory ), 104 m_pMyShell( 0 ) 105 { 106 } 107 108 109 FileProvider::~FileProvider() 110 { 111 if( m_pMyShell ) 112 delete m_pMyShell; 113 } 114 115 116 ////////////////////////////////////////////////////////////////////////// 117 // XInterface 118 ////////////////////////////////////////////////////////////////////////// 119 120 void SAL_CALL 121 FileProvider::acquire( 122 void ) 123 throw() 124 { 125 OWeakObject::acquire(); 126 } 127 128 129 void SAL_CALL 130 FileProvider::release( 131 void ) 132 throw() 133 { 134 OWeakObject::release(); 135 } 136 137 138 Any SAL_CALL 139 FileProvider::queryInterface( 140 const Type& rType ) 141 throw( RuntimeException ) 142 { 143 Any aRet = cppu::queryInterface( 144 rType, 145 SAL_STATIC_CAST( XContentProvider*, this ), 146 SAL_STATIC_CAST( XInitialization*, this ), 147 SAL_STATIC_CAST( XContentIdentifierFactory*, this ), 148 SAL_STATIC_CAST( XServiceInfo*, this ), 149 SAL_STATIC_CAST( XTypeProvider*, this ), 150 SAL_STATIC_CAST( XFileIdentifierConverter*,this ), 151 SAL_STATIC_CAST( XPropertySet*, this ) ); 152 return aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType ); 153 } 154 155 /////////////////////////////////////////////////////////////////////////////// 156 // XInitialization 157 158 void SAL_CALL FileProvider::init() 159 { 160 if( ! m_pMyShell ) 161 m_pMyShell = new shell( m_xMultiServiceFactory, this, sal_True ); 162 } 163 164 165 void SAL_CALL 166 FileProvider::initialize( 167 const Sequence< Any >& aArguments ) 168 throw (Exception, RuntimeException) 169 { 170 if( ! m_pMyShell ) { 171 rtl::OUString config; 172 if( aArguments.getLength() > 0 && 173 (aArguments[0] >>= config) && 174 config.compareToAscii("NoConfig") == 0 ) 175 m_pMyShell = new shell( m_xMultiServiceFactory, this, sal_False ); 176 else 177 m_pMyShell = new shell( m_xMultiServiceFactory, this, sal_True ); 178 } 179 } 180 181 182 //////////////////////////////////////////////////////////////////////////////// 183 // 184 // XTypeProvider methods. 185 186 187 XTYPEPROVIDER_IMPL_7( FileProvider, 188 XTypeProvider, 189 XServiceInfo, 190 XInitialization, 191 XContentIdentifierFactory, 192 XPropertySet, 193 XFileIdentifierConverter, 194 XContentProvider ) 195 196 197 //////////////////////////////////////////////////////////////////////////////// 198 // XServiceInfo methods. 199 200 rtl::OUString SAL_CALL 201 FileProvider::getImplementationName() 202 throw( RuntimeException ) 203 { 204 return fileaccess::shell::getImplementationName_static(); 205 } 206 207 208 sal_Bool SAL_CALL 209 FileProvider::supportsService( 210 const rtl::OUString& ServiceName ) 211 throw( RuntimeException ) 212 { 213 return ServiceName == rtl::OUString::createFromAscii( "com.sun.star.ucb.FileContentProvider" ); 214 } 215 216 217 Sequence< rtl::OUString > SAL_CALL 218 FileProvider::getSupportedServiceNames( 219 void ) 220 throw( RuntimeException ) 221 { 222 return fileaccess::shell::getSupportedServiceNames_static(); 223 } 224 225 226 227 Reference< XSingleServiceFactory > SAL_CALL 228 FileProvider::createServiceFactory( 229 const Reference< XMultiServiceFactory >& rxServiceMgr ) 230 { 231 /** 232 * Create a single service factory.<BR> 233 * Note: The function pointer ComponentInstantiation points to a function throws Exception. 234 * 235 * @param rServiceManager the service manager used by the implementation. 236 * @param rImplementationName the implementation name. An empty string is possible. 237 * @param ComponentInstantiation the function pointer to create an object. 238 * @param rServiceNames the service supported by the implementation. 239 * @return a factory that support the interfaces XServiceProvider, XServiceInfo 240 * XSingleServiceFactory and XComponent. 241 * 242 * @see createOneInstanceFactory 243 */ 244 /* 245 * Reference< ::com::sun::star::XSingleServiceFactory > createSingleFactory 246 * ( 247 * const ::com::sun::star::Reference< ::com::sun::star::XMultiServiceFactory > & rServiceManager, 248 * const ::rtl::OUString & rImplementationName, 249 * ComponentInstantiation pCreateFunction, 250 251 * const ::com::sun::star::Sequence< ::rtl::OUString > & rServiceNames 252 * ); 253 */ 254 255 return Reference< XSingleServiceFactory > ( cppu::createSingleFactory( 256 rxServiceMgr, 257 fileaccess::shell::getImplementationName_static(), 258 FileProvider::CreateInstance, 259 fileaccess::shell::getSupportedServiceNames_static() ) ); 260 } 261 262 Reference< XInterface > SAL_CALL 263 FileProvider::CreateInstance( 264 const Reference< XMultiServiceFactory >& xMultiServiceFactory ) 265 { 266 XServiceInfo* xP = (XServiceInfo*) new FileProvider( xMultiServiceFactory ); 267 return Reference< XInterface >::query( xP ); 268 } 269 270 271 272 //////////////////////////////////////////////////////////////////////////////// 273 // XContent 274 //////////////////////////////////////////////////////////////////////////////// 275 276 277 Reference< XContent > SAL_CALL 278 FileProvider::queryContent( 279 const Reference< XContentIdentifier >& xIdentifier ) 280 throw( IllegalIdentifierException, 281 RuntimeException) 282 { 283 init(); 284 rtl::OUString aUnc; 285 sal_Bool err = m_pMyShell->getUnqFromUrl( xIdentifier->getContentIdentifier(), 286 aUnc ); 287 288 if( err ) 289 throw IllegalIdentifierException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); 290 291 return Reference< XContent >( new BaseContent( m_pMyShell,xIdentifier,aUnc ) ); 292 } 293 294 295 296 sal_Int32 SAL_CALL 297 FileProvider::compareContentIds( 298 const Reference< XContentIdentifier >& Id1, 299 const Reference< XContentIdentifier >& Id2 ) 300 throw( RuntimeException ) 301 { 302 init(); 303 rtl::OUString aUrl1 = Id1->getContentIdentifier(); 304 rtl::OUString aUrl2 = Id2->getContentIdentifier(); 305 306 sal_Int32 iComp = aUrl1.compareTo( aUrl2 ); 307 308 if ( 0 != iComp ) 309 { 310 rtl::OUString aPath1, aPath2; 311 312 m_pMyShell->getUnqFromUrl( aUrl1, aPath1 ); 313 m_pMyShell->getUnqFromUrl( aUrl2, aPath2 ); 314 315 osl::FileBase::RC error; 316 osl::DirectoryItem aItem1, aItem2; 317 318 error = osl::DirectoryItem::get( aPath1, aItem1 ); 319 if ( error == osl::FileBase::E_None ) 320 error = osl::DirectoryItem::get( aPath2, aItem2 ); 321 322 if ( error != osl::FileBase::E_None ) 323 return iComp; 324 325 osl::FileStatus aStatus1( FileStatusMask_FileURL ); 326 osl::FileStatus aStatus2( FileStatusMask_FileURL ); 327 error = aItem1.getFileStatus( aStatus1 ); 328 if ( error == osl::FileBase::E_None ) 329 error = aItem2.getFileStatus( aStatus2 ); 330 331 if ( error == osl::FileBase::E_None ) 332 { 333 iComp = aStatus1.getFileURL().compareTo( aStatus2.getFileURL() ); 334 335 // Quick hack for Windows to threat all file systems as case insensitive 336 #ifdef WNT 337 if ( 0 != iComp ) 338 { 339 error = osl::FileBase::getSystemPathFromFileURL( aStatus1.getFileURL(), aPath1 ); 340 if ( error == osl::FileBase::E_None ) 341 error = osl::FileBase::getSystemPathFromFileURL( aStatus2.getFileURL(), aPath2 ); 342 343 if ( error == osl::FileBase::E_None ) 344 iComp = rtl_ustr_compareIgnoreAsciiCase( aPath1.getStr(), aPath2.getStr() ); 345 } 346 #endif 347 } 348 } 349 350 return iComp; 351 } 352 353 354 355 Reference< XContentIdentifier > SAL_CALL 356 FileProvider::createContentIdentifier( 357 const rtl::OUString& ContentId ) 358 throw( RuntimeException ) 359 { 360 init(); 361 FileContentIdentifier* p = new FileContentIdentifier( m_pMyShell,ContentId,false ); 362 return Reference< XContentIdentifier >( p ); 363 } 364 365 366 367 //XPropertySetInfoImpl 368 369 class XPropertySetInfoImpl2 370 : public cppu::OWeakObject, 371 public XPropertySetInfo 372 { 373 public: 374 XPropertySetInfoImpl2(); 375 ~XPropertySetInfoImpl2(); 376 377 // XInterface 378 virtual Any SAL_CALL 379 queryInterface( 380 const Type& aType ) 381 throw( RuntimeException); 382 383 virtual void SAL_CALL 384 acquire( 385 void ) 386 throw(); 387 388 virtual void SAL_CALL 389 release( 390 void ) 391 throw(); 392 393 394 virtual Sequence< Property > SAL_CALL 395 getProperties( 396 void ) 397 throw( RuntimeException ); 398 399 virtual Property SAL_CALL 400 getPropertyByName( 401 const rtl::OUString& aName ) 402 throw( UnknownPropertyException, 403 RuntimeException); 404 405 virtual sal_Bool SAL_CALL 406 hasPropertyByName( const rtl::OUString& Name ) 407 throw( RuntimeException ); 408 409 410 private: 411 Sequence< Property > m_seq; 412 }; 413 414 415 XPropertySetInfoImpl2::XPropertySetInfoImpl2() 416 : m_seq( 3 ) 417 { 418 m_seq[0] = Property( rtl::OUString::createFromAscii( "HostName" ), 419 -1, 420 getCppuType( static_cast< rtl::OUString* >( 0 ) ), 421 PropertyAttribute::READONLY ); 422 423 m_seq[1] = Property( rtl::OUString::createFromAscii( "HomeDirectory" ), 424 -1, 425 getCppuType( static_cast< rtl::OUString* >( 0 ) ), 426 PropertyAttribute::READONLY ); 427 428 m_seq[2] = Property( rtl::OUString::createFromAscii( "FileSystemNotation" ), 429 -1, 430 getCppuType( static_cast< sal_Int32* >( 0 ) ), 431 PropertyAttribute::READONLY ); 432 } 433 434 435 XPropertySetInfoImpl2::~XPropertySetInfoImpl2() 436 { 437 // nothing 438 } 439 440 441 void SAL_CALL 442 XPropertySetInfoImpl2::acquire( 443 void ) 444 throw() 445 { 446 OWeakObject::acquire(); 447 } 448 449 450 void SAL_CALL 451 XPropertySetInfoImpl2::release( 452 void ) 453 throw() 454 { 455 OWeakObject::release(); 456 } 457 458 459 Any SAL_CALL 460 XPropertySetInfoImpl2::queryInterface( 461 const Type& rType ) 462 throw( RuntimeException ) 463 { 464 Any aRet = cppu::queryInterface( rType, 465 SAL_STATIC_CAST( XPropertySetInfo*,this) ); 466 return aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType ); 467 } 468 469 470 Property SAL_CALL 471 XPropertySetInfoImpl2::getPropertyByName( 472 const rtl::OUString& aName ) 473 throw( UnknownPropertyException, 474 RuntimeException) 475 { 476 for( sal_Int32 i = 0; i < m_seq.getLength(); ++i ) 477 if( m_seq[i].Name == aName ) 478 return m_seq[i]; 479 480 throw UnknownPropertyException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); 481 } 482 483 484 485 Sequence< Property > SAL_CALL 486 XPropertySetInfoImpl2::getProperties( 487 void ) 488 throw( RuntimeException ) 489 { 490 return m_seq; 491 } 492 493 494 sal_Bool SAL_CALL 495 XPropertySetInfoImpl2::hasPropertyByName( 496 const rtl::OUString& aName ) 497 throw( RuntimeException ) 498 { 499 for( sal_Int32 i = 0; i < m_seq.getLength(); ++i ) 500 if( m_seq[i].Name == aName ) 501 return true; 502 return false; 503 } 504 505 506 507 508 509 void SAL_CALL FileProvider::initProperties( void ) 510 { 511 osl::MutexGuard aGuard( m_aMutex ); 512 if( ! m_xPropertySetInfo.is() ) 513 { 514 osl_getLocalHostname( &m_HostName.pData ); 515 516 #if defined ( UNX ) 517 m_FileSystemNotation = FileSystemNotation::UNIX_NOTATION; 518 #elif defined( WNT ) || defined( OS2 ) 519 m_FileSystemNotation = FileSystemNotation::DOS_NOTATION; 520 #else 521 m_FileSystemNotation = FileSystemNotation::UNKNOWN_NOTATION; 522 #endif 523 osl::Security aSecurity; 524 aSecurity.getHomeDir( m_HomeDirectory ); 525 526 // static const sal_Int32 UNKNOWN_NOTATION = (sal_Int32)0; 527 // static const sal_Int32 UNIX_NOTATION = (sal_Int32)1; 528 // static const sal_Int32 DOS_NOTATION = (sal_Int32)2; 529 // static const sal_Int32 MAC_NOTATION = (sal_Int32)3; 530 531 XPropertySetInfoImpl2* p = new XPropertySetInfoImpl2(); 532 m_xPropertySetInfo = Reference< XPropertySetInfo >( p ); 533 } 534 } 535 536 537 // XPropertySet 538 539 Reference< XPropertySetInfo > SAL_CALL 540 FileProvider::getPropertySetInfo( ) 541 throw( RuntimeException ) 542 { 543 initProperties(); 544 return m_xPropertySetInfo; 545 } 546 547 548 void SAL_CALL 549 FileProvider::setPropertyValue( const rtl::OUString& aPropertyName, 550 const Any& ) 551 throw( UnknownPropertyException, 552 PropertyVetoException, 553 IllegalArgumentException, 554 WrappedTargetException, 555 RuntimeException ) 556 { 557 if( aPropertyName.compareToAscii( "FileSystemNotation" ) == 0 || 558 aPropertyName.compareToAscii( "HomeDirectory" ) == 0 || 559 aPropertyName.compareToAscii( "HostName" ) == 0 ) 560 return; 561 else 562 throw UnknownPropertyException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); 563 } 564 565 566 567 Any SAL_CALL 568 FileProvider::getPropertyValue( 569 const rtl::OUString& aPropertyName ) 570 throw( UnknownPropertyException, 571 WrappedTargetException, 572 RuntimeException ) 573 { 574 initProperties(); 575 if( aPropertyName.compareToAscii( "FileSystemNotation" ) == 0 ) 576 { 577 Any aAny; 578 aAny <<= m_FileSystemNotation; 579 return aAny; 580 } 581 else if( aPropertyName.compareToAscii( "HomeDirectory" ) == 0 ) 582 { 583 Any aAny; 584 aAny <<= m_HomeDirectory; 585 return aAny; 586 } 587 else if( aPropertyName.compareToAscii( "HostName" ) == 0 ) 588 { 589 Any aAny; 590 aAny <<= m_HostName; 591 return aAny; 592 } 593 else 594 throw UnknownPropertyException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); 595 } 596 597 598 void SAL_CALL 599 FileProvider::addPropertyChangeListener( 600 const rtl::OUString&, 601 const Reference< XPropertyChangeListener >& ) 602 throw( UnknownPropertyException, 603 WrappedTargetException, 604 RuntimeException) 605 { 606 return; 607 } 608 609 610 void SAL_CALL 611 FileProvider::removePropertyChangeListener( 612 const rtl::OUString&, 613 const Reference< XPropertyChangeListener >& ) 614 throw( UnknownPropertyException, 615 WrappedTargetException, 616 RuntimeException ) 617 { 618 return; 619 } 620 621 void SAL_CALL 622 FileProvider::addVetoableChangeListener( 623 const rtl::OUString&, 624 const Reference< XVetoableChangeListener >& ) 625 throw( UnknownPropertyException, 626 WrappedTargetException, 627 RuntimeException ) 628 { 629 return; 630 } 631 632 633 void SAL_CALL 634 FileProvider::removeVetoableChangeListener( 635 const rtl::OUString&, 636 const Reference< XVetoableChangeListener >& ) 637 throw( UnknownPropertyException, 638 WrappedTargetException, 639 RuntimeException) 640 { 641 return; 642 } 643 644 645 646 // XFileIdentifierConverter 647 648 sal_Int32 SAL_CALL 649 FileProvider::getFileProviderLocality( const rtl::OUString& BaseURL ) 650 throw( RuntimeException ) 651 { 652 // If the base URL is a 'file' URL, return 10 (very 'local'), otherwise 653 // return -1 (missmatch). What is missing is a fast comparison to ASCII, 654 // ignoring case: 655 return BaseURL.getLength() >= 5 656 && (BaseURL[0] == 'F' || BaseURL[0] == 'f') 657 && (BaseURL[1] == 'I' || BaseURL[1] == 'i') 658 && (BaseURL[2] == 'L' || BaseURL[2] == 'l') 659 && (BaseURL[3] == 'E' || BaseURL[3] == 'e') 660 && BaseURL[4] == ':' ? 661 10 : -1; 662 } 663 664 rtl::OUString SAL_CALL FileProvider::getFileURLFromSystemPath( const rtl::OUString&, 665 const rtl::OUString& SystemPath ) 666 throw( RuntimeException ) 667 { 668 rtl::OUString aNormalizedPath; 669 if ( osl::FileBase::getFileURLFromSystemPath( SystemPath,aNormalizedPath ) != osl::FileBase::E_None ) 670 return rtl::OUString(); 671 672 return aNormalizedPath; 673 } 674 675 rtl::OUString SAL_CALL FileProvider::getSystemPathFromFileURL( const rtl::OUString& URL ) 676 throw( RuntimeException ) 677 { 678 rtl::OUString aSystemPath; 679 if (osl::FileBase::getSystemPathFromFileURL( URL,aSystemPath ) != osl::FileBase::E_None ) 680 return rtl::OUString(); 681 682 return aSystemPath; 683 } 684 685