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