/************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * Copyright 2000, 2010 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite * * This file is part of OpenOffice.org. * * OpenOffice.org is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 * only, as published by the Free Software Foundation. * * OpenOffice.org is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License version 3 for more details * (a copy is included in the LICENSE file that accompanied this code). * * You should have received a copy of the GNU Lesser General Public License * version 3 along with OpenOffice.org. If not, see * * for a copy of the LGPLv3 License. * ************************************************************************/ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_scripting.hxx" #include #include #include #include #include #include #include #include #include #include #include #include "ScriptStorageManager.hxx" #include #include #include using namespace ::rtl; using namespace ::com::sun::star; using namespace ::com::sun::star::uno; using namespace ::drafts::com::sun::star::script::framework; namespace scripting_impl { static OUString s_implName = ::rtl::OUString::createFromAscii( "drafts.com.sun.star.script.framework.storage.ScriptStorageManager" ); static OUString s_serviceName = ::rtl::OUString::createFromAscii( "drafts.com.sun.star.script.framework.storage.ScriptStorageManager" ); static Sequence< OUString > s_serviceNames = Sequence< OUString >( &s_serviceName, 1 ); //extern ::rtl_StandardModuleCount s_moduleCount = MODULE_COUNT_INIT; //extern ::rtl_StandardModuleCount s_moduleCount; //************************************************************************* // ScriptStorageManager Constructor ScriptStorageManager::ScriptStorageManager( const Reference< XComponentContext > & xContext ) SAL_THROW ( ( RuntimeException ) ) : m_xContext( xContext, UNO_SET_THROW ), m_count( 0 ), m_securityMgr( xContext ) { OSL_TRACE( "< ScriptStorageManager ctor called >\n" ); //s_moduleCount.modCnt.acquire( &s_moduleCount.modCnt ); m_xMgr.set( m_xContext->getServiceManager(), UNO_SET_THROW ); try { // obtain the macro expander singleton to use in determining the // location of the application script storage Reference< util::XMacroExpander > xME( m_xContext->getValueByName( OUString::createFromAscii( "/singletons/com.sun.star.util.theMacroExpander" ) ), UNO_QUERY_THROW ); OUString base = OUString::createFromAscii( SAL_CONFIGFILE( "${$BRAND_BASE_DIR/program/bootstrap" ) ); setupAppStorage( xME, base.concat( OUString::createFromAscii( "::BaseInstallation}/share" ) ), OUSTR( "SHARE" ) ); setupAppStorage( xME, base.concat( OUString::createFromAscii( "::UserInstallation}/user" ) ), OUSTR( "USER" ) ); } catch ( Exception & e ) { throw RuntimeException( OUSTR( "ScriptStorageManager::ScriptStorageManager: " ).concat( e.Message ), Reference< XInterface >() ); } OSL_ASSERT( m_count == 2 ); } //************************************************************************* // ScriptStorageManager setupAppStorage void ScriptStorageManager::setupAppStorage( const Reference< util::XMacroExpander > & xME, const OUString & storageStr, const OUString & appStr) SAL_THROW ( ( RuntimeException ) ) { try { Reference< ucb::XSimpleFileAccess > xSFA( m_xMgr->createInstanceWithContext( OUString::createFromAscii( "com.sun.star.ucb.SimpleFileAccess" ), m_xContext ), UNO_QUERY_THROW ); setupAnyStorage( xSFA, xME->expandMacros( storageStr ), appStr ); } catch ( Exception & e ) { throw RuntimeException( OUSTR( "ScriptStorageManager::setupAppStorage: " ).concat( e.Message ), Reference< XInterface >() ); } } //************************************************************************* // ScriptStorageManager setupAnyStorage sal_Int32 ScriptStorageManager::setupAnyStorage( const Reference< ucb::XSimpleFileAccess > & xSFA, const OUString & storageStr, const OUString & origStringURI ) SAL_THROW ( ( RuntimeException ) ) { // Required for scope of fnc to protect all access read and writes to m_count ::osl::Guard< ::osl::Mutex > aGuard( m_mutex ); try { // create a ScriptingStorage using the SimpleFileAccess, the storageID // (from the count), and the URL to the application's shared area Sequence < Any > aArgs( 3 ); aArgs[ 0 ] <<= xSFA; aArgs[ 1 ] <<= m_count; aArgs[ 2 ] <<= storageStr; OSL_TRACE( "creating storage for: %s\n", ::rtl::OUStringToOString( storageStr, RTL_TEXTENCODING_ASCII_US ).pData->buffer ); Reference< XInterface > xInterface( m_xMgr->createInstanceWithArgumentsAndContext( OUString::createFromAscii( "drafts.com.sun.star.script.framework.storage.ScriptStorage" ), aArgs, m_xContext ), UNO_QUERY_THROW ); // and place it in the hash_map. Increment the counter m_ScriptStorageMap[ m_count++ ] = xInterface; sal_Int32 sid = m_count - 1; // create hash of original uri i.e. file:///home/users/docs/mydoc.sxw // and storage id (sid) this will allow us to retrieve // the sid based on the url of the document. m_StorageIdOrigURIHash [ origStringURI ] = sid; OSL_TRACE( "\tcreated with ID=%d\n", m_count - 1 ); } catch ( Exception & e ) { throw RuntimeException( OUSTR( "ScriptStorageManager::setupAnyStorage: " ).concat( e.Message ), Reference< XInterface >() ); } return m_count -1; } //************************************************************************* // ScriptStorageManager Destructor ScriptStorageManager::~ScriptStorageManager() SAL_THROW ( () ) { OSL_TRACE( "< ScriptStorageManager dtor called >\n" ); // s_moduleCount.modCnt.release( &s_moduleCount.modCnt ); } //************************************************************************* // This method assumes that the XSimpleFileAccess knows it's on root URL // and can be used with relative URLs sal_Int32 SAL_CALL ScriptStorageManager::createScriptStorage( const Reference< ucb::XSimpleFileAccess >& xSFA ) throw ( RuntimeException ) { OSL_TRACE( "** ==> ScriptStorageManager in createScriptingStorage\n" ); ENSURE_OR_THROW( xSFA.is(), "ScriptStorageManager::createScriptStorage: XSimpleFileAccess is not valid" ); return setupAnyStorage( xSFA, ::rtl::OUString::createFromAscii( "" ), ::rtl::OUString::createFromAscii( "" ) ); } //************************************************************************* sal_Int32 SAL_CALL ScriptStorageManager::createScriptStorageWithURI( const Reference< ucb::XSimpleFileAccess >& xSFA, const OUString & cStringURI ) throw ( RuntimeException ) { OSL_TRACE( "** ==> ScriptStorageManager in createScriptingStorageWithURI\n" ); ENSURE_OR_THROW( xSFA.is(), "ScriptStorageManager::createScriptStorage: XSimpleFileAccess is not valid" ); // related to issue 11866 // warning dialog gets launched when adding binding to script in doc // workaround issue: no functionProvider created on doc open // if NODIALOG tag, strip from stringURI, set boolean=true bool displayDialog = true; ::rtl::OUString dialogTag = ::rtl::OUString::createFromAscii( "NoDialog::" ); ::rtl::OUString stringURI = cStringURI; if( stringURI.indexOf( dialogTag ) == 0 ) { OSL_TRACE( "ScriptStorageManager::createScriptStorage: will not display security dialogs" ); stringURI = stringURI.copy( dialogTag.getLength() ); displayDialog = false; } sal_Int32 returnedID = getScriptStorageID(stringURI); // convert file:///... url to vnd... syntax ::rtl::OUString canonicalURI( ::rtl::OUString::createFromAscii( "vnd.sun.star.pkg://" ) ); canonicalURI = canonicalURI.concat( ::rtl::Uri::encode( stringURI, rtl_UriCharClassUricNoSlash, rtl_UriEncodeCheckEscapes, RTL_TEXTENCODING_ASCII_US ) ); if (returnedID == -1) { OSL_TRACE("Creating new storage for %s", ::rtl::OUStringToOString( stringURI, RTL_TEXTENCODING_ASCII_US ).pData->buffer ); returnedID = setupAnyStorage( xSFA, canonicalURI, stringURI ); } else { OSL_TRACE("Using existing storage for %s", ::rtl::OUStringToOString( stringURI, RTL_TEXTENCODING_ASCII_US ).pData->buffer ); } // np - removed previous scripting framework security handling // now handled by modification to existing calls in sfx for basic // /* if( displayDialog ) { try { OSL_TRACE("Adding to security mgr for %s", ::rtl::OUStringToOString( stringURI, RTL_TEXTENCODING_ASCII_US ).pData->buffer ); m_securityMgr.addScriptStorage( stringURI, returnedID ); } catch ( RuntimeException & rte ) { throw RuntimeException( OUSTR( "ScriptStorageManager::createScriptStorageWithURI: " ).concat( rte.Message ), Reference< XInterface >() ); } } else { OSL_TRACE("No need to security mgr for %s", ::rtl::OUStringToOString( stringURI, RTL_TEXTENCODING_ASCII_US ).pData->buffer ); }*/ return returnedID; } //************************************************************************* Reference < XInterface > SAL_CALL ScriptStorageManager::getScriptStorage( sal_Int32 scriptStorageID ) throw( RuntimeException ) { OSL_TRACE( "** ==> ScriptStorageManager in getStorageInstance\n" ); OSL_TRACE( "** ==> request for id=%d",scriptStorageID ); ScriptStorage_map::const_iterator itr = m_ScriptStorageMap.find( scriptStorageID ); if ( itr == m_ScriptStorageMap.end() ) { throw RuntimeException( OUSTR( "ScriptStorageManager::getScriptStorage: invalid storage ID" ), Reference< XInterface >() ); } ENSURE_OR_THROW( itr->second.is(), "ScriptStorageManager::getScriptStorage: Cannot get ScriptStorage from ScriptStorageHash" ); return itr->second; } //******************************************************************* sal_Int32 SAL_CALL ScriptStorageManager::getScriptStorageID( const ::rtl::OUString& origURI ) throw (::com::sun::star::uno::RuntimeException) { StorageId_hash::const_iterator it = m_StorageIdOrigURIHash.find( origURI ); if ( it == m_StorageIdOrigURIHash.end() ) { OUString message = OUSTR( "ScriptStorageManager::getScriptStorageID(): Cannot find storage for " ); if ( origURI.getLength() == 0 ) { message = message.concat( OUSTR("Empty URI") ); } else { message = message.concat( origURI ); } OSL_TRACE( ::rtl::OUStringToOString( message, RTL_TEXTENCODING_ASCII_US ).pData->buffer ); return -1; } return it->second; } //******************************************************************* void ScriptStorageManager::removeScriptDocURIHashEntry( const OUString & origURI ) { StorageId_hash::iterator it = m_StorageIdOrigURIHash.find( origURI ); if ( it == m_StorageIdOrigURIHash.end() ) { OSL_TRACE( "ScriptStorageManager::removeScriptDocURIHashEntry: no entry to remove" ); return; } // remove entry for this doc url from orig uri map. m_StorageIdOrigURIHash.erase( it ); } //******************************************************************* void SAL_CALL ScriptStorageManager::refreshScriptStorage( const OUString & stringURI ) throw( RuntimeException ) { OSL_TRACE( "** => ScriptStorageManager in refreshScriptStorage\n" ); OSL_TRACE( "** => refreshing URI: %s\n", ::rtl::OUStringToOString( stringURI, RTL_TEXTENCODING_ASCII_US ).pData->buffer); sal_Int32 storageID = getScriptStorageID( stringURI ); if ( storageID == -1 ) { OSL_TRACE( "** id was -1, no storage"); // Refreshing noexistent storage - just return return; } try { Reference < storage::XScriptStorageRefresh > xSSR( getScriptStorage( storageID ), UNO_QUERY ); xSSR->refresh(); } catch ( RuntimeException & e ) { throw RuntimeException( OUSTR( "ScriptStorageManager::refreshScriptStorage: " ).concat( e.Message ), Reference< XInterface >() ); } catch ( Exception & e ) { throw RuntimeException( OUSTR( "ScriptStorageManager::refreshScriptStorage: " ).concat( e.Message ), Reference< XInterface >() ); } } //************************************************************************* void SAL_CALL ScriptStorageManager::checkPermission( const OUString & scriptStorageURI, const OUString & permissionRequest ) throw ( RuntimeException, lang::IllegalArgumentException, css::security::AccessControlException ) { try { m_securityMgr.checkPermission( scriptStorageURI, permissionRequest ); } catch ( css::security::AccessControlException & e ) { throw css::security::AccessControlException( OUSTR( "ScriptStorageManager::checkPermission: AccessControlException: " ).concat( e.Message ), Reference< XInterface >(), e.LackingPermission ); } catch ( lang::IllegalArgumentException & e ) { throw lang::IllegalArgumentException( OUSTR( "ScriptStorageManager::checkPermission: IllegalArgumentException: " ).concat( e.Message ), Reference< XInterface >(), e.ArgumentPosition ); } catch ( RuntimeException & e ) { throw RuntimeException( OUSTR( "ScriptStorageManager::checkPermission: RuntimeException: " ).concat( e.Message ), Reference< XInterface >() ); } } //************************************************************************* OUString SAL_CALL ScriptStorageManager::getImplementationName( ) throw( RuntimeException ) { return s_implName; } //************************************************************************* sal_Bool SAL_CALL ScriptStorageManager::supportsService( const OUString& serviceName ) throw( RuntimeException ) { OUString const * pNames = s_serviceNames.getConstArray(); for ( sal_Int32 nPos = s_serviceNames.getLength(); nPos--; ) { if ( serviceName.equals( pNames[ nPos ] ) ) { return sal_True; } } return sal_False; } //************************************************************************* Sequence< OUString > SAL_CALL ScriptStorageManager::getSupportedServiceNames( ) throw( RuntimeException ) { return s_serviceNames; } //************************************************************************* void SAL_CALL ScriptStorageManager::disposing( const ::com::sun::star::lang::EventObject& Source ) throw ( ::com::sun::star::uno::RuntimeException ) { OSL_TRACE( "ScriptStorageManager::disposing started" ); OSL_TRACE( "event object type=%s", ::rtl::OUStringToOString( getCppuType( &Source ).getTypeName(), RTL_TEXTENCODING_ASCII_US ).pData->buffer ); OUString storageURI; bool removeSecurityPermission = true; try { Reference< XInterface > xInterface = Source.Source; // no UNO_QUERY_THROW since we want a 2nd change to query if it's // not a document being disposed Reference< frame::XModel > xModel = Reference< frame::XModel > ( xInterface, UNO_QUERY ); if( xModel.is() ) { storageURI = xModel->getURL(); } else { // UNO_QURY_THROW here since it's supposed to be either a doc // or a XScriptInfo (in the case of a filesys script) Reference< storage::XScriptInfo > xScriptInfo = Reference< storage::XScriptInfo > ( xInterface, UNO_QUERY_THROW ); storageURI = xScriptInfo->getParcelURI().concat( xScriptInfo->getFunctionName() ); // to save the user seeing the security dialogs every time they // run the script we hang on to the permission for a given script // for the lifetime of the Office removeSecurityPermission = false; // possibly need to encode it?? } if ( storageURI.getLength() > 0 ) { OSL_TRACE( "URI disposing is ... %s", ::rtl::OUStringToOString( storageURI, RTL_TEXTENCODING_ASCII_US ).pData->buffer ); } } catch ( RuntimeException& e ) { OUString message = OUSTR( "ScriptStorageManager::disposing: can't get script context, reason = " ); message = message.concat( e.Message ); OSL_TRACE( ::rtl::OUStringToOString( message, RTL_TEXTENCODING_ASCII_US ).pData->buffer ); return; } // grab storage id. sal_Int32 scriptStorageID = getScriptStorageID( storageURI ); // no need to do anything if there's no doc storage if( scriptStorageID == -1 ) { return; } OSL_TRACE( "disposing storageID = %d", scriptStorageID ); // attempt to get the storage from the hash to ensure that we have a // valid storageID ScriptStorage_map::const_iterator itr = m_ScriptStorageMap.find( scriptStorageID ); if ( itr == m_ScriptStorageMap.end() ) { OSL_TRACE( "Entry for storage id %d doesn't exist in map", scriptStorageID ); return; } // erase the entry from the hash m_ScriptStorageMap.erase( scriptStorageID ); removeScriptDocURIHashEntry( storageURI ); if ( removeSecurityPermission ) { m_securityMgr.removePermissionSettings ( storageURI ); } } } // Namespace namespace scripting_runtimemgr { //************************************************************************* Reference< XInterface > SAL_CALL ssm_create( const Reference< XComponentContext > & xCompC ) { return ( cppu::OWeakObject * ) new ::scripting_impl::ScriptStorageManager( xCompC ); } //************************************************************************* Sequence< OUString > ssm_getSupportedServiceNames( ) SAL_THROW( () ) { return ::scripting_impl::s_serviceNames; } //************************************************************************* OUString ssm_getImplementationName( ) SAL_THROW( () ) { return ::scripting_impl::s_implName; } }