/* -*- 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 #include #if HAVE_FEATURE_MACOSX_SANDBOX #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "filtask.hxx" #include "filcmd.hxx" #include "filglob.hxx" #include "filinpstr.hxx" #include "filprp.hxx" #include "filrset.hxx" #include "filstr.hxx" #include "prov.hxx" /******************************************************************************/ /* */ /* TaskHandling */ /* */ /******************************************************************************/ using namespace fileaccess; using namespace com::sun::star; using namespace com::sun::star::uno; using namespace com::sun::star::ucb; #if OSL_DEBUG_LEVEL > 0 #define THROW_WHERE SAL_WHERE #else #define THROW_WHERE "" #endif TaskManager::UnqPathData::UnqPathData() : properties( nullptr ), notifier( nullptr ), xS( nullptr ), xC( nullptr ), xA( nullptr ) { // empty } TaskManager::UnqPathData::UnqPathData( const UnqPathData& a ) : properties( a.properties ), notifier( a.notifier ), xS( a.xS ), xC( a.xC ), xA( a.xA ) { } TaskManager::UnqPathData& TaskManager::UnqPathData::operator=( UnqPathData& a ) { properties = a.properties; notifier = a.notifier; xS = a.xS; xC = a.xC; xA = a.xA; a.properties = nullptr; a.notifier = nullptr; a.xS = nullptr; a.xC = nullptr; a.xA = nullptr; return *this; } TaskManager::UnqPathData::~UnqPathData() { delete properties; delete notifier; } TaskManager::MyProperty::MyProperty( const OUString& thePropertyName ) : PropertyName( thePropertyName ) , Handle(-1) , isNative(false) , State(beans::PropertyState_AMBIGUOUS_VALUE) , Attributes(0) { // empty } TaskManager::MyProperty::MyProperty( bool theisNative, const OUString& thePropertyName, sal_Int32 theHandle, const css::uno::Type& theTyp, const css::uno::Any& theValue, const css::beans::PropertyState& theState, sal_Int16 theAttributes ) : PropertyName( thePropertyName ), Handle( theHandle ), isNative( theisNative ), Typ( theTyp ), Value( theValue ), State( theState ), Attributes( theAttributes ) { // empty } TaskManager::MyProperty::~MyProperty() { // empty for now } #include "filinl.hxx" TaskManager::TaskManager( const uno::Reference< uno::XComponentContext >& rxContext, FileProvider* pProvider, bool bWithConfig ) : m_nCommandId( 0 ), m_bWithConfig( bWithConfig ), m_pProvider( pProvider ), m_xContext( rxContext ), Title( "Title" ), CasePreservingURL( "CasePreservingURL" ), IsDocument( "IsDocument" ), IsFolder( "IsFolder" ), DateModified( "DateModified" ), Size( "Size" ), IsVolume( "IsVolume" ), IsRemoveable( "IsRemoveable" ), IsRemote( "IsRemote" ), IsCompactDisc( "IsCompactDisc" ), IsFloppy( "IsFloppy" ), IsHidden( "IsHidden" ), ContentType( "ContentType" ), IsReadOnly( "IsReadOnly" ), CreatableContentsInfo( "CreatableContentsInfo" ), FolderContentType( "application/vnd.sun.staroffice.fsys-folder" ), FileContentType( "application/vnd.sun.staroffice.fsys-file" ), m_sCommandInfo( 9 ) { // Title m_aDefaultProperties.insert( MyProperty( true, Title, -1 , cppu::UnoType::get(), uno::Any(), beans::PropertyState_DEFAULT_VALUE, beans::PropertyAttribute::MAYBEVOID | beans::PropertyAttribute::BOUND ) ); // CasePreservingURL m_aDefaultProperties.insert( MyProperty( true, CasePreservingURL, -1 , cppu::UnoType::get(), uno::Any(), beans::PropertyState_DEFAULT_VALUE, beans::PropertyAttribute::MAYBEVOID | beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ) ); // IsFolder m_aDefaultProperties.insert( MyProperty( true, IsFolder, -1 , cppu::UnoType::get(), uno::Any(), beans::PropertyState_DEFAULT_VALUE, beans::PropertyAttribute::MAYBEVOID | beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ) ); // IsDocument m_aDefaultProperties.insert( MyProperty( true, IsDocument, -1 , cppu::UnoType::get(), uno::Any(), beans::PropertyState_DEFAULT_VALUE, beans::PropertyAttribute::MAYBEVOID | beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ) ); // Removable m_aDefaultProperties.insert( MyProperty( true, IsVolume, -1 , cppu::UnoType::get(), uno::Any(), beans::PropertyState_DEFAULT_VALUE, beans::PropertyAttribute::MAYBEVOID | beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ) ); // Removable m_aDefaultProperties.insert( MyProperty( true, IsRemoveable, -1 , cppu::UnoType::get(), uno::Any(), beans::PropertyState_DEFAULT_VALUE, beans::PropertyAttribute::MAYBEVOID | beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ) ); // Remote m_aDefaultProperties.insert( MyProperty( true, IsRemote, -1 , cppu::UnoType::get(), uno::Any(), beans::PropertyState_DEFAULT_VALUE, beans::PropertyAttribute::MAYBEVOID | beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ) ); // CompactDisc m_aDefaultProperties.insert( MyProperty( true, IsCompactDisc, -1 , cppu::UnoType::get(), uno::Any(), beans::PropertyState_DEFAULT_VALUE, beans::PropertyAttribute::MAYBEVOID | beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ) ); // Floppy m_aDefaultProperties.insert( MyProperty( true, IsFloppy, -1 , cppu::UnoType::get(), uno::Any(), beans::PropertyState_DEFAULT_VALUE, beans::PropertyAttribute::MAYBEVOID | beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ) ); // Hidden m_aDefaultProperties.insert( MyProperty( true, IsHidden, -1 , cppu::UnoType::get(), uno::Any(), beans::PropertyState_DEFAULT_VALUE, beans::PropertyAttribute::MAYBEVOID | beans::PropertyAttribute::BOUND #if defined(_WIN32) )); #else | beans::PropertyAttribute::READONLY)); // under unix/linux only readable #endif // ContentType m_aDefaultProperties.insert( MyProperty( false, ContentType, -1 , cppu::UnoType::get(), uno::Any(OUString()), beans::PropertyState_DEFAULT_VALUE, beans::PropertyAttribute::MAYBEVOID | beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ) ); // DateModified m_aDefaultProperties.insert( MyProperty( true, DateModified, -1 , cppu::UnoType::get(), uno::Any(), beans::PropertyState_DEFAULT_VALUE, beans::PropertyAttribute::MAYBEVOID | beans::PropertyAttribute::BOUND ) ); // Size m_aDefaultProperties.insert( MyProperty( true, Size, -1, cppu::UnoType::get(), uno::Any(), beans::PropertyState_DEFAULT_VALUE, beans::PropertyAttribute::MAYBEVOID | beans::PropertyAttribute::BOUND ) ); // IsReadOnly m_aDefaultProperties.insert( MyProperty( true, IsReadOnly, -1 , cppu::UnoType::get(), uno::Any(), beans::PropertyState_DEFAULT_VALUE, beans::PropertyAttribute::MAYBEVOID | beans::PropertyAttribute::BOUND ) ); // CreatableContentsInfo m_aDefaultProperties.insert( MyProperty( true, CreatableContentsInfo, -1 , cppu::UnoType>::get(), uno::Any(), beans::PropertyState_DEFAULT_VALUE, beans::PropertyAttribute::MAYBEVOID | beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ) ); // Commands m_sCommandInfo[0].Name = "getCommandInfo"; m_sCommandInfo[0].Handle = -1; m_sCommandInfo[0].ArgType = cppu::UnoType::get(); m_sCommandInfo[1].Name = "getPropertySetInfo"; m_sCommandInfo[1].Handle = -1; m_sCommandInfo[1].ArgType = cppu::UnoType::get(); m_sCommandInfo[2].Name = "getPropertyValues"; m_sCommandInfo[2].Handle = -1; m_sCommandInfo[2].ArgType = cppu::UnoType>::get(); m_sCommandInfo[3].Name = "setPropertyValues"; m_sCommandInfo[3].Handle = -1; m_sCommandInfo[3].ArgType = cppu::UnoType>::get(); m_sCommandInfo[4].Name = "open"; m_sCommandInfo[4].Handle = -1; m_sCommandInfo[4].ArgType = cppu::UnoType::get(); m_sCommandInfo[5].Name = "transfer"; m_sCommandInfo[5].Handle = -1; m_sCommandInfo[5].ArgType = cppu::UnoType::get(); m_sCommandInfo[6].Name = "delete"; m_sCommandInfo[6].Handle = -1; m_sCommandInfo[6].ArgType = cppu::UnoType::get(); m_sCommandInfo[7].Name = "insert"; m_sCommandInfo[7].Handle = -1; m_sCommandInfo[7].ArgType = cppu::UnoType::get(); m_sCommandInfo[7].Name = "createNewContent"; m_sCommandInfo[7].Handle = -1; m_sCommandInfo[7].ArgType = cppu::UnoType::get(); if(m_bWithConfig) { uno::Reference< XPropertySetRegistryFactory > xRegFac = ucb::Store::create( m_xContext ); // Open/create a registry m_xFileRegistry = xRegFac->createPropertySetRegistry( OUString() ); } } TaskManager::~TaskManager() { } void SAL_CALL TaskManager::startTask( sal_Int32 CommandId, const uno::Reference< XCommandEnvironment >& xCommandEnv ) { osl::MutexGuard aGuard( m_aMutex ); TaskMap::iterator it = m_aTaskMap.find( CommandId ); if( it != m_aTaskMap.end() ) { throw DuplicateCommandIdentifierException( OSL_LOG_PREFIX ); } m_aTaskMap[ CommandId ] = TaskHandling( xCommandEnv ); } void SAL_CALL TaskManager::endTask( sal_Int32 CommandId, const OUString& aUncPath, BaseContent* pContent) { osl::MutexGuard aGuard( m_aMutex ); TaskMap::iterator it = m_aTaskMap.find( CommandId ); if( it == m_aTaskMap.end() ) return; sal_Int32 ErrorCode = it->second.getInstalledError(); sal_Int32 MinorCode = it->second.getMinorErrorCode(); bool isHandled = it->second.isHandled(); Reference< XCommandEnvironment > xComEnv = it->second.getCommandEnvironment(); m_aTaskMap.erase( it ); if( ErrorCode != TASKHANDLER_NO_ERROR ) throw_handler( ErrorCode, MinorCode, xComEnv, aUncPath, pContent, isHandled); } void SAL_CALL TaskManager::abort( sal_Int32 CommandId ) { if( CommandId ) { osl::MutexGuard aGuard( m_aMutex ); TaskMap::iterator it = m_aTaskMap.find( CommandId ); if( it == m_aTaskMap.end() ) return; else it->second.abort(); } } void SAL_CALL TaskManager::clearError( sal_Int32 CommandId ) { osl::MutexGuard aGuard( m_aMutex ); TaskMap::iterator it = m_aTaskMap.find( CommandId ); if( it != m_aTaskMap.end() ) it->second.clearError(); } void SAL_CALL TaskManager::retrieveError( sal_Int32 CommandId, sal_Int32 &ErrorCode, sal_Int32 &minorCode) { osl::MutexGuard aGuard( m_aMutex ); TaskMap::iterator it = m_aTaskMap.find( CommandId ); if( it != m_aTaskMap.end() ) { ErrorCode = it->second.getInstalledError(); minorCode = it->second. getMinorErrorCode(); } } void SAL_CALL TaskManager::installError( sal_Int32 CommandId, sal_Int32 ErrorCode, sal_Int32 MinorCode ) { osl::MutexGuard aGuard( m_aMutex ); TaskMap::iterator it = m_aTaskMap.find( CommandId ); if( it != m_aTaskMap.end() ) it->second.installError( ErrorCode,MinorCode ); } sal_Int32 SAL_CALL TaskManager::getCommandId() { osl::MutexGuard aGuard( m_aMutex ); return ++m_nCommandId; } void SAL_CALL TaskManager::handleTask( sal_Int32 CommandId, const uno::Reference< task::XInteractionRequest >& request ) { osl::MutexGuard aGuard( m_aMutex ); TaskMap::iterator it = m_aTaskMap.find( CommandId ); uno::Reference< task::XInteractionHandler > xInt; if( it != m_aTaskMap.end() ) { xInt = it->second.getInteractionHandler(); if( xInt.is() ) xInt->handle( request ); it->second.setHandled(); } } /*********************************************************************************/ /* */ /* de/registerNotifier-Implementation */ /* */ /*********************************************************************************/ // This two methods register and deregister a change listener for the content belonging // to URL aUnqPath void SAL_CALL TaskManager::registerNotifier( const OUString& aUnqPath, Notifier* pNotifier ) { osl::MutexGuard aGuard( m_aMutex ); ContentMap::iterator it = m_aContent.emplace( aUnqPath,UnqPathData() ).first; if( ! it->second.notifier ) it->second.notifier = new NotifierList; std::list< Notifier* >& nlist = *( it->second.notifier ); std::list::iterator it1 = nlist.begin(); while( it1 != nlist.end() ) // Every "Notifier" only once { if( *it1 == pNotifier ) return; ++it1; } nlist.push_back( pNotifier ); } void SAL_CALL TaskManager::deregisterNotifier( const OUString& aUnqPath,Notifier* pNotifier ) { osl::MutexGuard aGuard( m_aMutex ); ContentMap::iterator it = m_aContent.find( aUnqPath ); if( it == m_aContent.end() ) return; it->second.notifier->remove( pNotifier ); if( it->second.notifier->empty() ) m_aContent.erase( it ); } /*********************************************************************************/ /* */ /* de/associate-Implementation */ /* */ /*********************************************************************************/ // Used to associate and deassociate a new property with // the content belonging to URL UnqPath. // The default value and the attributes are input void SAL_CALL TaskManager::associate( const OUString& aUnqPath, const OUString& PropertyName, const uno::Any& DefaultValue, const sal_Int16 Attributes ) { MyProperty newProperty( false, PropertyName, -1, DefaultValue.getValueType(), DefaultValue, beans::PropertyState_DEFAULT_VALUE, Attributes ); TaskManager::PropertySet::iterator it1 = m_aDefaultProperties.find( newProperty ); if( it1 != m_aDefaultProperties.end() ) throw beans::PropertyExistException( THROW_WHERE ); { osl::MutexGuard aGuard( m_aMutex ); ContentMap::iterator it = m_aContent.emplace( aUnqPath,UnqPathData() ).first; // Load the XPersistentPropertySetInfo and create it, if it does not exist load( it,true ); PropertySet& properties = *(it->second.properties); it1 = properties.find( newProperty ); if( it1 != properties.end() ) throw beans::PropertyExistException(THROW_WHERE ); // Property does not exist properties.insert( newProperty ); it->second.xC->addProperty( PropertyName,Attributes,DefaultValue ); } notifyPropertyAdded( getPropertySetListeners( aUnqPath ), PropertyName ); } void SAL_CALL TaskManager::deassociate( const OUString& aUnqPath, const OUString& PropertyName ) { MyProperty oldProperty( PropertyName ); TaskManager::PropertySet::iterator it1 = m_aDefaultProperties.find( oldProperty ); if( it1 != m_aDefaultProperties.end() ) throw beans::NotRemoveableException( THROW_WHERE ); osl::MutexGuard aGuard( m_aMutex ); ContentMap::iterator it = m_aContent.emplace( aUnqPath,UnqPathData() ).first; load( it,false ); PropertySet& properties = *(it->second.properties); it1 = properties.find( oldProperty ); if( it1 == properties.end() ) throw beans::UnknownPropertyException( THROW_WHERE ); properties.erase( it1 ); if( it->second.xC.is() ) it->second.xC->removeProperty( PropertyName ); if( properties.size() == 9 ) { MyProperty ContentTProperty( ContentType ); if( properties.find( ContentTProperty )->getState() == beans::PropertyState_DEFAULT_VALUE ) { it->second.xS = nullptr; it->second.xC = nullptr; it->second.xA = nullptr; if(m_xFileRegistry.is()) m_xFileRegistry->removePropertySet( aUnqPath ); } } notifyPropertyRemoved( getPropertySetListeners( aUnqPath ), PropertyName ); } /*********************************************************************************/ /* */ /* page-Implementation */ /* */ /*********************************************************************************/ // Given an xOutputStream, this method writes the content of the file belonging to // URL aUnqPath into the XOutputStream void SAL_CALL TaskManager::page( sal_Int32 CommandId, const OUString& aUnqPath, const uno::Reference< io::XOutputStream >& xOutputStream ) { osl::File aFile( aUnqPath ); osl::FileBase::RC err = aFile.open( osl_File_OpenFlag_Read ); if( err != osl::FileBase::E_None ) { aFile.close(); installError( CommandId, TASKHANDLING_OPEN_FILE_FOR_PAGING, err ); return; } const sal_uInt64 bfz = 4*1024; sal_Int8 BFF[bfz]; sal_uInt64 nrc; // Retrieved number of Bytes; do { err = aFile.read( static_cast(BFF),bfz,nrc ); if( err == osl::FileBase::E_None ) { uno::Sequence< sal_Int8 > seq( BFF, (sal_uInt32)nrc ); try { xOutputStream->writeBytes( seq ); } catch (const io::NotConnectedException&) { installError( CommandId, TASKHANDLING_NOTCONNECTED_FOR_PAGING ); break; } catch (const io::BufferSizeExceededException&) { installError( CommandId, TASKHANDLING_BUFFERSIZEEXCEEDED_FOR_PAGING ); break; } catch (const io::IOException&) { installError( CommandId, TASKHANDLING_IOEXCEPTION_FOR_PAGING ); break; } } else { installError( CommandId, TASKHANDLING_READING_FILE_FOR_PAGING, err ); break; } } while( nrc == bfz ); aFile.close(); try { xOutputStream->closeOutput(); } catch (const io::NotConnectedException&) { } catch (const io::BufferSizeExceededException&) { } catch (const io::IOException&) { } } /*********************************************************************************/ /* */ /* open-Implementation */ /* */ /*********************************************************************************/ // Given a file URL aUnqPath, this methods returns a XInputStream which reads from the open file. uno::Reference< io::XInputStream > SAL_CALL TaskManager::open( sal_Int32 CommandId, const OUString& aUnqPath, bool bLock ) { XInputStream_impl* pInputStream = new XInputStream_impl( aUnqPath, bLock ); // from filinpstr.hxx sal_Int32 ErrorCode = pInputStream->CtorSuccess(); if( ErrorCode != TASKHANDLER_NO_ERROR ) { installError( CommandId, ErrorCode, pInputStream->getMinorError() ); delete pInputStream; pInputStream = nullptr; } return uno::Reference< io::XInputStream >( pInputStream ); } /*********************************************************************************/ /* */ /* open for read/write access-Implementation */ /* */ /*********************************************************************************/ // Given a file URL aUnqPath, this methods returns a XStream which can be used // to read and write from/to the file. uno::Reference< io::XStream > SAL_CALL TaskManager::open_rw( sal_Int32 CommandId, const OUString& aUnqPath, bool bLock ) { XStream_impl* pStream = new XStream_impl( aUnqPath, bLock ); // from filstr.hxx sal_Int32 ErrorCode = pStream->CtorSuccess(); if( ErrorCode != TASKHANDLER_NO_ERROR ) { installError( CommandId, ErrorCode, pStream->getMinorError() ); delete pStream; pStream = nullptr; } return uno::Reference< io::XStream >( pStream ); } /*********************************************************************************/ /* */ /* ls-Implementation */ /* */ /*********************************************************************************/ // This method returns the result set containing the children of the directory belonging // to file URL aUnqPath uno::Reference< XDynamicResultSet > SAL_CALL TaskManager::ls( sal_Int32 CommandId, const OUString& aUnqPath, const sal_Int32 OpenMode, const uno::Sequence< beans::Property >& seq, const uno::Sequence< NumberedSortingInfo >& seqSort ) { XResultSet_impl* p = new XResultSet_impl( this,aUnqPath,OpenMode,seq,seqSort ); sal_Int32 ErrorCode = p->CtorSuccess(); if( ErrorCode != TASKHANDLER_NO_ERROR ) { installError( CommandId, ErrorCode, p->getMinorError() ); delete p; p = nullptr; } return uno::Reference< XDynamicResultSet > ( p ); } /*********************************************************************************/ /* */ /* info_c implementation */ /* */ /*********************************************************************************/ // Info for commands uno::Reference< XCommandInfo > SAL_CALL TaskManager::info_c() { XCommandInfo_impl* p = new XCommandInfo_impl( this ); return uno::Reference< XCommandInfo >( p ); } /*********************************************************************************/ /* */ /* info_p-Implementation */ /* */ /*********************************************************************************/ // Info for the properties uno::Reference< beans::XPropertySetInfo > SAL_CALL TaskManager::info_p( const OUString& aUnqPath ) { osl::MutexGuard aGuard( m_aMutex ); XPropertySetInfo_impl* p = new XPropertySetInfo_impl( this,aUnqPath ); return uno::Reference< beans::XPropertySetInfo >( p ); } /*********************************************************************************/ /* */ /* setv-Implementation */ /* */ /*********************************************************************************/ // Sets the values of the properties belonging to fileURL aUnqPath uno::Sequence< uno::Any > SAL_CALL TaskManager::setv( const OUString& aUnqPath, const uno::Sequence< beans::PropertyValue >& values ) { osl::MutexGuard aGuard( m_aMutex ); sal_Int32 propChanged = 0; uno::Sequence< uno::Any > ret( values.getLength() ); uno::Sequence< beans::PropertyChangeEvent > seqChanged( values.getLength() ); TaskManager::ContentMap::iterator it = m_aContent.find( aUnqPath ); PropertySet& properties = *( it->second.properties ); TaskManager::PropertySet::iterator it1; uno::Any aAny; for( sal_Int32 i = 0; i < values.getLength(); ++i ) { MyProperty toset( values[i].Name ); it1 = properties.find( toset ); if( it1 == properties.end() ) { ret[i] <<= beans::UnknownPropertyException( THROW_WHERE ); continue; } aAny = it1->getValue(); if( aAny == values[i].Value ) continue; // nothing needs to be changed if( it1->getAttributes() & beans::PropertyAttribute::READONLY ) { ret[i] <<= lang::IllegalAccessException( THROW_WHERE ); continue; } seqChanged[ propChanged ].PropertyName = values[i].Name; seqChanged[ propChanged ].PropertyHandle = -1; seqChanged[ propChanged ].Further = false; seqChanged[ propChanged ].OldValue = aAny; seqChanged[ propChanged++ ].NewValue = values[i].Value; it1->setValue( values[i].Value ); // Put the new value into the local cash if( ! it1->IsNative() ) { // Also put logical properties into storage if( !it->second.xS.is() ) load( it,true ); if( ( values[i].Name == ContentType ) && it1->getState() == beans::PropertyState_DEFAULT_VALUE ) { // Special logic for ContentType // 09.07.01: Not reached anymore, because ContentType is readonly it1->setState( beans::PropertyState_DIRECT_VALUE ); it->second.xC->addProperty( values[i].Name, beans::PropertyAttribute::MAYBEVOID, values[i].Value ); } try { it->second.xS->setPropertyValue( values[i].Name,values[i].Value ); } catch (const uno::Exception&e) { --propChanged; // unsuccessful setting ret[i] <<= e; } } else { // native properties // Setting of physical file properties if( values[i].Name == Size ) { sal_Int64 newSize = 0; if( values[i].Value >>= newSize ) { // valid value for the size osl::File aFile(aUnqPath); bool err = aFile.open(osl_File_OpenFlag_Write) != osl::FileBase::E_None || aFile.setSize(sal_uInt64(newSize)) != osl::FileBase::E_None || aFile.close() != osl::FileBase::E_None; if( err ) { --propChanged; // unsuccessful setting uno::Sequence names(comphelper::InitAnyPropertySequence( { {"Uri", uno::Any(aUnqPath)} })); ret[i] <<= InteractiveAugmentedIOException( OUString(), nullptr, task::InteractionClassification_ERROR, IOErrorCode_GENERAL, names ); } } else ret[i] <<= beans::IllegalTypeException( THROW_WHERE ); } else if(values[i].Name == IsReadOnly || values[i].Name == IsHidden) { bool value = false; if( values[i].Value >>= value ) { osl::DirectoryItem aDirItem; osl::FileBase::RC err = osl::DirectoryItem::get(aUnqPath,aDirItem); sal_uInt64 nAttributes(0); if(err == osl::FileBase::E_None) { osl::FileStatus aFileStatus(osl_FileStatus_Mask_Attributes); err = aDirItem.getFileStatus(aFileStatus); if(err == osl::FileBase::E_None && aFileStatus.isValid(osl_FileStatus_Mask_Attributes)) nAttributes = aFileStatus.getAttributes(); } // now we have the attributes provided all went well. if(err == osl::FileBase::E_None) { if(values[i].Name == IsReadOnly) { nAttributes &= ~(osl_File_Attribute_OwnWrite | osl_File_Attribute_GrpWrite | osl_File_Attribute_OthWrite | osl_File_Attribute_ReadOnly); if(value) nAttributes |= osl_File_Attribute_ReadOnly; else nAttributes |= ( osl_File_Attribute_OwnWrite | osl_File_Attribute_GrpWrite | osl_File_Attribute_OthWrite); } else if(values[i].Name == IsHidden) { nAttributes &= ~(osl_File_Attribute_Hidden); if(value) nAttributes |= osl_File_Attribute_Hidden; } err = osl::File::setAttributes( aUnqPath,nAttributes); } if( err != osl::FileBase::E_None ) { --propChanged; // unsuccessful setting uno::Sequence names(comphelper::InitAnyPropertySequence( { {"Uri", uno::Any(aUnqPath)} })); IOErrorCode ioError; switch( err ) { case osl::FileBase::E_NOMEM: // not enough memory for allocating structures
ioError = IOErrorCode_OUT_OF_MEMORY; break; case osl::FileBase::E_INVAL: // the format of the parameters was not valid

