1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 #include <osl/mutex.hxx>
29 #include <osl/diagnose.h>
30 
31 #include <uno/mapping.hxx>
32 
33 #include <cppuhelper/factory.hxx>
34 #include <cppuhelper/implbase1.hxx>
35 
36 #include <tools/ref.hxx>
37 #include <tools/urlobj.hxx>
38 #include <ucbhelper/content.hxx>
39 #include <unotools/streamwrap.hxx>
40 #include <tools/stream.hxx>
41 
42 #include <com/sun/star/beans/Property.hpp>
43 #include <com/sun/star/beans/XPropertySet.hpp>
44 #include <com/sun/star/container/XChild.hpp>
45 #include <com/sun/star/io/XActiveDataSink.hpp>
46 #include <com/sun/star/io/XActiveDataSource.hpp>
47 #include <com/sun/star/io/XActiveDataStreamer.hpp>
48 #include <com/sun/star/sdbc/XResultSet.hpp>
49 #include <com/sun/star/ucb/CommandFailedException.hpp>
50 #include <com/sun/star/ucb/ContentInfo.hpp>
51 #include <com/sun/star/ucb/ContentInfoAttribute.hpp>
52 #include <com/sun/star/ucb/InsertCommandArgument.hpp>
53 #include <com/sun/star/ucb/InteractiveIOException.hpp>
54 #include <com/sun/star/ucb/NameClash.hpp>
55 #include <com/sun/star/ucb/NameClashException.hpp>
56 #include <com/sun/star/ucb/OpenCommandArgument2.hpp>
57 #include <com/sun/star/ucb/OpenMode.hpp>
58 #include <com/sun/star/ucb/XCommandEnvironment.hpp>
59 #include <com/sun/star/ucb/XContent.hpp>
60 #include <com/sun/star/ucb/XContentAccess.hpp>
61 #include <com/sun/star/ucb/XSimpleFileAccess3.hpp>
62 #include <com/sun/star/util/XMacroExpander.hpp>
63 
64 #define IMPLEMENTATION_NAME "com.sun.star.comp.ucb.SimpleFileAccess"
65 #define SERVICE_NAME "com.sun.star.ucb.SimpleFileAccess"
66 
67 using namespace ::com::sun::star::uno;
68 using namespace ::com::sun::star::lang;
69 using namespace ::com::sun::star::io;
70 using namespace ::com::sun::star::ucb;
71 using namespace ::com::sun::star::sdbc;
72 using namespace ::com::sun::star::task;
73 using namespace ::com::sun::star::util;
74 using namespace ::com::sun::star::beans;
75 using namespace ::com::sun::star::registry;
76 using namespace ::com::sun::star::container;
77 
78 namespace io_FileAccess
79 {
80 
81 
82 //===========================================================================
83 // Implementation XSimpleFileAccess
84 
85 typedef cppu::WeakImplHelper1< XSimpleFileAccess3 > FileAccessHelper;
86 class OCommandEnvironment;
87 
88 class OFileAccess : public FileAccessHelper
89 {
90     Reference< XMultiServiceFactory > mxSMgr;
91     Reference< XCommandEnvironment > mxEnvironment;
92     OCommandEnvironment* mpEnvironment;
93 
94     void transferImpl( const rtl::OUString& rSource, const rtl::OUString& rDest, sal_Bool bMoveData )
95         throw(CommandAbortedException, Exception, RuntimeException);
96     bool createNewFile( const rtl::OUString & rParentURL,
97                         const rtl::OUString & rTitle,
98                         const Reference< XInputStream >& data )
99         throw ( Exception );
100 
101 public:
102     OFileAccess( const Reference< XMultiServiceFactory > & xSMgr )
103         : mxSMgr( xSMgr), mpEnvironment( NULL ) {}
104 
105     // Methods
106     virtual void SAL_CALL copy( const ::rtl::OUString& SourceURL, const ::rtl::OUString& DestURL ) throw(::com::sun::star::ucb::CommandAbortedException, ::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException);
107     virtual void SAL_CALL move( const ::rtl::OUString& SourceURL, const ::rtl::OUString& DestURL ) throw(::com::sun::star::ucb::CommandAbortedException, ::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException);
108     virtual void SAL_CALL kill( const ::rtl::OUString& FileURL ) throw(::com::sun::star::ucb::CommandAbortedException, ::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException);
109     virtual sal_Bool SAL_CALL isFolder( const ::rtl::OUString& FileURL ) throw(::com::sun::star::ucb::CommandAbortedException, ::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException);
110     virtual sal_Bool SAL_CALL isReadOnly( const ::rtl::OUString& FileURL ) throw(::com::sun::star::ucb::CommandAbortedException, ::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException);
111     virtual void SAL_CALL setReadOnly( const ::rtl::OUString& FileURL, sal_Bool bReadOnly ) throw(::com::sun::star::ucb::CommandAbortedException, ::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException);
112     virtual void SAL_CALL createFolder( const ::rtl::OUString& NewFolderURL ) throw(::com::sun::star::ucb::CommandAbortedException, ::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException);
113     virtual sal_Int32 SAL_CALL getSize( const ::rtl::OUString& FileURL ) throw(::com::sun::star::ucb::CommandAbortedException, ::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException);
114     virtual ::rtl::OUString SAL_CALL getContentType( const ::rtl::OUString& FileURL ) throw(::com::sun::star::ucb::CommandAbortedException, ::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException);
115     virtual ::com::sun::star::util::DateTime SAL_CALL getDateTimeModified( const ::rtl::OUString& FileURL ) throw(::com::sun::star::ucb::CommandAbortedException, ::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException);
116     virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getFolderContents( const ::rtl::OUString& FolderURL, sal_Bool bIncludeFolders ) throw(::com::sun::star::ucb::CommandAbortedException, ::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException);
117     virtual sal_Bool SAL_CALL exists( const ::rtl::OUString& FileURL ) throw(::com::sun::star::ucb::CommandAbortedException, ::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException);
118     virtual ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > SAL_CALL openFileRead( const ::rtl::OUString& FileURL ) throw(::com::sun::star::ucb::CommandAbortedException, ::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException);
119     virtual ::com::sun::star::uno::Reference< ::com::sun::star::io::XOutputStream > SAL_CALL openFileWrite( const ::rtl::OUString& FileURL ) throw(::com::sun::star::ucb::CommandAbortedException, ::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException);
120     virtual ::com::sun::star::uno::Reference< ::com::sun::star::io::XStream > SAL_CALL openFileReadWrite( const ::rtl::OUString& FileURL ) throw(::com::sun::star::ucb::CommandAbortedException, ::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException);
121     virtual void SAL_CALL setInteractionHandler( const ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >& Handler ) throw(::com::sun::star::uno::RuntimeException);
122     virtual void SAL_CALL writeFile( const ::rtl::OUString& FileURL, const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >& data ) throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException);
123     virtual sal_Bool SAL_CALL isHidden( const ::rtl::OUString& FileURL ) throw(::com::sun::star::ucb::CommandAbortedException, ::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException);
124     virtual void SAL_CALL setHidden( const ::rtl::OUString& FileURL, sal_Bool bHidden ) throw(::com::sun::star::ucb::CommandAbortedException, ::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException);
125 };
126 
127 
128 //===========================================================================
129 // Implementation XActiveDataSink
130 
131 typedef cppu::WeakImplHelper1< XActiveDataSink > ActiveDataSinkHelper;
132 
133 class OActiveDataSink : public ActiveDataSinkHelper
134 {
135     Reference< XInputStream > mxStream;
136 
137 public:
138 
139     // Methods
140     virtual void SAL_CALL setInputStream( const Reference< XInputStream >& aStream )
141         throw(RuntimeException);
142     virtual Reference< XInputStream > SAL_CALL getInputStream(  )
143         throw(RuntimeException);
144 };
145 
146 void OActiveDataSink::setInputStream( const Reference< XInputStream >& aStream )
147     throw(RuntimeException)
148 {
149     mxStream = aStream;
150 }
151 
152 Reference< XInputStream > OActiveDataSink::getInputStream()
153     throw(RuntimeException)
154 {
155     return mxStream;
156 }
157 
158 
159 //===========================================================================
160 // Implementation XActiveDataSource
161 
162 typedef cppu::WeakImplHelper1< XActiveDataSource > ActiveDataSourceHelper;
163 
164 class OActiveDataSource : public ActiveDataSourceHelper
165 {
166     Reference< XOutputStream > mxStream;
167 
168 public:
169 
170     // Methods
171     virtual void SAL_CALL setOutputStream( const Reference< XOutputStream >& aStream )
172         throw(RuntimeException);
173     virtual Reference< XOutputStream > SAL_CALL getOutputStream()
174         throw(RuntimeException);
175 };
176 
177 void OActiveDataSource::setOutputStream( const Reference< XOutputStream >& aStream )
178     throw(RuntimeException)
179 {
180     mxStream = aStream;
181 }
182 
183 Reference< XOutputStream > OActiveDataSource::getOutputStream()
184     throw(RuntimeException)
185 {
186     return mxStream;
187 }
188 
189 
190 //===========================================================================
191 // Implementation XActiveDataStreamer
192 
193 typedef cppu::WeakImplHelper1< XActiveDataStreamer > ActiveDataStreamerHelper;
194 
195 class OActiveDataStreamer : public ActiveDataStreamerHelper
196 {
197     Reference< XStream > mxStream;
198 
199 public:
200 
201     // Methods
202     virtual void SAL_CALL setStream( const Reference< XStream >& aStream )
203         throw(RuntimeException);
204     virtual Reference< XStream > SAL_CALL getStream()
205         throw(RuntimeException);
206 };
207 
208 void OActiveDataStreamer::setStream( const Reference< XStream >& aStream )
209     throw(RuntimeException)
210 {
211     mxStream = aStream;
212 }
213 
214 Reference< XStream > OActiveDataStreamer::getStream()
215     throw(RuntimeException)
216 {
217     return mxStream;
218 }
219 
220 
221 
222 //===========================================================================
223 // Implementation XCommandEnvironment
224 
225 typedef cppu::WeakImplHelper1< XCommandEnvironment > CommandEnvironmentHelper;
226 
227 class OCommandEnvironment : public CommandEnvironmentHelper
228 {
229     Reference< XInteractionHandler > mxInteraction;
230 
231 public:
232     void setHandler( Reference< XInteractionHandler > xInteraction_ )
233     {
234         mxInteraction = xInteraction_;
235     }
236 
237     // Methods
238     virtual Reference< XInteractionHandler > SAL_CALL getInteractionHandler()
239         throw(RuntimeException);
240     virtual Reference< XProgressHandler > SAL_CALL getProgressHandler()
241         throw(RuntimeException);
242 };
243 
244 Reference< XInteractionHandler > OCommandEnvironment::getInteractionHandler()
245     throw(RuntimeException)
246 {
247     return mxInteraction;
248 }
249 
250 Reference< XProgressHandler > OCommandEnvironment::getProgressHandler()
251     throw(RuntimeException)
252 {
253     Reference< XProgressHandler > xRet;
254     return xRet;
255 }
256 
257 //===========================================================================
258 
259 void OFileAccess::transferImpl( const rtl::OUString& rSource,
260                                 const rtl::OUString& rDest,
261                                 sal_Bool bMoveData )
262     throw(CommandAbortedException, Exception, RuntimeException)
263 {
264     // SfxContentHelper::Transfer_Impl
265     INetURLObject aSourceObj( rSource, INET_PROT_FILE );
266     INetURLObject aDestObj( rDest, INET_PROT_FILE );
267     String aName = aDestObj.getName(
268         INetURLObject::LAST_SEGMENT, true, INetURLObject::DECODE_WITH_CHARSET );
269     String aDestURL;
270     String aSourceURL = aSourceObj.GetMainURL( INetURLObject::NO_DECODE );
271     if ( aDestObj.removeSegment() )
272     {
273         // hierarchical URL.
274 
275         aDestObj.setFinalSlash();
276         aDestURL = aDestObj.GetMainURL( INetURLObject::NO_DECODE );
277     }
278     else
279     {
280         // non-hierachical URL
281 
282         // #i29648#
283         //
284 #if 0
285         // Note: A hierachical UCB content implements interface XChild, which
286         // has a method getParent(). Unfortunately this does not always help
287         // here, because it is not guaranteed that a content object for a
288         // non-existing resource can be created. Thus, it will happen that an
289         // exception is thrown when trying to create a UCB content for the
290         // destination URL.
291 
292         try
293         {
294             ucbhelper::Content aFullDest(
295                 aDestObj.GetMainURL(
296                     INetURLObject::NO_DECODE ), mxEnvironment );
297 
298             Reference< XChild > xChild( aFullDest.get(), UNO_QUERY_THROW );
299             Reference< com::sun::star::ucb::XContent >
300                 xParent( xChild->getParent(), UNO_QUERY_THROW );
301             ucbhelper::Content aParent( xParent, mxEnvironment );
302 
303             aDestURL = aParent.getURL();
304 
305             rtl::OUString aNameTmp;
306             aFullDest.getPropertyValue(
307                 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Title" ) ) )
308                     >>= aNameTmp;
309             aName = aNameTmp;
310         }
311         catch ( Exception const & )
312         {
313             throw RuntimeException(
314                 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
315                                    "OFileAccess::transferrImpl - Unable to "
316                                    "obtain destination folder URL!" ) ),
317                 static_cast< cppu::OWeakObject * >( this ) );
318         }
319 #else
320         if ( aDestObj.GetProtocol() == INET_PROT_VND_SUN_STAR_EXPAND )
321         {
322             // Hack: Expand destination URL using Macro Expander and try again
323             //       with the hopefully hierarchical expanded URL...
324 
325             try
326             {
327                 Reference< XComponentContext > xCtx;
328                 Reference< XPropertySet > xPropSet( mxSMgr, UNO_QUERY_THROW );
329                 if ( xPropSet.is() )
330                 {
331                     xPropSet->getPropertyValue(
332                         rtl::OUString(
333                             RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" ) ) )
334                                 >>= xCtx;
335                 }
336 
337                 Reference< XMacroExpander > xExpander;
338 
339                 xCtx->getValueByName(
340                     rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
341                         "/singletons/com.sun.star.util.theMacroExpander" ) ) )
342                             >>= xExpander;
343 
344                 OSL_ENSURE( xExpander.is(),
345                             "Unable to obtain macro expander singleton!" );
346 
347                 aDestURL = xExpander->expandMacros(
348                     aDestObj.GetURLPath( INetURLObject::DECODE_WITH_CHARSET ) );
349             }
350             catch ( Exception const & )
351             {
352                 throw RuntimeException(
353                     rtl::OUString(
354                         RTL_CONSTASCII_USTRINGPARAM(
355                             "OFileAccess::transferrImpl - Unable to obtain "
356                             "destination folder URL!" ) ),
357                     static_cast< cppu::OWeakObject * >( this ) );
358             }
359 
360             transferImpl( rSource, aDestURL, bMoveData );
361             return;
362         }
363 
364         throw RuntimeException(
365             rtl::OUString(
366                 RTL_CONSTASCII_USTRINGPARAM(
367                     "OFileAccess::transferrImpl - Unable to obtain "
368                     "destination folder URL!" ) ),
369                 static_cast< cppu::OWeakObject * >( this ) );
370 #endif
371     }
372 
373     ucbhelper::Content aDestPath( aDestURL,   mxEnvironment );
374     ucbhelper::Content aSrc     ( aSourceURL, mxEnvironment );
375 
376     try
377     {
378         aDestPath.transferContent( aSrc,
379                                    bMoveData
380                                     ? ucbhelper::InsertOperation_MOVE
381                                     : ucbhelper::InsertOperation_COPY,
382                                    aName,
383                                    ::com::sun::star::ucb::NameClash::OVERWRITE );
384     }
385     catch ( ::com::sun::star::ucb::CommandFailedException const & )
386     {
387         // Interaction Handler already handled the error that has occured...
388     }
389 }
390 
391 void OFileAccess::copy( const rtl::OUString& SourceURL, const rtl::OUString& DestURL )
392     throw(CommandAbortedException, Exception, RuntimeException)
393 {
394     transferImpl( SourceURL, DestURL, sal_False );
395 }
396 
397 void OFileAccess::move( const rtl::OUString& SourceURL, const rtl::OUString& DestURL )
398     throw(CommandAbortedException, Exception, RuntimeException)
399 {
400     transferImpl( SourceURL, DestURL, sal_True );
401 }
402 
403 void OFileAccess::kill( const rtl::OUString& FileURL )
404     throw(CommandAbortedException, Exception, RuntimeException)
405 {
406     // SfxContentHelper::Kill
407     INetURLObject aDeleteObj( FileURL, INET_PROT_FILE );
408     ucbhelper::Content aCnt( aDeleteObj.GetMainURL( INetURLObject::NO_DECODE ), mxEnvironment );
409     try
410     {
411         aCnt.executeCommand( rtl::OUString::createFromAscii( "delete" ), makeAny( sal_Bool( sal_True ) ) );
412     }
413     catch ( ::com::sun::star::ucb::CommandFailedException const & )
414     {
415         // Interaction Handler already handled the error that has occured...
416     }
417 }
418 
419 sal_Bool OFileAccess::isFolder( const rtl::OUString& FileURL )
420     throw(CommandAbortedException, Exception, RuntimeException)
421 {
422     sal_Bool bRet = sal_False;
423     try
424     {
425         INetURLObject aURLObj( FileURL, INET_PROT_FILE );
426         ucbhelper::Content aCnt( aURLObj.GetMainURL( INetURLObject::NO_DECODE ), mxEnvironment );
427         bRet = aCnt.isFolder();
428     }
429     catch (Exception &) {}
430     return bRet;
431 }
432 
433 sal_Bool OFileAccess::isReadOnly( const rtl::OUString& FileURL )
434     throw(CommandAbortedException, Exception, RuntimeException)
435 {
436     INetURLObject aURLObj( FileURL, INET_PROT_FILE );
437     ucbhelper::Content aCnt( aURLObj.GetMainURL( INetURLObject::NO_DECODE ), mxEnvironment );
438     Any aRetAny = aCnt.getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsReadOnly" ) ) );
439     sal_Bool bRet = sal_False;
440     aRetAny >>= bRet;
441     return bRet;
442 }
443 
444 void OFileAccess::setReadOnly( const rtl::OUString& FileURL, sal_Bool bReadOnly )
445     throw(CommandAbortedException, Exception, RuntimeException)
446 {
447     INetURLObject aURLObj( FileURL, INET_PROT_FILE );
448     ucbhelper::Content aCnt( aURLObj.GetMainURL( INetURLObject::NO_DECODE ), mxEnvironment );
449     Any aAny;
450     aAny <<= bReadOnly;
451     aCnt.setPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsReadOnly" ) ), aAny );
452 }
453 
454 void OFileAccess::createFolder( const rtl::OUString& NewFolderURL )
455     throw(CommandAbortedException, Exception, RuntimeException)
456 {
457     // Does the folder already exist?
458     if( !NewFolderURL.getLength() || isFolder( NewFolderURL ) )
459         return;
460 
461     // SfxContentHelper::MakeFolder
462     INetURLObject aURL( NewFolderURL, INET_PROT_FILE );
463     String aNewFolderURLStr = aURL.GetMainURL( INetURLObject::NO_DECODE );
464     String aTitle = aURL.getName( INetURLObject::LAST_SEGMENT, true, INetURLObject::DECODE_WITH_CHARSET );
465     if ( aTitle.Len() )
466     {
467         aURL.removeSegment();
468 
469         // Does the base folder exist? Otherwise create it first
470         String aBaseFolderURLStr = aURL.GetMainURL( INetURLObject::NO_DECODE );
471         if( !isFolder( aBaseFolderURLStr ) )
472         {
473             createFolder( aBaseFolderURLStr );
474         }
475     }
476 
477     ucbhelper::Content aCnt( aURL.GetMainURL( INetURLObject::NO_DECODE ), mxEnvironment );
478 
479     Sequence< ContentInfo > aInfo = aCnt.queryCreatableContentsInfo();
480     sal_Int32 nCount = aInfo.getLength();
481     if ( nCount == 0 )
482         return;
483 
484     for ( sal_Int32 i = 0; i < nCount; ++i )
485     {
486         // Simply look for the first KIND_FOLDER...
487         const ContentInfo & rCurr = aInfo[i];
488         if ( rCurr.Attributes & ContentInfoAttribute::KIND_FOLDER )
489         {
490             // Make sure the only required bootstrap property is "Title",
491             const Sequence< Property > & rProps = rCurr.Properties;
492             if ( rProps.getLength() != 1 )
493                 continue;
494 
495             if ( !rProps[ 0 ].Name.equalsAsciiL(
496                     RTL_CONSTASCII_STRINGPARAM( "Title" ) ) )
497                 continue;
498 
499             Sequence<rtl::OUString> aNames(1);
500             rtl::OUString* pNames = aNames.getArray();
501             pNames[0] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Title" ) );
502             Sequence< Any > aValues(1);
503             Any* pValues = aValues.getArray();
504             pValues[0] = makeAny( rtl::OUString( aTitle ) );
505 
506             ucbhelper::Content aNew;
507             try
508             {
509                 if ( !aCnt.insertNewContent( rCurr.Type, aNames, aValues, aNew ) )
510                     continue;
511 
512                 // Success. We're done.
513                 return;
514             }
515             catch ( ::com::sun::star::ucb::CommandFailedException const & )
516             {
517                 // Interaction Handler already handled the error that has occured...
518                 continue;
519             }
520         }
521     }
522 }
523 
524 sal_Int32 OFileAccess::getSize( const rtl::OUString& FileURL )
525     throw(CommandAbortedException, Exception, RuntimeException)
526 {
527     // SfxContentHelper::GetSize
528     sal_Int32 nSize = 0;
529     sal_Int64 nTemp = 0;
530     INetURLObject aObj( FileURL, INET_PROT_FILE );
531     ucbhelper::Content aCnt( aObj.GetMainURL( INetURLObject::NO_DECODE ), mxEnvironment );
532     aCnt.getPropertyValue( rtl::OUString::createFromAscii( "Size" ) ) >>= nTemp;
533     nSize = (sal_Int32)nTemp;
534     return nSize;
535 }
536 
537 rtl::OUString OFileAccess::getContentType( const rtl::OUString& FileURL )
538     throw(CommandAbortedException, Exception, RuntimeException)
539 {
540     INetURLObject aObj( FileURL, INET_PROT_FILE );
541     ucbhelper::Content aCnt( aObj.GetMainURL( INetURLObject::NO_DECODE ), mxEnvironment );
542 
543     Reference< XContent > xContent = aCnt.get();
544     rtl::OUString aTypeStr = xContent->getContentType();
545     return aTypeStr;
546 }
547 
548 DateTime OFileAccess::getDateTimeModified( const rtl::OUString& FileURL )
549     throw(CommandAbortedException, Exception, RuntimeException)
550 {
551     INetURLObject aFileObj( FileURL, INET_PROT_FILE );
552     DateTime aDateTime;
553 
554     Reference< XCommandEnvironment > aCmdEnv;
555     ucbhelper::Content aYoung( aFileObj.GetMainURL( INetURLObject::NO_DECODE ), aCmdEnv );
556     aYoung.getPropertyValue( rtl::OUString::createFromAscii( "DateModified" ) ) >>= aDateTime;
557     return aDateTime;
558 }
559 
560 
561 DECLARE_LIST( StringList_Impl, rtl::OUString* )
562 
563 Sequence< rtl::OUString > OFileAccess::getFolderContents( const rtl::OUString& FolderURL, sal_Bool bIncludeFolders )
564     throw(CommandAbortedException, Exception, RuntimeException)
565 {
566     // SfxContentHelper::GetFolderContents
567 
568     StringList_Impl* pFiles = NULL;
569     INetURLObject aFolderObj( FolderURL, INET_PROT_FILE );
570 
571     ucbhelper::Content aCnt( aFolderObj.GetMainURL( INetURLObject::NO_DECODE ), mxEnvironment );
572     Reference< XResultSet > xResultSet;
573     Sequence< rtl::OUString > aProps(0);
574     //Sequence< rtl::OUString > aProps(1);
575     //rtl::OUString* pProps = aProps.getArray();
576     //pProps[0] == rtl::OUString::createFromAscii( "Url" );
577 
578     ucbhelper::ResultSetInclude eInclude = bIncludeFolders ? ucbhelper::INCLUDE_FOLDERS_AND_DOCUMENTS : ucbhelper::INCLUDE_DOCUMENTS_ONLY;
579 
580     try
581     {
582         xResultSet = aCnt.createCursor( aProps, eInclude );
583     }
584     catch ( ::com::sun::star::ucb::CommandFailedException const & )
585     {
586         // Interaction Handler already handled the error that has occured...
587     }
588 
589     if ( xResultSet.is() )
590     {
591         pFiles = new StringList_Impl;
592         Reference< com::sun::star::ucb::XContentAccess > xContentAccess( xResultSet, UNO_QUERY );
593 
594         while ( xResultSet->next() )
595         {
596             rtl::OUString aId = xContentAccess->queryContentIdentifierString();
597             INetURLObject aURL( aId, INET_PROT_FILE );
598             rtl::OUString* pFile = new rtl::OUString( aURL.GetMainURL( INetURLObject::NO_DECODE ) );
599             pFiles->Insert( pFile, LIST_APPEND );
600         }
601     }
602 
603     if ( pFiles )
604     {
605         sal_uIntPtr nCount = pFiles->Count();
606         Sequence < rtl::OUString > aRet( nCount );
607         rtl::OUString* pRet = aRet.getArray();
608         for ( sal_uInt16 i = 0; i < nCount; ++i )
609         {
610             rtl::OUString* pFile = pFiles->GetObject(i);
611             pRet[i] = *( pFile );
612             delete pFile;
613         }
614         delete pFiles;
615         return aRet;
616     }
617     else
618         return Sequence < rtl::OUString > ();
619 }
620 
621 sal_Bool OFileAccess::exists( const rtl::OUString& FileURL )
622     throw(CommandAbortedException, Exception, RuntimeException)
623 {
624     sal_Bool bRet = sal_False;
625     try
626     {
627         bRet = isFolder( FileURL );
628         if( !bRet )
629         {
630             Reference< XInputStream > xStream = openFileRead( FileURL );
631             bRet = xStream.is();
632             if( bRet )
633                 xStream->closeInput();
634         }
635     }
636     catch (Exception &) {}
637     return bRet;
638 }
639 
640 Reference< XInputStream > OFileAccess::openFileRead( const rtl::OUString& FileURL )
641     throw(CommandAbortedException, Exception, RuntimeException)
642 {
643     Reference< XInputStream > xRet;
644     INetURLObject aObj( FileURL, INET_PROT_FILE );
645     ucbhelper::Content aCnt( aObj.GetMainURL( INetURLObject::NO_DECODE ), mxEnvironment );
646 
647     Reference< XActiveDataSink > xSink = (XActiveDataSink*)(new OActiveDataSink());
648 
649     try
650     {
651         sal_Bool bRet = aCnt.openStream( xSink );
652         if( bRet )
653             xRet = xSink->getInputStream();
654     }
655     catch ( ::com::sun::star::ucb::CommandFailedException const & )
656     {
657         // Interaction Handler already handled the error that has occured...
658     }
659 
660     return xRet;
661 }
662 
663 Reference< XOutputStream > OFileAccess::openFileWrite( const rtl::OUString& FileURL )
664     throw(CommandAbortedException, Exception, RuntimeException)
665 {
666     Reference< XOutputStream > xRet;
667     Reference< XStream > xStream = OFileAccess::openFileReadWrite( FileURL );
668     if( xStream.is() )
669         xRet = xStream->getOutputStream();
670     return xRet;
671 }
672 
673 Reference< XStream > OFileAccess::openFileReadWrite( const rtl::OUString& FileURL )
674     throw(CommandAbortedException, Exception, RuntimeException)
675 {
676     Reference< XActiveDataStreamer > xSink = (XActiveDataStreamer*)new OActiveDataStreamer();
677     Reference< XInterface > xSinkIface = Reference< XInterface >::query( xSink );
678 
679     OpenCommandArgument2 aArg;
680     aArg.Mode       = OpenMode::DOCUMENT;
681     aArg.Priority   = 0; // unused
682     aArg.Sink       = xSink;
683     aArg.Properties = Sequence< Property >( 0 ); // unused
684 
685     Any aCmdArg;
686     aCmdArg <<= aArg;
687 
688     INetURLObject aFileObj( FileURL, INET_PROT_FILE );
689     ucbhelper::Content aCnt( aFileObj.GetMainURL( INetURLObject::NO_DECODE ), mxEnvironment );
690 
691     // Be silent...
692     Reference< XInteractionHandler > xIH;
693     if ( mpEnvironment )
694     {
695         xIH = mpEnvironment->getInteractionHandler();
696         mpEnvironment->setHandler( 0 );
697     }
698 
699     try
700     {
701         aCnt.executeCommand( rtl::OUString::createFromAscii( "open" ), aCmdArg );
702     }
703     catch ( InteractiveIOException const & e )
704     {
705         if ( xIH.is() )
706             mpEnvironment->setHandler( xIH );
707 
708         if ( e.Code == IOErrorCode_NOT_EXISTING )
709         {
710             // Create file...
711             SvMemoryStream aStream(0,0);
712             ::utl::OInputStreamWrapper* pInput = new ::utl::OInputStreamWrapper( aStream );
713             Reference< XInputStream > xInput( pInput );
714             InsertCommandArgument aInsertArg;
715             aInsertArg.Data = xInput;
716             aInsertArg.ReplaceExisting = sal_False;
717 
718             aCmdArg <<= aInsertArg;
719             aCnt.executeCommand( rtl::OUString::createFromAscii( "insert" ), aCmdArg );
720 
721             // Retry...
722             return openFileReadWrite( FileURL );
723         }
724 
725         throw;
726     }
727 
728     if ( xIH.is() )
729         mpEnvironment->setHandler( xIH );
730 
731     Reference< XStream > xRet = xSink->getStream();
732     return xRet;
733 }
734 
735 void OFileAccess::setInteractionHandler( const Reference< XInteractionHandler >& Handler )
736     throw(RuntimeException)
737 {
738     if( !mpEnvironment )
739     {
740         mpEnvironment = new OCommandEnvironment();
741         mxEnvironment = (XCommandEnvironment*)mpEnvironment;
742     }
743     mpEnvironment->setHandler( Handler );
744 }
745 
746 bool OFileAccess::createNewFile( const rtl::OUString & rParentURL,
747                                  const rtl::OUString & rTitle,
748                                  const Reference< XInputStream >& data )
749     throw ( Exception )
750 {
751     ucbhelper::Content aParentCnt( rParentURL, mxEnvironment );
752 
753     Sequence< ContentInfo > aInfo = aParentCnt.queryCreatableContentsInfo();
754     sal_Int32 nCount = aInfo.getLength();
755     if ( nCount == 0 )
756         return false;
757 
758     for ( sal_Int32 i = 0; i < nCount; ++i )
759     {
760         const ContentInfo & rCurr = aInfo[i];
761         if ( ( rCurr.Attributes
762                & ContentInfoAttribute::KIND_DOCUMENT ) &&
763              ( rCurr.Attributes
764                & ContentInfoAttribute::INSERT_WITH_INPUTSTREAM ) )
765         {
766             // Make sure the only required bootstrap property is
767             // "Title",
768             const Sequence< Property > & rProps = rCurr.Properties;
769             if ( rProps.getLength() != 1 )
770                 continue;
771 
772             if ( !rProps[ 0 ].Name.equalsAsciiL(
773                      RTL_CONSTASCII_STRINGPARAM( "Title" ) ) )
774                 continue;
775 
776             Sequence<rtl::OUString> aNames(1);
777             rtl::OUString* pNames = aNames.getArray();
778             pNames[0] = rtl::OUString(
779                             RTL_CONSTASCII_USTRINGPARAM( "Title" ) );
780             Sequence< Any > aValues(1);
781             Any* pValues = aValues.getArray();
782             pValues[0] = makeAny( rtl::OUString( rTitle ) );
783 
784             try
785             {
786                 ucbhelper::Content aNew;
787                 if ( aParentCnt.insertNewContent(
788                          rCurr.Type, aNames, aValues, data, aNew ) )
789                     return true; // success.
790                 else
791                     continue;
792             }
793             catch ( CommandFailedException const & )
794             {
795                 // Interaction Handler already handled the
796                 // error that has occured...
797                 continue;
798             }
799         }
800     }
801 
802     return false;
803 }
804 
805 void SAL_CALL OFileAccess::writeFile( const rtl::OUString& FileURL,
806                                       const Reference< XInputStream >& data )
807     throw ( Exception, RuntimeException )
808 {
809     INetURLObject aURL( FileURL, INET_PROT_FILE );
810     try
811     {
812         ucbhelper::Content aCnt(
813             aURL.GetMainURL( INetURLObject::NO_DECODE ), mxEnvironment );
814 
815         try
816         {
817             aCnt.writeStream( data, sal_True /* bReplaceExisting */ );
818         }
819         catch ( CommandFailedException const & )
820         {
821             // Interaction Handler already handled the error that has occured...
822         }
823     }
824     catch ( ContentCreationException const & e )
825     {
826         // Most probably file does not exist. Try to create.
827         if ( e.eError == ContentCreationError_CONTENT_CREATION_FAILED )
828         {
829             INetURLObject aParentURLObj( aURL );
830             if ( aParentURLObj.removeSegment() )
831             {
832                 String aParentURL
833                     = aParentURLObj.GetMainURL( INetURLObject::NO_DECODE );
834 
835                 // ensure all parent folders exist.
836                 createFolder( aParentURL );
837 
838                 // create the new file...
839                 String aTitle
840                     = aURL.getName( INetURLObject::LAST_SEGMENT,
841                                     true,
842                                     INetURLObject::DECODE_WITH_CHARSET );
843                 if ( createNewFile( aParentURL, aTitle, data ) )
844                 {
845                     // success
846                     return;
847                 }
848             }
849         }
850 
851         throw;
852     }
853 }
854 
855 sal_Bool OFileAccess::isHidden( const ::rtl::OUString& FileURL )
856     throw(CommandAbortedException, Exception, RuntimeException)
857 {
858     INetURLObject aURLObj( FileURL, INET_PROT_FILE );
859     ucbhelper::Content aCnt( aURLObj.GetMainURL( INetURLObject::NO_DECODE ), mxEnvironment );
860     Any aRetAny = aCnt.getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsHidden" ) ) );
861     sal_Bool bRet = sal_False;
862     aRetAny >>= bRet;
863     return bRet;
864 }
865 
866 void OFileAccess::setHidden( const ::rtl::OUString& FileURL, sal_Bool bHidden )
867     throw(CommandAbortedException, Exception, RuntimeException)
868 {
869     INetURLObject aURLObj( FileURL, INET_PROT_FILE );
870     ucbhelper::Content aCnt( aURLObj.GetMainURL( INetURLObject::NO_DECODE ), mxEnvironment );
871     Any aAny;
872     aAny <<= bHidden;
873     aCnt.setPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsHidden" ) ), aAny );
874 }
875 
876 //==================================================================================================
877 //==================================================================================================
878 //==================================================================================================
879 
880 Reference< XInterface > SAL_CALL FileAccess_CreateInstance( const Reference< XMultiServiceFactory > & xSMgr )
881 {
882     return Reference < XInterface >( ( cppu::OWeakObject * ) new OFileAccess( xSMgr ) );
883 }
884 
885 
886 Sequence< rtl::OUString > FileAccess_getSupportedServiceNames()
887 {
888     static Sequence < rtl::OUString > *pNames = 0;
889     if( ! pNames )
890     {
891         osl::MutexGuard guard( osl::Mutex::getGlobalMutex() );
892         if( !pNames )
893         {
894             static Sequence< rtl::OUString > seqNames(1);
895             seqNames.getArray()[0] = rtl::OUString::createFromAscii( SERVICE_NAME );
896             pNames = &seqNames;
897         }
898     }
899     return *pNames;
900 }
901 
902 
903 }
904 
905 //==================================================================================================
906 // Component exports
907 
908 extern "C"
909 {
910 //==================================================================================================
911 void SAL_CALL component_getImplementationEnvironment(
912     const sal_Char ** ppEnvTypeName, uno_Environment ** /*ppEnv*/ )
913 {
914     *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME;
915 }
916 //==================================================================================================
917 void * SAL_CALL component_getFactory(
918     const sal_Char * pImplName, void * pServiceManager, void * /*pRegistryKey*/ )
919 {
920     void * pRet = 0;
921 
922     if (pServiceManager && rtl_str_compare( pImplName, IMPLEMENTATION_NAME ) == 0)
923     {
924         Reference< XSingleServiceFactory > xFactory( cppu::createSingleFactory(
925             reinterpret_cast< XMultiServiceFactory * >( pServiceManager ),
926             rtl::OUString::createFromAscii( pImplName ),
927             io_FileAccess::FileAccess_CreateInstance,
928             io_FileAccess::FileAccess_getSupportedServiceNames() ) );
929 
930         if (xFactory.is())
931         {
932             xFactory->acquire();
933             pRet = xFactory.get();
934         }
935     }
936 
937     return pRet;
938 }
939 }
940 
941 
942