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_file.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" SAL_DLLPUBLIC_EXPORT 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" SAL_DLLPUBLIC_EXPORT 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 {
138 Any aRet = cppu::queryInterface(
139 rType,
140 SAL_STATIC_CAST( XContentProvider*, this ),
141 SAL_STATIC_CAST( XInitialization*, this ),
142 SAL_STATIC_CAST( XContentIdentifierFactory*, this ),
143 SAL_STATIC_CAST( XServiceInfo*, this ),
144 SAL_STATIC_CAST( XTypeProvider*, this ),
145 SAL_STATIC_CAST( XFileIdentifierConverter*,this ),
146 SAL_STATIC_CAST( XPropertySet*, this ) );
147 return aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType );
148 }
149
150 ///////////////////////////////////////////////////////////////////////////////
151 // XInitialization
152
init()153 void SAL_CALL FileProvider::init()
154 {
155 if( ! m_pMyShell )
156 m_pMyShell = new shell( m_xMultiServiceFactory, this, sal_True );
157 }
158
159
160 void SAL_CALL
initialize(const Sequence<Any> & aArguments)161 FileProvider::initialize(
162 const Sequence< Any >& aArguments )
163 {
164 if( ! m_pMyShell ) {
165 rtl::OUString config;
166 if( aArguments.getLength() > 0 &&
167 (aArguments[0] >>= config) &&
168 config.compareToAscii("NoConfig") == 0 )
169 m_pMyShell = new shell( m_xMultiServiceFactory, this, sal_False );
170 else
171 m_pMyShell = new shell( m_xMultiServiceFactory, this, sal_True );
172 }
173 }
174
175
176 ////////////////////////////////////////////////////////////////////////////////
177 //
178 // XTypeProvider methods.
179
180
XTYPEPROVIDER_IMPL_7(FileProvider,XTypeProvider,XServiceInfo,XInitialization,XContentIdentifierFactory,XPropertySet,XFileIdentifierConverter,XContentProvider)181 XTYPEPROVIDER_IMPL_7( FileProvider,
182 XTypeProvider,
183 XServiceInfo,
184 XInitialization,
185 XContentIdentifierFactory,
186 XPropertySet,
187 XFileIdentifierConverter,
188 XContentProvider )
189
190
191 ////////////////////////////////////////////////////////////////////////////////
192 // XServiceInfo methods.
193
194 rtl::OUString SAL_CALL
195 FileProvider::getImplementationName()
196 {
197 return fileaccess::shell::getImplementationName_static();
198 }
199
200
201 sal_Bool SAL_CALL
supportsService(const rtl::OUString & ServiceName)202 FileProvider::supportsService(
203 const rtl::OUString& ServiceName )
204 {
205 return ServiceName == rtl::OUString::createFromAscii( "com.sun.star.ucb.FileContentProvider" );
206 }
207
208
209 Sequence< rtl::OUString > SAL_CALL
getSupportedServiceNames(void)210 FileProvider::getSupportedServiceNames(
211 void )
212 {
213 return fileaccess::shell::getSupportedServiceNames_static();
214 }
215
216
217
218 Reference< XSingleServiceFactory > SAL_CALL
createServiceFactory(const Reference<XMultiServiceFactory> & rxServiceMgr)219 FileProvider::createServiceFactory(
220 const Reference< XMultiServiceFactory >& rxServiceMgr )
221 {
222 /**
223 * Create a single service factory.<BR>
224 * Note: The function pointer ComponentInstantiation points to a function throws Exception.
225 *
226 * @param rServiceManager the service manager used by the implementation.
227 * @param rImplementationName the implementation name. An empty string is possible.
228 * @param ComponentInstantiation the function pointer to create an object.
229 * @param rServiceNames the service supported by the implementation.
230 * @return a factory that support the interfaces XServiceProvider, XServiceInfo
231 * XSingleServiceFactory and XComponent.
232 *
233 * @see createOneInstanceFactory
234 */
235 /*
236 * Reference< ::com::sun::star::XSingleServiceFactory > createSingleFactory
237 * (
238 * const ::com::sun::star::Reference< ::com::sun::star::XMultiServiceFactory > & rServiceManager,
239 * const ::rtl::OUString & rImplementationName,
240 * ComponentInstantiation pCreateFunction,
241
242 * const ::com::sun::star::Sequence< ::rtl::OUString > & rServiceNames
243 * );
244 */
245
246 return Reference< XSingleServiceFactory > ( cppu::createSingleFactory(
247 rxServiceMgr,
248 fileaccess::shell::getImplementationName_static(),
249 FileProvider::CreateInstance,
250 fileaccess::shell::getSupportedServiceNames_static() ) );
251 }
252
253 Reference< XInterface > SAL_CALL
CreateInstance(const Reference<XMultiServiceFactory> & xMultiServiceFactory)254 FileProvider::CreateInstance(
255 const Reference< XMultiServiceFactory >& xMultiServiceFactory )
256 {
257 XServiceInfo* xP = (XServiceInfo*) new FileProvider( xMultiServiceFactory );
258 return Reference< XInterface >::query( xP );
259 }
260
261
262
263 ////////////////////////////////////////////////////////////////////////////////
264 // XContent
265 ////////////////////////////////////////////////////////////////////////////////
266
267
268 Reference< XContent > SAL_CALL
queryContent(const Reference<XContentIdentifier> & xIdentifier)269 FileProvider::queryContent(
270 const Reference< XContentIdentifier >& xIdentifier )
271 {
272 init();
273 rtl::OUString aUnc;
274 sal_Bool err = m_pMyShell->getUnqFromUrl( xIdentifier->getContentIdentifier(),
275 aUnc );
276
277 if( err )
278 throw IllegalIdentifierException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
279
280 return Reference< XContent >( new BaseContent( m_pMyShell,xIdentifier,aUnc ) );
281 }
282
283
284
285 sal_Int32 SAL_CALL
compareContentIds(const Reference<XContentIdentifier> & Id1,const Reference<XContentIdentifier> & Id2)286 FileProvider::compareContentIds(
287 const Reference< XContentIdentifier >& Id1,
288 const Reference< XContentIdentifier >& Id2 )
289 {
290 init();
291 rtl::OUString aUrl1 = Id1->getContentIdentifier();
292 rtl::OUString aUrl2 = Id2->getContentIdentifier();
293
294 sal_Int32 iComp = aUrl1.compareTo( aUrl2 );
295
296 if ( 0 != iComp )
297 {
298 rtl::OUString aPath1, aPath2;
299
300 m_pMyShell->getUnqFromUrl( aUrl1, aPath1 );
301 m_pMyShell->getUnqFromUrl( aUrl2, aPath2 );
302
303 osl::FileBase::RC error;
304 osl::DirectoryItem aItem1, aItem2;
305
306 error = osl::DirectoryItem::get( aPath1, aItem1 );
307 if ( error == osl::FileBase::E_None )
308 error = osl::DirectoryItem::get( aPath2, aItem2 );
309
310 if ( error != osl::FileBase::E_None )
311 return iComp;
312
313 osl::FileStatus aStatus1( FileStatusMask_FileURL );
314 osl::FileStatus aStatus2( FileStatusMask_FileURL );
315 error = aItem1.getFileStatus( aStatus1 );
316 if ( error == osl::FileBase::E_None )
317 error = aItem2.getFileStatus( aStatus2 );
318
319 if ( error == osl::FileBase::E_None )
320 {
321 iComp = aStatus1.getFileURL().compareTo( aStatus2.getFileURL() );
322
323 // Quick hack for Windows to treat all file systems as case insensitive
324 #ifdef WNT
325 if ( 0 != iComp )
326 {
327 error = osl::FileBase::getSystemPathFromFileURL( aStatus1.getFileURL(), aPath1 );
328 if ( error == osl::FileBase::E_None )
329 error = osl::FileBase::getSystemPathFromFileURL( aStatus2.getFileURL(), aPath2 );
330
331 if ( error == osl::FileBase::E_None )
332 iComp = rtl_ustr_compareIgnoreAsciiCase( aPath1.getStr(), aPath2.getStr() );
333 }
334 #endif
335 }
336 }
337
338 return iComp;
339 }
340
341
342
343 Reference< XContentIdentifier > SAL_CALL
createContentIdentifier(const rtl::OUString & ContentId)344 FileProvider::createContentIdentifier(
345 const rtl::OUString& ContentId )
346 {
347 init();
348 FileContentIdentifier* p = new FileContentIdentifier( m_pMyShell,ContentId,false );
349 return Reference< XContentIdentifier >( p );
350 }
351
352
353
354 //XPropertySetInfoImpl
355
356 class XPropertySetInfoImpl2
357 : public cppu::OWeakObject,
358 public XPropertySetInfo
359 {
360 public:
361 XPropertySetInfoImpl2();
362 ~XPropertySetInfoImpl2();
363
364 // XInterface
365 virtual Any SAL_CALL
366 queryInterface(
367 const Type& aType );
368
369 virtual void SAL_CALL
370 acquire(
371 void )
372 throw();
373
374 virtual void SAL_CALL
375 release(
376 void )
377 throw();
378
379
380 virtual Sequence< Property > SAL_CALL
381 getProperties(
382 void );
383
384 virtual Property SAL_CALL
385 getPropertyByName(
386 const rtl::OUString& aName );
387
388 virtual sal_Bool SAL_CALL
389 hasPropertyByName( const rtl::OUString& Name );
390
391
392 private:
393 Sequence< Property > m_seq;
394 };
395
396
XPropertySetInfoImpl2()397 XPropertySetInfoImpl2::XPropertySetInfoImpl2()
398 : m_seq( 3 )
399 {
400 m_seq[0] = Property( rtl::OUString::createFromAscii( "HostName" ),
401 -1,
402 getCppuType( static_cast< rtl::OUString* >( 0 ) ),
403 PropertyAttribute::READONLY );
404
405 m_seq[1] = Property( rtl::OUString::createFromAscii( "HomeDirectory" ),
406 -1,
407 getCppuType( static_cast< rtl::OUString* >( 0 ) ),
408 PropertyAttribute::READONLY );
409
410 m_seq[2] = Property( rtl::OUString::createFromAscii( "FileSystemNotation" ),
411 -1,
412 getCppuType( static_cast< sal_Int32* >( 0 ) ),
413 PropertyAttribute::READONLY );
414 }
415
416
~XPropertySetInfoImpl2()417 XPropertySetInfoImpl2::~XPropertySetInfoImpl2()
418 {
419 // nothing
420 }
421
422
423 void SAL_CALL
acquire(void)424 XPropertySetInfoImpl2::acquire(
425 void )
426 throw()
427 {
428 OWeakObject::acquire();
429 }
430
431
432 void SAL_CALL
release(void)433 XPropertySetInfoImpl2::release(
434 void )
435 throw()
436 {
437 OWeakObject::release();
438 }
439
440
441 Any SAL_CALL
queryInterface(const Type & rType)442 XPropertySetInfoImpl2::queryInterface(
443 const Type& rType )
444 {
445 Any aRet = cppu::queryInterface( rType,
446 SAL_STATIC_CAST( XPropertySetInfo*,this) );
447 return aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType );
448 }
449
450
451 Property SAL_CALL
getPropertyByName(const rtl::OUString & aName)452 XPropertySetInfoImpl2::getPropertyByName(
453 const rtl::OUString& aName )
454 {
455 for( sal_Int32 i = 0; i < m_seq.getLength(); ++i )
456 if( m_seq[i].Name == aName )
457 return m_seq[i];
458
459 throw UnknownPropertyException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
460 }
461
462
463
464 Sequence< Property > SAL_CALL
getProperties(void)465 XPropertySetInfoImpl2::getProperties(
466 void )
467 {
468 return m_seq;
469 }
470
471
472 sal_Bool SAL_CALL
hasPropertyByName(const rtl::OUString & aName)473 XPropertySetInfoImpl2::hasPropertyByName(
474 const rtl::OUString& aName )
475 {
476 for( sal_Int32 i = 0; i < m_seq.getLength(); ++i )
477 if( m_seq[i].Name == aName )
478 return true;
479 return false;
480 }
481
482
483
484
485
initProperties(void)486 void SAL_CALL FileProvider::initProperties( void )
487 {
488 osl::MutexGuard aGuard( m_aMutex );
489 if( ! m_xPropertySetInfo.is() )
490 {
491 osl_getLocalHostname( &m_HostName.pData );
492
493 #if defined ( UNX )
494 m_FileSystemNotation = FileSystemNotation::UNIX_NOTATION;
495 #elif defined( WNT ) || defined( OS2 )
496 m_FileSystemNotation = FileSystemNotation::DOS_NOTATION;
497 #else
498 m_FileSystemNotation = FileSystemNotation::UNKNOWN_NOTATION;
499 #endif
500 osl::Security aSecurity;
501 aSecurity.getHomeDir( m_HomeDirectory );
502
503 // static const sal_Int32 UNKNOWN_NOTATION = (sal_Int32)0;
504 // static const sal_Int32 UNIX_NOTATION = (sal_Int32)1;
505 // static const sal_Int32 DOS_NOTATION = (sal_Int32)2;
506 // static const sal_Int32 MAC_NOTATION = (sal_Int32)3;
507
508 XPropertySetInfoImpl2* p = new XPropertySetInfoImpl2();
509 m_xPropertySetInfo = Reference< XPropertySetInfo >( p );
510 }
511 }
512
513
514 // XPropertySet
515
516 Reference< XPropertySetInfo > SAL_CALL
getPropertySetInfo()517 FileProvider::getPropertySetInfo( )
518 {
519 initProperties();
520 return m_xPropertySetInfo;
521 }
522
523
524 void SAL_CALL
setPropertyValue(const rtl::OUString & aPropertyName,const Any &)525 FileProvider::setPropertyValue( const rtl::OUString& aPropertyName,
526 const Any& )
527 {
528 if( aPropertyName.compareToAscii( "FileSystemNotation" ) == 0 ||
529 aPropertyName.compareToAscii( "HomeDirectory" ) == 0 ||
530 aPropertyName.compareToAscii( "HostName" ) == 0 )
531 return;
532 else
533 throw UnknownPropertyException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
534 }
535
536
537
538 Any SAL_CALL
getPropertyValue(const rtl::OUString & aPropertyName)539 FileProvider::getPropertyValue(
540 const rtl::OUString& aPropertyName )
541 {
542 initProperties();
543 if( aPropertyName.compareToAscii( "FileSystemNotation" ) == 0 )
544 {
545 Any aAny;
546 aAny <<= m_FileSystemNotation;
547 return aAny;
548 }
549 else if( aPropertyName.compareToAscii( "HomeDirectory" ) == 0 )
550 {
551 Any aAny;
552 aAny <<= m_HomeDirectory;
553 return aAny;
554 }
555 else if( aPropertyName.compareToAscii( "HostName" ) == 0 )
556 {
557 Any aAny;
558 aAny <<= m_HostName;
559 return aAny;
560 }
561 else
562 throw UnknownPropertyException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
563 }
564
565
566 void SAL_CALL
addPropertyChangeListener(const rtl::OUString &,const Reference<XPropertyChangeListener> &)567 FileProvider::addPropertyChangeListener(
568 const rtl::OUString&,
569 const Reference< XPropertyChangeListener >& )
570 {
571 return;
572 }
573
574
575 void SAL_CALL
removePropertyChangeListener(const rtl::OUString &,const Reference<XPropertyChangeListener> &)576 FileProvider::removePropertyChangeListener(
577 const rtl::OUString&,
578 const Reference< XPropertyChangeListener >& )
579 {
580 return;
581 }
582
583 void SAL_CALL
addVetoableChangeListener(const rtl::OUString &,const Reference<XVetoableChangeListener> &)584 FileProvider::addVetoableChangeListener(
585 const rtl::OUString&,
586 const Reference< XVetoableChangeListener >& )
587 {
588 return;
589 }
590
591
592 void SAL_CALL
removeVetoableChangeListener(const rtl::OUString &,const Reference<XVetoableChangeListener> &)593 FileProvider::removeVetoableChangeListener(
594 const rtl::OUString&,
595 const Reference< XVetoableChangeListener >& )
596 {
597 return;
598 }
599
600
601
602 // XFileIdentifierConverter
603
604 sal_Int32 SAL_CALL
getFileProviderLocality(const rtl::OUString & BaseURL)605 FileProvider::getFileProviderLocality( const rtl::OUString& BaseURL )
606 {
607 // If the base URL is a 'file' URL, return 10 (very 'local'), otherwise
608 // return -1 (mismatch). What is missing is a fast comparison to ASCII,
609 // ignoring case:
610 return BaseURL.getLength() >= 5
611 && (BaseURL[0] == 'F' || BaseURL[0] == 'f')
612 && (BaseURL[1] == 'I' || BaseURL[1] == 'i')
613 && (BaseURL[2] == 'L' || BaseURL[2] == 'l')
614 && (BaseURL[3] == 'E' || BaseURL[3] == 'e')
615 && BaseURL[4] == ':' ?
616 10 : -1;
617 }
618
getFileURLFromSystemPath(const rtl::OUString &,const rtl::OUString & SystemPath)619 rtl::OUString SAL_CALL FileProvider::getFileURLFromSystemPath( const rtl::OUString&,
620 const rtl::OUString& SystemPath )
621 {
622 rtl::OUString aNormalizedPath;
623 if ( osl::FileBase::getFileURLFromSystemPath( SystemPath,aNormalizedPath ) != osl::FileBase::E_None )
624 return rtl::OUString();
625
626 return aNormalizedPath;
627 }
628
getSystemPathFromFileURL(const rtl::OUString & URL)629 rtl::OUString SAL_CALL FileProvider::getSystemPathFromFileURL( const rtl::OUString& URL )
630 {
631 rtl::OUString aSystemPath;
632 if (osl::FileBase::getSystemPathFromFileURL( URL,aSystemPath ) != osl::FileBase::E_None )
633 return rtl::OUString();
634
635 return aSystemPath;
636 }
637