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_svtools.hxx"
30 #include "contentenumeration.hxx"
31 #include <svl/urlfilter.hxx>
32 #include <svtools/inettbc.hxx>
33 #include <svtools/imagemgr.hxx>
34 
35 /** === begin UNO includes === **/
36 #include <com/sun/star/beans/XPropertySet.hpp>
37 #include <com/sun/star/sdbc/XResultSet.hpp>
38 #include <com/sun/star/sdbc/XRow.hpp>
39 #include <com/sun/star/ucb/XDynamicResultSet.hpp>
40 #include <com/sun/star/ucb/XContentAccess.hpp>
41 #include <com/sun/star/util/DateTime.hpp>
42 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
43 /** === end UNO includes === **/
44 #include <comphelper/processfactory.hxx>
45 #include <tools/debug.hxx>
46 #include <vcl/svapp.hxx>
47 #include <vos/mutex.hxx>
48 
49 #include <memory>
50 
51 //........................................................................
52 namespace svt
53 {
54 //........................................................................
55 
56 #define ROW_TITLE           1
57 #define ROW_SIZE            2
58 #define ROW_DATE_MOD        3
59 #define ROW_DATE_CREATE     4
60 #define ROW_IS_FOLDER       5
61 #define ROW_TARGET_URL      6
62 #define ROW_IS_HIDDEN		7
63 #define ROW_IS_VOLUME		8
64 #define ROW_IS_REMOTE		9
65 #define ROW_IS_REMOVEABLE	10
66 #define ROW_IS_FLOPPY		11
67 #define ROW_IS_COMPACTDISC	12
68 
69 #define CONVERT_DATETIME( aUnoDT, aToolsDT ) \
70     aToolsDT = ::DateTime( Date( aUnoDT.Day, aUnoDT.Month, aUnoDT.Year ), \
71 						   Time( aUnoDT.Hours, aUnoDT.Minutes, aUnoDT.Seconds, aUnoDT.HundredthSeconds ) );
72 
73     using ::com::sun::star::uno::Reference;
74     using ::com::sun::star::uno::Sequence;
75     using ::com::sun::star::uno::Exception;
76     using ::com::sun::star::uno::UNO_QUERY;
77     using ::com::sun::star::uno::Any;
78     using ::com::sun::star::util::DateTime;
79     using ::com::sun::star::sdbc::XResultSet;
80     using ::com::sun::star::sdbc::XRow;
81     using ::com::sun::star::ucb::XDynamicResultSet;
82     using ::com::sun::star::ucb::CommandAbortedException;
83     using ::com::sun::star::ucb::XContentAccess;
84     using ::com::sun::star::ucb::XCommandEnvironment;
85     using ::com::sun::star::beans::XPropertySet;
86     using ::rtl::OUString;
87     using ::ucbhelper::ResultSetInclude;
88     using ::ucbhelper::INCLUDE_FOLDERS_AND_DOCUMENTS;
89 
90     //====================================================================
91     //= FileViewContentEnumerator
92     //====================================================================
93     //--------------------------------------------------------------------
94     FileViewContentEnumerator::FileViewContentEnumerator(
95             const Reference< XCommandEnvironment >& _rxCommandEnv,
96             ContentData& _rContentToFill, ::osl::Mutex& _rContentMutex,
97             const IContentTitleTranslation* _pTranslator )
98         :m_rContent              ( _rContentToFill )
99         ,m_rContentMutex         ( _rContentMutex  )
100         ,m_refCount              ( 0               )
101         ,m_xCommandEnv           ( _rxCommandEnv   )
102         ,m_pFilter               ( NULL            )
103         ,m_pTranslator           ( _pTranslator    )
104         ,m_bCancelled            ( false           )
105 		,m_rBlackList			 ( ::com::sun::star::uno::Sequence< ::rtl::OUString >() )
106     {
107     }
108 
109     //--------------------------------------------------------------------
110     FileViewContentEnumerator::~FileViewContentEnumerator()
111     {
112     }
113 
114     //--------------------------------------------------------------------
115     void FileViewContentEnumerator::cancel()
116     {
117         ::osl::MutexGuard aGuard( m_aMutex );
118         m_bCancelled = true;
119         m_pResultHandler = NULL;
120         m_pTranslator = NULL;
121         m_pFilter = NULL;
122         m_aFolder.aContent = ::ucbhelper::Content();
123         m_aFolder.sURL = String();
124     }
125 
126     //--------------------------------------------------------------------
127     EnumerationResult FileViewContentEnumerator::enumerateFolderContentSync(
128 		const FolderDescriptor& _rFolder,
129 		const IUrlFilter* _pFilter,
130 		const ::com::sun::star::uno::Sequence< ::rtl::OUString >& rBlackList )
131     {
132         {
133             ::osl::MutexGuard aGuard( m_aMutex );
134             m_aFolder = _rFolder;
135             m_pFilter = _pFilter;
136             m_pResultHandler = NULL;
137 			m_rBlackList = rBlackList;
138         }
139         return enumerateFolderContent();
140     }
141 
142     //--------------------------------------------------------------------
143     void FileViewContentEnumerator::enumerateFolderContent(
144         const FolderDescriptor& _rFolder, const IUrlFilter* _pFilter, IEnumerationResultHandler* _pResultHandler )
145     {
146         // ensure that we don't get deleted while herein
147         acquire();
148             // the matching "release" will be called in onTerminated
149             // Note that onTerminated is only called if run was left normally.
150             // If somebody terminates the thread from the outside, then onTerminated
151             // will never be called. However, our terminate method is not accessible
152             // to our clients, so the only class which could misbehave is this class
153             // here itself ...
154 
155         ::osl::MutexGuard aGuard( m_aMutex );
156         m_aFolder = _rFolder;
157         m_pFilter = _pFilter;
158         m_pResultHandler = _pResultHandler;
159 
160         OSL_ENSURE( m_aFolder.aContent.get().is() || m_aFolder.sURL.Len(),
161             "FileViewContentEnumerator::enumerateFolderContent: invalid folder descriptor!" );
162 
163         // start the thread
164         create();
165     }
166 
167     //--------------------------------------------------------------------
168     oslInterlockedCount SAL_CALL FileViewContentEnumerator::acquire()
169     {
170         return osl_incrementInterlockedCount( &m_refCount );
171     }
172 
173     //--------------------------------------------------------------------
174     oslInterlockedCount SAL_CALL FileViewContentEnumerator::release()
175     {
176         if ( 0 == osl_decrementInterlockedCount( &m_refCount ) )
177         {
178             delete this;
179             return 0;
180         }
181         return m_refCount;
182     }
183 
184     //--------------------------------------------------------------------
185     EnumerationResult FileViewContentEnumerator::enumerateFolderContent()
186     {
187         EnumerationResult eResult = ERROR;
188         try
189         {
190 
191             Reference< XResultSet > xResultSet;
192             Sequence< OUString > aProps(12);
193 
194             aProps[0] = OUString::createFromAscii( "Title" );
195             aProps[1] = OUString::createFromAscii( "Size" );
196             aProps[2] = OUString::createFromAscii( "DateModified" );
197             aProps[3] = OUString::createFromAscii( "DateCreated" );
198             aProps[4] = OUString::createFromAscii( "IsFolder" );
199             aProps[5] = OUString::createFromAscii( "TargetURL" );
200             aProps[6] = OUString::createFromAscii( "IsHidden" );
201             aProps[7] = OUString::createFromAscii( "IsVolume" );
202             aProps[8] = OUString::createFromAscii( "IsRemote" );
203             aProps[9] = OUString::createFromAscii( "IsRemoveable" );
204             aProps[10] = OUString::createFromAscii( "IsFloppy" );
205             aProps[11] = OUString::createFromAscii( "IsCompactDisc" );
206 
207             Reference< XCommandEnvironment > xEnvironment;
208             try
209             {
210                 FolderDescriptor aFolder;
211                 {
212                     ::osl::MutexGuard aGuard( m_aMutex );
213                     aFolder = m_aFolder;
214                     xEnvironment = m_xCommandEnv;
215                 }
216                 if ( !aFolder.aContent.get().is() )
217                 {
218 					aFolder.aContent = ::ucbhelper::Content( aFolder.sURL, xEnvironment );
219                     {
220                         ::osl::MutexGuard aGuard( m_aMutex );
221                         m_aFolder.aContent = aFolder.aContent;
222                     }
223                 }
224 
225                 Reference< XDynamicResultSet > xDynResultSet;
226                 ResultSetInclude eInclude = INCLUDE_FOLDERS_AND_DOCUMENTS;
227                 xDynResultSet = aFolder.aContent.createDynamicCursor( aProps, eInclude );
228 
229                 if ( xDynResultSet.is() )
230                     xResultSet = xDynResultSet->getStaticResultSet();
231             }
232             catch( CommandAbortedException& )
233             {
234                 DBG_ERRORFILE( "createCursor: CommandAbortedException" );
235             }
236             catch( Exception& )
237             {
238             }
239 
240             bool bCancelled = false;
241             if ( xResultSet.is() )
242             {
243                 Reference< XRow > xRow( xResultSet, UNO_QUERY );
244                 Reference< XContentAccess > xContentAccess( xResultSet, UNO_QUERY );
245 
246                 try
247                 {
248                     SortingData_Impl* pData;
249                     DateTime aDT;
250 
251                     while ( !bCancelled && xResultSet->next() )
252                     {
253                         sal_Bool bIsHidden = xRow->getBoolean( ROW_IS_HIDDEN );
254                         // don't show hidden files
255                         if ( !bIsHidden || xRow->wasNull() )
256                         {
257                             pData = NULL;
258 
259                             aDT = xRow->getTimestamp( ROW_DATE_MOD );
260                             sal_Bool bContainsDate = !xRow->wasNull();
261                             if ( !bContainsDate )
262                             {
263                                 aDT = xRow->getTimestamp( ROW_DATE_CREATE );
264                                 bContainsDate = !xRow->wasNull();
265                             }
266 
267                             OUString aContentURL = xContentAccess->queryContentIdentifierString();
268                             OUString aTargetURL = xRow->getString( ROW_TARGET_URL );
269                             sal_Bool bHasTargetURL = !xRow->wasNull() && aTargetURL.getLength() > 0;
270 
271                             OUString sRealURL = bHasTargetURL ? aTargetURL : aContentURL;
272 
273                             // check for restrictions
274                             {
275                                 ::osl::MutexGuard aGuard( m_aMutex );
276                                 if ( m_pFilter && !m_pFilter->isUrlAllowed( sRealURL ) )
277                                     continue;
278 
279 								if ( /* m_rBlackList.hasElements() && */ URLOnBlackList ( sRealURL ) )
280 									continue;
281                             }
282 
283                             pData = new SortingData_Impl;
284                             pData->maTargetURL = sRealURL;
285 
286                             pData->mbIsFolder = xRow->getBoolean( ROW_IS_FOLDER ) && !xRow->wasNull();
287                             pData->mbIsVolume = xRow->getBoolean( ROW_IS_VOLUME ) && !xRow->wasNull();
288                             pData->mbIsRemote = xRow->getBoolean( ROW_IS_REMOTE ) && !xRow->wasNull();
289                             pData->mbIsRemoveable = xRow->getBoolean( ROW_IS_REMOVEABLE ) && !xRow->wasNull();
290                             pData->mbIsFloppy = xRow->getBoolean( ROW_IS_FLOPPY ) && !xRow->wasNull();
291                             pData->mbIsCompactDisc = xRow->getBoolean( ROW_IS_COMPACTDISC ) && !xRow->wasNull();
292                             pData->SetNewTitle( xRow->getString( ROW_TITLE ) );
293                             pData->maSize = xRow->getLong( ROW_SIZE );
294 
295                             if ( bHasTargetURL &&
296                                 INetURLObject( aContentURL ).GetProtocol() == INET_PROT_VND_SUN_STAR_HIER )
297                             {
298 								::ucbhelper::Content aCnt( aTargetURL, xEnvironment );
299 								try
300 								{
301                                 aCnt.getPropertyValue( OUString::createFromAscii( "Size" ) ) >>= pData->maSize;
302                                 aCnt.getPropertyValue( OUString::createFromAscii( "DateModified" ) ) >>= aDT;
303 								}
304 								catch (...) {}
305                             }
306 
307                             if ( bContainsDate )
308                             {
309                                 CONVERT_DATETIME( aDT, pData->maModDate );
310                             }
311 
312                             if ( pData->mbIsFolder )
313                             {
314                                 ::vos::OGuard aGuard( Application::GetSolarMutex() );
315                                 ::svtools::VolumeInfo aVolInfo( pData->mbIsVolume, pData->mbIsRemote,
316                                                                 pData->mbIsRemoveable, pData->mbIsFloppy,
317                                                                 pData->mbIsCompactDisc );
318                                 pData->maType = SvFileInformationManager::GetFolderDescription( aVolInfo );
319                             }
320                             else
321                                 pData->maType = SvFileInformationManager::GetFileDescription(
322                                     INetURLObject( pData->maTargetURL ) );
323 
324                             // replace names on demand
325                             {
326                                 ::osl::MutexGuard aGuard( m_aMutex );
327                                 if( m_pTranslator )
328                                 {
329                                     OUString sNewTitle;
330                                     sal_Bool bTranslated = sal_False;
331 
332                                     if ( pData->mbIsFolder )
333                                         bTranslated = m_pTranslator->GetTranslation( pData->GetTitle(), sNewTitle );
334                                     else
335                                         bTranslated = implGetDocTitle( pData->maTargetURL, sNewTitle );
336 
337                                     if ( bTranslated )
338                                         pData->ChangeTitle( sNewTitle );
339                                 }
340                             }
341 
342                             {
343                                 ::osl::MutexGuard aGuard( m_rContentMutex );
344                                 m_rContent.push_back( pData );
345                             }
346                         }
347 
348                         {
349                             ::osl::MutexGuard aGuard( m_aMutex );
350                             bCancelled = m_bCancelled;
351                         }
352                     }
353                     eResult = SUCCESS;
354                 }
355                 catch( CommandAbortedException& )
356                 {
357                     DBG_ERRORFILE( "FileViewContentEnumerator::enumerateFolderContent: caught an CommandAbortedException while enumerating!" );
358                 }
359                 catch( Exception& )
360                 {
361                     DBG_ERRORFILE( "FileViewContentEnumerator::enumerateFolderContent: caught an exception other than CommandAbortedException while enumerating!" );
362                 }
363             }
364         }
365         catch( CommandAbortedException& )
366         {
367             DBG_ERRORFILE( "FileViewContentEnumerator::enumerateFolderContent: caught an CommandAbortedException!" );
368         }
369         catch( Exception& )
370         {
371             DBG_ERRORFILE( "FileViewContentEnumerator::enumerateFolderContent: caught an exception other than CommandAbortedException!" );
372         }
373 
374         IEnumerationResultHandler* pHandler = NULL;
375         {
376             ::osl::MutexGuard aGuard( m_aMutex );
377             pHandler = m_pResultHandler;
378             if ( m_bCancelled )
379                 return ERROR;
380         }
381 
382         {
383             ::osl::MutexGuard aGuard( m_rContentMutex );
384             if ( eResult != SUCCESS )
385                 // clear any "intermediate" and unfinished result
386                 m_rContent.clear();
387         }
388 
389         if ( pHandler )
390             pHandler->enumerationDone( eResult );
391         return eResult;
392     }
393 
394     //--------------------------------------------------------------------
395 
396 	sal_Bool FileViewContentEnumerator::URLOnBlackList ( const ::rtl::OUString& sRealURL )
397 	{
398 		::rtl::OUString entryName = sRealURL.copy( sRealURL.lastIndexOf( rtl::OUString::createFromAscii("/")) +1 );
399 
400 		for (int i = 0; i < m_rBlackList.getLength() ; i++)
401 		{
402 			if ( entryName.equals(  m_rBlackList[i] ) )
403 				return true;
404 		}
405 
406 		return false;
407 	}
408 
409 	//--------------------------------------------------------------------
410     sal_Bool FileViewContentEnumerator::implGetDocTitle( const OUString& _rTargetURL, OUString& _rRet ) const
411     {
412         sal_Bool bRet = sal_False;
413 
414         try
415         {
416             ::osl::MutexGuard aGuard( m_aMutex );
417             if( !m_xDocInfo.is() )
418             {
419                 m_xDocInfo = m_xDocInfo.query(
420                     ::comphelper::getProcessServiceFactory()->createInstance(
421                         String( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.document.StandaloneDocumentInfo") )
422                     )
423                 );
424             }
425 
426             DBG_ASSERT( m_xDocInfo.is(), "FileViewContentEnumerator::implGetDocTitle: no DocumentProperties service!" );
427             if ( !m_xDocInfo.is() )
428                 return sal_False;
429 
430             m_xDocInfo->loadFromURL( _rTargetURL );
431             Reference< XPropertySet > xPropSet( m_xDocInfo, UNO_QUERY );
432 
433             Any aAny = xPropSet->getPropertyValue( OUString::createFromAscii( "Title" ) );
434 
435             OUString sTitle;
436             if ( ( aAny >>= sTitle ) && sTitle.getLength() > 0 )
437             {
438                 _rRet = sTitle;
439                 bRet = sal_True;
440             }
441         }
442         catch ( const Exception& )
443         {
444         }
445 
446         return bRet;
447     }
448 
449     //--------------------------------------------------------------------
450     void SAL_CALL FileViewContentEnumerator::run()
451     {
452         enumerateFolderContent();
453     }
454 
455     //--------------------------------------------------------------------
456     void SAL_CALL FileViewContentEnumerator::onTerminated()
457     {
458         release();
459     }
460 
461 //........................................................................
462 } // namespace svt
463 //........................................................................
464 
465