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