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