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