xref: /trunk/main/ucb/source/ucp/file/shell.cxx (revision c965e8147ebb85b50d3d7752a44d8fd7e8f598ac) !
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 #ifndef INCLUDED_STL_STACK
27 #include <stack>
28 #define INCLUDED_STL_STACK
29 #endif
30 
31 #include "osl/diagnose.h"
32 #include <rtl/uri.hxx>
33 #include <rtl/ustrbuf.hxx>
34 #include <osl/time.h>
35 #include <osl/file.hxx>
36 #include <com/sun/star/lang/IllegalAccessException.hpp>
37 #include <com/sun/star/beans/IllegalTypeException.hpp>
38 #include <com/sun/star/ucb/InteractiveAugmentedIOException.hpp>
39 #include <com/sun/star/ucb/InsertCommandArgument.hpp>
40 #include <com/sun/star/ucb/NameClash.hpp>
41 #include <com/sun/star/ucb/XContentIdentifier.hpp>
42 #include <com/sun/star/lang/XComponent.hpp>
43 #include <com/sun/star/ucb/XContentAccess.hpp>
44 #include <com/sun/star/beans/PropertyAttribute.hpp>
45 #include <com/sun/star/io/XSeekable.hpp>
46 #include <com/sun/star/io/XTruncate.hpp>
47 #include <com/sun/star/ucb/OpenCommandArgument.hpp>
48 #include <com/sun/star/ucb/XPropertySetRegistryFactory.hpp>
49 #include <com/sun/star/ucb/TransferInfo.hpp>
50 #include <com/sun/star/ucb/ContentInfoAttribute.hpp>
51 #include <com/sun/star/beans/PropertyChangeEvent.hpp>
52 #include <com/sun/star/beans/XPropertiesChangeListener.hpp>
53 #include <rtl/string.hxx>
54 #include "filerror.hxx"
55 #include "filglob.hxx"
56 #include "filcmd.hxx"
57 #include "filinpstr.hxx"
58 #include "filstr.hxx"
59 #include "filrset.hxx"
60 #include "filrow.hxx"
61 #include "filprp.hxx"
62 #include "filid.hxx"
63 #include "shell.hxx"
64 #include "prov.hxx"
65 #include "bc.hxx"
66 
67 
68 using namespace fileaccess;
69 using namespace com::sun::star;
70 using namespace com::sun::star::ucb;
71 
72 
UnqPathData()73 shell::UnqPathData::UnqPathData()
74     : properties( 0 ),
75       notifier( 0 ),
76       xS( 0 ),
77       xC( 0 ),
78       xA( 0 )
79 {
80     // empty
81 }
82 
83 
UnqPathData(const UnqPathData & a)84 shell::UnqPathData::UnqPathData( const UnqPathData& a )
85     : properties( a.properties ),
86       notifier( a.notifier ),
87       xS( a.xS ),
88       xC( a.xC ),
89       xA( a.xA )
90 {
91 }
92 
93 
operator =(UnqPathData & a)94 shell::UnqPathData& shell::UnqPathData::operator=( UnqPathData& a )
95 {
96     properties = a.properties;
97     notifier = a.notifier;
98     xS = a.xS;
99     xC = a.xC;
100     xA = a.xA;
101     a.properties = 0;
102     a.notifier = 0;
103     a.xS = 0;
104     a.xC = 0;
105     a.xA = 0;
106     return *this;
107 }
108 
~UnqPathData()109 shell::UnqPathData::~UnqPathData()
110 {
111     if( properties )
112         delete properties;
113     if( notifier )
114         delete notifier;
115 }
116 
117 
118 
119 ////////////////////////////////////////////////////////////////////////////////////////
120 
121 
122 
123 
124 
MyProperty(const rtl::OUString & __PropertyName)125 shell::MyProperty::MyProperty( const rtl::OUString&                         __PropertyName )
126     : PropertyName( __PropertyName )
127 {
128     // empty
129 }
130 
131 
MyProperty(const sal_Bool & __isNative,const rtl::OUString & __PropertyName,const sal_Int32 & __Handle,const com::sun::star::uno::Type & __Typ,const com::sun::star::uno::Any & __Value,const com::sun::star::beans::PropertyState & __State,const sal_Int16 & __Attributes)132 shell::MyProperty::MyProperty( const sal_Bool&                              __isNative,
133                                const rtl::OUString&                         __PropertyName,
134                                const sal_Int32&                             __Handle,
135                                const com::sun::star::uno::Type&              __Typ,
136                                const com::sun::star::uno::Any&              __Value,
137                                const com::sun::star::beans::PropertyState&  __State,
138                                const sal_Int16&                             __Attributes )
139     : PropertyName( __PropertyName ),
140       Handle( __Handle ),
141       isNative( __isNative ),
142       Typ( __Typ ),
143       Value( __Value ),
144       State( __State ),
145       Attributes( __Attributes )
146 {
147     // empty
148 }
149 
~MyProperty()150 shell::MyProperty::~MyProperty()
151 {
152     // empty for now
153 }
154 
155 
156 #include "filinl.hxx"
157 
158 
shell(const uno::Reference<lang::XMultiServiceFactory> & xMultiServiceFactory,FileProvider * pProvider,sal_Bool bWithConfig)159 shell::shell( const uno::Reference< lang::XMultiServiceFactory >& xMultiServiceFactory,
160               FileProvider* pProvider, sal_Bool bWithConfig )
161     : TaskManager(),
162       m_bWithConfig( bWithConfig ),
163       m_pProvider( pProvider ),
164       m_xMultiServiceFactory( xMultiServiceFactory ),
165       Title( rtl::OUString::createFromAscii( "Title" ) ),
166       CasePreservingURL(
167           rtl::OUString::createFromAscii( "CasePreservingURL" ) ),
168       IsDocument( rtl::OUString::createFromAscii( "IsDocument" ) ),
169       IsFolder( rtl::OUString::createFromAscii( "IsFolder" ) ),
170       DateModified( rtl::OUString::createFromAscii( "DateModified" ) ),
171       Size( rtl::OUString::createFromAscii( "Size" ) ),
172       IsVolume( rtl::OUString::createFromAscii( "IsVolume" ) ),
173       IsRemoveable( rtl::OUString::createFromAscii( "IsRemoveable" ) ),
174       IsRemote( rtl::OUString::createFromAscii( "IsRemote" ) ),
175       IsCompactDisc( rtl::OUString::createFromAscii( "IsCompactDisc" ) ),
176       IsFloppy( rtl::OUString::createFromAscii( "IsFloppy" ) ),
177       IsHidden( rtl::OUString::createFromAscii( "IsHidden" ) ),
178       ContentType( rtl::OUString::createFromAscii( "ContentType" ) ),
179       IsReadOnly( rtl::OUString::createFromAscii( "IsReadOnly" ) ),
180       CreatableContentsInfo( rtl::OUString::createFromAscii( "CreatableContentsInfo" ) ),
181       FolderContentType( rtl::OUString::createFromAscii( "application/vnd.sun.staroffice.fsys-folder" ) ),
182       FileContentType( rtl::OUString::createFromAscii( "application/vnd.sun.staroffice.fsys-file" ) ),
183       m_sCommandInfo( 9 )
184 {
185     // Title
186     m_aDefaultProperties.insert( MyProperty( true,
187                                              Title,
188                                              -1 ,
189                                              getCppuType( static_cast< rtl::OUString* >( 0 ) ),
190                                              uno::Any(),
191                                              beans::PropertyState_DEFAULT_VALUE,
192                                              beans::PropertyAttribute::MAYBEVOID
193                                              | beans::PropertyAttribute::BOUND ) );
194 
195     // CasePreservingURL
196     m_aDefaultProperties.insert(
197         MyProperty( true,
198                     CasePreservingURL,
199                     -1 ,
200                     getCppuType( static_cast< rtl::OUString* >( 0 ) ),
201                     uno::Any(),
202                     beans::PropertyState_DEFAULT_VALUE,
203                     beans::PropertyAttribute::MAYBEVOID
204                     | beans::PropertyAttribute::BOUND
205                     | beans::PropertyAttribute::READONLY ) );
206 
207 
208     // IsFolder
209     m_aDefaultProperties.insert( MyProperty( true,
210                                              IsFolder,
211                                              -1 ,
212                                              getCppuType( static_cast< sal_Bool* >( 0 ) ),
213                                              uno::Any(),
214                                              beans::PropertyState_DEFAULT_VALUE,
215                                              beans::PropertyAttribute::MAYBEVOID
216                                              | beans::PropertyAttribute::BOUND
217                                              | beans::PropertyAttribute::READONLY ) );
218 
219 
220     // IsDocument
221     m_aDefaultProperties.insert( MyProperty( true,
222                                              IsDocument,
223                                              -1 ,
224                                              getCppuType( static_cast< sal_Bool* >( 0 ) ),
225                                              uno::Any(),
226                                              beans::PropertyState_DEFAULT_VALUE,
227                                              beans::PropertyAttribute::MAYBEVOID
228                                              | beans::PropertyAttribute::BOUND
229                                              | beans::PropertyAttribute::READONLY ) );
230 
231     // Removable
232     m_aDefaultProperties.insert( MyProperty( true,
233                                              IsVolume,
234                                              -1 ,
235                                              getCppuType( static_cast< sal_Bool* >( 0 ) ),
236                                              uno::Any(),
237                                              beans::PropertyState_DEFAULT_VALUE,
238                                              beans::PropertyAttribute::MAYBEVOID
239                                              | beans::PropertyAttribute::BOUND
240                                              | beans::PropertyAttribute::READONLY ) );
241 
242 
243     // Removable
244     m_aDefaultProperties.insert( MyProperty( true,
245                                              IsRemoveable,
246                                              -1 ,
247                                              getCppuType( static_cast< sal_Bool* >( 0 ) ),
248                                              uno::Any(),
249                                              beans::PropertyState_DEFAULT_VALUE,
250                                              beans::PropertyAttribute::MAYBEVOID
251                                              | beans::PropertyAttribute::BOUND
252                                              | beans::PropertyAttribute::READONLY ) );
253 
254     // Remote
255     m_aDefaultProperties.insert( MyProperty( true,
256                                              IsRemote,
257                                              -1 ,
258                                              getCppuType( static_cast< sal_Bool* >( 0 ) ),
259                                              uno::Any(),
260                                              beans::PropertyState_DEFAULT_VALUE,
261                                              beans::PropertyAttribute::MAYBEVOID
262                                              | beans::PropertyAttribute::BOUND
263                                              | beans::PropertyAttribute::READONLY ) );
264 
265     // CompactDisc
266     m_aDefaultProperties.insert( MyProperty( true,
267                                              IsCompactDisc,
268                                              -1 ,
269                                              getCppuType( static_cast< sal_Bool* >( 0 ) ),
270                                              uno::Any(),
271                                              beans::PropertyState_DEFAULT_VALUE,
272                                              beans::PropertyAttribute::MAYBEVOID
273                                              | beans::PropertyAttribute::BOUND
274                                              | beans::PropertyAttribute::READONLY ) );
275 
276     // Floppy
277     m_aDefaultProperties.insert( MyProperty( true,
278                                              IsFloppy,
279                                              -1 ,
280                                              getCppuType( static_cast< sal_Bool* >( 0 ) ),
281                                              uno::Any(),
282                                              beans::PropertyState_DEFAULT_VALUE,
283                                              beans::PropertyAttribute::MAYBEVOID
284                                              | beans::PropertyAttribute::BOUND
285                                              | beans::PropertyAttribute::READONLY ) );
286 
287     // Hidden
288     m_aDefaultProperties.insert(
289         MyProperty(
290             true,
291             IsHidden,
292             -1 ,
293             getCppuType( static_cast< sal_Bool* >( 0 ) ),
294             uno::Any(),
295             beans::PropertyState_DEFAULT_VALUE,
296             beans::PropertyAttribute::MAYBEVOID
297             | beans::PropertyAttribute::BOUND
298 #if defined( WNT ) || defined( OS2 )
299         ));
300 #else
301     | beans::PropertyAttribute::READONLY)); // under unix/linux only readable
302 #endif
303 
304 
305     // ContentType
306     uno::Any aAny;
307     aAny <<= rtl::OUString();
308     m_aDefaultProperties.insert( MyProperty( false,
309                                              ContentType,
310                                              -1 ,
311                                              getCppuType( static_cast< rtl::OUString* >( 0 ) ),
312                                              aAny,
313                                              beans::PropertyState_DEFAULT_VALUE,
314                                              beans::PropertyAttribute::MAYBEVOID
315                                              | beans::PropertyAttribute::BOUND
316                                              | beans::PropertyAttribute::READONLY ) );
317 
318 
319     // DateModified
320     m_aDefaultProperties.insert( MyProperty( true,
321                                              DateModified,
322                                              -1 ,
323                                              getCppuType( static_cast< util::DateTime* >( 0 ) ),
324                                              uno::Any(),
325                                              beans::PropertyState_DEFAULT_VALUE,
326                                              beans::PropertyAttribute::MAYBEVOID
327                                              | beans::PropertyAttribute::BOUND ) );
328 
329     // Size
330     m_aDefaultProperties.insert( MyProperty( true,
331                                              Size,
332                                              -1,
333                                              getCppuType( static_cast< sal_Int64* >( 0 ) ),
334                                              uno::Any(),
335                                              beans::PropertyState_DEFAULT_VALUE,
336                                              beans::PropertyAttribute::MAYBEVOID
337                                              | beans::PropertyAttribute::BOUND ) );
338 
339     // IsReadOnly
340     m_aDefaultProperties.insert( MyProperty( true,
341                                              IsReadOnly,
342                                              -1 ,
343                                              getCppuType( static_cast< sal_Bool* >( 0 ) ),
344                                              uno::Any(),
345                                              beans::PropertyState_DEFAULT_VALUE,
346                                              beans::PropertyAttribute::MAYBEVOID
347                                              | beans::PropertyAttribute::BOUND ) );
348 
349 
350     // CreatableContentsInfo
351     m_aDefaultProperties.insert( MyProperty( true,
352                                              CreatableContentsInfo,
353                                              -1 ,
354                                              getCppuType( static_cast< const uno::Sequence< ucb::ContentInfo > * >( 0 ) ),
355                                              uno::Any(),
356                                              beans::PropertyState_DEFAULT_VALUE,
357                                              beans::PropertyAttribute::MAYBEVOID
358                                              | beans::PropertyAttribute::BOUND
359                                              | beans::PropertyAttribute::READONLY ) );
360 
361     // Commands
362     m_sCommandInfo[0].Name = rtl::OUString::createFromAscii( "getCommandInfo" );
363     m_sCommandInfo[0].Handle = -1;
364     m_sCommandInfo[0].ArgType = getCppuVoidType();
365 
366     m_sCommandInfo[1].Name = rtl::OUString::createFromAscii( "getPropertySetInfo" );
367     m_sCommandInfo[1].Handle = -1;
368     m_sCommandInfo[1].ArgType = getCppuVoidType();
369 
370     m_sCommandInfo[2].Name = rtl::OUString::createFromAscii( "getPropertyValues" );
371     m_sCommandInfo[2].Handle = -1;
372     m_sCommandInfo[2].ArgType = getCppuType( static_cast< uno::Sequence< beans::Property >* >( 0 ) );
373 
374     m_sCommandInfo[3].Name = rtl::OUString::createFromAscii( "setPropertyValues" );
375     m_sCommandInfo[3].Handle = -1;
376     m_sCommandInfo[3].ArgType = getCppuType( static_cast< uno::Sequence< beans::PropertyValue >* >( 0 ) );
377 
378     m_sCommandInfo[4].Name = rtl::OUString::createFromAscii( "open" );
379     m_sCommandInfo[4].Handle = -1;
380     m_sCommandInfo[4].ArgType = getCppuType( static_cast< OpenCommandArgument* >( 0 ) );
381 
382     m_sCommandInfo[5].Name = rtl::OUString::createFromAscii( "transfer" );
383     m_sCommandInfo[5].Handle = -1;
384     m_sCommandInfo[5].ArgType = getCppuType( static_cast< TransferInfo* >( 0 ) );
385 
386     m_sCommandInfo[6].Name = rtl::OUString::createFromAscii( "delete" );
387     m_sCommandInfo[6].Handle = -1;
388     m_sCommandInfo[6].ArgType = getCppuType( static_cast< sal_Bool* >( 0 ) );
389 
390     m_sCommandInfo[7].Name = rtl::OUString::createFromAscii( "insert" );
391     m_sCommandInfo[7].Handle = -1;
392     m_sCommandInfo[7].ArgType = getCppuType( static_cast< InsertCommandArgument* > ( 0 ) );
393 
394     m_sCommandInfo[7].Name = rtl::OUString::createFromAscii( "createNewContent" );
395     m_sCommandInfo[7].Handle = -1;
396     m_sCommandInfo[7].ArgType = getCppuType( static_cast< ucb::ContentInfo * > ( 0 ) );
397 
398     if(m_bWithConfig)
399     {
400         rtl::OUString Store = rtl::OUString::createFromAscii( "com.sun.star.ucb.Store" );
401         uno::Reference< XPropertySetRegistryFactory > xRegFac(
402             m_xMultiServiceFactory->createInstance( Store ),
403             uno::UNO_QUERY );
404         if ( xRegFac.is() )
405         {
406             // Open/create a registry
407             m_xFileRegistry = xRegFac->createPropertySetRegistry( rtl::OUString() );
408         }
409     }
410 }
411 
412 
~shell()413 shell::~shell()
414 {
415 }
416 
417 
418 /*********************************************************************************/
419 /*                                                                               */
420 /*                     de/registerNotifier-Implementation                        */
421 /*                                                                               */
422 /*********************************************************************************/
423 
424 //
425 //  This two methods register and deregister a change listener for the content belonging
426 //  to URL aUnqPath
427 //
428 
429 void SAL_CALL
registerNotifier(const rtl::OUString & aUnqPath,Notifier * pNotifier)430 shell::registerNotifier( const rtl::OUString& aUnqPath, Notifier* pNotifier )
431 {
432     osl::MutexGuard aGuard( m_aMutex );
433 
434     ContentMap::iterator it =
435         m_aContent.insert( ContentMap::value_type( aUnqPath,UnqPathData() ) ).first;
436 
437     if( ! it->second.notifier )
438         it->second.notifier = new NotifierList();
439 
440     std::list< Notifier* >& nlist = *( it->second.notifier );
441 
442     std::list<Notifier*>::iterator it1 = nlist.begin();
443     while( it1 != nlist.end() )               // Every "Notifier" only once
444     {
445         if( *it1 == pNotifier ) return;
446         ++it1;
447     }
448     nlist.push_back( pNotifier );
449 }
450 
451 
452 
453 void SAL_CALL
deregisterNotifier(const rtl::OUString & aUnqPath,Notifier * pNotifier)454 shell::deregisterNotifier( const rtl::OUString& aUnqPath,Notifier* pNotifier )
455 {
456     osl::MutexGuard aGuard( m_aMutex );
457 
458     ContentMap::iterator it = m_aContent.find( aUnqPath );
459     if( it == m_aContent.end() )
460         return;
461 
462     it->second.notifier->remove( pNotifier );
463 
464     if( ! it->second.notifier->size() )
465         m_aContent.erase( it );
466 }
467 
468 
469 
470 /*********************************************************************************/
471 /*                                                                               */
472 /*                     de/associate-Implementation                               */
473 /*                                                                               */
474 /*********************************************************************************/
475 //
476 //  Used to associate and deassociate a new property with
477 //  the content belonging to URL UnqPath.
478 //  The default value and the attributes are input
479 //
480 
481 void SAL_CALL
associate(const rtl::OUString & aUnqPath,const rtl::OUString & PropertyName,const uno::Any & DefaultValue,const sal_Int16 Attributes)482 shell::associate( const rtl::OUString& aUnqPath,
483                   const rtl::OUString& PropertyName,
484                   const uno::Any& DefaultValue,
485                   const sal_Int16 Attributes )
486 {
487     MyProperty newProperty( false,
488                             PropertyName,
489                             -1,
490                             DefaultValue.getValueType(),
491                             DefaultValue,
492                             beans::PropertyState_DEFAULT_VALUE,
493                             Attributes );
494 
495     shell::PropertySet::iterator it1 = m_aDefaultProperties.find( newProperty );
496     if( it1 != m_aDefaultProperties.end() )
497         throw beans::PropertyExistException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
498 
499     {
500         osl::MutexGuard aGuard( m_aMutex );
501 
502         ContentMap::iterator it = m_aContent.insert( ContentMap::value_type( aUnqPath,UnqPathData() ) ).first;
503 
504         // Load the XPersistentPropertySetInfo and create it, if it does not exist
505         load( it,true );
506 
507         PropertySet& properties = *(it->second.properties);
508         it1 = properties.find( newProperty );
509         if( it1 != properties.end() )
510             throw beans::PropertyExistException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
511 
512         // Property does not exist
513         properties.insert( newProperty );
514         it->second.xC->addProperty( PropertyName,Attributes,DefaultValue );
515     }
516     notifyPropertyAdded( getPropertySetListeners( aUnqPath ), PropertyName );
517 }
518 
519 
520 
521 
522 void SAL_CALL
deassociate(const rtl::OUString & aUnqPath,const rtl::OUString & PropertyName)523 shell::deassociate( const rtl::OUString& aUnqPath,
524             const rtl::OUString& PropertyName )
525 {
526     MyProperty oldProperty( PropertyName );
527 
528     shell::PropertySet::iterator it1 = m_aDefaultProperties.find( oldProperty );
529     if( it1 != m_aDefaultProperties.end() )
530         throw beans::NotRemoveableException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
531 
532     osl::MutexGuard aGuard( m_aMutex );
533 
534     ContentMap::iterator it = m_aContent.insert( ContentMap::value_type( aUnqPath,UnqPathData() ) ).first;
535 
536     load( it,false );
537 
538     PropertySet& properties = *(it->second.properties);
539 
540     it1 = properties.find( oldProperty );
541     if( it1 == properties.end() )
542         throw beans::UnknownPropertyException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
543 
544     properties.erase( it1 );
545 
546     if( it->second.xC.is() )
547         it->second.xC->removeProperty( PropertyName );
548 
549     if( properties.size() == 9 )
550     {
551         MyProperty ContentTProperty( ContentType );
552 
553         if( properties.find( ContentTProperty )->getState() == beans::PropertyState_DEFAULT_VALUE )
554         {
555             it->second.xS = 0;
556             it->second.xC = 0;
557             it->second.xA = 0;
558             if(m_xFileRegistry.is())
559                 m_xFileRegistry->removePropertySet( aUnqPath );
560         }
561     }
562     notifyPropertyRemoved( getPropertySetListeners( aUnqPath ), PropertyName );
563 }
564 
565 
566 
567 
568 /*********************************************************************************/
569 /*                                                                               */
570 /*                     page-Implementation                                       */
571 /*                                                                               */
572 /*********************************************************************************/
573 //
574 //  Given an xOutputStream, this method writes the content of the file belonging to
575 //  URL aUnqPath into the XOutputStream
576 //
577 
578 
page(sal_Int32 CommandId,const rtl::OUString & aUnqPath,const uno::Reference<io::XOutputStream> & xOutputStream)579 void SAL_CALL shell::page( sal_Int32 CommandId,
580                            const rtl::OUString& aUnqPath,
581                            const uno::Reference< io::XOutputStream >& xOutputStream )
582     throw()
583 {
584     uno::Reference< XContentProvider > xProvider( m_pProvider );
585     osl::File aFile( aUnqPath );
586     osl::FileBase::RC err = aFile.open( OpenFlag_Read );
587 
588     if( err != osl::FileBase::E_None )
589     {
590         aFile.close();
591         installError( CommandId,
592                       TASKHANDLING_OPEN_FILE_FOR_PAGING,
593                       err );
594         return;
595     }
596 
597     const sal_uInt64 bfz = 4*1024;
598     sal_Int8 BFF[bfz];
599     sal_uInt64 nrc;  // Retrieved number of Bytes;
600 
601     do
602     {
603         err = aFile.read( (void*) BFF,bfz,nrc );
604         if(  err == osl::FileBase::E_None )
605         {
606             uno::Sequence< sal_Int8 > seq( BFF, (sal_uInt32)nrc );
607             try
608             {
609                 xOutputStream->writeBytes( seq );
610             }
611             catch( io::NotConnectedException )
612             {
613                 installError( CommandId,
614                               TASKHANDLING_NOTCONNECTED_FOR_PAGING );
615                 break;
616             }
617             catch( io::BufferSizeExceededException )
618             {
619                 installError( CommandId,
620                               TASKHANDLING_BUFFERSIZEEXCEEDED_FOR_PAGING );
621                 break;
622             }
623             catch( io::IOException )
624             {
625                 installError( CommandId,
626                               TASKHANDLING_IOEXCEPTION_FOR_PAGING );
627                 break;
628             }
629         }
630         else
631         {
632             installError( CommandId,
633                           TASKHANDLING_READING_FILE_FOR_PAGING,
634                           err );
635             break;
636         }
637     } while( nrc == bfz );
638 
639 
640     aFile.close();
641 
642 
643     try
644     {
645         xOutputStream->closeOutput();
646     }
647     catch( io::NotConnectedException )
648     {
649     }
650     catch( io::BufferSizeExceededException )
651     {
652     }
653     catch( io::IOException )
654     {
655     }
656 }
657 
658 
659 /*********************************************************************************/
660 /*                                                                               */
661 /*                     open-Implementation                                       */
662 /*                                                                               */
663 /*********************************************************************************/
664 //
665 //  Given a file URL aUnqPath, this methods returns a XInputStream which reads from the open file.
666 //
667 
668 
669 uno::Reference< io::XInputStream > SAL_CALL
open(sal_Int32 CommandId,const rtl::OUString & aUnqPath,sal_Bool bLock)670 shell::open( sal_Int32 CommandId,
671              const rtl::OUString& aUnqPath,
672              sal_Bool bLock )
673     throw()
674 {
675     XInputStream_impl* xInputStream = new XInputStream_impl( this, aUnqPath, bLock ); // from filinpstr.hxx
676 
677     sal_Int32 ErrorCode = xInputStream->CtorSuccess();
678 
679     if( ErrorCode != TASKHANDLER_NO_ERROR )
680     {
681         installError( CommandId,
682                       ErrorCode,
683                       xInputStream->getMinorError() );
684 
685         delete xInputStream;
686         xInputStream = 0;
687     }
688 
689     return uno::Reference< io::XInputStream >( xInputStream );
690 }
691 
692 
693 
694 
695 /*********************************************************************************/
696 /*                                                                               */
697 /*                     open for read/write access-Implementation                 */
698 /*                                                                               */
699 /*********************************************************************************/
700 //
701 //  Given a file URL aUnqPath, this methods returns a XStream which can be used
702 //  to read and write from/to the file.
703 //
704 
705 
706 uno::Reference< io::XStream > SAL_CALL
open_rw(sal_Int32 CommandId,const rtl::OUString & aUnqPath,sal_Bool bLock)707 shell::open_rw( sal_Int32 CommandId,
708                 const rtl::OUString& aUnqPath,
709                 sal_Bool bLock )
710     throw()
711 {
712     XStream_impl* xStream = new XStream_impl( this, aUnqPath, bLock );  // from filstr.hxx
713 
714     sal_Int32 ErrorCode = xStream->CtorSuccess();
715 
716     if( ErrorCode != TASKHANDLER_NO_ERROR )
717     {
718         installError( CommandId,
719                       ErrorCode,
720                       xStream->getMinorError() );
721 
722         delete xStream;
723         xStream = 0;
724     }
725     return uno::Reference< io::XStream >( xStream );
726 }
727 
728 
729 
730 /*********************************************************************************/
731 /*                                                                               */
732 /*                       ls-Implementation                                       */
733 /*                                                                               */
734 /*********************************************************************************/
735 //
736 //  This method returns the result set containing the children of the directory belonging
737 //  to file URL aUnqPath
738 //
739 
740 
741 uno::Reference< XDynamicResultSet > SAL_CALL
ls(sal_Int32 CommandId,const rtl::OUString & aUnqPath,const sal_Int32 OpenMode,const uno::Sequence<beans::Property> & seq,const uno::Sequence<NumberedSortingInfo> & seqSort)742 shell::ls( sal_Int32 CommandId,
743            const rtl::OUString& aUnqPath,
744            const sal_Int32 OpenMode,
745            const uno::Sequence< beans::Property >& seq,
746            const uno::Sequence< NumberedSortingInfo >& seqSort )
747     throw()
748 {
749     XResultSet_impl* p = new XResultSet_impl( this,aUnqPath,OpenMode,seq,seqSort );
750 
751     sal_Int32 ErrorCode = p->CtorSuccess();
752 
753     if( ErrorCode != TASKHANDLER_NO_ERROR )
754     {
755         installError( CommandId,
756                       ErrorCode,
757                       p->getMinorError() );
758 
759         delete p;
760         p = 0;
761     }
762 
763     return uno::Reference< XDynamicResultSet > ( p );
764 }
765 
766 
767 
768 
769 /*********************************************************************************/
770 /*                                                                               */
771 /*                          info_c implementation                                */
772 /*                                                                               */
773 /*********************************************************************************/
774 // Info for commands
775 
776 uno::Reference< XCommandInfo > SAL_CALL
info_c()777 shell::info_c()
778     throw()
779 {
780     XCommandInfo_impl* p = new XCommandInfo_impl( this );
781     return uno::Reference< XCommandInfo >( p );
782 }
783 
784 
785 
786 
787 /*********************************************************************************/
788 /*                                                                               */
789 /*                     info_p-Implementation                                     */
790 /*                                                                               */
791 /*********************************************************************************/
792 // Info for the properties
793 
794 uno::Reference< beans::XPropertySetInfo > SAL_CALL
info_p(const rtl::OUString & aUnqPath)795 shell::info_p( const rtl::OUString& aUnqPath )
796     throw()
797 {
798     osl::MutexGuard aGuard( m_aMutex );
799     XPropertySetInfo_impl* p = new XPropertySetInfo_impl( this,aUnqPath );
800     return uno::Reference< beans::XPropertySetInfo >( p );
801 }
802 
803 
804 
805 
806 /*********************************************************************************/
807 /*                                                                               */
808 /*                     setv-Implementation                                       */
809 /*                                                                               */
810 /*********************************************************************************/
811 //
812 //  Sets the values of the properties belonging to fileURL aUnqPath
813 //
814 
815 
816 uno::Sequence< uno::Any > SAL_CALL
setv(const rtl::OUString & aUnqPath,const uno::Sequence<beans::PropertyValue> & values)817 shell::setv( const rtl::OUString& aUnqPath,
818              const uno::Sequence< beans::PropertyValue >& values )
819     throw()
820 {
821     osl::MutexGuard aGuard( m_aMutex );
822 
823     sal_Int32 propChanged = 0;
824     uno::Sequence< uno::Any > ret( values.getLength() );
825     uno::Sequence< beans::PropertyChangeEvent > seqChanged( values.getLength() );
826 
827     shell::ContentMap::iterator it = m_aContent.find( aUnqPath );
828     PropertySet& properties = *( it->second.properties );
829     shell::PropertySet::iterator it1;
830     uno::Any aAny;
831 
832     for( sal_Int32 i = 0; i < values.getLength(); ++i )
833     {
834         MyProperty toset( values[i].Name );
835         it1 = properties.find( toset );
836         if( it1 == properties.end() )
837         {
838             ret[i] <<= beans::UnknownPropertyException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
839             continue;
840         }
841 
842         aAny = it1->getValue();
843         if( aAny == values[i].Value )
844             continue;  // nothing needs to be changed
845 
846         if( it1->getAttributes() & beans::PropertyAttribute::READONLY )
847         {
848             ret[i] <<= lang::IllegalAccessException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
849             continue;
850         }
851 
852         seqChanged[ propChanged   ].PropertyName = values[i].Name;
853         seqChanged[ propChanged   ].PropertyHandle   = -1;
854         seqChanged[ propChanged   ].Further   = false;
855         seqChanged[ propChanged   ].OldValue <<= aAny;
856         seqChanged[ propChanged++ ].NewValue = values[i].Value;
857 
858         it1->setValue( values[i].Value );  // Put the new value into the local cash
859 
860         if( ! it1->IsNative() )
861         {
862             // Also put logical properties into storage
863             if( !it->second.xS.is() )
864                 load( it,true );
865 
866             if( ( values[i].Name == ContentType ) &&
867                 it1->getState() == beans::PropertyState_DEFAULT_VALUE )
868             {   // Special logic for ContentType
869                 //  09.07.01: Not reached anymore, because ContentType is readonly
870                 it1->setState( beans::PropertyState_DIRECT_VALUE );
871                 it->second.xC->addProperty( values[i].Name,
872                                             beans::PropertyAttribute::MAYBEVOID,
873                                             values[i].Value );
874             }
875 
876             try
877             {
878                 it->second.xS->setPropertyValue( values[i].Name,values[i].Value );
879             }
880             catch( const uno::Exception& e )
881             {
882                 --propChanged; // unsuccessful setting
883                 ret[i] <<= e;
884             }
885         }
886         else
887         {
888             // native properties
889             // Setting of physical file properties
890             if( values[i].Name == Size )
891             {
892                 sal_Int64 newSize = 0;
893                 if( values[i].Value >>= newSize )
894                 {   // valid value for the size
895                     osl::File aFile(aUnqPath);
896                     bool err =
897                         aFile.open(OpenFlag_Write) != osl::FileBase::E_None ||
898                         aFile.setSize(sal_uInt64(newSize)) != osl::FileBase::E_None ||
899                         aFile.close() != osl::FileBase::E_None;
900 
901                     if( err )
902                     {
903                         --propChanged; // unsuccessful setting
904                         uno::Sequence< uno::Any > names( 1 );
905                         ret[0] <<= beans::PropertyValue(
906                             rtl::OUString::createFromAscii("Uri"), -1,
907                             uno::makeAny(aUnqPath),
908                             beans::PropertyState_DIRECT_VALUE);
909                         IOErrorCode ioError(IOErrorCode_GENERAL);
910                         ret[i] <<= InteractiveAugmentedIOException(
911                             rtl::OUString(),
912                             0,
913                             task::InteractionClassification_ERROR,
914                             ioError,
915                             names );
916                     }
917                 }
918                 else
919                     ret[i] <<= beans::IllegalTypeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
920             }
921             else if(values[i].Name == IsReadOnly ||
922                     values[i].Name == IsHidden)
923             {
924                 sal_Bool value = sal_False;
925                 if( values[i].Value >>= value )
926                 {
927                     osl::DirectoryItem aDirItem;
928                     osl::FileBase::RC err =
929                         osl::DirectoryItem::get(aUnqPath,aDirItem);
930                     sal_uInt64 nAttributes(0);
931                     if(err == osl::FileBase::E_None)
932                     {
933                         osl::FileStatus aFileStatus(FileStatusMask_Attributes);
934                         err = aDirItem.getFileStatus(aFileStatus);
935                         if(err == osl::FileBase::E_None &&
936                            aFileStatus.isValid(FileStatusMask_Attributes))
937                             nAttributes = aFileStatus.getAttributes();
938                     }
939                     // now we have the attributes provided all went well.
940                     if(err == osl::FileBase::E_None) {
941                         if(values[i].Name == IsReadOnly)
942                         {
943                             nAttributes &= ~(Attribute_OwnWrite |
944                                              Attribute_GrpWrite |
945                                              Attribute_OthWrite |
946                                              Attribute_ReadOnly);
947                             if(value)
948                                 nAttributes |= Attribute_ReadOnly;
949                             else
950                                 nAttributes |= (
951                                     Attribute_OwnWrite |
952                                     Attribute_GrpWrite |
953                                     Attribute_OthWrite);
954                         }
955                         else if(values[i].Name == IsHidden)
956                         {
957                             nAttributes &= ~(Attribute_Hidden);
958                             if(value)
959                                 nAttributes |= Attribute_Hidden;
960                         }
961                         err = osl::File::setAttributes(
962                             aUnqPath,nAttributes);
963                     }
964 
965                     if( err != osl::FileBase::E_None )
966                     {
967                         --propChanged; // unsuccessful setting
968                         uno::Sequence< uno::Any > names( 1 );
969                         names[0] <<= beans::PropertyValue(
970                             rtl::OUString::createFromAscii("Uri"), -1,
971                             uno::makeAny(aUnqPath),
972                             beans::PropertyState_DIRECT_VALUE);
973                         IOErrorCode ioError;
974                         switch( err )
975                         {
976                         case osl::FileBase::E_NOMEM:
977                             // not enough memory for allocating structures <br>
978                             ioError = IOErrorCode_OUT_OF_MEMORY;
979                             break;
980                         case osl::FileBase::E_INVAL:
981                             // the format of the parameters was not valid<p>
982                             ioError = IOErrorCode_INVALID_PARAMETER;
983                             break;
984                         case osl::FileBase::E_NAMETOOLONG:
985                             // File name too long<br>
986                             ioError = IOErrorCode_NAME_TOO_LONG;
987                             break;
988                         case osl::FileBase::E_NOENT:
989                             // No such file or directory<br>
990                         case osl::FileBase::E_NOLINK:
991                             // Link has been severed<br>
992                             ioError = IOErrorCode_NOT_EXISTING;
993                             break;
994                         case osl::FileBase::E_ROFS:
995                             // #i4735# handle ROFS transparently
996                             // as ACCESS_DENIED
997                         case  osl::FileBase::E_PERM:
998                         case osl::FileBase::E_ACCES:
999                             // permission denied<br>
1000                             ioError = IOErrorCode_ACCESS_DENIED;
1001                             break;
1002                         case osl::FileBase::E_LOOP:
1003                             // Too many symbolic links encountered<br>
1004                         case osl::FileBase::E_FAULT:
1005                             // Bad address<br>
1006                         case osl::FileBase::E_IO:
1007                             // I/O error<br>
1008                         case osl::FileBase::E_NOSYS:
1009                             // Function not implemented<br>
1010                         case osl::FileBase::E_MULTIHOP:
1011                             // Multihop attempted<br>
1012                         case osl::FileBase::E_INTR:
1013                             // function call was interrupted<p>
1014                         default:
1015                             ioError = IOErrorCode_GENERAL;
1016                             break;
1017                         }
1018                         ret[i] <<= InteractiveAugmentedIOException(
1019                             rtl::OUString(),
1020                             0,
1021                             task::InteractionClassification_ERROR,
1022                             ioError,
1023                             names );
1024                     }
1025                 }
1026                 else
1027                     ret[i] <<= beans::IllegalTypeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
1028             }
1029         }
1030     }   // end for
1031 
1032     if( propChanged )
1033     {
1034         seqChanged.realloc( propChanged );
1035         notifyPropertyChanges( getPropertyChangeNotifier( aUnqPath ),seqChanged );
1036     }
1037 
1038     return ret;
1039 }
1040 
1041 /*********************************************************************************/
1042 /*                                                                               */
1043 /*                     getv-Implementation                                       */
1044 /*                                                                               */
1045 /*********************************************************************************/
1046 //
1047 //  Reads the values of the properties belonging to fileURL aUnqPath;
1048 //  Returns an XRow object containing the values in the requested order.
1049 //
1050 
1051 
1052 uno::Reference< sdbc::XRow > SAL_CALL
getv(sal_Int32 CommandId,const rtl::OUString & aUnqPath,const uno::Sequence<beans::Property> & properties)1053 shell::getv( sal_Int32 CommandId,
1054              const rtl::OUString& aUnqPath,
1055              const uno::Sequence< beans::Property >& properties )
1056     throw()
1057 {
1058     uno::Sequence< uno::Any > seq( properties.getLength() );
1059 
1060     sal_Int32 n_Mask;
1061     getMaskFromProperties( n_Mask,properties );
1062     osl::FileStatus aFileStatus( n_Mask );
1063 
1064     osl::DirectoryItem aDirItem;
1065     osl::FileBase::RC nError1 = osl::DirectoryItem::get( aUnqPath,aDirItem );
1066     if( nError1 != osl::FileBase::E_None )
1067         installError(CommandId,
1068                      TASKHANDLING_OPEN_FILE_FOR_PAGING, // BEAWARE, REUSED
1069                      nError1);
1070 
1071     osl::FileBase::RC nError2 = aDirItem.getFileStatus( aFileStatus );
1072     if( nError1 == osl::FileBase::E_None &&
1073         nError2 != osl::FileBase::E_None )
1074         installError(CommandId,
1075                      TASKHANDLING_OPEN_FILE_FOR_PAGING, // BEAWARE, REUSED
1076                      nError2);
1077 
1078     {
1079         osl::MutexGuard aGuard( m_aMutex );
1080 
1081         shell::ContentMap::iterator it = m_aContent.find( aUnqPath );
1082         commit( it,aFileStatus );
1083 
1084         shell::PropertySet::iterator it1;
1085         PropertySet& propset = *(it->second.properties);
1086 
1087         for( sal_Int32 i = 0; i < seq.getLength(); ++i )
1088         {
1089             MyProperty readProp( properties[i].Name );
1090             it1 = propset.find( readProp );
1091             if( it1 == propset.end() )
1092                 seq[i] = uno::Any();
1093             else
1094                 seq[i] = it1->getValue();
1095         }
1096     }
1097 
1098     XRow_impl* p = new XRow_impl( this,seq );
1099     return uno::Reference< sdbc::XRow >( p );
1100 }
1101 
1102 
1103 /********************************************************************************/
1104 /*                                                                              */
1105 /*                         transfer-commandos                                   */
1106 /*                                                                              */
1107 /********************************************************************************/
1108 
1109 
1110 /********************************************************************************/
1111 /*                                                                              */
1112 /*                         move-implementation                                  */
1113 /*                                                                              */
1114 /********************************************************************************/
1115 //
1116 //  Moves the content belonging to fileURL srcUnqPath to fileURL dstUnqPath.
1117 //
1118 
1119 void SAL_CALL
move(sal_Int32 CommandId,const rtl::OUString srcUnqPath,const rtl::OUString dstUnqPathIn,const sal_Int32 NameClash)1120 shell::move( sal_Int32 CommandId,
1121              const rtl::OUString srcUnqPath,
1122              const rtl::OUString dstUnqPathIn,
1123              const sal_Int32 NameClash )
1124     throw()
1125 {
1126     // --> #i88446# Method notifyContentExchanged( getContentExchangedEventListeners( srcUnqPath,dstUnqPath,!isDocument ) ); crashes if
1127     // srcUnqPath and dstUnqPathIn are equal
1128     if( srcUnqPath == dstUnqPathIn )
1129         return;
1130     // <--
1131     //
1132     osl::FileBase::RC nError;
1133     rtl::OUString dstUnqPath( dstUnqPathIn );
1134 
1135     switch( NameClash )
1136     {
1137     case NameClash::KEEP:
1138         {
1139             nError = osl_File_move( srcUnqPath,dstUnqPath,true );
1140             if( nError != osl::FileBase::E_None && nError != osl::FileBase::E_EXIST )
1141             {
1142                 installError( CommandId,
1143                               TASKHANDLING_KEEPERROR_FOR_MOVE,
1144                               nError );
1145                 return;
1146             }
1147             break;
1148         }
1149     case NameClash::OVERWRITE:
1150         {
1151             // stat to determine whether we have a symlink
1152             rtl::OUString targetPath(dstUnqPath);
1153 
1154             osl::FileStatus aStatus(FileStatusMask_Type|FileStatusMask_LinkTargetURL);
1155             osl::DirectoryItem aItem;
1156             osl::DirectoryItem::get(dstUnqPath,aItem);
1157             aItem.getFileStatus(aStatus);
1158 
1159             if( aStatus.isValid(FileStatusMask_Type)          &&
1160                 aStatus.isValid(FileStatusMask_LinkTargetURL) &&
1161                 aStatus.getFileType() == osl::FileStatus::Link )
1162                 targetPath = aStatus.getLinkTargetURL();
1163 
1164             // Will do nothing if file does not exist.
1165             osl::File::remove( targetPath );
1166 
1167             nError = osl_File_move( srcUnqPath,targetPath );
1168             if( nError != osl::FileBase::E_None )
1169             {
1170                 installError( CommandId,
1171                               TASKHANDLING_OVERWRITE_FOR_MOVE,
1172                               nError );
1173                 return;
1174             }
1175             break;
1176         }
1177     case NameClash::RENAME:
1178         {
1179             rtl::OUString newDstUnqPath;
1180             nError = osl_File_move( srcUnqPath,dstUnqPath,true );
1181             if( nError == osl::FileBase::E_EXIST )
1182             {
1183                 // "invent" a new valid title.
1184 
1185                 sal_Int32 nPos = -1;
1186                 sal_Int32 nLastDot = dstUnqPath.lastIndexOf( '.' );
1187                 sal_Int32 nLastSlash = dstUnqPath.lastIndexOf( '/' );
1188                 if( ( nLastSlash < nLastDot )                  // dot is part of last(!) path segment
1189                     && ( nLastSlash != ( nLastDot - 1 ) ) )    // file name does not start with a dot
1190                     nPos = nLastDot;
1191                 else
1192                     nPos = dstUnqPath.getLength();
1193 
1194                 sal_Int32 nTry = 0;
1195 
1196                 do
1197                 {
1198                     newDstUnqPath = dstUnqPath;
1199 
1200                     rtl::OUString aPostFix( rtl::OUString::createFromAscii( "_" ) );
1201                     aPostFix += rtl::OUString::valueOf( ++nTry );
1202 
1203                     newDstUnqPath = newDstUnqPath.replaceAt( nPos, 0, aPostFix );
1204 
1205                     nError = osl_File_move( srcUnqPath,newDstUnqPath,true );
1206                 }
1207                 while( ( nError == osl::FileBase::E_EXIST ) && ( nTry < 10000 ) );
1208             }
1209 
1210             if( nError == osl::FileBase::E_EXIST )
1211             {
1212                 installError( CommandId,
1213                               TASKHANDLING_RENAME_FOR_MOVE );
1214                 return;
1215             }
1216             else if( nError != osl::FileBase::E_None )
1217             {
1218                 installError( CommandId,
1219                               TASKHANDLING_RENAMEMOVE_FOR_MOVE,
1220                               nError );
1221                 return;
1222             }
1223             else
1224                 dstUnqPath = newDstUnqPath;
1225 
1226             break;
1227         }
1228     case NameClash::ERROR:
1229         {
1230             nError = osl_File_move( srcUnqPath,dstUnqPath,true );
1231             if( nError == osl::FileBase::E_EXIST )
1232             {
1233                 installError( CommandId,
1234                               TASKHANDLING_NAMECLASH_FOR_MOVE );
1235                 return;
1236             }
1237             else if( nError != osl::FileBase::E_None )
1238             {
1239                 installError( CommandId,
1240                               TASKHANDLING_NAMECLASHMOVE_FOR_MOVE,
1241                               nError );
1242                 return;
1243             }
1244             break;
1245         }
1246         case NameClash::ASK:
1247         default:
1248         {
1249             nError = osl_File_move( srcUnqPath,dstUnqPath,true );
1250             if( nError == osl::FileBase::E_EXIST )
1251             {
1252                 installError( CommandId,
1253                               TASKHANDLING_NAMECLASHSUPPORT_FOR_MOVE,
1254                               NameClash::ASK);
1255                 return;
1256             }
1257         }
1258         break;
1259     }
1260 
1261     // Determine, whether we have moved a file or a folder
1262     osl::DirectoryItem aItem;
1263     nError = osl::DirectoryItem::get( dstUnqPath,aItem );
1264     if( nError != osl::FileBase::E_None )
1265     {
1266         installError( CommandId,
1267                       TASKHANDLING_TRANSFER_BY_MOVE_SOURCE,
1268                       nError );
1269         return;
1270     }
1271     osl::FileStatus aStatus( FileStatusMask_Type );
1272     nError = aItem.getFileStatus( aStatus );
1273     if( nError != osl::FileBase::E_None || ! aStatus.isValid( FileStatusMask_Type ) )
1274     {
1275         installError( CommandId,
1276                       TASKHANDLING_TRANSFER_BY_MOVE_SOURCESTAT,
1277                       nError );
1278         return;
1279     }
1280     sal_Bool isDocument = ( aStatus.getFileType() == osl::FileStatus::Regular );
1281 
1282 
1283     copyPersistentSet( srcUnqPath,dstUnqPath,!isDocument );
1284 
1285     rtl::OUString aDstParent = getParentName( dstUnqPath );
1286     rtl::OUString aDstTitle  = getTitle( dstUnqPath );
1287 
1288     rtl::OUString aSrcParent = getParentName( srcUnqPath );
1289     rtl::OUString aSrcTitle  = getTitle( srcUnqPath );
1290 
1291     notifyInsert( getContentEventListeners( aDstParent ),dstUnqPath );
1292     if(  aDstParent != aSrcParent )
1293         notifyContentRemoved( getContentEventListeners( aSrcParent ),srcUnqPath );
1294 
1295     notifyContentExchanged( getContentExchangedEventListeners( srcUnqPath,dstUnqPath,!isDocument ) );
1296     erasePersistentSet( srcUnqPath,!isDocument );
1297 }
1298 
1299 
1300 
1301 /********************************************************************************/
1302 /*                                                                              */
1303 /*                         copy-implementation                                  */
1304 /*                                                                              */
1305 /********************************************************************************/
1306 //
1307 //  Copies the content belonging to fileURL srcUnqPath to fileURL dstUnqPath ( files and directories )
1308 //
1309 
1310 namespace {
1311 
getType(TaskManager & task,sal_Int32 id,rtl::OUString const & fileUrl,osl::DirectoryItem * item,osl::FileStatus::Type * type)1312 bool getType(
1313     TaskManager & task, sal_Int32 id, rtl::OUString const & fileUrl,
1314     osl::DirectoryItem * item, osl::FileStatus::Type * type)
1315 {
1316     OSL_ASSERT(item != 0 && type != 0);
1317     osl::FileBase::RC err = osl::DirectoryItem::get(fileUrl, *item);
1318     if (err != osl::FileBase::E_None) {
1319         task.installError(id, TASKHANDLING_TRANSFER_BY_COPY_SOURCE, err);
1320         return false;
1321     }
1322     osl::FileStatus stat(FileStatusMask_Type);
1323     err = item->getFileStatus(stat);
1324     if (err != osl::FileBase::E_None) {
1325         task.installError(id, TASKHANDLING_TRANSFER_BY_COPY_SOURCESTAT, err);
1326         return false;
1327     }
1328     *type = stat.getFileType();
1329     return true;
1330 }
1331 
1332 }
1333 
1334 void SAL_CALL
copy(sal_Int32 CommandId,const rtl::OUString srcUnqPath,const rtl::OUString dstUnqPathIn,sal_Int32 NameClash)1335 shell::copy(
1336     sal_Int32 CommandId,
1337     const rtl::OUString srcUnqPath,
1338     const rtl::OUString dstUnqPathIn,
1339     sal_Int32 NameClash )
1340     throw()
1341 {
1342     osl::FileBase::RC nError;
1343     rtl::OUString dstUnqPath( dstUnqPathIn );
1344 
1345     // Resolve symbolic links within the source path.  If srcUnqPath denotes a
1346     // symbolic link (targeting either a file or a folder), the contents of the
1347     // target is copied (recursively, in the case of a folder).  However, if
1348     // recursively copying the contents of a folder causes a symbolic link to be
1349     // copied, the symbolic link itself is copied.
1350     osl::DirectoryItem item;
1351     osl::FileStatus::Type type;
1352     if (!getType(*this, CommandId, srcUnqPath, &item, &type)) {
1353         return;
1354     }
1355     rtl::OUString rslvdSrcUnqPath;
1356     if (type == osl::FileStatus::Link) {
1357         osl::FileStatus stat(FileStatusMask_LinkTargetURL);
1358         nError = item.getFileStatus(stat);
1359         if (nError != osl::FileBase::E_None) {
1360             installError(
1361                 CommandId, TASKHANDLING_TRANSFER_BY_COPY_SOURCESTAT, nError);
1362             return;
1363         }
1364         rslvdSrcUnqPath = stat.getLinkTargetURL();
1365         if (!getType(*this, CommandId, srcUnqPath, &item, &type)) {
1366             return;
1367         }
1368     } else {
1369         rslvdSrcUnqPath = srcUnqPath;
1370     }
1371 
1372     sal_Bool isDocument
1373         = type != osl::FileStatus::Directory && type != osl::FileStatus::Volume;
1374     sal_Int32 IsWhat = isDocument ? -1 : 1;
1375 
1376     switch( NameClash )
1377     {
1378         case NameClash::KEEP:
1379         {
1380             nError = copy_recursive( rslvdSrcUnqPath,dstUnqPath,IsWhat,true );
1381             if( nError != osl::FileBase::E_None && nError != osl::FileBase::E_EXIST )
1382             {
1383                 installError( CommandId,
1384                               TASKHANDLING_KEEPERROR_FOR_COPY,
1385                               nError );
1386                 return;
1387             }
1388             break;
1389         }
1390         case NameClash::OVERWRITE:
1391         {
1392             // remove (..., MustExist = sal_False).
1393             remove( CommandId, dstUnqPath, IsWhat, sal_False );
1394 
1395             // copy.
1396             nError = copy_recursive( rslvdSrcUnqPath,dstUnqPath,IsWhat,false );
1397             if( nError != osl::FileBase::E_None )
1398             {
1399                 installError( CommandId,
1400                               TASKHANDLING_OVERWRITE_FOR_COPY,
1401                               nError );
1402                 return;
1403             }
1404             break;
1405         }
1406         case NameClash::RENAME:
1407         {
1408             rtl::OUString newDstUnqPath;
1409             nError = copy_recursive( rslvdSrcUnqPath,dstUnqPath,IsWhat,true );
1410 
1411             if( nError == osl::FileBase::E_EXIST )
1412             {
1413                 // "invent" a new valid title.
1414 
1415                 sal_Int32 nPos = -1;
1416                 sal_Int32 nLastDot = dstUnqPath.lastIndexOf( '.' );
1417                 sal_Int32 nLastSlash = dstUnqPath.lastIndexOf( '/' );
1418                 if ( ( nLastSlash < nLastDot ) // dot is part of last(!) path segment
1419                      && ( nLastSlash != ( nLastDot - 1 ) ) ) // file name does not start with a dot
1420                     nPos = nLastDot;
1421                 else
1422                     nPos = dstUnqPath.getLength();
1423 
1424                 sal_Int32 nTry = 0;
1425 
1426                 do
1427                 {
1428                     newDstUnqPath = dstUnqPath;
1429 
1430                     rtl::OUString aPostFix( rtl::OUString::createFromAscii( "_" ) );
1431                     aPostFix += rtl::OUString::valueOf( ++nTry );
1432 
1433                     newDstUnqPath = newDstUnqPath.replaceAt( nPos, 0, aPostFix );
1434 
1435                     nError = copy_recursive( rslvdSrcUnqPath,newDstUnqPath,IsWhat,true );
1436                 }
1437                 while( ( nError == osl::FileBase::E_EXIST ) && ( nTry < 10000 ) );
1438             }
1439 
1440             if( nError == osl::FileBase::E_EXIST )
1441             {
1442                 installError( CommandId,
1443                               TASKHANDLING_RENAME_FOR_COPY );
1444                 return;
1445             }
1446             else if( nError != osl::FileBase::E_None )
1447             {
1448                 installError( CommandId,
1449                               TASKHANDLING_RENAMEMOVE_FOR_COPY,
1450                               nError );
1451                 return;
1452             }
1453             else
1454                 dstUnqPath = newDstUnqPath;
1455 
1456             break;
1457         }
1458         case NameClash::ERROR:
1459         {
1460             nError = copy_recursive( rslvdSrcUnqPath,dstUnqPath,IsWhat,true );
1461 
1462             if( nError == osl::FileBase::E_EXIST )
1463             {
1464                 installError( CommandId,
1465                               TASKHANDLING_NAMECLASH_FOR_COPY );
1466                 return;
1467             }
1468             else if( nError != osl::FileBase::E_None )
1469             {
1470                 installError( CommandId,
1471                               TASKHANDLING_NAMECLASHMOVE_FOR_COPY,
1472                               nError );
1473                 return;
1474             }
1475             break;
1476         }
1477         case NameClash::ASK:
1478         default:
1479         {
1480             nError = copy_recursive( rslvdSrcUnqPath,dstUnqPath,IsWhat,true );
1481 
1482             if( nError == osl::FileBase::E_EXIST )
1483             {
1484                 installError( CommandId,
1485                               TASKHANDLING_NAMECLASHSUPPORT_FOR_COPY,
1486                               NameClash);
1487                 return;
1488             }
1489             break;
1490         }
1491     }
1492 
1493     copyPersistentSet( srcUnqPath,dstUnqPath, !isDocument );
1494     notifyInsert( getContentEventListeners( getParentName( dstUnqPath ) ),dstUnqPath );
1495 }
1496 
1497 
1498 
1499 /********************************************************************************/
1500 /*                                                                              */
1501 /*                         remove-implementation                                */
1502 /*                                                                              */
1503 /********************************************************************************/
1504 //
1505 //  Deletes the content belonging to fileURL aUnqPath( recursively in case of directory )
1506 //  Return: success of operation
1507 //
1508 
1509 
1510 sal_Bool SAL_CALL
remove(sal_Int32 CommandId,const rtl::OUString & aUnqPath,sal_Int32 IsWhat,sal_Bool MustExist)1511 shell::remove( sal_Int32 CommandId,
1512                const rtl::OUString& aUnqPath,
1513                sal_Int32 IsWhat,
1514                sal_Bool  MustExist )
1515     throw()
1516 {
1517     sal_Int32 nMask = FileStatusMask_Type | FileStatusMask_FileURL;
1518 
1519     osl::DirectoryItem aItem;
1520     osl::FileStatus aStatus( nMask );
1521     osl::FileBase::RC nError;
1522 
1523     if( IsWhat == 0 ) // Determine whether we are removing a directory or a file
1524     {
1525         nError = osl::DirectoryItem::get( aUnqPath, aItem );
1526         if( nError != osl::FileBase::E_None )
1527         {
1528             if (MustExist)
1529             {
1530                 installError( CommandId,
1531                               TASKHANDLING_NOSUCHFILEORDIR_FOR_REMOVE,
1532                               nError );
1533             }
1534             return (!MustExist);
1535         }
1536 
1537         nError = aItem.getFileStatus( aStatus );
1538         if( nError != osl::FileBase::E_None || ! aStatus.isValid( nMask ) )
1539         {
1540             installError( CommandId,
1541                           TASKHANDLING_VALIDFILESTATUS_FOR_REMOVE,
1542                           nError != osl::FileBase::E_None ? nError : TASKHANDLER_NO_ERROR );
1543             return sal_False;
1544         }
1545 
1546         if( aStatus.getFileType() == osl::FileStatus::Regular ||
1547             aStatus.getFileType() == osl::FileStatus::Link )
1548             IsWhat = -1;  // RemoveFile
1549         else if(  aStatus.getFileType() == osl::FileStatus::Directory ||
1550                   aStatus.getFileType() == osl::FileStatus::Volume )
1551             IsWhat = +1;  // RemoveDirectory
1552     }
1553 
1554 
1555     if( IsWhat == -1 )    // Removing a file
1556     {
1557         nError = osl::File::remove( aUnqPath );
1558         if( nError != osl::FileBase::E_None )
1559         {
1560             if (MustExist)
1561             {
1562                 installError( CommandId,
1563                               TASKHANDLING_DELETEFILE_FOR_REMOVE,
1564                               nError );
1565             }
1566             return (!MustExist);
1567         }
1568         else
1569         {
1570             notifyContentDeleted( getContentDeletedEventListeners(aUnqPath) );
1571             erasePersistentSet( aUnqPath ); // Removes from XPersistentPropertySet
1572         }
1573     }
1574     else if( IsWhat == +1 )    // Removing a directory
1575     {
1576         osl::Directory aDirectory( aUnqPath );
1577 
1578         nError = aDirectory.open();
1579         if( nError != osl::FileBase::E_None )
1580         {
1581             if (MustExist)
1582             {
1583                 installError( CommandId,
1584                               TASKHANDLING_OPENDIRECTORY_FOR_REMOVE,
1585                               nError );
1586             }
1587             return (!MustExist);
1588         }
1589 
1590         sal_Bool whileSuccess = sal_True;
1591         sal_Int32 recurse = 0;
1592         rtl::OUString name;
1593 
1594         nError = aDirectory.getNextItem( aItem );
1595         while( nError == osl::FileBase::E_None )
1596         {
1597             nError = aItem.getFileStatus( aStatus );
1598             if( nError != osl::FileBase::E_None || ! aStatus.isValid( nMask ) )
1599             {
1600                 installError( CommandId,
1601                               TASKHANDLING_VALIDFILESTATUSWHILE_FOR_REMOVE,
1602                               nError != osl::FileBase::E_None ? nError : TASKHANDLER_NO_ERROR );
1603                 whileSuccess = sal_False;
1604                 break;
1605             }
1606 
1607             if( aStatus.getFileType() == osl::FileStatus::Regular ||
1608                 aStatus.getFileType() == osl::FileStatus::Link )
1609                 recurse = -1;
1610             else if( aStatus.getFileType() == osl::FileStatus::Directory ||
1611                      aStatus.getFileType() == osl::FileStatus::Volume )
1612                 recurse = +1;
1613 
1614             name = aStatus.getFileURL();
1615             whileSuccess = remove(
1616                 CommandId, name, recurse, MustExist );
1617             if( !whileSuccess )
1618                 break;
1619 
1620             nError = aDirectory.getNextItem( aItem );
1621         }
1622 
1623         aDirectory.close();
1624 
1625         if( ! whileSuccess )
1626             return sal_False;     // error code is installed
1627 
1628         if( nError != osl::FileBase::E_NOENT )
1629         {
1630             installError( CommandId,
1631                           TASKHANDLING_DIRECTORYEXHAUSTED_FOR_REMOVE,
1632                           nError );
1633             return sal_False;
1634         }
1635 
1636         nError = osl::Directory::remove( aUnqPath );
1637         if( nError != osl::FileBase::E_None )
1638         {
1639             if (MustExist)
1640             {
1641                 installError( CommandId,
1642                               TASKHANDLING_DELETEDIRECTORY_FOR_REMOVE,
1643                               nError );
1644             }
1645             return (!MustExist);
1646         }
1647         else
1648         {
1649             notifyContentDeleted( getContentDeletedEventListeners(aUnqPath) );
1650             erasePersistentSet( aUnqPath );
1651         }
1652     }
1653     else   // Don't know what to remove
1654     {
1655         installError( CommandId,
1656                       TASKHANDLING_FILETYPE_FOR_REMOVE );
1657         return sal_False;
1658     }
1659 
1660     return sal_True;
1661 }
1662 
1663 
1664 /********************************************************************************/
1665 /*                                                                              */
1666 /*                         mkdir-implementation                                 */
1667 /*                                                                              */
1668 /********************************************************************************/
1669 //
1670 //  Creates new directory with given URL, recursively if necessary
1671 //  Return:: success of operation
1672 //
1673 
1674 sal_Bool SAL_CALL
mkdir(sal_Int32 CommandId,const rtl::OUString & rUnqPath,sal_Bool OverWrite)1675 shell::mkdir( sal_Int32 CommandId,
1676               const rtl::OUString& rUnqPath,
1677               sal_Bool OverWrite )
1678     throw()
1679 {
1680     rtl::OUString aUnqPath;
1681 
1682     // remove trailing slash
1683     if ( rUnqPath[ rUnqPath.getLength() - 1 ] == sal_Unicode( '/' ) )
1684         aUnqPath = rUnqPath.copy( 0, rUnqPath.getLength() - 1 );
1685     else
1686         aUnqPath = rUnqPath;
1687 
1688     osl::FileBase::RC nError = osl::Directory::create( aUnqPath );
1689 
1690     switch ( nError )
1691     {
1692         case osl::FileBase::E_EXIST:   // Directory cannot be overwritten
1693         {
1694             if( !OverWrite )
1695             {
1696                 installError( CommandId,
1697                               TASKHANDLING_FOLDER_EXISTS_MKDIR );
1698                 return sal_False;
1699             }
1700             else
1701                 return sal_True;
1702         }
1703         case osl::FileBase::E_INVAL:
1704         {
1705             installError(CommandId,
1706                          TASKHANDLING_INVALID_NAME_MKDIR);
1707             return sal_False;
1708         }
1709         case osl::FileBase::E_None:
1710         {
1711             rtl::OUString aPrtPath = getParentName( aUnqPath );
1712             notifyInsert( getContentEventListeners( aPrtPath ),aUnqPath );
1713             return sal_True;
1714         }
1715         default:
1716             return ensuredir(
1717                 CommandId,
1718                 aUnqPath,
1719                 TASKHANDLING_CREATEDIRECTORY_MKDIR );
1720     }
1721 }
1722 
1723 
1724 /********************************************************************************/
1725 /*                                                                              */
1726 /*                         mkfil-implementation                                 */
1727 /*                                                                              */
1728 /********************************************************************************/
1729 //
1730 //  Creates new file with given URL.
1731 //  The content of aInputStream becomes the content of the file
1732 //  Return:: success of operation
1733 //
1734 
1735 sal_Bool SAL_CALL
mkfil(sal_Int32 CommandId,const rtl::OUString & aUnqPath,sal_Bool Overwrite,const uno::Reference<io::XInputStream> & aInputStream)1736 shell::mkfil( sal_Int32 CommandId,
1737               const rtl::OUString& aUnqPath,
1738               sal_Bool Overwrite,
1739               const uno::Reference< io::XInputStream >& aInputStream )
1740     throw()
1741 {
1742     // return value unimportant
1743     sal_Bool bSuccess = write( CommandId,
1744                                aUnqPath,
1745                                Overwrite,
1746                                aInputStream );
1747     if ( bSuccess )
1748     {
1749         rtl::OUString aPrtPath = getParentName( aUnqPath );
1750         notifyInsert( getContentEventListeners( aPrtPath ),aUnqPath );
1751     }
1752     return bSuccess;
1753 }
1754 
1755 
1756 /********************************************************************************/
1757 /*                                                                              */
1758 /*                         write-implementation                                 */
1759 /*                                                                              */
1760 /********************************************************************************/
1761 //
1762 //  writes to the file with given URL.
1763 //  The content of aInputStream becomes the content of the file
1764 //  Return:: success of operation
1765 //
1766 
1767 sal_Bool SAL_CALL
write(sal_Int32 CommandId,const rtl::OUString & aUnqPath,sal_Bool OverWrite,const uno::Reference<io::XInputStream> & aInputStream)1768 shell::write( sal_Int32 CommandId,
1769               const rtl::OUString& aUnqPath,
1770               sal_Bool OverWrite,
1771               const uno::Reference< io::XInputStream >& aInputStream )
1772     throw()
1773 {
1774     if( ! aInputStream.is() )
1775     {
1776         installError( CommandId,
1777                       TASKHANDLING_INPUTSTREAM_FOR_WRITE );
1778         return sal_False;
1779     }
1780 
1781     // Create parent path, if necessary.
1782     if ( ! ensuredir( CommandId,
1783                       getParentName( aUnqPath ),
1784                       TASKHANDLING_ENSUREDIR_FOR_WRITE ) )
1785         return sal_False;
1786 
1787     osl::FileBase::RC err;
1788     osl::File aFile( aUnqPath );
1789 
1790     if( OverWrite )
1791     {
1792         err = aFile.open( OpenFlag_Write | OpenFlag_Create );
1793 
1794         if( err != osl::FileBase::E_None )
1795         {
1796             aFile.close();
1797             err = aFile.open( OpenFlag_Write );
1798 
1799             if( err != osl::FileBase::E_None )
1800             {
1801                 installError( CommandId,
1802                               TASKHANDLING_NO_OPEN_FILE_FOR_OVERWRITE,
1803                               err );
1804                 return sal_False;
1805             }
1806 
1807             // the existing file was just opened and should be overwritten now,
1808             // truncate it first
1809 
1810             err = aFile.setSize( 0 );
1811             if( err != osl::FileBase::E_None  )
1812             {
1813                 installError( CommandId,
1814                               TASKHANDLING_FILESIZE_FOR_WRITE,
1815                               err );
1816                 return sal_False;
1817             }
1818         }
1819     }
1820     else
1821     {
1822         err = aFile.open( OpenFlag_Read | OpenFlag_NoLock );
1823         if( err == osl::FileBase::E_None )  // The file exists and shall not be overwritten
1824         {
1825             installError( CommandId,
1826                           TASKHANDLING_NOREPLACE_FOR_WRITE,  // Now an exception
1827                           err );
1828 
1829             aFile.close();
1830             return sal_False;
1831         }
1832 
1833         // as a temporary solution the creation does not lock the file at all
1834         // in future it should be possible to create the file without lock explicitly
1835         err = aFile.open( OpenFlag_Write | OpenFlag_Create | OpenFlag_NoLock );
1836 
1837         if( err != osl::FileBase::E_None )
1838         {
1839             aFile.close();
1840             installError( CommandId,
1841                           TASKHANDLING_NO_OPEN_FILE_FOR_WRITE,
1842                           err );
1843             return sal_False;
1844         }
1845     }
1846 
1847     sal_Bool bSuccess = sal_True;
1848 
1849     sal_uInt64 nWrittenBytes;
1850     sal_Int32 nReadBytes = 0, nRequestedBytes = 32768 /*32k*/;
1851     uno::Sequence< sal_Int8 > seq( nRequestedBytes );
1852 
1853     do
1854     {
1855         try
1856         {
1857             nReadBytes = aInputStream->readBytes( seq,
1858                                                   nRequestedBytes );
1859         }
1860         catch( const io::NotConnectedException& )
1861         {
1862             installError( CommandId,
1863                           TASKHANDLING_NOTCONNECTED_FOR_WRITE );
1864             bSuccess = sal_False;
1865             break;
1866         }
1867         catch( const io::BufferSizeExceededException& )
1868         {
1869             installError( CommandId,
1870                           TASKHANDLING_BUFFERSIZEEXCEEDED_FOR_WRITE );
1871             bSuccess = sal_False;
1872             break;
1873         }
1874         catch( const io::IOException& )
1875         {
1876             installError( CommandId,
1877                           TASKHANDLING_IOEXCEPTION_FOR_WRITE );
1878             bSuccess = sal_False;
1879             break;
1880         }
1881 
1882         if( nReadBytes )
1883         {
1884             const sal_Int8* p = seq.getConstArray();
1885 
1886             err = aFile.write( ((void*)(p)),
1887                                sal_uInt64( nReadBytes ),
1888                                nWrittenBytes );
1889 
1890             if( err != osl::FileBase::E_None )
1891             {
1892                 installError( CommandId,
1893                               TASKHANDLING_FILEIOERROR_FOR_WRITE,
1894                               err );
1895                 bSuccess = sal_False;
1896                 break;
1897             }
1898             else if( nWrittenBytes != sal_uInt64( nReadBytes ) )
1899             {
1900                 installError( CommandId,
1901                               TASKHANDLING_FILEIOERROR_FOR_NO_SPACE );
1902                 bSuccess = sal_False;
1903                 break;
1904             }
1905         }
1906     } while( nReadBytes == nRequestedBytes );
1907 
1908     // Force the data onto the physical medium before success is reported.
1909     // Closing alone only flushes osl's own buffer into the OS page cache; the
1910     // file system journals the new file size but not the data, so a crash or
1911     // power loss between here and the next writeback leaves a file of the
1912     // right length containing nothing but zeros (i126990).
1913     if( bSuccess )
1914     {
1915         err = aFile.sync();
1916         if( err != osl::FileBase::E_None )
1917         {
1918             installError( CommandId,
1919                           TASKHANDLING_FILEIOERROR_FOR_WRITE,
1920                           err );
1921             bSuccess = sal_False;
1922         }
1923     }
1924 
1925     err = aFile.close();
1926     if( err != osl::FileBase::E_None  )
1927     {
1928         installError( CommandId,
1929                       TASKHANDLING_FILEIOERROR_FOR_WRITE,
1930                       err );
1931         bSuccess = sal_False;
1932     }
1933 
1934     return bSuccess;
1935 }
1936 
1937 
1938 
1939 /*********************************************************************************/
1940 /*                                                                               */
1941 /*                 insertDefaultProperties-Implementation                        */
1942 /*                                                                               */
1943 /*********************************************************************************/
1944 
1945 
insertDefaultProperties(const rtl::OUString & aUnqPath)1946 void SAL_CALL shell::insertDefaultProperties( const rtl::OUString& aUnqPath )
1947 {
1948     osl::MutexGuard aGuard( m_aMutex );
1949 
1950     ContentMap::iterator it =
1951         m_aContent.insert( ContentMap::value_type( aUnqPath,UnqPathData() ) ).first;
1952 
1953     load( it,false );
1954 
1955     MyProperty ContentTProperty( ContentType );
1956 
1957     PropertySet& properties = *(it->second.properties);
1958     sal_Bool ContentNotDefau = properties.find( ContentTProperty ) != properties.end();
1959 
1960     shell::PropertySet::iterator it1 = m_aDefaultProperties.begin();
1961     while( it1 != m_aDefaultProperties.end() )
1962     {
1963         if( ContentNotDefau && it1->getPropertyName() == ContentType )
1964         {
1965             // No insertion
1966         }
1967         else
1968             properties.insert( *it1 );
1969         ++it1;
1970     }
1971 }
1972 
1973 
1974 
1975 
1976 /******************************************************************************/
1977 /*                                                                            */
1978 /*                          mapping of file urls                              */
1979 /*                          to uncpath and vice versa                         */
1980 /*                                                                            */
1981 /******************************************************************************/
1982 
1983 
getUnqFromUrl(const rtl::OUString & Url,rtl::OUString & Unq)1984 sal_Bool SAL_CALL shell::getUnqFromUrl( const rtl::OUString& Url,rtl::OUString& Unq )
1985 {
1986     if( 0 == Url.compareToAscii( "file:///" ) ||
1987         0 == Url.compareToAscii( "file://localhost/" ) ||
1988         0 == Url.compareToAscii( "file://127.0.0.1/" ) )
1989     {
1990         Unq = rtl::OUString::createFromAscii( "file:///" );
1991         return false;
1992     }
1993 
1994     sal_Bool err = osl::FileBase::E_None != osl::FileBase::getSystemPathFromFileURL( Url,Unq );
1995 
1996     Unq = Url;
1997 
1998     sal_Int32 l = Unq.getLength()-1;
1999     if( ! err && Unq.getStr()[ l ] == '/' &&
2000         Unq.indexOf( '/', RTL_CONSTASCII_LENGTH("//") ) < l )
2001         Unq = Unq.copy(0, Unq.getLength() - 1);
2002 
2003     return err;
2004 }
2005 
2006 
2007 
getUrlFromUnq(const rtl::OUString & Unq,rtl::OUString & Url)2008 sal_Bool SAL_CALL shell::getUrlFromUnq( const rtl::OUString& Unq,rtl::OUString& Url )
2009 {
2010     sal_Bool err = osl::FileBase::E_None != osl::FileBase::getSystemPathFromFileURL( Unq,Url );
2011 
2012     Url = Unq;
2013 
2014     return err;
2015 }
2016 
2017 
2018 
2019 // Helper function for public copy
2020 
2021 osl::FileBase::RC SAL_CALL
copy_recursive(const rtl::OUString & srcUnqPath,const rtl::OUString & dstUnqPath,sal_Int32 TypeToCopy,sal_Bool testExistBeforeCopy)2022 shell::copy_recursive( const rtl::OUString& srcUnqPath,
2023                        const rtl::OUString& dstUnqPath,
2024                        sal_Int32 TypeToCopy,
2025                        sal_Bool testExistBeforeCopy )
2026     throw()
2027 {
2028     osl::FileBase::RC err = osl::FileBase::E_None;
2029 
2030     if( TypeToCopy == -1 ) // Document
2031     {
2032         err = osl_File_copy( srcUnqPath,dstUnqPath,testExistBeforeCopy );
2033     }
2034     else if( TypeToCopy == +1 ) // Folder
2035     {
2036         osl::Directory aDir( srcUnqPath );
2037         aDir.open();
2038 
2039         err = osl::Directory::create( dstUnqPath );
2040         osl::FileBase::RC next = err;
2041         if( err == osl::FileBase::E_None )
2042         {
2043             sal_Int32 n_Mask = FileStatusMask_FileURL | FileStatusMask_FileName | FileStatusMask_Type;
2044 
2045             osl::DirectoryItem aDirItem;
2046 
2047             while( err == osl::FileBase::E_None && ( next = aDir.getNextItem( aDirItem ) ) == osl::FileBase::E_None )
2048             {
2049                 sal_Bool IsDoc = false;
2050                 osl::FileStatus aFileStatus( n_Mask );
2051                 aDirItem.getFileStatus( aFileStatus );
2052                 if( aFileStatus.isValid( FileStatusMask_Type ) )
2053                     IsDoc = aFileStatus.getFileType() == osl::FileStatus::Regular;
2054 
2055                 // Getting the information for the next recursive copy
2056                 sal_Int32 newTypeToCopy = IsDoc ? -1 : +1;
2057 
2058                 rtl::OUString newSrcUnqPath;
2059                 if( aFileStatus.isValid( FileStatusMask_FileURL ) )
2060                     newSrcUnqPath = aFileStatus.getFileURL();
2061 
2062                 rtl::OUString newDstUnqPath = dstUnqPath;
2063                 rtl::OUString tit;
2064                 if( aFileStatus.isValid( FileStatusMask_FileName ) )
2065                     tit = rtl::Uri::encode( aFileStatus.getFileName(),
2066                                           rtl_UriCharClassPchar,
2067                                           rtl_UriEncodeIgnoreEscapes,
2068                                           RTL_TEXTENCODING_UTF8 );
2069 
2070                 if( newDstUnqPath.lastIndexOf( sal_Unicode('/') ) != newDstUnqPath.getLength()-1 )
2071                     newDstUnqPath += rtl::OUString::createFromAscii( "/" );
2072 
2073                 newDstUnqPath += tit;
2074 
2075                 if ( newSrcUnqPath != dstUnqPath )
2076                     err = copy_recursive( newSrcUnqPath,newDstUnqPath,newTypeToCopy,false );
2077             }
2078 
2079             if( err == osl::FileBase::E_None && next != osl::FileBase::E_NOENT )
2080                 err = next;
2081         }
2082         aDir.close();
2083     }
2084 
2085     return err;
2086 }
2087 
2088 
2089 
2090 // Helper function for mkfil,mkdir and write
2091 // Creates whole path
2092 // returns success of the operation
2093 
2094 
ensuredir(sal_Int32 CommandId,const rtl::OUString & rUnqPath,sal_Int32 errorCode)2095 sal_Bool SAL_CALL shell::ensuredir( sal_Int32 CommandId,
2096                                     const rtl::OUString& rUnqPath,
2097                                     sal_Int32 errorCode )
2098     throw()
2099 {
2100     rtl::OUString aPath;
2101 
2102     if ( rUnqPath.getLength() < 1 )
2103         return sal_False;
2104 
2105     if ( rUnqPath[ rUnqPath.getLength() - 1 ] == sal_Unicode( '/' ) )
2106         aPath = rUnqPath.copy( 0, rUnqPath.getLength() - 1 );
2107     else
2108         aPath = rUnqPath;
2109 
2110 
2111     // HACK: create directory on a mount point with nobrowse option
2112     // returns ENOSYS in any case !!
2113     osl::Directory aDirectory( aPath );
2114     osl::FileBase::RC nError = aDirectory.open();
2115     aDirectory.close();
2116 
2117     if( nError == osl::File::E_None )
2118         return sal_True;
2119 
2120     nError = osl::Directory::create( aPath );
2121 
2122     if( nError == osl::File::E_None )
2123         notifyInsert( getContentEventListeners( getParentName( aPath ) ),aPath );
2124 
2125     sal_Bool  bSuccess = ( nError == osl::File::E_None || nError == osl::FileBase::E_EXIST );
2126 
2127     if( ! bSuccess )
2128     {
2129         rtl::OUString aParentDir = getParentName( aPath );
2130 
2131         if ( aParentDir != aPath )
2132         {   // Create first the parent directory
2133             bSuccess = ensuredir( CommandId,
2134                                   getParentName( aPath ),
2135                                   errorCode );
2136 
2137             // After parent directory structure exists try it one's more
2138 
2139             if ( bSuccess )
2140             {   // Parent directory exists, retry creation of directory
2141                 nError = osl::Directory::create( aPath );
2142 
2143                 if( nError == osl::File::E_None )
2144                     notifyInsert( getContentEventListeners( getParentName( aPath ) ),aPath );
2145 
2146                 bSuccess =( nError == osl::File::E_None || nError == osl::FileBase::E_EXIST );
2147             }
2148         }
2149     }
2150 
2151     if( ! bSuccess )
2152         installError( CommandId,
2153                       errorCode,
2154                       nError );
2155 
2156     return bSuccess;
2157 }
2158 
2159 
2160 
2161 
2162 //
2163 //  Given a sequence of properties seq, this method determines the mask
2164 //  used to instantiate a osl::FileStatus, so that a call to
2165 //  osl::DirectoryItem::getFileStatus fills the required fields.
2166 //
2167 
2168 
2169 void SAL_CALL
getMaskFromProperties(sal_Int32 & n_Mask,const uno::Sequence<beans::Property> & seq)2170 shell::getMaskFromProperties(
2171     sal_Int32& n_Mask,
2172     const uno::Sequence< beans::Property >& seq )
2173 {
2174     n_Mask = 0;
2175     for(sal_Int32 j = 0; j < seq.getLength(); ++j) {
2176         if(seq[j].Name == Title)
2177             n_Mask |= FileStatusMask_FileName;
2178         else if(seq[j].Name == CasePreservingURL)
2179             n_Mask |= FileStatusMask_FileURL;
2180         else if(seq[j].Name == IsDocument ||
2181                 seq[j].Name == IsFolder ||
2182                 seq[j].Name == IsVolume ||
2183                 seq[j].Name == IsRemoveable ||
2184                 seq[j].Name == IsRemote ||
2185                 seq[j].Name == IsCompactDisc ||
2186                 seq[j].Name == IsFloppy ||
2187                 seq[j].Name == ContentType)
2188             n_Mask |= (FileStatusMask_Type | FileStatusMask_LinkTargetURL);
2189         else if(seq[j].Name == Size)
2190             n_Mask |= (FileStatusMask_FileSize |
2191                       FileStatusMask_Type |
2192                       FileStatusMask_LinkTargetURL);
2193         else if(seq[j].Name == IsHidden ||
2194                 seq[j].Name == IsReadOnly)
2195             n_Mask |= FileStatusMask_Attributes;
2196         else if(seq[j].Name == DateModified)
2197             n_Mask |= FileStatusMask_ModifyTime;
2198 //         n_Mask = FileStatusMask_FileURL;
2199 //         n_Mask |= FileStatusMask_LinkTargetURL;
2200 //         n_Mask |= FileStatusMask_FileName;
2201 //         n_Mask |= FileStatusMask_Type;
2202 //         n_Mask |= FileStatusMask_ModifyTime;
2203 //         n_Mask |= FileStatusMask_FileSize;
2204 //         n_Mask |= FileStatusMask_Attributes;
2205     }
2206 }
2207 
2208 
2209 
2210 /*********************************************************************************/
2211 /*                                                                               */
2212 /*                     load-Implementation                                       */
2213 /*                                                                               */
2214 /*********************************************************************************/
2215 //
2216 //  Load the properties from configuration, if create == true create them.
2217 //  The Properties are stored under the url belonging to it->first.
2218 //
2219 
2220 void SAL_CALL
load(const ContentMap::iterator & it,sal_Bool create)2221 shell::load( const ContentMap::iterator& it, sal_Bool create )
2222 {
2223     if( ! it->second.properties )
2224         it->second.properties = new PropertySet;
2225 
2226     if( ( ! it->second.xS.is() ||
2227           ! it->second.xC.is() ||
2228           ! it->second.xA.is() )
2229         && m_xFileRegistry.is() )
2230     {
2231 
2232         uno::Reference< ucb::XPersistentPropertySet > xS = m_xFileRegistry->openPropertySet( it->first,create );
2233         if( xS.is() )
2234         {
2235             uno::Reference< beans::XPropertyContainer > xC( xS,uno::UNO_QUERY );
2236             uno::Reference< beans::XPropertyAccess >    xA( xS,uno::UNO_QUERY );
2237 
2238             it->second.xS = xS;
2239             it->second.xC = xC;
2240             it->second.xA = xA;
2241 
2242             // Now put in all values in the storage in the local hash;
2243 
2244             PropertySet& properties = *(it->second.properties);
2245             uno::Sequence< beans::Property > seq = xS->getPropertySetInfo()->getProperties();
2246 
2247             for( sal_Int32 i = 0; i < seq.getLength(); ++i )
2248             {
2249                 MyProperty readProp( false,
2250                                      seq[i].Name,
2251                                      seq[i].Handle,
2252                                      seq[i].Type,
2253                                      xS->getPropertyValue( seq[i].Name ),
2254                                      beans::PropertyState_DIRECT_VALUE,
2255                                      seq[i].Attributes );
2256                 if( properties.find( readProp ) == properties.end() )
2257                     properties.insert( readProp );
2258             }
2259         }
2260         else if( create )
2261         {
2262             // Catastrophic error
2263         }
2264     }
2265 }
2266 
2267 
2268 
2269 
2270 /*********************************************************************************/
2271 /*                                                                               */
2272 /*                     commit-Implementation                                     */
2273 /*                                                                               */
2274 /*********************************************************************************/
2275 // Commit inserts the determined properties in the filestatus object into
2276 // the internal map, so that is possible to determine on a subsequent
2277 // setting of file properties which properties have changed without filestat
2278 
2279 
2280 void SAL_CALL
commit(const shell::ContentMap::iterator & it,const osl::FileStatus & aFileStatus)2281 shell::commit( const shell::ContentMap::iterator& it,
2282                const osl::FileStatus& aFileStatus )
2283 {
2284     uno::Any aAny;
2285     uno::Any emptyAny;
2286     shell::PropertySet::iterator it1;
2287 
2288     if( it->second.properties == 0 )
2289     {
2290         rtl::OUString aPath = it->first;
2291         insertDefaultProperties( aPath );
2292     }
2293 
2294     PropertySet& properties = *( it->second.properties );
2295 
2296     it1 = properties.find( MyProperty( Title ) );
2297     if( it1 != properties.end() )
2298     {
2299         if( aFileStatus.isValid( FileStatusMask_FileName ) )
2300         {
2301             aAny <<= aFileStatus.getFileName();
2302             it1->setValue( aAny );
2303         }
2304     }
2305 
2306     it1 = properties.find( MyProperty( CasePreservingURL ) );
2307     if( it1 != properties.end() )
2308     {
2309         if( aFileStatus.isValid( FileStatusMask_FileURL ) )
2310         {
2311             aAny <<= aFileStatus.getFileURL();
2312             it1->setValue( aAny );
2313         }
2314     }
2315 
2316 
2317     sal_Bool isDirectory,isFile,isVolume,isRemoveable,isRemote,isFloppy,isCompactDisc;
2318 
2319     sal_Int64 dirSize = 0;
2320 
2321     if( aFileStatus.isValid( FileStatusMask_FileSize ) )
2322         dirSize = aFileStatus.getFileSize();
2323 
2324     if( aFileStatus.isValid( FileStatusMask_Type ) )
2325     {
2326         if( osl::FileStatus::Link == aFileStatus.getFileType() &&
2327             aFileStatus.isValid( FileStatusMask_LinkTargetURL ) )
2328         {
2329             osl::DirectoryItem aDirItem;
2330             osl::FileStatus aFileStatus2( FileStatusMask_Type );
2331             if( osl::FileBase::E_None == osl::DirectoryItem::get( aFileStatus.getLinkTargetURL(),aDirItem ) &&
2332                 osl::FileBase::E_None == aDirItem.getFileStatus( aFileStatus2 )    &&
2333                 aFileStatus2.isValid( FileStatusMask_Type ) )
2334             {
2335                 isVolume = osl::FileStatus::Volume == aFileStatus2.getFileType();
2336                 isDirectory =
2337                     osl::FileStatus::Volume == aFileStatus2.getFileType() ||
2338                     osl::FileStatus::Directory == aFileStatus2.getFileType();
2339                 isFile =
2340                     osl::FileStatus::Regular == aFileStatus2.getFileType();
2341 
2342                 if( aFileStatus2.isValid( FileStatusMask_FileSize ) )
2343                     dirSize = aFileStatus2.getFileSize();
2344             }
2345             else
2346             {
2347                 // extremely ugly, but otherwise default construction
2348                 // of aDirItem and aFileStatus2
2349                 // before the preciding if
2350                 isVolume = osl::FileStatus::Volume == aFileStatus.getFileType();
2351                 isDirectory =
2352                     osl::FileStatus::Volume == aFileStatus.getFileType() ||
2353                     osl::FileStatus::Directory == aFileStatus.getFileType();
2354                 isFile =
2355                     osl::FileStatus::Regular == aFileStatus.getFileType();
2356             }
2357         }
2358         else
2359         {
2360             isVolume = osl::FileStatus::Volume == aFileStatus.getFileType();
2361             isDirectory =
2362                 osl::FileStatus::Volume == aFileStatus.getFileType() ||
2363                 osl::FileStatus::Directory == aFileStatus.getFileType();
2364             isFile =
2365                 osl::FileStatus::Regular == aFileStatus.getFileType();
2366         }
2367 
2368         it1 = properties.find( MyProperty( IsVolume ) );
2369         if( it1 != properties.end() )
2370             it1->setValue( uno::makeAny( isVolume ) );
2371 
2372         it1 = properties.find( MyProperty( IsFolder ) );
2373         if( it1 != properties.end() )
2374             it1->setValue( uno::makeAny( isDirectory ) );
2375 
2376         it1 = properties.find( MyProperty( IsDocument ) );
2377         if( it1 != properties.end() )
2378             it1->setValue( uno::makeAny( isFile ) );
2379 
2380         osl::VolumeInfo aVolumeInfo( VolumeInfoMask_Attributes );
2381         if( isVolume &&
2382             osl::FileBase::E_None == osl::Directory::getVolumeInfo( it->first,aVolumeInfo ) &&
2383             aVolumeInfo.isValid( VolumeInfoMask_Attributes ) )
2384         {
2385             // Retrieve the flags;
2386             isRemote = aVolumeInfo.getRemoteFlag();
2387             isRemoveable = aVolumeInfo.getRemoveableFlag();
2388             isCompactDisc = aVolumeInfo.getCompactDiscFlag();
2389             isFloppy = aVolumeInfo.getFloppyDiskFlag();
2390 
2391             it1 = properties.find( MyProperty( IsRemote ) );
2392             if( it1 != properties.end() )
2393                 it1->setValue( uno::makeAny( isRemote ) );
2394 
2395             it1 = properties.find( MyProperty( IsRemoveable ) );
2396             if( it1 != properties.end() )
2397                 it1->setValue( uno::makeAny( isRemoveable ) );
2398 
2399             it1 = properties.find( MyProperty( IsCompactDisc ) );
2400             if( it1 != properties.end() )
2401                 it1->setValue( uno::makeAny( isCompactDisc ) );
2402 
2403             it1 = properties.find( MyProperty( IsFloppy ) );
2404             if( it1 != properties.end() )
2405                 it1->setValue( uno::makeAny( isFloppy ) );
2406         }
2407         else
2408         {
2409             sal_Bool dummy = false;
2410             aAny <<= dummy;
2411             it1 = properties.find( MyProperty( IsRemote ) );
2412             if( it1 != properties.end() )
2413                 it1->setValue( aAny );
2414 
2415             it1 = properties.find( MyProperty( IsRemoveable ) );
2416             if( it1 != properties.end() )
2417                 it1->setValue( aAny );
2418 
2419             it1 = properties.find( MyProperty( IsCompactDisc ) );
2420             if( it1 != properties.end() )
2421                 it1->setValue( aAny );
2422 
2423             it1 = properties.find( MyProperty( IsFloppy ) );
2424             if( it1 != properties.end() )
2425                 it1->setValue( aAny );
2426         }
2427     }
2428     else
2429     {
2430         isDirectory = sal_False;
2431     }
2432 
2433     it1 = properties.find( MyProperty( Size ) );
2434     if( it1 != properties.end() )
2435         it1->setValue( uno::makeAny( dirSize ) );
2436 
2437     it1 = properties.find( MyProperty( IsReadOnly ) );
2438     if( it1 != properties.end() )
2439     {
2440         if( aFileStatus.isValid( FileStatusMask_Attributes ) )
2441         {
2442             sal_uInt64 Attr = aFileStatus.getAttributes();
2443             sal_Bool readonly = ( Attr & Attribute_ReadOnly ) != 0;
2444             it1->setValue( uno::makeAny( readonly ) );
2445         }
2446     }
2447 
2448     it1 = properties.find( MyProperty( IsHidden ) );
2449     if( it1 != properties.end() )
2450     {
2451         if( aFileStatus.isValid( FileStatusMask_Attributes ) )
2452         {
2453             sal_uInt64 Attr = aFileStatus.getAttributes();
2454             sal_Bool ishidden = ( Attr & Attribute_Hidden ) != 0;
2455             it1->setValue( uno::makeAny( ishidden ) );
2456         }
2457     }
2458 
2459     it1 = properties.find( MyProperty( DateModified ) );
2460     if( it1 != properties.end() )
2461     {
2462         if( aFileStatus.isValid( FileStatusMask_ModifyTime ) )
2463         {
2464             TimeValue temp = aFileStatus.getModifyTime();
2465 
2466             // Convert system time to local time (for EA)
2467             TimeValue myLocalTime;
2468             osl_getLocalTimeFromSystemTime( &temp, &myLocalTime );
2469 
2470             oslDateTime myDateTime;
2471             osl_getDateTimeFromTimeValue( &myLocalTime, &myDateTime );
2472             util::DateTime aDateTime;
2473 
2474             aDateTime.HundredthSeconds = (unsigned short)(myDateTime.NanoSeconds / 10000000);
2475             aDateTime.Seconds = myDateTime.Seconds;
2476             aDateTime.Minutes = myDateTime.Minutes;
2477             aDateTime.Hours = myDateTime.Hours;
2478             aDateTime.Day = myDateTime.Day;
2479             aDateTime.Month = myDateTime.Month;
2480             aDateTime.Year = myDateTime.Year;
2481             it1->setValue( uno::makeAny( aDateTime ) );
2482         }
2483     }
2484 
2485     it1 = properties.find( MyProperty( CreatableContentsInfo ) );
2486     if( it1 != properties.end() )
2487         it1->setValue( uno::makeAny(
2488             isDirectory || !aFileStatus.isValid( FileStatusMask_Type )
2489                 ? queryCreatableContentsInfo()
2490                 : uno::Sequence< ucb::ContentInfo >() ) );
2491 }
2492 
2493 
2494 // Special optimized method for getting the properties of a
2495 // directoryitem, which is returned by osl::DirectoryItem::getNextItem()
2496 
2497 
2498 uno::Reference< sdbc::XRow > SAL_CALL
getv(Notifier * pNotifier,const uno::Sequence<beans::Property> & properties,osl::DirectoryItem & aDirItem,rtl::OUString & aUnqPath,sal_Bool & aIsRegular)2499 shell::getv(
2500     Notifier* pNotifier,
2501     const uno::Sequence< beans::Property >& properties,
2502     osl::DirectoryItem& aDirItem,
2503     rtl::OUString& aUnqPath,
2504     sal_Bool& aIsRegular )
2505 {
2506     uno::Sequence< uno::Any > seq( properties.getLength() );
2507 
2508     sal_Int32 n_Mask;
2509     getMaskFromProperties( n_Mask,properties );
2510 
2511     // Always retrieve the type and the target URL because item might be a link
2512     osl::FileStatus aFileStatus( n_Mask |
2513                                  FileStatusMask_FileURL |
2514                                  FileStatusMask_Type |
2515                                  FileStatusMask_LinkTargetURL );
2516     aDirItem.getFileStatus( aFileStatus );
2517     aUnqPath = aFileStatus.getFileURL();
2518 
2519     // If the directory item type is a link retrieve the type of the target
2520 
2521     if ( aFileStatus.getFileType() == osl::FileStatus::Link )
2522     {
2523         // Assume failure
2524         aIsRegular = false;
2525         osl::FileBase::RC result = osl::FileBase::E_INVAL;
2526         osl::DirectoryItem aTargetItem;
2527         osl::DirectoryItem::get( aFileStatus.getLinkTargetURL(), aTargetItem );
2528         if ( aTargetItem.is() )
2529         {
2530             osl::FileStatus aTargetStatus( FileStatusMask_Type );
2531 
2532             if ( osl::FileBase::E_None ==
2533                  ( result = aTargetItem.getFileStatus( aTargetStatus ) ) )
2534                 aIsRegular =
2535                     aTargetStatus.getFileType() == osl::FileStatus::Regular;
2536         }
2537     }
2538     else
2539         aIsRegular = aFileStatus.getFileType() == osl::FileStatus::Regular;
2540 
2541     registerNotifier( aUnqPath,pNotifier );
2542     insertDefaultProperties( aUnqPath );
2543     {
2544         osl::MutexGuard aGuard( m_aMutex );
2545 
2546         shell::ContentMap::iterator it = m_aContent.find( aUnqPath );
2547         commit( it,aFileStatus );
2548 
2549         shell::PropertySet::iterator it1;
2550         PropertySet& propset = *(it->second.properties);
2551 
2552         for( sal_Int32 i = 0; i < seq.getLength(); ++i )
2553         {
2554             MyProperty readProp( properties[i].Name );
2555             it1 = propset.find( readProp );
2556             if( it1 == propset.end() )
2557                 seq[i] = uno::Any();
2558             else
2559                 seq[i] = it1->getValue();
2560         }
2561     }
2562     deregisterNotifier( aUnqPath,pNotifier );
2563 
2564     XRow_impl* p = new XRow_impl( this,seq );
2565     return uno::Reference< sdbc::XRow >( p );
2566 }
2567 
2568 
2569 
2570 
2571 
2572 
2573 // EventListener
2574 
2575 
2576 std::list< ContentEventNotifier* >* SAL_CALL
getContentEventListeners(const rtl::OUString & aName)2577 shell::getContentEventListeners( const rtl::OUString& aName )
2578 {
2579     std::list< ContentEventNotifier* >* p = new std::list< ContentEventNotifier* >;
2580     std::list< ContentEventNotifier* >& listeners = *p;
2581     {
2582         osl::MutexGuard aGuard( m_aMutex );
2583         shell::ContentMap::iterator it = m_aContent.find( aName );
2584         if( it != m_aContent.end() && it->second.notifier )
2585         {
2586             std::list<Notifier*>& listOfNotifiers = *( it->second.notifier );
2587             std::list<Notifier*>::iterator it1 = listOfNotifiers.begin();
2588             while( it1 != listOfNotifiers.end() )
2589             {
2590                 Notifier* pointer = *it1;
2591                 ContentEventNotifier* notifier = pointer->cCEL();
2592                 if( notifier )
2593                     listeners.push_back( notifier );
2594                 ++it1;
2595             }
2596         }
2597     }
2598     return p;
2599 }
2600 
2601 
2602 
2603 std::list< ContentEventNotifier* >* SAL_CALL
getContentDeletedEventListeners(const rtl::OUString & aName)2604 shell::getContentDeletedEventListeners( const rtl::OUString& aName )
2605 {
2606     std::list< ContentEventNotifier* >* p = new std::list< ContentEventNotifier* >;
2607     std::list< ContentEventNotifier* >& listeners = *p;
2608     {
2609         osl::MutexGuard aGuard( m_aMutex );
2610         shell::ContentMap::iterator it = m_aContent.find( aName );
2611         if( it != m_aContent.end() && it->second.notifier )
2612         {
2613             std::list<Notifier*>& listOfNotifiers = *( it->second.notifier );
2614             std::list<Notifier*>::iterator it1 = listOfNotifiers.begin();
2615             while( it1 != listOfNotifiers.end() )
2616             {
2617                 Notifier* pointer = *it1;
2618                 ContentEventNotifier* notifier = pointer->cDEL();
2619                 if( notifier )
2620                     listeners.push_back( notifier );
2621                 ++it1;
2622             }
2623         }
2624     }
2625     return p;
2626 }
2627 
2628 
2629 void SAL_CALL
notifyInsert(std::list<ContentEventNotifier * > * listeners,const rtl::OUString & aChildName)2630 shell::notifyInsert( std::list< ContentEventNotifier* >* listeners,const rtl::OUString& aChildName )
2631 {
2632     std::list< ContentEventNotifier* >::iterator it = listeners->begin();
2633     while( it != listeners->end() )
2634     {
2635         (*it)->notifyChildInserted( aChildName );
2636         delete (*it);
2637         ++it;
2638     }
2639     delete listeners;
2640 }
2641 
2642 
2643 void SAL_CALL
notifyContentDeleted(std::list<ContentEventNotifier * > * listeners)2644 shell::notifyContentDeleted( std::list< ContentEventNotifier* >* listeners )
2645 {
2646     std::list< ContentEventNotifier* >::iterator it = listeners->begin();
2647     while( it != listeners->end() )
2648     {
2649         (*it)->notifyDeleted();
2650         delete (*it);
2651         ++it;
2652     }
2653     delete listeners;
2654 }
2655 
2656 
2657 void SAL_CALL
notifyContentRemoved(std::list<ContentEventNotifier * > * listeners,const rtl::OUString & aChildName)2658 shell::notifyContentRemoved( std::list< ContentEventNotifier* >* listeners,
2659                              const rtl::OUString& aChildName )
2660 {
2661     std::list< ContentEventNotifier* >::iterator it = listeners->begin();
2662     while( it != listeners->end() )
2663     {
2664         (*it)->notifyRemoved( aChildName );
2665         delete (*it);
2666         ++it;
2667     }
2668     delete listeners;
2669 }
2670 
2671 
2672 
2673 
2674 std::list< PropertySetInfoChangeNotifier* >* SAL_CALL
getPropertySetListeners(const rtl::OUString & aName)2675 shell::getPropertySetListeners( const rtl::OUString& aName )
2676 {
2677     std::list< PropertySetInfoChangeNotifier* >* p = new std::list< PropertySetInfoChangeNotifier* >;
2678     std::list< PropertySetInfoChangeNotifier* >& listeners = *p;
2679     {
2680         osl::MutexGuard aGuard( m_aMutex );
2681         shell::ContentMap::iterator it = m_aContent.find( aName );
2682         if( it != m_aContent.end() && it->second.notifier )
2683         {
2684             std::list<Notifier*>& listOfNotifiers = *( it->second.notifier );
2685             std::list<Notifier*>::iterator it1 = listOfNotifiers.begin();
2686             while( it1 != listOfNotifiers.end() )
2687             {
2688                 Notifier* pointer = *it1;
2689                 PropertySetInfoChangeNotifier* notifier = pointer->cPSL();
2690                 if( notifier )
2691                     listeners.push_back( notifier );
2692                 ++it1;
2693             }
2694         }
2695     }
2696     return p;
2697 }
2698 
2699 
2700 void SAL_CALL
notifyPropertyAdded(std::list<PropertySetInfoChangeNotifier * > * listeners,const rtl::OUString & aPropertyName)2701 shell::notifyPropertyAdded( std::list< PropertySetInfoChangeNotifier* >* listeners,
2702                             const rtl::OUString& aPropertyName )
2703 {
2704     std::list< PropertySetInfoChangeNotifier* >::iterator it = listeners->begin();
2705     while( it != listeners->end() )
2706     {
2707         (*it)->notifyPropertyAdded( aPropertyName );
2708         delete (*it);
2709         ++it;
2710     }
2711     delete listeners;
2712 }
2713 
2714 
2715 void SAL_CALL
notifyPropertyRemoved(std::list<PropertySetInfoChangeNotifier * > * listeners,const rtl::OUString & aPropertyName)2716 shell::notifyPropertyRemoved( std::list< PropertySetInfoChangeNotifier* >* listeners,
2717                               const rtl::OUString& aPropertyName )
2718 {
2719     std::list< PropertySetInfoChangeNotifier* >::iterator it = listeners->begin();
2720     while( it != listeners->end() )
2721     {
2722         (*it)->notifyPropertyRemoved( aPropertyName );
2723         delete (*it);
2724         ++it;
2725     }
2726     delete listeners;
2727 }
2728 
2729 
2730 
2731 std::vector< std::list< ContentEventNotifier* >* >* SAL_CALL
getContentExchangedEventListeners(const rtl::OUString aOldPrefix,const rtl::OUString aNewPrefix,sal_Bool withChilds)2732 shell::getContentExchangedEventListeners( const rtl::OUString aOldPrefix,
2733                                           const rtl::OUString aNewPrefix,
2734                                           sal_Bool withChilds )
2735 {
2736 
2737     std::vector< std::list< ContentEventNotifier* >* >* aVectorOnHeap =
2738         new std::vector< std::list< ContentEventNotifier* >* >;
2739     std::vector< std::list< ContentEventNotifier* >* >&  aVector = *aVectorOnHeap;
2740 
2741     sal_Int32 count;
2742     rtl::OUString aOldName;
2743     rtl::OUString aNewName;
2744     std::vector< rtl::OUString > oldChildList;
2745 
2746     {
2747         osl::MutexGuard aGuard( m_aMutex );
2748 
2749         if( ! withChilds )
2750         {
2751             aOldName = aOldPrefix;
2752             aNewName = aNewPrefix;
2753             count = 1;
2754         }
2755         else
2756         {
2757             ContentMap::iterator itnames = m_aContent.begin();
2758             while( itnames != m_aContent.end() )
2759             {
2760                 if( isChild( aOldPrefix,itnames->first ) )
2761                 {
2762                     oldChildList.push_back( itnames->first );
2763                 }
2764                 ++itnames;
2765             }
2766             count = oldChildList.size();
2767         }
2768 
2769 
2770         for( sal_Int32 j = 0; j < count; ++j )
2771         {
2772             std::list< ContentEventNotifier* >* p = new std::list< ContentEventNotifier* >;
2773             std::list< ContentEventNotifier* >& listeners = *p;
2774 
2775             if( withChilds )
2776             {
2777                 aOldName = oldChildList[j];
2778                 aNewName = newName( aNewPrefix,aOldPrefix,aOldName );
2779             }
2780 
2781             shell::ContentMap::iterator itold = m_aContent.find( aOldName );
2782             if( itold != m_aContent.end() )
2783             {
2784                 shell::ContentMap::iterator itnew = m_aContent.insert(
2785                     ContentMap::value_type( aNewName,UnqPathData() ) ).first;
2786 
2787                 // copy Ownership also
2788                 delete itnew->second.properties;
2789                 itnew->second.properties = itold->second.properties;
2790                 itold->second.properties = 0;
2791 
2792                 // copy existing list
2793                 std::list< Notifier* >* copyList = itnew->second.notifier;
2794                 itnew->second.notifier = itold->second.notifier;
2795                 itold->second.notifier = 0;
2796 
2797                 m_aContent.erase( itold );
2798 
2799                 if( itnew != m_aContent.end() && itnew->second.notifier )
2800                 {
2801                     std::list<Notifier*>& listOfNotifiers = *( itnew->second.notifier );
2802                     std::list<Notifier*>::iterator it1 = listOfNotifiers.begin();
2803                     while( it1 != listOfNotifiers.end() )
2804                     {
2805                         Notifier* pointer = *it1;
2806                         ContentEventNotifier* notifier = pointer->cEXC( aNewName );
2807                         if( notifier )
2808                             listeners.push_back( notifier );
2809                         ++it1;
2810                     }
2811                 }
2812 
2813                 // Merge with preexisting notifiers
2814                 // However, these may be in status BaseContent::Deleted
2815                 if( copyList != 0 )
2816                 {
2817                     std::list< Notifier* >::iterator copyIt = copyList->begin();
2818                     while( copyIt != copyList->end() )
2819                     {
2820                         itnew->second.notifier->push_back( *copyIt );
2821                         ++copyIt;
2822                     }
2823                 }
2824                 delete copyList;
2825             }
2826             aVector.push_back( p );
2827         }
2828     }
2829 
2830     return aVectorOnHeap;
2831 }
2832 
2833 
2834 
2835 void SAL_CALL
notifyContentExchanged(std::vector<std::list<ContentEventNotifier * > * > * listeners_vec)2836 shell::notifyContentExchanged( std::vector< std::list< ContentEventNotifier* >* >* listeners_vec )
2837 {
2838     std::list< ContentEventNotifier* >* listeners;
2839     for( sal_uInt32 i = 0; i < listeners_vec->size(); ++i )
2840     {
2841         listeners = (*listeners_vec)[i];
2842         std::list< ContentEventNotifier* >::iterator it = listeners->begin();
2843         while( it != listeners->end() )
2844         {
2845             (*it)->notifyExchanged();
2846             delete (*it);
2847             ++it;
2848         }
2849         delete listeners;
2850     }
2851     delete listeners_vec;
2852 }
2853 
2854 
2855 
2856 std::list< PropertyChangeNotifier* >* SAL_CALL
getPropertyChangeNotifier(const rtl::OUString & aName)2857 shell::getPropertyChangeNotifier( const rtl::OUString& aName )
2858 {
2859     std::list< PropertyChangeNotifier* >* p = new std::list< PropertyChangeNotifier* >;
2860     std::list< PropertyChangeNotifier* >& listeners = *p;
2861     {
2862         osl::MutexGuard aGuard( m_aMutex );
2863         shell::ContentMap::iterator it = m_aContent.find( aName );
2864         if( it != m_aContent.end() && it->second.notifier )
2865         {
2866             std::list<Notifier*>& listOfNotifiers = *( it->second.notifier );
2867             std::list<Notifier*>::iterator it1 = listOfNotifiers.begin();
2868             while( it1 != listOfNotifiers.end() )
2869             {
2870                 Notifier* pointer = *it1;
2871                 PropertyChangeNotifier* notifier = pointer->cPCL();
2872                 if( notifier )
2873                     listeners.push_back( notifier );
2874                 ++it1;
2875             }
2876         }
2877     }
2878     return p;
2879 }
2880 
2881 
notifyPropertyChanges(std::list<PropertyChangeNotifier * > * listeners,const uno::Sequence<beans::PropertyChangeEvent> & seqChanged)2882 void SAL_CALL shell::notifyPropertyChanges( std::list< PropertyChangeNotifier* >* listeners,
2883                                             const uno::Sequence< beans::PropertyChangeEvent >& seqChanged )
2884 {
2885     std::list< PropertyChangeNotifier* >::iterator it = listeners->begin();
2886     while( it != listeners->end() )
2887     {
2888         (*it)->notifyPropertyChanged( seqChanged );
2889         delete (*it);
2890         ++it;
2891     }
2892     delete listeners;
2893 }
2894 
2895 
2896 
2897 
2898 /********************************************************************************/
2899 /*                       remove persistent propertyset                          */
2900 /********************************************************************************/
2901 
2902 void SAL_CALL
erasePersistentSet(const rtl::OUString & aUnqPath,sal_Bool withChilds)2903 shell::erasePersistentSet( const rtl::OUString& aUnqPath,
2904                            sal_Bool withChilds )
2905 {
2906     if( ! m_xFileRegistry.is() )
2907     {
2908         OSL_ASSERT( m_xFileRegistry.is() );
2909         return;
2910     }
2911 
2912     uno::Sequence< rtl::OUString > seqNames;
2913 
2914     if( withChilds )
2915     {
2916         uno::Reference< container::XNameAccess > xName( m_xFileRegistry,uno::UNO_QUERY );
2917         seqNames = xName->getElementNames();
2918     }
2919 
2920     sal_Int32 count = withChilds ? seqNames.getLength() : 1;
2921 
2922     rtl::OUString
2923         old_Name = aUnqPath;
2924 
2925     for( sal_Int32 j = 0; j < count; ++j )
2926     {
2927         if( withChilds  && ! ( isChild( old_Name,seqNames[j] ) ) )
2928             continue;
2929 
2930         if( withChilds )
2931         {
2932             old_Name = seqNames[j];
2933         }
2934 
2935         {
2936             // Release possible references
2937             osl::MutexGuard aGuard( m_aMutex );
2938             ContentMap::iterator it = m_aContent.find( old_Name );
2939             if( it != m_aContent.end() )
2940             {
2941                 it->second.xS = 0;
2942                 it->second.xC = 0;
2943                 it->second.xA = 0;
2944 
2945                 delete it->second.properties;
2946                 it->second.properties = 0;
2947             }
2948         }
2949 
2950         if( m_xFileRegistry.is() )
2951             m_xFileRegistry->removePropertySet( old_Name );
2952     }
2953 }
2954 
2955 
2956 
2957 
2958 /********************************************************************************/
2959 /*                       copy persistent propertyset                            */
2960 /*                       from srcUnqPath to dstUnqPath                          */
2961 /********************************************************************************/
2962 
2963 
2964 void SAL_CALL
copyPersistentSet(const rtl::OUString & srcUnqPath,const rtl::OUString & dstUnqPath,sal_Bool withChilds)2965 shell::copyPersistentSet( const rtl::OUString& srcUnqPath,
2966                           const rtl::OUString& dstUnqPath,
2967                           sal_Bool withChilds )
2968 {
2969     if( ! m_xFileRegistry.is() )
2970     {
2971         OSL_ASSERT( m_xFileRegistry.is() );
2972         return;
2973     }
2974 
2975     uno::Sequence< rtl::OUString > seqNames;
2976 
2977     if( withChilds )
2978     {
2979         uno::Reference< container::XNameAccess > xName( m_xFileRegistry,uno::UNO_QUERY );
2980         seqNames = xName->getElementNames();
2981     }
2982 
2983     sal_Int32 count = withChilds ? seqNames.getLength() : 1;
2984 
2985     rtl::OUString
2986         old_Name = srcUnqPath,
2987         new_Name = dstUnqPath;
2988 
2989     for( sal_Int32 j = 0; j < count; ++j )
2990     {
2991         if( withChilds  && ! ( isChild( srcUnqPath,seqNames[j] ) ) )
2992             continue;
2993 
2994         if( withChilds )
2995         {
2996             old_Name = seqNames[j];
2997             new_Name = newName( dstUnqPath,srcUnqPath,old_Name );
2998         }
2999 
3000         uno::Reference< XPersistentPropertySet > x_src;
3001 
3002         if( m_xFileRegistry.is() )
3003         {
3004             x_src = m_xFileRegistry->openPropertySet( old_Name,false );
3005             m_xFileRegistry->removePropertySet( new_Name );
3006         }
3007 
3008         if( x_src.is() )
3009         {
3010             uno::Sequence< beans::Property > seqProperty =
3011                 x_src->getPropertySetInfo()->getProperties();
3012 
3013             if( seqProperty.getLength() )
3014             {
3015                 uno::Reference< XPersistentPropertySet >
3016                     x_dstS = m_xFileRegistry->openPropertySet( new_Name,true );
3017                 uno::Reference< beans::XPropertyContainer >
3018                     x_dstC( x_dstS,uno::UNO_QUERY );
3019 
3020                 for( sal_Int32 i = 0; i < seqProperty.getLength(); ++i )
3021                 {
3022                     x_dstC->addProperty( seqProperty[i].Name,
3023                                          seqProperty[i].Attributes,
3024                                          x_src->getPropertyValue( seqProperty[i].Name ) );
3025                 }
3026             }
3027         }
3028     }         // end for( sal_Int...
3029 }
3030 
queryCreatableContentsInfo()3031 uno::Sequence< ucb::ContentInfo > shell::queryCreatableContentsInfo()
3032 {
3033     uno::Sequence< ucb::ContentInfo > seq(2);
3034 
3035     // file
3036     seq[0].Type       = FileContentType;
3037     seq[0].Attributes = ucb::ContentInfoAttribute::INSERT_WITH_INPUTSTREAM
3038                         | ucb::ContentInfoAttribute::KIND_DOCUMENT;
3039 
3040     uno::Sequence< beans::Property > props( 1 );
3041     props[0] = beans::Property(
3042         rtl::OUString::createFromAscii( "Title" ),
3043         -1,
3044         getCppuType( static_cast< rtl::OUString* >( 0 ) ),
3045         beans::PropertyAttribute::MAYBEVOID
3046         | beans::PropertyAttribute::BOUND );
3047     seq[0].Properties = props;
3048 
3049     // folder
3050     seq[1].Type       = FolderContentType;
3051     seq[1].Attributes = ucb::ContentInfoAttribute::KIND_FOLDER;
3052     seq[1].Properties = props;
3053     return seq;
3054 }
3055 
3056 /*******************************************************************************/
3057 /*                                                                             */
3058 /*                 some miscellaneous static functions                         */
3059 /*                                                                             */
3060 /*******************************************************************************/
3061 
3062 void SAL_CALL
getScheme(rtl::OUString & Scheme)3063 shell::getScheme( rtl::OUString& Scheme )
3064 {
3065   Scheme = rtl::OUString::createFromAscii( "file" );
3066 }
3067 
3068 rtl::OUString SAL_CALL
getImplementationName_static(void)3069 shell::getImplementationName_static( void )
3070 {
3071   return rtl::OUString::createFromAscii( "com.sun.star.comp.ucb.FileProvider" );
3072 }
3073 
3074 
3075 uno::Sequence< rtl::OUString > SAL_CALL
getSupportedServiceNames_static(void)3076 shell::getSupportedServiceNames_static( void )
3077 {
3078   rtl::OUString Supported = rtl::OUString::createFromAscii( "com.sun.star.ucb.FileContentProvider" ) ;
3079   com::sun::star::uno::Sequence< rtl::OUString > Seq( &Supported,1 );
3080   return Seq;
3081 }
3082