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