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