xref: /trunk/main/ucb/source/ucp/file/prov.cxx (revision 91144cd0085a7583d2099b982122deb2184ab956)
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