ioError = IOErrorCode_INVALID_PARAMETER; break; case osl::FileBase::E_NAMETOOLONG: // File name too long
ioError = IOErrorCode_NAME_TOO_LONG; break; case osl::FileBase::E_NOENT: // No such file or directory
case osl::FileBase::E_NOLINK: // Link has been severed
ioError = IOErrorCode_NOT_EXISTING; break; case osl::FileBase::E_ROFS: // #i4735# handle ROFS transparently // as ACCESS_DENIED case osl::FileBase::E_PERM: case osl::FileBase::E_ACCES: // permission denied
ioError = IOErrorCode_ACCESS_DENIED; break; case osl::FileBase::E_LOOP: // Too many symbolic links encountered
case osl::FileBase::E_FAULT: // Bad address
case osl::FileBase::E_IO: // I/O error
case osl::FileBase::E_NOSYS: // Function not implemented
case osl::FileBase::E_MULTIHOP: // Multihop attempted
case osl::FileBase::E_INTR: // function call was interrupted

default: ioError = IOErrorCode_GENERAL; break; } ret[i] <<= InteractiveAugmentedIOException( OUString(), nullptr, task::InteractionClassification_ERROR, ioError, names ); } } else ret[i] <<= beans::IllegalTypeException( THROW_WHERE ); } } } // end for if( propChanged ) { seqChanged.realloc( propChanged ); notifyPropertyChanges( getPropertyChangeNotifier( aUnqPath ),seqChanged ); } return ret; } /*********************************************************************************/ /* */ /* getv-Implementation */ /* */ /*********************************************************************************/ // Reads the values of the properties belonging to fileURL aUnqPath; // Returns an XRow object containing the values in the requested order. uno::Reference< sdbc::XRow > SAL_CALL TaskManager::getv( sal_Int32 CommandId, const OUString& aUnqPath, const uno::Sequence< beans::Property >& properties ) { uno::Sequence< uno::Any > seq( properties.getLength() ); sal_Int32 n_Mask; getMaskFromProperties( n_Mask,properties ); osl::FileStatus aFileStatus( n_Mask ); osl::DirectoryItem aDirItem; osl::FileBase::RC nError1 = osl::DirectoryItem::get( aUnqPath,aDirItem ); if( nError1 != osl::FileBase::E_None ) installError(CommandId, TASKHANDLING_OPEN_FILE_FOR_PAGING, // BEAWARE, REUSED nError1); osl::FileBase::RC nError2 = aDirItem.getFileStatus( aFileStatus ); if( nError1 == osl::FileBase::E_None && nError2 != osl::FileBase::E_None ) installError(CommandId, TASKHANDLING_OPEN_FILE_FOR_PAGING, // BEAWARE, REUSED nError2); { osl::MutexGuard aGuard( m_aMutex ); TaskManager::ContentMap::iterator it = m_aContent.find( aUnqPath ); commit( it,aFileStatus ); TaskManager::PropertySet::iterator it1; PropertySet& propset = *(it->second.properties); for( sal_Int32 i = 0; i < seq.getLength(); ++i ) { MyProperty readProp( properties[i].Name ); it1 = propset.find( readProp ); if( it1 == propset.end() ) seq[i] = uno::Any(); else seq[i] = it1->getValue(); } } XRow_impl* p = new XRow_impl( this,seq ); return uno::Reference< sdbc::XRow >( p ); } /********************************************************************************/ /* */ /* transfer-commandos */ /* */ /********************************************************************************/ /********************************************************************************/ /* */ /* move-implementation */ /* */ /********************************************************************************/ // Moves the content belonging to fileURL srcUnqPath to fileURL dstUnqPath. void SAL_CALL TaskManager::move( sal_Int32 CommandId, const OUString& srcUnqPath, const OUString& dstUnqPathIn, const sal_Int32 NameClash ) { // --> #i88446# Method notifyContentExchanged( getContentExchangedEventListeners( srcUnqPath,dstUnqPath,!isDocument ) ); crashes if // srcUnqPath and dstUnqPathIn are equal if( srcUnqPath == dstUnqPathIn ) return; osl::FileBase::RC nError; OUString dstUnqPath( dstUnqPathIn ); switch( NameClash ) { case NameClash::KEEP: { nError = osl_File_move( srcUnqPath,dstUnqPath,true ); if( nError != osl::FileBase::E_None && nError != osl::FileBase::E_EXIST ) { installError( CommandId, TASKHANDLING_KEEPERROR_FOR_MOVE, nError ); return; } break; } case NameClash::OVERWRITE: { // stat to determine whether we have a symlink OUString targetPath(dstUnqPath); osl::FileStatus aStatus(osl_FileStatus_Mask_Type|osl_FileStatus_Mask_LinkTargetURL); osl::DirectoryItem aItem; osl::DirectoryItem::get(dstUnqPath,aItem); aItem.getFileStatus(aStatus); if( aStatus.isValid(osl_FileStatus_Mask_Type) && aStatus.isValid(osl_FileStatus_Mask_LinkTargetURL) && aStatus.getFileType() == osl::FileStatus::Link ) targetPath = aStatus.getLinkTargetURL(); // Will do nothing if file does not exist. osl::File::remove( targetPath ); nError = osl_File_move( srcUnqPath,targetPath ); if( nError != osl::FileBase::E_None ) { installError( CommandId, TASKHANDLING_OVERWRITE_FOR_MOVE, nError ); return; } break; } case NameClash::RENAME: { OUString newDstUnqPath; nError = osl_File_move( srcUnqPath,dstUnqPath,true ); if( nError == osl::FileBase::E_EXIST ) { // "invent" a new valid title. sal_Int32 nPos = -1; sal_Int32 nLastDot = dstUnqPath.lastIndexOf( '.' ); sal_Int32 nLastSlash = dstUnqPath.lastIndexOf( '/' ); if( ( nLastSlash < nLastDot ) // dot is part of last(!) path segment && ( nLastSlash != ( nLastDot - 1 ) ) ) // file name does not start with a dot nPos = nLastDot; else nPos = dstUnqPath.getLength(); sal_Int32 nTry = 0; do { newDstUnqPath = dstUnqPath; OUString aPostfix = "_" + OUString::number( ++nTry ); newDstUnqPath = newDstUnqPath.replaceAt( nPos, 0, aPostfix ); nError = osl_File_move( srcUnqPath,newDstUnqPath,true ); } while( ( nError == osl::FileBase::E_EXIST ) && ( nTry < 10000 ) ); } if( nError == osl::FileBase::E_EXIST ) { installError( CommandId, TASKHANDLING_RENAME_FOR_MOVE ); return; } else if( nError != osl::FileBase::E_None ) { installError( CommandId, TASKHANDLING_RENAMEMOVE_FOR_MOVE, nError ); return; } else dstUnqPath = newDstUnqPath; break; } case NameClash::ERROR: { nError = osl_File_move( srcUnqPath,dstUnqPath,true ); if( nError == osl::FileBase::E_EXIST ) { installError( CommandId, TASKHANDLING_NAMECLASH_FOR_MOVE ); return; } else if( nError != osl::FileBase::E_None ) { installError( CommandId, TASKHANDLING_NAMECLASHMOVE_FOR_MOVE, nError ); return; } break; } case NameClash::ASK: default: { nError = osl_File_move( srcUnqPath,dstUnqPath,true ); if( nError == osl::FileBase::E_EXIST ) { installError( CommandId, TASKHANDLING_NAMECLASHSUPPORT_FOR_MOVE, NameClash::ASK); return; } } break; } // Determine, whether we have moved a file or a folder osl::DirectoryItem aItem; nError = osl::DirectoryItem::get( dstUnqPath,aItem ); if( nError != osl::FileBase::E_None ) { installError( CommandId, TASKHANDLING_TRANSFER_BY_MOVE_SOURCE, nError ); return; } osl::FileStatus aStatus( osl_FileStatus_Mask_Type ); nError = aItem.getFileStatus( aStatus ); if( nError != osl::FileBase::E_None || ! aStatus.isValid( osl_FileStatus_Mask_Type ) ) { installError( CommandId, TASKHANDLING_TRANSFER_BY_MOVE_SOURCESTAT, nError ); return; } bool isDocument = ( aStatus.getFileType() == osl::FileStatus::Regular ); copyPersistentSet( srcUnqPath,dstUnqPath,!isDocument ); OUString aDstParent = getParentName( dstUnqPath ); OUString aSrcParent = getParentName( srcUnqPath ); notifyInsert( getContentEventListeners( aDstParent ),dstUnqPath ); if( aDstParent != aSrcParent ) notifyContentRemoved( getContentEventListeners( aSrcParent ),srcUnqPath ); notifyContentExchanged( getContentExchangedEventListeners( srcUnqPath,dstUnqPath,!isDocument ) ); erasePersistentSet( srcUnqPath,!isDocument ); } /********************************************************************************/ /* */ /* copy-implementation */ /* */ /********************************************************************************/ // Copies the content belonging to fileURL srcUnqPath to fileURL dstUnqPath ( files and directories ) namespace { bool getType( TaskManager & task, sal_Int32 id, OUString const & fileUrl, osl::DirectoryItem * item, osl::FileStatus::Type * type) { OSL_ASSERT(item != nullptr && type != nullptr); osl::FileBase::RC err = osl::DirectoryItem::get(fileUrl, *item); if (err != osl::FileBase::E_None) { task.installError(id, TASKHANDLING_TRANSFER_BY_COPY_SOURCE, err); return false; } osl::FileStatus stat(osl_FileStatus_Mask_Type); err = item->getFileStatus(stat); if (err != osl::FileBase::E_None) { task.installError(id, TASKHANDLING_TRANSFER_BY_COPY_SOURCESTAT, err); return false; } *type = stat.getFileType(); return true; } } void SAL_CALL TaskManager::copy( sal_Int32 CommandId, const OUString& srcUnqPath, const OUString& dstUnqPathIn, sal_Int32 NameClash ) { osl::FileBase::RC nError; OUString dstUnqPath( dstUnqPathIn ); // Resolve symbolic links within the source path. If srcUnqPath denotes a // symbolic link (targeting either a file or a folder), the contents of the // target is copied (recursively, in the case of a folder). However, if // recursively copying the contents of a folder causes a symbolic link to be // copied, the symbolic link itself is copied. osl::DirectoryItem item; osl::FileStatus::Type type; if (!getType(*this, CommandId, srcUnqPath, &item, &type)) { return; } OUString rslvdSrcUnqPath; if (type == osl::FileStatus::Link) { osl::FileStatus stat(osl_FileStatus_Mask_LinkTargetURL); nError = item.getFileStatus(stat); if (nError != osl::FileBase::E_None) { installError( CommandId, TASKHANDLING_TRANSFER_BY_COPY_SOURCESTAT, nError); return; } rslvdSrcUnqPath = stat.getLinkTargetURL(); if (!getType(*this, CommandId, srcUnqPath, &item, &type)) { return; } } else { rslvdSrcUnqPath = srcUnqPath; } bool isDocument = type != osl::FileStatus::Directory && type != osl::FileStatus::Volume; FileUrlType IsWhat = isDocument ? FileUrlType::File : FileUrlType::Folder; switch( NameClash ) { case NameClash::KEEP: { nError = copy_recursive( rslvdSrcUnqPath,dstUnqPath,IsWhat,true ); if( nError != osl::FileBase::E_None && nError != osl::FileBase::E_EXIST ) { installError( CommandId, TASKHANDLING_KEEPERROR_FOR_COPY, nError ); return; } break; } case NameClash::OVERWRITE: { // remove (..., MustExist = sal_False). remove( CommandId, dstUnqPath, IsWhat, false ); // copy. nError = copy_recursive( rslvdSrcUnqPath,dstUnqPath,IsWhat,false ); if( nError != osl::FileBase::E_None ) { installError( CommandId, TASKHANDLING_OVERWRITE_FOR_COPY, nError ); return; } break; } case NameClash::RENAME: { OUString newDstUnqPath; nError = copy_recursive( rslvdSrcUnqPath,dstUnqPath,IsWhat,true ); if( nError == osl::FileBase::E_EXIST ) { // "invent" a new valid title. sal_Int32 nPos = -1; sal_Int32 nLastDot = dstUnqPath.lastIndexOf( '.' ); sal_Int32 nLastSlash = dstUnqPath.lastIndexOf( '/' ); if ( ( nLastSlash < nLastDot ) // dot is part of last(!) path segment && ( nLastSlash != ( nLastDot - 1 ) ) ) // file name does not start with a dot nPos = nLastDot; else nPos = dstUnqPath.getLength(); sal_Int32 nTry = 0; do { newDstUnqPath = dstUnqPath; OUString aPostfix = "_" + OUString::number( ++nTry ); newDstUnqPath = newDstUnqPath.replaceAt( nPos, 0, aPostfix ); nError = copy_recursive( rslvdSrcUnqPath,newDstUnqPath,IsWhat,true ); } while( ( nError == osl::FileBase::E_EXIST ) && ( nTry < 10000 ) ); } if( nError == osl::FileBase::E_EXIST ) { installError( CommandId, TASKHANDLING_RENAME_FOR_COPY ); return; } else if( nError != osl::FileBase::E_None ) { installError( CommandId, TASKHANDLING_RENAMEMOVE_FOR_COPY, nError ); return; } else dstUnqPath = newDstUnqPath; break; } case NameClash::ERROR: { nError = copy_recursive( rslvdSrcUnqPath,dstUnqPath,IsWhat,true ); if( nError == osl::FileBase::E_EXIST ) { installError( CommandId, TASKHANDLING_NAMECLASH_FOR_COPY ); return; } else if( nError != osl::FileBase::E_None ) { installError( CommandId, TASKHANDLING_NAMECLASHMOVE_FOR_COPY, nError ); return; } break; } case NameClash::ASK: default: { nError = copy_recursive( rslvdSrcUnqPath,dstUnqPath,IsWhat,true ); if( nError == osl::FileBase::E_EXIST ) { installError( CommandId, TASKHANDLING_NAMECLASHSUPPORT_FOR_COPY, NameClash); return; } break; } } copyPersistentSet( srcUnqPath,dstUnqPath, !isDocument ); notifyInsert( getContentEventListeners( getParentName( dstUnqPath ) ),dstUnqPath ); } /********************************************************************************/ /* */ /* remove-implementation */ /* */ /********************************************************************************/ // Deletes the content belonging to fileURL aUnqPath( recursively in case of directory ) // Return: success of operation bool SAL_CALL TaskManager::remove( sal_Int32 CommandId, const OUString& aUnqPath, FileUrlType IsWhat, bool MustExist ) { sal_Int32 nMask = osl_FileStatus_Mask_Type | osl_FileStatus_Mask_FileURL; osl::DirectoryItem aItem; osl::FileStatus aStatus( nMask ); osl::FileBase::RC nError; if( IsWhat == FileUrlType::Unknown ) // Determine whether we are removing a directory or a file { nError = osl::DirectoryItem::get( aUnqPath, aItem ); if( nError != osl::FileBase::E_None ) { if (MustExist) { installError( CommandId, TASKHANDLING_NOSUCHFILEORDIR_FOR_REMOVE, nError ); } return (!MustExist); } nError = aItem.getFileStatus( aStatus ); if( nError != osl::FileBase::E_None || ! aStatus.isValid( nMask ) ) { installError( CommandId, TASKHANDLING_VALIDFILESTATUS_FOR_REMOVE, nError != osl::FileBase::E_None ? nError : TASKHANDLER_NO_ERROR ); return false; } if( aStatus.getFileType() == osl::FileStatus::Regular || aStatus.getFileType() == osl::FileStatus::Link ) IsWhat = FileUrlType::File; else if( aStatus.getFileType() == osl::FileStatus::Directory || aStatus.getFileType() == osl::FileStatus::Volume ) IsWhat = FileUrlType::Folder; } if( IsWhat == FileUrlType::File ) { nError = osl::File::remove( aUnqPath ); if( nError != osl::FileBase::E_None ) { if (MustExist) { installError( CommandId, TASKHANDLING_DELETEFILE_FOR_REMOVE, nError ); } return (!MustExist); } else { notifyContentDeleted( getContentDeletedEventListeners(aUnqPath) ); erasePersistentSet( aUnqPath ); // Removes from XPersistentPropertySet } } else if( IsWhat == FileUrlType::Folder ) { osl::Directory aDirectory( aUnqPath ); nError = aDirectory.open(); if( nError != osl::FileBase::E_None ) { if (MustExist) { installError( CommandId, TASKHANDLING_OPENDIRECTORY_FOR_REMOVE, nError ); } return (!MustExist); } bool whileSuccess = true; FileUrlType recurse = FileUrlType::Unknown; OUString name; nError = aDirectory.getNextItem( aItem ); while( nError == osl::FileBase::E_None ) { nError = aItem.getFileStatus( aStatus ); if( nError != osl::FileBase::E_None || ! aStatus.isValid( nMask ) ) { installError( CommandId, TASKHANDLING_VALIDFILESTATUSWHILE_FOR_REMOVE, nError != osl::FileBase::E_None ? nError : TASKHANDLER_NO_ERROR ); whileSuccess = false; break; } if( aStatus.getFileType() == osl::FileStatus::Regular || aStatus.getFileType() == osl::FileStatus::Link ) recurse = FileUrlType::File; else if( aStatus.getFileType() == osl::FileStatus::Directory || aStatus.getFileType() == osl::FileStatus::Volume ) recurse = FileUrlType::Folder; name = aStatus.getFileURL(); whileSuccess = remove( CommandId, name, recurse, MustExist ); if( !whileSuccess ) break; nError = aDirectory.getNextItem( aItem ); } aDirectory.close(); if( ! whileSuccess ) return false; // error code is installed if( nError != osl::FileBase::E_NOENT ) { installError( CommandId, TASKHANDLING_DIRECTORYEXHAUSTED_FOR_REMOVE, nError ); return false; } nError = osl::Directory::remove( aUnqPath ); if( nError != osl::FileBase::E_None ) { if (MustExist) { installError( CommandId, TASKHANDLING_DELETEDIRECTORY_FOR_REMOVE, nError ); } return (!MustExist); } else { notifyContentDeleted( getContentDeletedEventListeners(aUnqPath) ); erasePersistentSet( aUnqPath ); } } else // Don't know what to remove { installError( CommandId, TASKHANDLING_FILETYPE_FOR_REMOVE ); return false; } return true; } /********************************************************************************/ /* */ /* mkdir-implementation */ /* */ /********************************************************************************/ // Creates new directory with given URL, recursively if necessary // Return:: success of operation bool SAL_CALL TaskManager::mkdir( sal_Int32 CommandId, const OUString& rUnqPath, bool OverWrite ) { OUString aUnqPath; // remove trailing slash if ( rUnqPath.endsWith("/") ) aUnqPath = rUnqPath.copy( 0, rUnqPath.getLength() - 1 ); else aUnqPath = rUnqPath; osl::FileBase::RC nError = osl::Directory::create( aUnqPath ); switch ( nError ) { case osl::FileBase::E_EXIST: // Directory cannot be overwritten { if( !OverWrite ) { installError( CommandId, TASKHANDLING_FOLDER_EXISTS_MKDIR ); return false; } else return true; } case osl::FileBase::E_INVAL: { installError(CommandId, TASKHANDLING_INVALID_NAME_MKDIR); return false; } case osl::FileBase::E_None: { OUString aPrtPath = getParentName( aUnqPath ); notifyInsert( getContentEventListeners( aPrtPath ),aUnqPath ); return true; } default: return ensuredir( CommandId, aUnqPath, TASKHANDLING_CREATEDIRECTORY_MKDIR ); } } /********************************************************************************/ /* */ /* mkfil-implementation */ /* */ /********************************************************************************/ // Creates new file with given URL. // The content of aInputStream becomes the content of the file // Return:: success of operation bool SAL_CALL TaskManager::mkfil( sal_Int32 CommandId, const OUString& aUnqPath, bool Overwrite, const uno::Reference< io::XInputStream >& aInputStream ) { // return value unimportant bool bSuccess = write( CommandId, aUnqPath, Overwrite, aInputStream ); if ( bSuccess ) { OUString aPrtPath = getParentName( aUnqPath ); notifyInsert( getContentEventListeners( aPrtPath ),aUnqPath ); } return bSuccess; } /********************************************************************************/ /* */ /* write-implementation */ /* */ /********************************************************************************/ // writes to the file with given URL. // The content of aInputStream becomes the content of the file // Return:: success of operation bool SAL_CALL TaskManager::write( sal_Int32 CommandId, const OUString& aUnqPath, bool OverWrite, const uno::Reference< io::XInputStream >& aInputStream ) { if( ! aInputStream.is() ) { installError( CommandId, TASKHANDLING_INPUTSTREAM_FOR_WRITE ); return false; } // Create parent path, if necessary. if ( ! ensuredir( CommandId, getParentName( aUnqPath ), TASKHANDLING_ENSUREDIR_FOR_WRITE ) ) return false; osl::FileBase::RC err; osl::File aFile( aUnqPath ); if( OverWrite ) { err = aFile.open( osl_File_OpenFlag_Write | osl_File_OpenFlag_Create ); if( err != osl::FileBase::E_None ) { aFile.close(); err = aFile.open( osl_File_OpenFlag_Write ); if( err != osl::FileBase::E_None ) { installError( CommandId, TASKHANDLING_NO_OPEN_FILE_FOR_OVERWRITE, err ); return false; } // the existing file was just opened and should be overwritten now, // truncate it first err = aFile.setSize( 0 ); if( err != osl::FileBase::E_None ) { installError( CommandId, TASKHANDLING_FILESIZE_FOR_WRITE, err ); return false; } } } else { err = aFile.open( osl_File_OpenFlag_Read | osl_File_OpenFlag_NoLock ); if( err == osl::FileBase::E_None ) // The file exists and shall not be overwritten { installError( CommandId, TASKHANDLING_NOREPLACE_FOR_WRITE, // Now an exception err ); aFile.close(); return false; } // as a temporary solution the creation does not lock the file at all // in future it should be possible to create the file without lock explicitly err = aFile.open( osl_File_OpenFlag_Write | osl_File_OpenFlag_Create | osl_File_OpenFlag_NoLock ); if( err != osl::FileBase::E_None ) { aFile.close(); installError( CommandId, TASKHANDLING_NO_OPEN_FILE_FOR_WRITE, err ); return false; } } bool bSuccess = true; sal_uInt64 nWrittenBytes; sal_Int32 nReadBytes = 0, nRequestedBytes = 32768 /*32k*/; uno::Sequence< sal_Int8 > seq( nRequestedBytes ); do { try { nReadBytes = aInputStream->readBytes( seq, nRequestedBytes ); } catch( const io::NotConnectedException& ) { installError( CommandId, TASKHANDLING_NOTCONNECTED_FOR_WRITE ); bSuccess = false; break; } catch( const io::BufferSizeExceededException& ) { installError( CommandId, TASKHANDLING_BUFFERSIZEEXCEEDED_FOR_WRITE ); bSuccess = false; break; } catch( const io::IOException& ) { installError( CommandId, TASKHANDLING_IOEXCEPTION_FOR_WRITE ); bSuccess = false; break; } if( nReadBytes ) { const sal_Int8* p = seq.getConstArray(); err = aFile.write( static_cast(p), sal_uInt64( nReadBytes ), nWrittenBytes ); if( err != osl::FileBase::E_None ) { installError( CommandId, TASKHANDLING_FILEIOERROR_FOR_WRITE, err ); bSuccess = false; break; } else if( nWrittenBytes != sal_uInt64( nReadBytes ) ) { installError( CommandId, TASKHANDLING_FILEIOERROR_FOR_NO_SPACE ); bSuccess = false; break; } } } while( nReadBytes == nRequestedBytes ); err = aFile.close(); if( err != osl::FileBase::E_None ) { installError( CommandId, TASKHANDLING_FILEIOERROR_FOR_WRITE, err ); bSuccess = false; } return bSuccess; } /*********************************************************************************/ /* */ /* insertDefaultProperties-Implementation */ /* */ /*********************************************************************************/ void SAL_CALL TaskManager::insertDefaultProperties( const OUString& aUnqPath ) { osl::MutexGuard aGuard( m_aMutex ); ContentMap::iterator it = m_aContent.emplace( aUnqPath,UnqPathData() ).first; load( it,false ); MyProperty ContentTProperty( ContentType ); PropertySet& properties = *(it->second.properties); bool ContentNotDefau = properties.find( ContentTProperty ) != properties.end(); TaskManager::PropertySet::iterator it1 = m_aDefaultProperties.begin(); while( it1 != m_aDefaultProperties.end() ) { if( ContentNotDefau && it1->getPropertyName() == ContentType ) { // No insertion } else properties.insert( *it1 ); ++it1; } } /******************************************************************************/ /* */ /* mapping of file urls */ /* to uncpath and vice versa */ /* */ /******************************************************************************/ bool SAL_CALL TaskManager::getUnqFromUrl( const OUString& Url, OUString& Unq ) { if ( Url == "file:///" || Url == "file://localhost/" || Url == "file://127.0.0.1/" ) { Unq = "file:///"; return false; } bool err = osl::FileBase::E_None != osl::FileBase::getSystemPathFromFileURL( Url,Unq ); Unq = Url; sal_Int32 l = Unq.getLength()-1; if( ! err && Unq.endsWith("/") && Unq.indexOf( '/', RTL_CONSTASCII_LENGTH("//") ) != -1 ) Unq = Unq.copy(0, l); return err; } bool SAL_CALL TaskManager::getUrlFromUnq( const OUString& Unq,OUString& Url ) { bool err = osl::FileBase::E_None != osl::FileBase::getSystemPathFromFileURL( Unq,Url ); Url = Unq; return err; } // Helper function for public copy osl::FileBase::RC SAL_CALL TaskManager::copy_recursive( const OUString& srcUnqPath, const OUString& dstUnqPath, FileUrlType TypeToCopy, bool testExistBeforeCopy ) { osl::FileBase::RC err = osl::FileBase::E_None; if( TypeToCopy == FileUrlType::File ) // Document { err = osl_File_copy( srcUnqPath,dstUnqPath,testExistBeforeCopy ); } else if( TypeToCopy == FileUrlType::Folder ) { osl::Directory aDir( srcUnqPath ); aDir.open(); err = osl::Directory::create( dstUnqPath ); osl::FileBase::RC next = err; if( err == osl::FileBase::E_None ) { sal_Int32 const n_Mask = osl_FileStatus_Mask_FileURL | osl_FileStatus_Mask_FileName | osl_FileStatus_Mask_Type; osl::DirectoryItem aDirItem; while( err == osl::FileBase::E_None && ( next = aDir.getNextItem( aDirItem ) ) == osl::FileBase::E_None ) { bool IsDoc = false; osl::FileStatus aFileStatus( n_Mask ); aDirItem.getFileStatus( aFileStatus ); if( aFileStatus.isValid( osl_FileStatus_Mask_Type ) ) IsDoc = aFileStatus.getFileType() == osl::FileStatus::Regular; // Getting the information for the next recursive copy FileUrlType newTypeToCopy = IsDoc ? FileUrlType::File : FileUrlType::Folder; OUString newSrcUnqPath; if( aFileStatus.isValid( osl_FileStatus_Mask_FileURL ) ) newSrcUnqPath = aFileStatus.getFileURL(); OUString newDstUnqPath = dstUnqPath; OUString tit; if( aFileStatus.isValid( osl_FileStatus_Mask_FileName ) ) tit = rtl::Uri::encode( aFileStatus.getFileName(), rtl_UriCharClassPchar, rtl_UriEncodeIgnoreEscapes, RTL_TEXTENCODING_UTF8 ); if( !newDstUnqPath.endsWith( "/" ) ) newDstUnqPath += "/"; newDstUnqPath += tit; if ( newSrcUnqPath != dstUnqPath ) err = copy_recursive( newSrcUnqPath,newDstUnqPath,newTypeToCopy,false ); } if( err == osl::FileBase::E_None && next != osl::FileBase::E_NOENT ) err = next; } aDir.close(); } return err; } // Helper function for mkfil,mkdir and write // Creates whole path // returns success of the operation bool SAL_CALL TaskManager::ensuredir( sal_Int32 CommandId, const OUString& rUnqPath, sal_Int32 errorCode ) { OUString aPath; if ( rUnqPath.isEmpty() ) return false; if ( rUnqPath.endsWith("/") ) aPath = rUnqPath.copy( 0, rUnqPath.getLength() - 1 ); else aPath = rUnqPath; #if HAVE_FEATURE_MACOSX_SANDBOX // Avoid annoying sandbox messages in the system.log from the // below aDirectory.open(), which ends up calling opendir(). // Surely it is easier to just call stat()? Calling stat() on an // arbitrary (?) directory does not seem to cause any sandbox // violation, while opendir() does. (Sorry I could not be bothered // to use some complex cross-platform abstraction over stat() here // in this OS X specific code block.) OUString aDirName; struct stat s; if( osl::FileBase::getSystemPathFromFileURL( aPath, aDirName ) == osl::FileBase::E_None && stat(OUStringToOString( aDirName, RTL_TEXTENCODING_UTF8).getStr(), &s ) == 0 && S_ISDIR( s.st_mode ) ) return sal_True; #endif // HACK: create directory on a mount point with nobrowse option // returns ENOSYS in any case !! osl::Directory aDirectory( aPath ); osl::FileBase::RC nError = aDirectory.open(); aDirectory.close(); if( nError == osl::File::E_None ) return true; nError = osl::Directory::create( aPath ); if( nError == osl::File::E_None ) notifyInsert( getContentEventListeners( getParentName( aPath ) ),aPath ); bool bSuccess = ( nError == osl::File::E_None || nError == osl::FileBase::E_EXIST ); if( ! bSuccess ) { OUString aParentDir = getParentName( aPath ); if ( aParentDir != aPath ) { // Create first the parent directory bSuccess = ensuredir( CommandId, getParentName( aPath ), errorCode ); // After parent directory structure exists try it one's more if ( bSuccess ) { // Parent directory exists, retry creation of directory nError = osl::Directory::create( aPath ); if( nError == osl::File::E_None ) notifyInsert( getContentEventListeners( getParentName( aPath ) ),aPath ); bSuccess =( nError == osl::File::E_None || nError == osl::FileBase::E_EXIST ); } } } if( ! bSuccess ) installError( CommandId, errorCode, nError ); return bSuccess; } // Given a sequence of properties seq, this method determines the mask // used to instantiate a osl::FileStatus, so that a call to // osl::DirectoryItem::getFileStatus fills the required fields. void SAL_CALL TaskManager::getMaskFromProperties( sal_Int32& n_Mask, const uno::Sequence< beans::Property >& seq ) { n_Mask = 0; for(sal_Int32 j = 0; j < seq.getLength(); ++j) { if(seq[j].Name == Title) n_Mask |= osl_FileStatus_Mask_FileName; else if(seq[j].Name == CasePreservingURL) n_Mask |= osl_FileStatus_Mask_FileURL; else if(seq[j].Name == IsDocument || seq[j].Name == IsFolder || seq[j].Name == IsVolume || seq[j].Name == IsRemoveable || seq[j].Name == IsRemote || seq[j].Name == IsCompactDisc || seq[j].Name == IsFloppy || seq[j].Name == ContentType) n_Mask |= (osl_FileStatus_Mask_Type | osl_FileStatus_Mask_LinkTargetURL); else if(seq[j].Name == Size) n_Mask |= (osl_FileStatus_Mask_FileSize | osl_FileStatus_Mask_Type | osl_FileStatus_Mask_LinkTargetURL); else if(seq[j].Name == IsHidden || seq[j].Name == IsReadOnly) n_Mask |= osl_FileStatus_Mask_Attributes; else if(seq[j].Name == DateModified) n_Mask |= osl_FileStatus_Mask_ModifyTime; } } /*********************************************************************************/ /* */ /* load-Implementation */ /* */ /*********************************************************************************/ // Load the properties from configuration, if create == true create them. // The Properties are stored under the url belonging to it->first. void SAL_CALL TaskManager::load( const ContentMap::iterator& it, bool create ) { if( ! it->second.properties ) it->second.properties = new PropertySet; if( ( ! it->second.xS.is() || ! it->second.xC.is() || ! it->second.xA.is() ) && m_xFileRegistry.is() ) { uno::Reference< ucb::XPersistentPropertySet > xS = m_xFileRegistry->openPropertySet( it->first,create ); if( xS.is() ) { uno::Reference< beans::XPropertyContainer > xC( xS,uno::UNO_QUERY ); uno::Reference< beans::XPropertyAccess > xA( xS,uno::UNO_QUERY ); it->second.xS = xS; it->second.xC = xC; it->second.xA = xA; // Now put in all values in the storage in the local hash; PropertySet& properties = *(it->second.properties); uno::Sequence< beans::Property > seq = xS->getPropertySetInfo()->getProperties(); for( sal_Int32 i = 0; i < seq.getLength(); ++i ) { MyProperty readProp( false, seq[i].Name, seq[i].Handle, seq[i].Type, xS->getPropertyValue( seq[i].Name ), beans::PropertyState_DIRECT_VALUE, seq[i].Attributes ); if( properties.find( readProp ) == properties.end() ) properties.insert( readProp ); } } else if( create ) { // Catastrophic error } } } /*********************************************************************************/ /* */ /* commit-Implementation */ /* */ /*********************************************************************************/ // Commit inserts the determined properties in the filestatus object into // the internal map, so that is possible to determine on a subsequent // setting of file properties which properties have changed without filestat void SAL_CALL TaskManager::commit( const TaskManager::ContentMap::iterator& it, const osl::FileStatus& aFileStatus ) { TaskManager::PropertySet::iterator it1; if( it->second.properties == nullptr ) { OUString aPath = it->first; insertDefaultProperties( aPath ); } PropertySet& properties = *( it->second.properties ); it1 = properties.find( MyProperty( Title ) ); if( it1 != properties.end() ) { if( aFileStatus.isValid( osl_FileStatus_Mask_FileName ) ) { it1->setValue( uno::Any(aFileStatus.getFileName()) ); } } it1 = properties.find( MyProperty( CasePreservingURL ) ); if( it1 != properties.end() ) { if( aFileStatus.isValid( osl_FileStatus_Mask_FileURL ) ) { it1->setValue( uno::Any(aFileStatus.getFileURL()) ); } } bool isDirectory,isFile,isVolume,isRemoveable,isRemote,isFloppy,isCompactDisc; sal_Int64 dirSize = 0; if( aFileStatus.isValid( osl_FileStatus_Mask_FileSize ) ) dirSize = aFileStatus.getFileSize(); if( aFileStatus.isValid( osl_FileStatus_Mask_Type ) ) { if( osl::FileStatus::Link == aFileStatus.getFileType() && aFileStatus.isValid( osl_FileStatus_Mask_LinkTargetURL ) ) { osl::DirectoryItem aDirItem; osl::FileStatus aFileStatus2( osl_FileStatus_Mask_Type ); if( osl::FileBase::E_None == osl::DirectoryItem::get( aFileStatus.getLinkTargetURL(),aDirItem ) && osl::FileBase::E_None == aDirItem.getFileStatus( aFileStatus2 ) && aFileStatus2.isValid( osl_FileStatus_Mask_Type ) ) { isVolume = osl::FileStatus::Volume == aFileStatus2.getFileType(); isDirectory = osl::FileStatus::Volume == aFileStatus2.getFileType() || osl::FileStatus::Directory == aFileStatus2.getFileType(); isFile = osl::FileStatus::Regular == aFileStatus2.getFileType(); if( aFileStatus2.isValid( osl_FileStatus_Mask_FileSize ) ) dirSize = aFileStatus2.getFileSize(); } else { // extremely ugly, but otherwise default construction // of aDirItem and aFileStatus2 // before the preceding if isVolume = osl::FileStatus::Volume == aFileStatus.getFileType(); isDirectory = osl::FileStatus::Volume == aFileStatus.getFileType() || osl::FileStatus::Directory == aFileStatus.getFileType(); isFile = osl::FileStatus::Regular == aFileStatus.getFileType(); } } else { isVolume = osl::FileStatus::Volume == aFileStatus.getFileType(); isDirectory = osl::FileStatus::Volume == aFileStatus.getFileType() || osl::FileStatus::Directory == aFileStatus.getFileType(); isFile = osl::FileStatus::Regular == aFileStatus.getFileType(); } it1 = properties.find( MyProperty( IsVolume ) ); if( it1 != properties.end() ) it1->setValue( uno::makeAny( isVolume ) ); it1 = properties.find( MyProperty( IsFolder ) ); if( it1 != properties.end() ) it1->setValue( uno::makeAny( isDirectory ) ); it1 = properties.find( MyProperty( IsDocument ) ); if( it1 != properties.end() ) it1->setValue( uno::makeAny( isFile ) ); osl::VolumeInfo aVolumeInfo( osl_VolumeInfo_Mask_Attributes ); if( isVolume && osl::FileBase::E_None == osl::Directory::getVolumeInfo( it->first,aVolumeInfo ) && aVolumeInfo.isValid( osl_VolumeInfo_Mask_Attributes ) ) { // Retrieve the flags; isRemote = aVolumeInfo.getRemoteFlag(); isRemoveable = aVolumeInfo.getRemoveableFlag(); isCompactDisc = aVolumeInfo.getCompactDiscFlag(); isFloppy = aVolumeInfo.getFloppyDiskFlag(); it1 = properties.find( MyProperty( IsRemote ) ); if( it1 != properties.end() ) it1->setValue( uno::makeAny( isRemote ) ); it1 = properties.find( MyProperty( IsRemoveable ) ); if( it1 != properties.end() ) it1->setValue( uno::makeAny( isRemoveable ) ); it1 = properties.find( MyProperty( IsCompactDisc ) ); if( it1 != properties.end() ) it1->setValue( uno::makeAny( isCompactDisc ) ); it1 = properties.find( MyProperty( IsFloppy ) ); if( it1 != properties.end() ) it1->setValue( uno::makeAny( isFloppy ) ); } else { uno::Any aAny(false); it1 = properties.find( MyProperty( IsRemote ) ); if( it1 != properties.end() ) it1->setValue( aAny ); it1 = properties.find( MyProperty( IsRemoveable ) ); if( it1 != properties.end() ) it1->setValue( aAny ); it1 = properties.find( MyProperty( IsCompactDisc ) ); if( it1 != properties.end() ) it1->setValue( aAny ); it1 = properties.find( MyProperty( IsFloppy ) ); if( it1 != properties.end() ) it1->setValue( aAny ); } } else { isDirectory = false; } it1 = properties.find( MyProperty( Size ) ); if( it1 != properties.end() ) it1->setValue( uno::makeAny( dirSize ) ); it1 = properties.find( MyProperty( IsReadOnly ) ); if( it1 != properties.end() ) { if( aFileStatus.isValid( osl_FileStatus_Mask_Attributes ) ) { sal_uInt64 Attr = aFileStatus.getAttributes(); bool readonly = ( Attr & osl_File_Attribute_ReadOnly ) != 0; it1->setValue( uno::makeAny( readonly ) ); } } it1 = properties.find( MyProperty( IsHidden ) ); if( it1 != properties.end() ) { if( aFileStatus.isValid( osl_FileStatus_Mask_Attributes ) ) { sal_uInt64 Attr = aFileStatus.getAttributes(); bool ishidden = ( Attr & osl_File_Attribute_Hidden ) != 0; it1->setValue( uno::makeAny( ishidden ) ); } } it1 = properties.find( MyProperty( DateModified ) ); if( it1 != properties.end() ) { if( aFileStatus.isValid( osl_FileStatus_Mask_ModifyTime ) ) { TimeValue temp = aFileStatus.getModifyTime(); // Convert system time to local time (for EA) TimeValue myLocalTime; if (!osl_getLocalTimeFromSystemTime( &temp, &myLocalTime )) { SAL_WARN( "ucb.ucp.file", "cannot convert (" << temp.Seconds << ", " << temp.Nanosec << ") to local time"); myLocalTime = temp; } oslDateTime myDateTime; osl_getDateTimeFromTimeValue( &myLocalTime, &myDateTime ); util::DateTime aDateTime; aDateTime.NanoSeconds = myDateTime.NanoSeconds; aDateTime.Seconds = myDateTime.Seconds; aDateTime.Minutes = myDateTime.Minutes; aDateTime.Hours = myDateTime.Hours; aDateTime.Day = myDateTime.Day; aDateTime.Month = myDateTime.Month; aDateTime.Year = myDateTime.Year; it1->setValue( uno::makeAny( aDateTime ) ); } } it1 = properties.find( MyProperty( CreatableContentsInfo ) ); if( it1 != properties.end() ) it1->setValue( uno::makeAny( isDirectory || !aFileStatus.isValid( osl_FileStatus_Mask_Type ) ? queryCreatableContentsInfo() : uno::Sequence< ucb::ContentInfo >() ) ); } // Special optimized method for getting the properties of a // directoryitem, which is returned by osl::DirectoryItem::getNextItem() bool SAL_CALL TaskManager::getv( Notifier* pNotifier, const uno::Sequence< beans::Property >& properties, osl::DirectoryItem& aDirItem, OUString& aUnqPath, bool& aIsRegular, uno::Reference< sdbc::XRow > & row ) { uno::Sequence< uno::Any > seq( properties.getLength() ); sal_Int32 n_Mask; getMaskFromProperties( n_Mask,properties ); // Always retrieve the type and the target URL because item might be a link osl::FileStatus aFileStatus( n_Mask | osl_FileStatus_Mask_FileURL | osl_FileStatus_Mask_Type | osl_FileStatus_Mask_LinkTargetURL ); osl::FileBase::RC aRes = aDirItem.getFileStatus( aFileStatus ); if ( aRes != osl::FileBase::E_None ) { SAL_WARN( "ucb.ucp.file", "osl::DirectoryItem::getFileStatus failed with " << +aRes); return false; } aUnqPath = aFileStatus.getFileURL(); // If the directory item type is a link retrieve the type of the target if ( aFileStatus.getFileType() == osl::FileStatus::Link ) { // Assume failure aIsRegular = false; osl::FileBase::RC result = osl::FileBase::E_INVAL; osl::DirectoryItem aTargetItem; osl::DirectoryItem::get( aFileStatus.getLinkTargetURL(), aTargetItem ); if ( aTargetItem.is() ) { osl::FileStatus aTargetStatus( osl_FileStatus_Mask_Type ); if ( osl::FileBase::E_None == ( result = aTargetItem.getFileStatus( aTargetStatus ) ) ) aIsRegular = aTargetStatus.getFileType() == osl::FileStatus::Regular; } } else aIsRegular = aFileStatus.getFileType() == osl::FileStatus::Regular; registerNotifier( aUnqPath,pNotifier ); insertDefaultProperties( aUnqPath ); { osl::MutexGuard aGuard( m_aMutex ); TaskManager::ContentMap::iterator it = m_aContent.find( aUnqPath ); commit( it,aFileStatus ); TaskManager::PropertySet::iterator it1; PropertySet& propset = *(it->second.properties); for( sal_Int32 i = 0; i < seq.getLength(); ++i ) { MyProperty readProp( properties[i].Name ); it1 = propset.find( readProp ); if( it1 == propset.end() ) seq[i] = uno::Any(); else seq[i] = it1->getValue(); } } deregisterNotifier( aUnqPath,pNotifier ); XRow_impl* p = new XRow_impl( this,seq ); row = uno::Reference< sdbc::XRow >( p ); return true; } // EventListener std::list< ContentEventNotifier* >* SAL_CALL TaskManager::getContentEventListeners( const OUString& aName ) { std::list< ContentEventNotifier* >* p = new std::list< ContentEventNotifier* >; std::list< ContentEventNotifier* >& listeners = *p; { osl::MutexGuard aGuard( m_aMutex ); TaskManager::ContentMap::iterator it = m_aContent.find( aName ); if( it != m_aContent.end() && it->second.notifier ) { std::list& listOfNotifiers = *( it->second.notifier ); std::list::iterator it1 = listOfNotifiers.begin(); while( it1 != listOfNotifiers.end() ) { Notifier* pointer = *it1; ContentEventNotifier* notifier = pointer->cCEL(); if( notifier ) listeners.push_back( notifier ); ++it1; } } } return p; } std::list< ContentEventNotifier* >* SAL_CALL TaskManager::getContentDeletedEventListeners( const OUString& aName ) { std::list< ContentEventNotifier* >* p = new std::list< ContentEventNotifier* >; std::list< ContentEventNotifier* >& listeners = *p; { osl::MutexGuard aGuard( m_aMutex ); TaskManager::ContentMap::iterator it = m_aContent.find( aName ); if( it != m_aContent.end() && it->second.notifier ) { std::list& listOfNotifiers = *( it->second.notifier ); std::list::iterator it1 = listOfNotifiers.begin(); while( it1 != listOfNotifiers.end() ) { Notifier* pointer = *it1; ContentEventNotifier* notifier = pointer->cDEL(); if( notifier ) listeners.push_back( notifier ); ++it1; } } } return p; } void SAL_CALL TaskManager::notifyInsert( std::list< ContentEventNotifier* >* listeners,const OUString& aChildName ) { std::list< ContentEventNotifier* >::iterator it = listeners->begin(); while( it != listeners->end() ) { (*it)->notifyChildInserted( aChildName ); delete (*it); ++it; } delete listeners; } void SAL_CALL TaskManager::notifyContentDeleted( std::list< ContentEventNotifier* >* listeners ) { std::list< ContentEventNotifier* >::iterator it = listeners->begin(); while( it != listeners->end() ) { (*it)->notifyDeleted(); delete (*it); ++it; } delete listeners; } void SAL_CALL TaskManager::notifyContentRemoved( std::list< ContentEventNotifier* >* listeners, const OUString& aChildName ) { std::list< ContentEventNotifier* >::iterator it = listeners->begin(); while( it != listeners->end() ) { (*it)->notifyRemoved( aChildName ); delete (*it); ++it; } delete listeners; } std::list< PropertySetInfoChangeNotifier* >* SAL_CALL TaskManager::getPropertySetListeners( const OUString& aName ) { std::list< PropertySetInfoChangeNotifier* >* p = new std::list< PropertySetInfoChangeNotifier* >; std::list< PropertySetInfoChangeNotifier* >& listeners = *p; { osl::MutexGuard aGuard( m_aMutex ); TaskManager::ContentMap::iterator it = m_aContent.find( aName ); if( it != m_aContent.end() && it->second.notifier ) { std::list& listOfNotifiers = *( it->second.notifier ); std::list::iterator it1 = listOfNotifiers.begin(); while( it1 != listOfNotifiers.end() ) { Notifier* pointer = *it1; PropertySetInfoChangeNotifier* notifier = pointer->cPSL(); if( notifier ) listeners.push_back( notifier ); ++it1; } } } return p; } void SAL_CALL TaskManager::notifyPropertyAdded( std::list< PropertySetInfoChangeNotifier* >* listeners, const OUString& aPropertyName ) { std::list< PropertySetInfoChangeNotifier* >::iterator it = listeners->begin(); while( it != listeners->end() ) { (*it)->notifyPropertyAdded( aPropertyName ); delete (*it); ++it; } delete listeners; } void SAL_CALL TaskManager::notifyPropertyRemoved( std::list< PropertySetInfoChangeNotifier* >* listeners, const OUString& aPropertyName ) { std::list< PropertySetInfoChangeNotifier* >::iterator it = listeners->begin(); while( it != listeners->end() ) { (*it)->notifyPropertyRemoved( aPropertyName ); delete (*it); ++it; } delete listeners; } std::vector< std::list< ContentEventNotifier* >* >* SAL_CALL TaskManager::getContentExchangedEventListeners( const OUString& aOldPrefix, const OUString& aNewPrefix, bool withChildren ) { std::vector< std::list< ContentEventNotifier* >* >* aVectorOnHeap = new std::vector< std::list< ContentEventNotifier* >* >; std::vector< std::list< ContentEventNotifier* >* >& aVector = *aVectorOnHeap; sal_Int32 count; OUString aOldName; OUString aNewName; std::vector< OUString > oldChildList; { osl::MutexGuard aGuard( m_aMutex ); if( ! withChildren ) { aOldName = aOldPrefix; aNewName = aNewPrefix; count = 1; } else { ContentMap::iterator itnames = m_aContent.begin(); while( itnames != m_aContent.end() ) { if( isChild( aOldPrefix,itnames->first ) ) { oldChildList.push_back( itnames->first ); } ++itnames; } count = oldChildList.size(); } for( sal_Int32 j = 0; j < count; ++j ) { std::list< ContentEventNotifier* >* p = new std::list< ContentEventNotifier* >; std::list< ContentEventNotifier* >& listeners = *p; if( withChildren ) { aOldName = oldChildList[j]; aNewName = newName( aNewPrefix,aOldPrefix,aOldName ); } TaskManager::ContentMap::iterator itold = m_aContent.find( aOldName ); if( itold != m_aContent.end() ) { TaskManager::ContentMap::iterator itnew = m_aContent.emplace( aNewName,UnqPathData() ).first; // copy Ownership also delete itnew->second.properties; itnew->second.properties = itold->second.properties; itold->second.properties = nullptr; // copy existing list std::list< Notifier* >* copyList = itnew->second.notifier; itnew->second.notifier = itold->second.notifier; itold->second.notifier = nullptr; m_aContent.erase( itold ); if( itnew != m_aContent.end() && itnew->second.notifier ) { std::list& listOfNotifiers = *( itnew->second.notifier ); std::list::iterator it1 = listOfNotifiers.begin(); while( it1 != listOfNotifiers.end() ) { Notifier* pointer = *it1; ContentEventNotifier* notifier = pointer->cEXC( aNewName ); if( notifier ) listeners.push_back( notifier ); ++it1; } } // Merge with preexisting notifiers // However, these may be in status BaseContent::Deleted if( copyList != nullptr ) { std::list< Notifier* >::iterator copyIt = copyList->begin(); while( copyIt != copyList->end() ) { itnew->second.notifier->push_back( *copyIt ); ++copyIt; } } delete copyList; } aVector.push_back( p ); } } return aVectorOnHeap; } void SAL_CALL TaskManager::notifyContentExchanged( std::vector< std::list< ContentEventNotifier* >* >* listeners_vec ) { for( std::list< ContentEventNotifier* >* listeners : *listeners_vec) { std::list< ContentEventNotifier* >::iterator it = listeners->begin(); while( it != listeners->end() ) { (*it)->notifyExchanged(); delete (*it); ++it; } delete listeners; } delete listeners_vec; } std::list< PropertyChangeNotifier* >* SAL_CALL TaskManager::getPropertyChangeNotifier( const OUString& aName ) { std::list< PropertyChangeNotifier* >* p = new std::list< PropertyChangeNotifier* >; std::list< PropertyChangeNotifier* >& listeners = *p; { osl::MutexGuard aGuard( m_aMutex ); TaskManager::ContentMap::iterator it = m_aContent.find( aName ); if( it != m_aContent.end() && it->second.notifier ) { std::list& listOfNotifiers = *( it->second.notifier ); std::list::iterator it1 = listOfNotifiers.begin(); while( it1 != listOfNotifiers.end() ) { Notifier* pointer = *it1; PropertyChangeNotifier* notifier = pointer->cPCL(); if( notifier ) listeners.push_back( notifier ); ++it1; } } } return p; } void SAL_CALL TaskManager::notifyPropertyChanges( std::list< PropertyChangeNotifier* >* listeners, const uno::Sequence< beans::PropertyChangeEvent >& seqChanged ) { std::list< PropertyChangeNotifier* >::iterator it = listeners->begin(); while( it != listeners->end() ) { (*it)->notifyPropertyChanged( seqChanged ); delete (*it); ++it; } delete listeners; } /********************************************************************************/ /* remove persistent propertyset */ /********************************************************************************/ void SAL_CALL TaskManager::erasePersistentSet( const OUString& aUnqPath, bool withChildren ) { if( ! m_xFileRegistry.is() ) { OSL_ASSERT( m_xFileRegistry.is() ); return; } uno::Sequence< OUString > seqNames; if( withChildren ) { uno::Reference< container::XNameAccess > xName( m_xFileRegistry,uno::UNO_QUERY ); seqNames = xName->getElementNames(); } sal_Int32 count = withChildren ? seqNames.getLength() : 1; OUString old_Name = aUnqPath; for( sal_Int32 j = 0; j < count; ++j ) { if( withChildren && ! ( isChild( old_Name,seqNames[j] ) ) ) continue; if( withChildren ) { old_Name = seqNames[j]; } { // Release possible references osl::MutexGuard aGuard( m_aMutex ); ContentMap::iterator it = m_aContent.find( old_Name ); if( it != m_aContent.end() ) { it->second.xS = nullptr; it->second.xC = nullptr; it->second.xA = nullptr; delete it->second.properties; it->second.properties = nullptr; } } if( m_xFileRegistry.is() ) m_xFileRegistry->removePropertySet( old_Name ); } } /********************************************************************************/ /* copy persistent propertyset */ /* from srcUnqPath to dstUnqPath */ /********************************************************************************/ void SAL_CALL TaskManager::copyPersistentSet( const OUString& srcUnqPath, const OUString& dstUnqPath, bool withChildren ) { if( ! m_xFileRegistry.is() ) { OSL_ASSERT( m_xFileRegistry.is() ); return; } uno::Sequence< OUString > seqNames; if( withChildren ) { uno::Reference< container::XNameAccess > xName( m_xFileRegistry,uno::UNO_QUERY ); seqNames = xName->getElementNames(); } sal_Int32 count = withChildren ? seqNames.getLength() : 1; OUString old_Name = srcUnqPath, new_Name = dstUnqPath; for( sal_Int32 j = 0; j < count; ++j ) { if( withChildren && ! ( isChild( srcUnqPath,seqNames[j] ) ) ) continue; if( withChildren ) { old_Name = seqNames[j]; new_Name = newName( dstUnqPath,srcUnqPath,old_Name ); } uno::Reference< XPersistentPropertySet > x_src; if( m_xFileRegistry.is() ) { x_src = m_xFileRegistry->openPropertySet( old_Name,false ); m_xFileRegistry->removePropertySet( new_Name ); } if( x_src.is() ) { uno::Sequence< beans::Property > seqProperty = x_src->getPropertySetInfo()->getProperties(); if( seqProperty.getLength() ) { uno::Reference< XPersistentPropertySet > x_dstS = m_xFileRegistry->openPropertySet( new_Name,true ); uno::Reference< beans::XPropertyContainer > x_dstC( x_dstS,uno::UNO_QUERY ); for( sal_Int32 i = 0; i < seqProperty.getLength(); ++i ) { x_dstC->addProperty( seqProperty[i].Name, seqProperty[i].Attributes, x_src->getPropertyValue( seqProperty[i].Name ) ); } } } } // end for( sal_Int... } uno::Sequence< ucb::ContentInfo > TaskManager::queryCreatableContentsInfo() { uno::Sequence< ucb::ContentInfo > seq(2); // file seq[0].Type = FileContentType; seq[0].Attributes = ucb::ContentInfoAttribute::INSERT_WITH_INPUTSTREAM | ucb::ContentInfoAttribute::KIND_DOCUMENT; uno::Sequence< beans::Property > props( 1 ); props[0] = beans::Property( "Title", -1, cppu::UnoType::get(), beans::PropertyAttribute::MAYBEVOID | beans::PropertyAttribute::BOUND ); seq[0].Properties = props; // folder seq[1].Type = FolderContentType; seq[1].Attributes = ucb::ContentInfoAttribute::KIND_FOLDER; seq[1].Properties = props; return seq; } /*******************************************************************************/ /* */ /* some miscellaneous static functions */ /* */ /*******************************************************************************/ void SAL_CALL TaskManager::getScheme( OUString& Scheme ) { Scheme = "file"; } OUString SAL_CALL TaskManager::getImplementationName_static() { return OUString("com.sun.star.comp.ucb.FileProvider"); } uno::Sequence< OUString > SAL_CALL TaskManager::getSupportedServiceNames_static() { OUString Supported("com.sun.star.ucb.FileContentProvider"); css::uno::Sequence< OUString > Seq( &Supported,1 ); return Seq; } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */