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