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