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