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