/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ #include "contentenumeration.hxx" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace svt { #define ROW_TITLE 1 #define ROW_SIZE 2 #define ROW_DATE_MOD 3 #define ROW_DATE_CREATE 4 #define ROW_IS_FOLDER 5 #define ROW_TARGET_URL 6 #define ROW_IS_HIDDEN 7 #define ROW_IS_VOLUME 8 #define ROW_IS_REMOTE 9 #define ROW_IS_REMOVABLE 10 #define ROW_IS_FLOPPY 11 #define ROW_IS_COMPACTDISC 12 using ::com::sun::star::uno::Reference; using ::com::sun::star::uno::Sequence; using ::com::sun::star::uno::Exception; using ::com::sun::star::uno::UNO_QUERY; using ::com::sun::star::util::DateTime; using ::com::sun::star::sdbc::XResultSet; using ::com::sun::star::sdbc::XRow; using ::com::sun::star::ucb::XDynamicResultSet; using ::com::sun::star::ucb::CommandAbortedException; using ::com::sun::star::ucb::XContentAccess; using ::com::sun::star::ucb::XCommandEnvironment; using ::ucbhelper::INCLUDE_FOLDERS_AND_DOCUMENTS; //= FileViewContentEnumerator FileViewContentEnumerator::FileViewContentEnumerator( const Reference< XCommandEnvironment >& _rxCommandEnv, ContentData& _rContentToFill, ::osl::Mutex& _rContentMutex ) :Thread ( "FileViewContentEnumerator" ) ,m_rContent ( _rContentToFill ) ,m_rContentMutex ( _rContentMutex ) ,m_xCommandEnv ( _rxCommandEnv ) ,m_pResultHandler ( nullptr ) ,m_bCancelled ( false ) { } FileViewContentEnumerator::~FileViewContentEnumerator() { } void FileViewContentEnumerator::cancel() { std::unique_lock aGuard( m_aMutex ); m_bCancelled = true; m_pResultHandler = nullptr; m_aFolder.aContent = ::ucbhelper::Content(); m_aFolder.sURL.clear(); } EnumerationResult FileViewContentEnumerator::enumerateFolderContentSync( const FolderDescriptor& _rFolder, const css::uno::Sequence< OUString >& rDenyList ) { { std::unique_lock aGuard( m_aMutex ); m_aFolder = _rFolder; m_pResultHandler = nullptr; m_rDenyList = rDenyList; } return enumerateFolderContent(); } void FileViewContentEnumerator::enumerateFolderContent( const FolderDescriptor& _rFolder, IEnumerationResultHandler* _pResultHandler ) { std::unique_lock aGuard( m_aMutex ); m_aFolder = _rFolder; m_pResultHandler = _pResultHandler; OSL_ENSURE( m_aFolder.aContent.get().is() || !m_aFolder.sURL.isEmpty(), "FileViewContentEnumerator::enumerateFolderContent: invalid folder descriptor!" ); launch(); //TODO: a protocol is missing how to join with the launched thread // before exit(3), to ensure the thread is no longer relying on any // infrastructure while that infrastructure is being shut down in // atexit handlers } EnumerationResult FileViewContentEnumerator::enumerateFolderContent() { EnumerationResult eResult = EnumerationResult::ERROR; try { Reference< XResultSet > xResultSet; Sequence< OUString > aProps{ u"Title"_ustr, u"Size"_ustr, u"DateModified"_ustr, u"DateCreated"_ustr, u"IsFolder"_ustr, u"TargetURL"_ustr, u"IsHidden"_ustr, u"IsVolume"_ustr, u"IsRemote"_ustr, u"IsRemoveable"_ustr, u"IsFloppy"_ustr, u"IsCompactDisc"_ustr }; Reference< XCommandEnvironment > xEnvironment; try { FolderDescriptor aFolder; { std::unique_lock aGuard( m_aMutex ); aFolder = m_aFolder; xEnvironment = m_xCommandEnv; } if ( !aFolder.aContent.get().is() ) { aFolder.aContent = ::ucbhelper::Content( aFolder.sURL, xEnvironment, comphelper::getProcessComponentContext() ); { std::unique_lock aGuard( m_aMutex ); m_aFolder.aContent = aFolder.aContent; } } Reference< XDynamicResultSet > xDynResultSet = aFolder.aContent.createDynamicCursor( aProps, INCLUDE_FOLDERS_AND_DOCUMENTS ); if ( xDynResultSet.is() ) xResultSet = xDynResultSet->getStaticResultSet(); } catch( CommandAbortedException& ) { TOOLS_WARN_EXCEPTION( "svtools.contnr", ""); } catch( Exception& ) { } if ( xResultSet.is() ) { Reference< XRow > xRow( xResultSet, UNO_QUERY ); Reference< XContentAccess > xContentAccess( xResultSet, UNO_QUERY ); try { DateTime aDT; bool bCancelled = false; while ( !bCancelled && xResultSet->next() ) { bool bIsHidden = xRow->getBoolean( ROW_IS_HIDDEN ); // don't show hidden files if ( !bIsHidden || xRow->wasNull() ) { aDT = xRow->getTimestamp( ROW_DATE_MOD ); bool bContainsDate = !xRow->wasNull(); if ( !bContainsDate ) { aDT = xRow->getTimestamp( ROW_DATE_CREATE ); bContainsDate = !xRow->wasNull(); } OUString aContentURL = xContentAccess->queryContentIdentifierString(); OUString aTargetURL = xRow->getString( ROW_TARGET_URL ); bool bHasTargetURL = !xRow->wasNull() && !aTargetURL.isEmpty(); OUString sRealURL = bHasTargetURL ? aTargetURL : aContentURL; // check for restrictions { std::unique_lock aGuard( m_aMutex ); if ( /* m_rDenyList.hasElements() && */ URLOnDenyList ( sRealURL ) ) continue; } std::unique_ptr pData(new SortingData_Impl); pData->maTargetURL = sRealURL; pData->mbIsFolder = xRow->getBoolean( ROW_IS_FOLDER ) && !xRow->wasNull(); pData->mbIsVolume = xRow->getBoolean( ROW_IS_VOLUME ) && !xRow->wasNull(); pData->mbIsRemote = xRow->getBoolean( ROW_IS_REMOTE ) && !xRow->wasNull(); pData->mbIsRemoveable = xRow->getBoolean( ROW_IS_REMOVABLE ) && !xRow->wasNull(); pData->mbIsFloppy = xRow->getBoolean( ROW_IS_FLOPPY ) && !xRow->wasNull(); pData->mbIsCompactDisc = xRow->getBoolean( ROW_IS_COMPACTDISC ) && !xRow->wasNull(); pData->SetNewTitle( xRow->getString( ROW_TITLE ) ); pData->maSize = xRow->getLong( ROW_SIZE ); if ( bHasTargetURL && INetURLObject( aContentURL ).GetProtocol() == INetProtocol::VndSunStarHier ) { ::ucbhelper::Content aCnt( aTargetURL, xEnvironment, comphelper::getProcessComponentContext() ); try { aCnt.getPropertyValue(u"Size"_ustr) >>= pData->maSize; aCnt.getPropertyValue(u"DateModified"_ustr) >>= aDT; } catch (...) {} } if ( bContainsDate ) { pData->maModDate = ::DateTime( aDT ); } if ( pData->mbIsFolder ) { ::svtools::VolumeInfo aVolInfo( pData->mbIsVolume, pData->mbIsRemote, pData->mbIsRemoveable, pData->mbIsFloppy, pData->mbIsCompactDisc ); pData->maType = SvFileInformationManager::GetFolderDescription( aVolInfo ); } else pData->maType = SvFileInformationManager::GetFileDescription( INetURLObject( pData->maTargetURL ) ); { ::osl::MutexGuard aGuard( m_rContentMutex ); m_rContent.push_back( std::move(pData) ); } } { std::unique_lock aGuard( m_aMutex ); bCancelled = m_bCancelled; } } eResult = EnumerationResult::SUCCESS; } catch( Exception const & ) { TOOLS_WARN_EXCEPTION( "svtools.contnr", "FileViewContentEnumerator::enumerateFolderContent: caught an exception while enumerating"); } } } catch( Exception const & ) { TOOLS_WARN_EXCEPTION( "svtools.contnr", "FileViewContentEnumerator::enumerateFolderContent" ); } IEnumerationResultHandler* pHandler = nullptr; { std::unique_lock aGuard( m_aMutex ); pHandler = m_pResultHandler; if ( m_bCancelled ) return EnumerationResult::ERROR; } { ::osl::MutexGuard aGuard( m_rContentMutex ); if ( eResult != EnumerationResult::SUCCESS ) // clear any "intermediate" and unfinished result m_rContent.clear(); } if ( pHandler ) pHandler->enumerationDone( eResult ); return eResult; } bool FileViewContentEnumerator::URLOnDenyList ( std::u16string_view sRealURL ) { std::u16string_view entryName = sRealURL.substr( sRealURL.rfind( '/' ) + 1 ); return comphelper::findValue(m_rDenyList, entryName) != -1; } void FileViewContentEnumerator::execute() { enumerateFolderContent(); } } // namespace svt /* vim:set shiftwidth=4 softtabstop=4 expandtab: */