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_unotools.hxx"
26 
27 #include "unotools/ucbhelper.hxx"
28 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
29 #include <com/sun/star/sdbc/XResultSet.hpp>
30 #include <com/sun/star/sdbc/XRow.hpp>
31 #include <com/sun/star/ucb/XContentIdentifierFactory.hpp>
32 #include <com/sun/star/ucb/XCommandProcessor.hpp>
33 #include <com/sun/star/ucb/CommandAbortedException.hpp>
34 #include <com/sun/star/ucb/IllegalIdentifierException.hpp>
35 #include <com/sun/star/ucb/NameClashException.hpp>
36 #include <com/sun/star/ucb/NameClash.hpp>
37 #include <com/sun/star/ucb/NumberedSortingInfo.hpp>
38 #include <com/sun/star/ucb/TransferInfo.hpp>
39 #include <com/sun/star/ucb/XAnyCompareFactory.hpp>
40 #include <com/sun/star/ucb/XCommandInfo.hpp>
41 #include <com/sun/star/ucb/XContentAccess.hpp>
42 #include <com/sun/star/ucb/ContentInfo.hpp>
43 #include <com/sun/star/ucb/ContentInfoAttribute.hpp>
44 #include <com/sun/star/ucb/XDynamicResultSet.hpp>
45 #include <com/sun/star/ucb/XSortedDynamicResultSetFactory.hpp>
46 #include <com/sun/star/util/DateTime.hpp>
47 #include <com/sun/star/container/XChild.hpp>
48 #include <com/sun/star/ucb/InteractiveIOException.hpp>
49 #include <com/sun/star/task/XInteractionHandler.hpp>
50 #include <ucbhelper/commandenvironment.hxx>
51 #include <ucbhelper/content.hxx>
52 #include <comphelper/processfactory.hxx>
53 #include <osl/file.hxx>
54 
55 #include <tools/wldcrd.hxx>
56 #include <tools/ref.hxx>
57 #include <tools/debug.hxx>
58 #include <tools/urlobj.hxx>
59 #include <tools/datetime.hxx>
60 #include <ucbhelper/contentbroker.hxx>
61 
62 #include "unotools/localfilehelper.hxx"
63 
64 using namespace ucbhelper;
65 using namespace com::sun::star;
66 using namespace com::sun::star::beans;
67 using namespace com::sun::star::container;
68 using namespace com::sun::star::lang;
69 using namespace com::sun::star::sdbc;
70 using namespace com::sun::star::task;
71 using namespace com::sun::star::uno;
72 using namespace com::sun::star::ucb;
73 using namespace rtl;
74 using namespace comphelper;
75 using namespace osl;
76 
77 DECLARE_LIST( StringList_Impl, OUString* )
78 
79 #define CONVERT_DATETIME( aUnoDT, aToolsDT ) \
80     aToolsDT = DateTime( Date( aUnoDT.Day, aUnoDT.Month, aUnoDT.Year ), \
81                          Time( aUnoDT.Hours, aUnoDT.Minutes, aUnoDT.Seconds, aUnoDT.HundredthSeconds ) );
82 
83 namespace utl
84 {
85 
Transfer_Impl(const String & rSource,const String & rDest,sal_Bool bMoveData,sal_Int32 nNameClash)86 sal_Bool UCBContentHelper::Transfer_Impl( const String& rSource, const String& rDest, sal_Bool bMoveData, sal_Int32 nNameClash )
87 {
88     sal_Bool bRet = sal_True, bKillSource = sal_False;
89     INetURLObject aSourceObj( rSource );
90     DBG_ASSERT( aSourceObj.GetProtocol() != INET_PROT_NOT_VALID, "Invalid URL!" );
91 
92     INetURLObject aDestObj( rDest );
93     DBG_ASSERT( aDestObj.GetProtocol() != INET_PROT_NOT_VALID, "Invalid URL!" );
94     if ( bMoveData && aSourceObj.GetProtocol() != aDestObj.GetProtocol() )
95     {
96         bMoveData = sal_False;
97         bKillSource = sal_True;
98     }
99     String aName = aDestObj.getName();
100     aDestObj.removeSegment();
101     aDestObj.setFinalSlash();
102 
103     try
104     {
105         Content aDestPath( aDestObj.GetMainURL( INetURLObject::NO_DECODE ), uno::Reference< ::com::sun::star::ucb::XCommandEnvironment > () );
106         uno::Reference< ::com::sun::star::ucb::XCommandInfo > xInfo = aDestPath.getCommands();
107         OUString aTransferName = OUString::createFromAscii( "transfer" );
108         if ( xInfo->hasCommandByName( aTransferName ) )
109         {
110             aDestPath.executeCommand( aTransferName, makeAny(
111                 ::com::sun::star::ucb::TransferInfo( bMoveData, aSourceObj.GetMainURL( INetURLObject::NO_DECODE ), aName, nNameClash ) ) );
112         }
113         else
114         {
115             DBG_ERRORFILE( "transfer command not available" );
116         }
117     }
118     catch( ::com::sun::star::ucb::CommandAbortedException& )
119     {
120         bRet = sal_False;
121     }
122     catch( ::com::sun::star::uno::Exception& )
123     {
124         bRet = sal_False;
125     }
126 
127     if ( bKillSource )
128         UCBContentHelper::Kill( rSource );
129 
130     return bRet;
131 }
132 
133 // -----------------------------------------------------------------------
134 
IsDocument(const String & rContent)135 sal_Bool UCBContentHelper::IsDocument( const String& rContent )
136 {
137     sal_Bool bRet = sal_False;
138     INetURLObject aObj( rContent );
139     DBG_ASSERT( aObj.GetProtocol() != INET_PROT_NOT_VALID, "Invalid URL!" );
140 
141     try
142     {
143         Content aCnt( aObj.GetMainURL( INetURLObject::NO_DECODE ), uno::Reference< ::com::sun::star::ucb::XCommandEnvironment > () );
144         bRet = aCnt.isDocument();
145     }
146     catch( ::com::sun::star::ucb::CommandAbortedException& )
147     {
148         DBG_WARNING( "CommandAbortedException" );
149     }
150     catch( ::com::sun::star::ucb::IllegalIdentifierException& )
151     {
152         DBG_WARNING( "IllegalIdentifierException" );
153     }
154     catch( ContentCreationException& )
155     {
156         DBG_WARNING( "IllegalIdentifierException" );
157     }
158     catch( ::com::sun::star::uno::Exception& )
159     {
160         DBG_WARNING( "Any other exception" );
161     }
162 
163     return bRet;
164 }
165 
166 // -----------------------------------------------------------------------
167 
GetProperty(const String & rContent,const::rtl::OUString & rName)168 Any UCBContentHelper::GetProperty( const String& rContent, const ::rtl::OUString& rName )
169 {
170     INetURLObject aObj( rContent );
171     DBG_ASSERT( aObj.GetProtocol() != INET_PROT_NOT_VALID, "Invalid URL!" );
172     try
173     {
174         Content aCnt( aObj.GetMainURL( INetURLObject::NO_DECODE ), uno::Reference< ::com::sun::star::ucb::XCommandEnvironment > () );
175         return aCnt.getPropertyValue( rName );
176     }
177     catch( ::com::sun::star::ucb::CommandAbortedException& )
178     {
179         DBG_WARNING( "CommandAbortedException" );
180     }
181     catch( ::com::sun::star::ucb::IllegalIdentifierException& )
182     {
183         DBG_WARNING( "IllegalIdentifierException" );
184     }
185     catch( ContentCreationException& )
186     {
187         DBG_WARNING( "IllegalIdentifierException" );
188     }
189     catch( ::com::sun::star::uno::Exception& )
190     {
191         DBG_WARNING( "Any other exception" );
192     }
193 
194     return Any();
195 }
196 
IsFolder(const String & rContent)197 sal_Bool UCBContentHelper::IsFolder( const String& rContent )
198 {
199     sal_Bool bRet = sal_False;
200     INetURLObject aObj( rContent );
201     DBG_ASSERT( aObj.GetProtocol() != INET_PROT_NOT_VALID, "Invalid URL!" );
202     try
203     {
204         Content aCnt( aObj.GetMainURL( INetURLObject::NO_DECODE ), uno::Reference< ::com::sun::star::ucb::XCommandEnvironment > () );
205         bRet = aCnt.isFolder();
206     }
207     catch( ::com::sun::star::ucb::CommandAbortedException& )
208     {
209         DBG_WARNING( "CommandAbortedException" );
210     }
211     catch( ::com::sun::star::ucb::IllegalIdentifierException& )
212     {
213         DBG_WARNING( "IllegalIdentifierException" );
214     }
215     catch( ContentCreationException& )
216     {
217         DBG_WARNING( "IllegalIdentifierException" );
218     }
219     catch( ::com::sun::star::uno::Exception& )
220     {
221         DBG_WARNING( "Any other exception" );
222     }
223 
224     return bRet;
225 }
226 
227 // -----------------------------------------------------------------------
228 
GetTitle(const String & rContent,String & rTitle)229 sal_Bool UCBContentHelper::GetTitle( const String& rContent, String& rTitle )
230 {
231     sal_Bool bRet = sal_False;
232     INetURLObject aObj( rContent );
233     DBG_ASSERT( aObj.GetProtocol() != INET_PROT_NOT_VALID, "Invalid URL!" );
234     try
235     {
236         Content aCnt( aObj.GetMainURL( INetURLObject::NO_DECODE ), uno::Reference< ::com::sun::star::ucb::XCommandEnvironment > () );
237         OUString aTemp;
238         if ( aCnt.getPropertyValue( OUString::createFromAscii( "Title" ) ) >>= aTemp )
239         {
240             rTitle = String( aTemp );
241             bRet = sal_True;
242         }
243     }
244     catch( ::com::sun::star::ucb::CommandAbortedException& )
245     {
246     }
247     catch( ::com::sun::star::uno::Exception& )
248     {
249     }
250     return bRet;
251 }
252 
253 // -----------------------------------------------------------------------
254 
Kill(const String & rContent)255 sal_Bool UCBContentHelper::Kill( const String& rContent )
256 {
257     sal_Bool bRet = sal_True;
258     INetURLObject aDeleteObj( rContent );
259     DBG_ASSERT( aDeleteObj.GetProtocol() != INET_PROT_NOT_VALID, "Invalid URL!" );
260 
261     try
262     {
263         Content aCnt( aDeleteObj.GetMainURL( INetURLObject::NO_DECODE ), uno::Reference< ::com::sun::star::ucb::XCommandEnvironment > () );
264         aCnt.executeCommand( OUString::createFromAscii( "delete" ), makeAny( sal_Bool( sal_True ) ) );
265     }
266     catch( ::com::sun::star::ucb::CommandAbortedException& )
267     {
268         DBG_WARNING( "CommandAbortedException" );
269         bRet = sal_False;
270     }
271     catch( ::com::sun::star::uno::Exception& )
272     {
273         DBG_WARNING( "Any other exception" );
274         bRet = sal_False;
275     }
276 
277     return bRet;
278 }
279 
280 // -----------------------------------------------------------------------
281 
GetFolderContents(const String & rFolder,sal_Bool bFolder,sal_Bool bSorted)282 Sequence < OUString > UCBContentHelper::GetFolderContents( const String& rFolder, sal_Bool bFolder, sal_Bool bSorted )
283 {
284     StringList_Impl* pFiles = NULL;
285     INetURLObject aFolderObj( rFolder );
286     DBG_ASSERT( aFolderObj.GetProtocol() != INET_PROT_NOT_VALID, "Invalid URL!" );
287     try
288     {
289         Content aCnt( aFolderObj.GetMainURL( INetURLObject::NO_DECODE ), uno::Reference< ::com::sun::star::ucb::XCommandEnvironment > () );
290         uno::Reference< XResultSet > xResultSet;
291         Sequence< OUString > aProps( bSorted ? 2 : 1 );
292         OUString* pProps = aProps.getArray();
293         pProps[0] = OUString::createFromAscii( "Title" );
294         if ( bSorted )
295             pProps[1] = OUString::createFromAscii( "IsFolder" );
296 
297         try
298         {
299             ResultSetInclude eInclude = bFolder ? INCLUDE_FOLDERS_AND_DOCUMENTS : INCLUDE_DOCUMENTS_ONLY;
300             if ( !bSorted )
301             {
302                 xResultSet = aCnt.createCursor( aProps, eInclude );
303             }
304             else
305             {
306                 uno::Reference< com::sun::star::ucb::XDynamicResultSet > xDynResultSet;
307                 xDynResultSet = aCnt.createDynamicCursor( aProps, eInclude );
308 
309                 uno::Reference < com::sun::star::ucb::XAnyCompareFactory > xFactory;
310                 uno::Reference < XMultiServiceFactory > xMgr = getProcessServiceFactory();
311                 uno::Reference < com::sun::star::ucb::XSortedDynamicResultSetFactory > xSRSFac(
312                     xMgr->createInstance( ::rtl::OUString::createFromAscii("com.sun.star.ucb.SortedDynamicResultSetFactory") ), UNO_QUERY );
313 
314                 Sequence< com::sun::star::ucb::NumberedSortingInfo > aSortInfo( 2 );
315                 com::sun::star::ucb::NumberedSortingInfo* pInfo = aSortInfo.getArray();
316                 pInfo[ 0 ].ColumnIndex = 2;
317                 pInfo[ 0 ].Ascending   = sal_False;
318                 pInfo[ 1 ].ColumnIndex = 1;
319                 pInfo[ 1 ].Ascending   = sal_True;
320 
321                 uno::Reference< com::sun::star::ucb::XDynamicResultSet > xDynamicResultSet;
322                 xDynamicResultSet =
323                     xSRSFac->createSortedDynamicResultSet( xDynResultSet, aSortInfo, xFactory );
324                 if ( xDynamicResultSet.is() )
325                 {
326                     xResultSet = xDynamicResultSet->getStaticResultSet();
327                 }
328             }
329         }
330         catch( ::com::sun::star::ucb::CommandAbortedException& )
331         {
332             // folder not exists?
333         }
334         catch( ::com::sun::star::uno::Exception& )
335         {
336         }
337 
338         if ( xResultSet.is() )
339         {
340             pFiles = new StringList_Impl;
341             uno::Reference< com::sun::star::ucb::XContentAccess > xContentAccess( xResultSet, UNO_QUERY );
342             try
343             {
344                 while ( xResultSet->next() )
345                 {
346                     OUString aId = xContentAccess->queryContentIdentifierString();
347                     OUString* pFile = new OUString( aId );
348                     pFiles->Insert( pFile, LIST_APPEND );
349                 }
350             }
351             catch( ::com::sun::star::ucb::CommandAbortedException& )
352             {
353             }
354             catch( ::com::sun::star::uno::Exception& )
355             {
356             }
357         }
358     }
359     catch( ::com::sun::star::uno::Exception& )
360     {
361     }
362 
363     if ( pFiles )
364     {
365         sal_uLong nCount = pFiles->Count();
366         Sequence < OUString > aRet( nCount );
367         OUString* pRet = aRet.getArray();
368         for ( sal_uLong i = 0; i < nCount; ++i )
369         {
370             OUString* pFile = pFiles->GetObject(i);
371             pRet[i] = *( pFile );
372             delete pFile;
373         }
374         delete pFiles;
375         return aRet;
376     }
377     else
378         return Sequence < OUString > ();
379 }
380 
381 // -----------------------------------------------------------------------
382 
GetResultSet(const String & rURL)383 Sequence < OUString > UCBContentHelper::GetResultSet( const String& rURL )
384 {
385     StringList_Impl* pList = NULL;
386     try
387     {
388         Content aCnt( rURL, uno::Reference< ::com::sun::star::ucb::XCommandEnvironment >() );
389         uno::Reference< XResultSet > xResultSet;
390         uno::Reference< com::sun::star::ucb::XDynamicResultSet > xDynResultSet;
391         Sequence< OUString > aProps(3);
392         OUString* pProps = aProps.getArray();
393         pProps[0] = OUString::createFromAscii( "Title" );
394         pProps[1] = OUString::createFromAscii( "ContentType" );
395         // TODO: can be optimized, property never used:
396         pProps[2] = OUString::createFromAscii( "IsFolder" );
397 
398         try
399         {
400             xDynResultSet = aCnt.createDynamicCursor( aProps, INCLUDE_FOLDERS_AND_DOCUMENTS );
401             if ( xDynResultSet.is() )
402                 xResultSet = xDynResultSet->getStaticResultSet();
403         }
404         catch( ::com::sun::star::ucb::CommandAbortedException& )
405         {
406         }
407         catch( ::com::sun::star::uno::Exception& )
408         {
409         }
410 
411         if ( xResultSet.is() )
412         {
413             pList = new StringList_Impl;
414             uno::Reference< com::sun::star::sdbc::XRow > xRow( xResultSet, UNO_QUERY );
415             uno::Reference< com::sun::star::ucb::XContentAccess > xContentAccess( xResultSet, UNO_QUERY );
416 
417             try
418             {
419                 while ( xResultSet->next() )
420                 {
421                     String aTitle( xRow->getString(1) );
422                     String aType( xRow->getString(2) );
423                     String aRow = aTitle;
424                     aRow += '\t';
425                     aRow += aType;
426                     aRow += '\t';
427                     aRow += String( xContentAccess->queryContentIdentifierString() );
428                     OUString* pRow = new OUString( aRow );
429                     pList->Insert( pRow, LIST_APPEND );
430                 }
431             }
432             catch( ::com::sun::star::ucb::CommandAbortedException& )
433             {
434             }
435             catch( ::com::sun::star::uno::Exception& )
436             {
437             }
438         }
439     }
440     catch( ::com::sun::star::uno::Exception& )
441     {
442     }
443 
444     if ( pList )
445     {
446         sal_uLong nCount = pList->Count();
447         Sequence < OUString > aRet( nCount );
448         OUString* pRet = aRet.getArray();
449         for ( sal_uLong i = 0; i < nCount; ++i )
450         {
451             OUString* pEntry = pList->GetObject(i);
452             pRet[i] = *( pEntry );
453             delete pEntry;
454         }
455         delete pList;
456         return aRet;
457     }
458     else
459         return Sequence < OUString > ();
460 }
461 
462 // -----------------------------------------------------------------------
463 
CopyTo(const String & rSource,const String & rDest)464 sal_Bool UCBContentHelper::CopyTo( const String& rSource, const String& rDest )
465 {
466     return Transfer_Impl( rSource, rDest, sal_False, NameClash::ERROR );
467 }
468 
469 // -----------------------------------------------------------------------
470 
MoveTo(const String & rSource,const String & rDest,sal_Int32 nNameClash)471 sal_Bool UCBContentHelper::MoveTo( const String& rSource, const String& rDest, sal_Int32 nNameClash )
472 {
473     return Transfer_Impl( rSource, rDest, sal_True, nNameClash );
474 }
475 
476 // -----------------------------------------------------------------------
477 
CanMakeFolder(const String & rFolder)478 sal_Bool UCBContentHelper::CanMakeFolder( const String& rFolder )
479 {
480     try
481     {
482         Content aCnt( rFolder, uno::Reference< XCommandEnvironment > () );
483         Sequence< ContentInfo > aInfo = aCnt.queryCreatableContentsInfo();
484         sal_Int32 nCount = aInfo.getLength();
485         if ( nCount == 0 )
486             return sal_False;
487 
488         for ( sal_Int32 i = 0; i < nCount; ++i )
489         {
490             // Simply look for the first KIND_FOLDER...
491             const ContentInfo & rCurr = aInfo[i];
492             if ( rCurr.Attributes & ContentInfoAttribute::KIND_FOLDER )
493                 return sal_True;
494         }
495     }
496     catch( ::com::sun::star::ucb::CommandAbortedException& ) {}
497     catch( RuntimeException& ) {}
498     catch( Exception& ) {}
499 
500     return sal_False;
501 }
502 
503 // -----------------------------------------------------------------------
504 
MakeFolder(const String & rFolder,sal_Bool bNewOnly)505 sal_Bool UCBContentHelper::MakeFolder( const String& rFolder, sal_Bool bNewOnly )
506 {
507     INetURLObject aURL( rFolder );
508     DBG_ASSERT( aURL.GetProtocol() != INET_PROT_NOT_VALID, "Invalid URL!" );
509     String aTitle = aURL.getName( INetURLObject::LAST_SEGMENT, true, INetURLObject::DECODE_WITH_CHARSET );
510     aURL.removeSegment();
511     Content aCnt;
512     Content aNew;
513     uno::Reference< XMultiServiceFactory > xFactory = ::comphelper::getProcessServiceFactory();
514     uno::Reference< XInteractionHandler > xInteractionHandler = uno::Reference< XInteractionHandler > (
515                xFactory->createInstance( OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.uui.InteractionHandler") ) ), UNO_QUERY );
516     if ( Content::create( aURL.GetMainURL( INetURLObject::NO_DECODE ), new CommandEnvironment( xInteractionHandler, uno::Reference< XProgressHandler >() ), aCnt ) )
517         return MakeFolder( aCnt, aTitle, aNew, bNewOnly );
518     else
519         return sal_False;
520 }
521 
MakeFolder(Content & aCnt,const String & aTitle,Content & rNew,sal_Bool bNewOnly)522 sal_Bool UCBContentHelper::MakeFolder( Content& aCnt, const String& aTitle, Content& rNew, sal_Bool bNewOnly )
523 {
524     sal_Bool bAlreadyExists = sal_False;
525 
526     try
527     {
528         Sequence< ContentInfo > aInfo = aCnt.queryCreatableContentsInfo();
529         sal_Int32 nCount = aInfo.getLength();
530         if ( nCount == 0 )
531             return sal_False;
532 
533         for ( sal_Int32 i = 0; i < nCount; ++i )
534         {
535             // Simply look for the first KIND_FOLDER...
536             const ContentInfo & rCurr = aInfo[i];
537             if ( rCurr.Attributes & ContentInfoAttribute::KIND_FOLDER )
538             {
539                 // Make sure the only required bootstrap property is "Title",
540                 const Sequence< Property > & rProps = rCurr.Properties;
541                 if ( rProps.getLength() != 1 )
542                     continue;
543 
544                 if ( !rProps[ 0 ].Name.equalsAsciiL(
545                         RTL_CONSTASCII_STRINGPARAM( "Title" ) ) )
546                     continue;
547 
548                 Sequence<OUString> aNames(1);
549                 OUString* pNames = aNames.getArray();
550                 pNames[0] = OUString( RTL_CONSTASCII_USTRINGPARAM( "Title" ) );
551                 Sequence<Any> aValues(1);
552                 Any* pValues = aValues.getArray();
553                 pValues[0] = makeAny( OUString( aTitle ) );
554 
555                 if ( !aCnt.insertNewContent( rCurr.Type, aNames, aValues, rNew ) )
556                     continue;
557 
558                 return sal_True;
559             }
560         }
561     }
562     catch ( InteractiveIOException& r )
563     {
564         if ( r.Code == IOErrorCode_ALREADY_EXISTING )
565         {
566             bAlreadyExists = sal_True;
567         }
568     }
569     catch ( NameClashException& )
570     {
571         bAlreadyExists = sal_True;
572     }
573     catch( ::com::sun::star::ucb::CommandAbortedException& )
574     {
575     }
576     catch( RuntimeException& )
577     {
578     }
579     catch( Exception& )
580     {
581     }
582 
583     if( bAlreadyExists && !bNewOnly )
584     {
585         INetURLObject aObj( aCnt.getURL() );
586         aObj.Append( aTitle );
587         rNew = Content( aObj.GetMainURL( INetURLObject::NO_DECODE ), uno::Reference < XCommandEnvironment >() );
588         return sal_True;
589     }
590 
591     return sal_False;
592 }
593 
594 // -----------------------------------------------------------------------
595 
HasParentFolder(const String & rFolder)596 sal_Bool UCBContentHelper::HasParentFolder( const String& rFolder )
597 {
598     sal_Bool bRet = sal_False;
599     try
600     {
601         Content aCnt( rFolder, uno::Reference< XCommandEnvironment > () );
602         uno::Reference< XChild > xChild( aCnt.get(), UNO_QUERY );
603         if ( xChild.is() )
604         {
605             uno::Reference< XContent > xParent( xChild->getParent(), UNO_QUERY );
606             if ( xParent.is() )
607             {
608                 String aParentURL = String( xParent->getIdentifier()->getContentIdentifier() );
609                 bRet = ( aParentURL.Len() > 0 && aParentURL != rFolder );
610             }
611         }
612     }
613     catch( ::com::sun::star::ucb::CommandAbortedException& )
614     {
615     }
616     catch( ::com::sun::star::uno::Exception& )
617     {
618     }
619 
620     return bRet;
621 }
622 
623 // -----------------------------------------------------------------------
624 
GetSize(const String & rContent)625 sal_uLong UCBContentHelper::GetSize( const String& rContent )
626 {
627     sal_uLong nSize = 0;
628     sal_Int64 nTemp = 0;
629     INetURLObject aObj( rContent );
630     DBG_ASSERT( aObj.GetProtocol() != INET_PROT_NOT_VALID, "Invalid URL!" );
631     try
632     {
633         Content aCnt( aObj.GetMainURL( INetURLObject::NO_DECODE ), uno::Reference< ::com::sun::star::ucb::XCommandEnvironment > () );
634         aCnt.getPropertyValue( OUString::createFromAscii( "Size" ) ) >>= nTemp;
635     }
636     catch( ::com::sun::star::ucb::CommandAbortedException& )
637     {
638     }
639     catch( ::com::sun::star::uno::Exception& )
640     {
641     }
642     nSize = (sal_uInt32)nTemp;
643     return nSize;
644 }
645 
646 // -----------------------------------------------------------------------
647 
IsYounger(const String & rIsYoung,const String & rIsOlder)648 sal_Bool UCBContentHelper::IsYounger( const String& rIsYoung, const String& rIsOlder )
649 {
650     DateTime aYoungDate, aOlderDate;
651     INetURLObject aYoungObj( rIsYoung );
652     DBG_ASSERT( aYoungObj.GetProtocol() != INET_PROT_NOT_VALID, "Invalid URL!" );
653     INetURLObject aOlderObj( rIsOlder );
654     DBG_ASSERT( aOlderObj.GetProtocol() != INET_PROT_NOT_VALID, "Invalid URL!" );
655     try
656     {
657         uno::Reference< ::com::sun::star::ucb::XCommandEnvironment > aCmdEnv;
658         Content aYoung( aYoungObj.GetMainURL( INetURLObject::NO_DECODE ), aCmdEnv );
659         ::com::sun::star::util::DateTime aTempYoungDate;
660         aYoung.getPropertyValue( OUString::createFromAscii( "DateModified" ) ) >>= aTempYoungDate;
661         CONVERT_DATETIME( aTempYoungDate, aYoungDate );
662         Content aOlder( aOlderObj.GetMainURL( INetURLObject::NO_DECODE ), aCmdEnv );
663         ::com::sun::star::util::DateTime aTempOlderDate;
664         aOlder.getPropertyValue( OUString::createFromAscii( "DateModified" ) ) >>= aTempOlderDate;
665         CONVERT_DATETIME( aTempOlderDate, aOlderDate );
666     }
667     catch( ::com::sun::star::ucb::CommandAbortedException& )
668     {
669     }
670     catch( ::com::sun::star::uno::Exception& )
671     {
672     }
673 
674     return ( aYoungDate > aOlderDate );
675 }
676 
677 // -----------------------------------------------------------------------
Find(const String & rFolder,const String & rName,String & rFile,sal_Bool bAllowWildCards)678 sal_Bool UCBContentHelper::Find( const String& rFolder, const String& rName, String& rFile, sal_Bool bAllowWildCards )
679 {
680     sal_Bool bWild = bAllowWildCards && ( rName.Search( '*' ) != STRING_NOTFOUND || rName.Search( '?' ) != STRING_NOTFOUND );
681 
682     sal_Bool bRet = sal_False;
683 
684     // get a list of URLs for all children of rFolder
685     Sequence< ::rtl::OUString > aFiles = GetFolderContents( rFolder, sal_False );
686 
687     const ::rtl::OUString* pFiles  = aFiles.getConstArray();
688     sal_uInt32 i, nCount = aFiles.getLength();
689     for ( i = 0; i < nCount; ++i )
690     {
691         // get the last name of the URLs and compare it with rName
692         INetURLObject aFileObject( pFiles[i] );
693         String aFile = aFileObject.getName(
694             INetURLObject::LAST_SEGMENT, true, INetURLObject::DECODE_WITH_CHARSET ).toAsciiLowerCase();
695         if ( (bWild && WildCard( rName ).Matches( aFile )) || aFile == rName )
696         {
697             // names match
698             rFile = aFileObject.GetMainURL( INetURLObject::NO_DECODE );
699             bRet = sal_True;
700             break;
701         }
702     }
703 
704     return bRet;
705 }
706 
707 // -----------------------------------------------------------------------
Exists(const String & rURL)708 sal_Bool UCBContentHelper::Exists( const String& rURL )
709 {
710 
711     String sObjectPhysicalName;
712     sal_Bool bIsLocalFile = ::utl::LocalFileHelper::ConvertURLToPhysicalName( rURL, sObjectPhysicalName );
713     // try to create a directory entry for the URL given
714     if ( bIsLocalFile )
715     {
716         ::rtl::OUString sIn( sObjectPhysicalName ), sOut;
717         if ( osl_File_E_None == osl_getFileURLFromSystemPath( sIn.pData, &sOut.pData ) )
718         {
719             // #106526 osl_getDirectoryItem is an existence check
720             // no further osl_getFileStatus call necessary
721             DirectoryItem aItem;
722             return (FileBase::E_None == DirectoryItem::get(sOut, aItem));
723         }
724         return sal_False;
725     }
726 
727     // divide URL into folder and name part
728     sal_Bool bRet = sal_False;
729     INetURLObject aObj( rURL );
730     ::rtl::OUString aFileName = aObj.getName(
731         INetURLObject::LAST_SEGMENT, true, INetURLObject::DECODE_WITH_CHARSET ).toAsciiLowerCase();
732     aObj.removeSegment();
733     aObj.removeFinalSlash();
734 
735     // get a list of URLs for all children of rFolder
736     Sequence< ::rtl::OUString > aFiles = GetFolderContents( aObj.GetMainURL( INetURLObject::NO_DECODE ), sal_True, sal_False );
737 
738     const ::rtl::OUString* pFiles  = aFiles.getConstArray();
739     sal_uInt32 i, nCount = aFiles.getLength();
740     for ( i = 0; i < nCount; ++i )
741     {
742         // get the last name of the URLs and compare it with rName
743         INetURLObject aFileObject( pFiles[i] );
744         ::rtl::OUString aFile = aFileObject.getName(
745             INetURLObject::LAST_SEGMENT, true, INetURLObject::DECODE_WITH_CHARSET ).toAsciiLowerCase();
746         if ( aFile == aFileName )
747         {
748             // names match
749             bRet = sal_True;
750             break;
751         }
752     }
753 
754     return bRet;
755 }
756 
757 // -----------------------------------------------------------------------
FindInPath(const String & rPath,const String & rName,String & rFile,char cDelim,sal_Bool bAllowWildCards)758 sal_Bool UCBContentHelper::FindInPath( const String& rPath, const String& rName, String& rFile, char cDelim, sal_Bool bAllowWildCards )
759 {
760     // extract the single folder names from the path variable and try to find the file in one of these folders
761     sal_uInt16 nTokenCount = rPath.GetTokenCount( cDelim );
762     for ( sal_uInt16 nToken = 0; nToken < nTokenCount; ++nToken )
763     {
764         String aPath = rPath.GetToken( nToken, cDelim );
765         if ( Find( aPath, rName, rFile, bAllowWildCards ) )
766             return sal_True;
767     }
768 
769     return sal_False;
770 }
771 
772 // -----------------------------------------------------------------------
IsSubPath(const::rtl::OUString & rPath,const::rtl::OUString & rSubfolderCandidate,const uno::Reference<::com::sun::star::ucb::XContentProvider> & xProv)773 sal_Bool UCBContentHelper::IsSubPath( const ::rtl::OUString& rPath, const ::rtl::OUString& rSubfolderCandidate, const uno::Reference< ::com::sun::star::ucb::XContentProvider >& xProv )
774 {
775     sal_Bool bResult = sal_False;
776 
777     uno::Reference< ::com::sun::star::ucb::XContentProvider > xContentProvider = xProv;
778 
779     // the comparing is done in the following way:
780     // - first compare in case sensitive way
781     // - if name are different try a fallback comparing inf case insensitive way
782     // - if the last comparing succeeded get casepreserving normalized names for the files and compare them
783     // ( the second step is required because retrieving of the normalized names might be very expensive in some cases )
784 
785     INetURLObject aCandidate( rSubfolderCandidate );
786     INetURLObject aCandidateLowCase( rSubfolderCandidate.toAsciiLowerCase() ); // will be used for case insensitive comparing
787     INetURLObject aParentFolder( rPath );
788     INetURLObject aParentFolderLowCase( rPath.toAsciiLowerCase() ); // will be used for case insensitive comparing
789 
790     if ( aCandidate.GetProtocol() == aParentFolder.GetProtocol() )
791     {
792         if ( !xContentProvider.is() )
793         {
794             ::ucbhelper::ContentBroker* pBroker = NULL;
795             if ( aCandidate.GetProtocol() == INET_PROT_FILE )
796             {
797                 pBroker = ::ucbhelper::ContentBroker::get();
798                 if ( pBroker )
799                     xContentProvider = pBroker->getContentProviderInterface();
800             }
801         }
802 
803         INetURLObject aLastTmpObj;
804         do
805         {
806             if ( aParentFolder == aCandidate )
807             {
808                 // if case sensitive comparing succeeded there is no need for additional checks
809                 bResult = sal_True;
810             }
811             else if ( xContentProvider.is() && aParentFolderLowCase == aCandidateLowCase )
812             {
813                 // the comparing was done using caseinsensitive way
814                 // the case sensitive comparing have failed already
815                 // the normalized urls must be retrieved
816                 try
817                 {
818                     uno::Reference< ::com::sun::star::ucb::XContent > xSecCont =
819                         xContentProvider->queryContent(
820                             uno::Reference< ::com::sun::star::ucb::XContentIdentifierFactory >(
821                                 xContentProvider, ::com::sun::star::uno::UNO_QUERY_THROW )->createContentIdentifier(
822                                     aParentFolder.GetMainURL( INetURLObject::NO_DECODE ) ) );
823 
824                     uno::Reference< ::com::sun::star::ucb::XContent > xLocCont =
825                         xContentProvider->queryContent(
826                             uno::Reference< ::com::sun::star::ucb::XContentIdentifierFactory >(
827                                 xContentProvider, ::com::sun::star::uno::UNO_QUERY_THROW )->createContentIdentifier(
828                                     aCandidate.GetMainURL( INetURLObject::NO_DECODE ) ) );
829 
830                     if ( !xSecCont.is() || !xLocCont.is() )
831                         throw ::com::sun::star::uno::RuntimeException();
832 
833                     ::rtl::OUString aSecNormStr;
834                     ::rtl::OUString aLocNormStr;
835 
836                     bResult =
837                     ( ( uno::Reference< ::com::sun::star::ucb::XCommandProcessor >(
838                             xSecCont, ::com::sun::star::uno::UNO_QUERY_THROW )->execute(
839                                 ::com::sun::star::ucb::Command(
840                                     rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "getCasePreservingURL" ) ),
841                                     -1,
842                                     ::com::sun::star::uno::Any() ),
843                                 0,
844                                 uno::Reference< ::com::sun::star::ucb::XCommandEnvironment >() )
845                         >>= aSecNormStr )
846                     && ( uno::Reference< ::com::sun::star::ucb::XCommandProcessor >(
847                             xLocCont, ::com::sun::star::uno::UNO_QUERY_THROW )->execute(
848                                 ::com::sun::star::ucb::Command(
849                                     rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "getCasePreservingURL" ) ),
850                                     -1,
851                                     ::com::sun::star::uno::Any() ),
852                                 0,
853                                 uno::Reference< ::com::sun::star::ucb::XCommandEnvironment >() )
854                         >>= aLocNormStr )
855                     && aLocNormStr.equals( aSecNormStr ) );
856                 }
857                 catch( ::com::sun::star::uno::Exception& )
858                 {}
859             }
860 
861             // INetURLObject::removeSegment sometimes return true without exchanging URL,
862             // for example in case of "file:///"
863             aLastTmpObj = aCandidate;
864 
865         } while( aCandidate.removeSegment() && aCandidateLowCase.removeSegment() && aCandidate != aLastTmpObj && !bResult );
866     }
867 
868     return bResult;
869 }
870 
871 // -----------------------------------------------------------------------
EqualURLs(const::rtl::OUString & aFirstURL,const::rtl::OUString & aSecondURL)872 sal_Bool UCBContentHelper::EqualURLs( const ::rtl::OUString& aFirstURL, const ::rtl::OUString& aSecondURL )
873 {
874 	sal_Bool bResult = sal_False;
875 
876 	if ( aFirstURL.getLength() && aSecondURL.getLength() )
877 	{
878 		INetURLObject aFirst( aFirstURL );
879 		INetURLObject aSecond( aSecondURL );
880 
881         if ( aFirst.GetProtocol() != INET_PROT_NOT_VALID && aSecond.GetProtocol() != INET_PROT_NOT_VALID )
882 		{
883 			try
884 			{
885     			::ucbhelper::ContentBroker* pBroker = ::ucbhelper::ContentBroker::get();
886 				if ( !pBroker )
887 					throw uno::RuntimeException();
888 
889 				uno::Reference< ::com::sun::star::ucb::XContentIdentifierFactory > xIdFac
890 					= pBroker->getContentIdentifierFactoryInterface();
891 				if ( !xIdFac.is() )
892 					throw uno::RuntimeException();
893 
894 				uno::Reference< ::com::sun::star::ucb::XContentIdentifier > xIdFirst
895 					= xIdFac->createContentIdentifier( aFirst.GetMainURL( INetURLObject::NO_DECODE ) );
896 				uno::Reference< ::com::sun::star::ucb::XContentIdentifier > xIdSecond
897 					= xIdFac->createContentIdentifier( aSecond.GetMainURL( INetURLObject::NO_DECODE ) );
898 
899 				if ( xIdFirst.is() && xIdSecond.is() )
900 				{
901 					uno::Reference< ::com::sun::star::ucb::XContentProvider > xProvider =
902 															pBroker->getContentProviderInterface();
903 					if ( !xProvider.is() )
904 						throw uno::RuntimeException();
905 					bResult = !xProvider->compareContentIds( xIdFirst, xIdSecond );
906 				}
907 			}
908 			catch( uno::Exception& )
909 			{
910 				OSL_ENSURE( sal_False, "Can't compare URL's, treat as different!\n" );
911 			}
912 		}
913 	}
914 
915 	return bResult;
916 }
917 
918 
919 
920 } // namespace utl
921 
922