| /************************************************************** |
| * |
| * 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 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_scripting.hxx" |
| |
| #include <stdio.h> |
| |
| #include <cppuhelper/implementationentry.hxx> |
| #include <sal/config.h> |
| #include <rtl/uri.hxx> |
| |
| #include <com/sun/star/ucb/XSimpleFileAccess.hpp> |
| #include <com/sun/star/util/XMacroExpander.hpp> |
| #include <com/sun/star/lang/XComponent.hpp> |
| #include <com/sun/star/lang/XMultiComponentFactory.hpp> |
| #include <com/sun/star/beans/XPropertySet.hpp> |
| #include <com/sun/star/frame/XModel.hpp> |
| #include <drafts/com/sun/star/script/framework/storage/XScriptInfoAccess.hpp> |
| |
| #include "ScriptStorageManager.hxx" |
| #include <util/util.hxx> |
| #include <util/scriptingconstants.hxx> |
| #include <tools/diagnose_ex.h> |
| |
| 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( "${$OOO_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; |
| } |
| } |