1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_scripting.hxx" 30 31 #include <stdio.h> 32 33 #include <cppuhelper/implementationentry.hxx> 34 #include <sal/config.h> 35 #include <rtl/uri.hxx> 36 37 #include <com/sun/star/ucb/XSimpleFileAccess.hpp> 38 #include <com/sun/star/util/XMacroExpander.hpp> 39 #include <com/sun/star/lang/XComponent.hpp> 40 #include <com/sun/star/lang/XMultiComponentFactory.hpp> 41 #include <com/sun/star/beans/XPropertySet.hpp> 42 #include <com/sun/star/frame/XModel.hpp> 43 #include <drafts/com/sun/star/script/framework/storage/XScriptInfoAccess.hpp> 44 45 #include "ScriptStorageManager.hxx" 46 #include <util/util.hxx> 47 #include <util/scriptingconstants.hxx> 48 #include <tools/diagnose_ex.h> 49 50 using namespace ::rtl; 51 using namespace ::com::sun::star; 52 using namespace ::com::sun::star::uno; 53 using namespace ::drafts::com::sun::star::script::framework; 54 55 namespace scripting_impl 56 { 57 58 static OUString s_implName = 59 ::rtl::OUString::createFromAscii( 60 "drafts.com.sun.star.script.framework.storage.ScriptStorageManager" ); 61 static OUString s_serviceName = 62 ::rtl::OUString::createFromAscii( 63 "drafts.com.sun.star.script.framework.storage.ScriptStorageManager" ); 64 static Sequence< OUString > s_serviceNames = Sequence< OUString >( &s_serviceName, 1 ); 65 66 //extern ::rtl_StandardModuleCount s_moduleCount = MODULE_COUNT_INIT; 67 //extern ::rtl_StandardModuleCount s_moduleCount; 68 69 70 //************************************************************************* 71 // ScriptStorageManager Constructor 72 ScriptStorageManager::ScriptStorageManager( const Reference< 73 XComponentContext > & xContext ) SAL_THROW ( ( RuntimeException ) ) 74 : m_xContext( xContext, UNO_SET_THROW ), m_count( 0 ), m_securityMgr( xContext ) 75 { 76 OSL_TRACE( "< ScriptStorageManager ctor called >\n" ); 77 //s_moduleCount.modCnt.acquire( &s_moduleCount.modCnt ); 78 79 m_xMgr.set( m_xContext->getServiceManager(), UNO_SET_THROW ); 80 81 try 82 { 83 // obtain the macro expander singleton to use in determining the 84 // location of the application script storage 85 Reference< util::XMacroExpander > xME( m_xContext->getValueByName( OUString::createFromAscii( 86 "/singletons/com.sun.star.util.theMacroExpander" ) ), UNO_QUERY_THROW ); 87 88 OUString base = OUString::createFromAscii( 89 SAL_CONFIGFILE( "${$BRAND_BASE_DIR/program/bootstrap" ) ); 90 91 setupAppStorage( xME, 92 base.concat( OUString::createFromAscii( "::BaseInstallation}/share" ) ), 93 OUSTR( "SHARE" ) ); 94 setupAppStorage( xME, 95 base.concat( OUString::createFromAscii( "::UserInstallation}/user" ) ), 96 OUSTR( "USER" ) ); 97 98 } 99 catch ( Exception & e ) 100 { 101 throw RuntimeException( OUSTR( "ScriptStorageManager::ScriptStorageManager: " ).concat( e.Message ), Reference< XInterface >() ); 102 } 103 OSL_ASSERT( m_count == 2 ); 104 } 105 106 //************************************************************************* 107 // ScriptStorageManager setupAppStorage 108 void 109 ScriptStorageManager::setupAppStorage( 110 const Reference< util::XMacroExpander > & xME, 111 const OUString & storageStr, 112 const OUString & appStr) 113 SAL_THROW ( ( RuntimeException ) ) 114 { 115 try 116 { 117 Reference< ucb::XSimpleFileAccess > xSFA( 118 m_xMgr->createInstanceWithContext( 119 OUString::createFromAscii( "com.sun.star.ucb.SimpleFileAccess" ), 120 m_xContext 121 ), 122 UNO_QUERY_THROW 123 ); 124 125 setupAnyStorage( xSFA, xME->expandMacros( storageStr ), appStr ); 126 } 127 catch ( Exception & e ) 128 { 129 throw RuntimeException( 130 OUSTR( "ScriptStorageManager::setupAppStorage: " ).concat( e.Message ), 131 Reference< XInterface >() ); 132 } 133 } 134 135 //************************************************************************* 136 // ScriptStorageManager setupAnyStorage 137 sal_Int32 138 ScriptStorageManager::setupAnyStorage( 139 const Reference< ucb::XSimpleFileAccess > & xSFA, 140 const OUString & storageStr, 141 const OUString & origStringURI ) 142 SAL_THROW ( ( RuntimeException ) ) 143 { 144 // Required for scope of fnc to protect all access read and writes to m_count 145 ::osl::Guard< ::osl::Mutex > aGuard( m_mutex ); 146 try 147 { 148 149 // create a ScriptingStorage using the SimpleFileAccess, the storageID 150 // (from the count), and the URL to the application's shared area 151 Sequence < Any > aArgs( 3 ); 152 aArgs[ 0 ] <<= xSFA; 153 aArgs[ 1 ] <<= m_count; 154 aArgs[ 2 ] <<= storageStr; 155 156 OSL_TRACE( "creating storage for: %s\n", 157 ::rtl::OUStringToOString( storageStr, 158 RTL_TEXTENCODING_ASCII_US ).pData->buffer ); 159 160 Reference< XInterface > xInterface( 161 m_xMgr->createInstanceWithArgumentsAndContext( 162 OUString::createFromAscii( "drafts.com.sun.star.script.framework.storage.ScriptStorage" ), 163 aArgs, 164 m_xContext 165 ), 166 UNO_QUERY_THROW 167 ); 168 169 // and place it in the hash_map. Increment the counter 170 m_ScriptStorageMap[ m_count++ ] = xInterface; 171 sal_Int32 sid = m_count - 1; 172 173 // create hash of original uri i.e. file:///home/users/docs/mydoc.sxw 174 // and storage id (sid) this will allow us to retrieve 175 // the sid based on the url of the document. 176 m_StorageIdOrigURIHash [ origStringURI ] = sid; 177 OSL_TRACE( "\tcreated with ID=%d\n", m_count - 1 ); 178 179 } 180 catch ( Exception & e ) 181 { 182 throw RuntimeException( 183 OUSTR( "ScriptStorageManager::setupAnyStorage: " ).concat( 184 e.Message ), Reference< XInterface >() ); 185 } 186 187 return m_count -1; 188 } 189 190 //************************************************************************* 191 // ScriptStorageManager Destructor 192 ScriptStorageManager::~ScriptStorageManager() 193 SAL_THROW ( () ) 194 { 195 OSL_TRACE( "< ScriptStorageManager dtor called >\n" ); 196 // s_moduleCount.modCnt.release( &s_moduleCount.modCnt ); 197 } 198 199 //************************************************************************* 200 // This method assumes that the XSimpleFileAccess knows it's on root URL 201 // and can be used with relative URLs 202 sal_Int32 SAL_CALL 203 ScriptStorageManager::createScriptStorage( 204 const Reference< ucb::XSimpleFileAccess >& xSFA ) 205 throw ( RuntimeException ) 206 { 207 OSL_TRACE( "** ==> ScriptStorageManager in createScriptingStorage\n" ); 208 ENSURE_OR_THROW( xSFA.is(), "ScriptStorageManager::createScriptStorage: XSimpleFileAccess is not valid" ); 209 210 return setupAnyStorage( xSFA, ::rtl::OUString::createFromAscii( "" ), 211 ::rtl::OUString::createFromAscii( "" ) ); 212 } 213 214 //************************************************************************* 215 sal_Int32 SAL_CALL 216 ScriptStorageManager::createScriptStorageWithURI( 217 const Reference< ucb::XSimpleFileAccess >& xSFA, const OUString & cStringURI ) 218 throw ( RuntimeException ) 219 { 220 OSL_TRACE( "** ==> ScriptStorageManager in createScriptingStorageWithURI\n" ); 221 ENSURE_OR_THROW( xSFA.is(), "ScriptStorageManager::createScriptStorage: XSimpleFileAccess is not valid" ); 222 223 // related to issue 11866 224 // warning dialog gets launched when adding binding to script in doc 225 // workaround issue: no functionProvider created on doc open 226 // if NODIALOG tag, strip from stringURI, set boolean=true 227 bool displayDialog = true; 228 ::rtl::OUString dialogTag = ::rtl::OUString::createFromAscii( "NoDialog::" ); 229 ::rtl::OUString stringURI = cStringURI; 230 if( stringURI.indexOf( dialogTag ) == 0 ) 231 { 232 OSL_TRACE( "ScriptStorageManager::createScriptStorage: will not display security dialogs" ); 233 stringURI = stringURI.copy( dialogTag.getLength() ); 234 displayDialog = false; 235 } 236 sal_Int32 returnedID = getScriptStorageID(stringURI); 237 238 239 // convert file:///... url to vnd... syntax 240 ::rtl::OUString canonicalURI( 241 ::rtl::OUString::createFromAscii( "vnd.sun.star.pkg://" ) ); 242 canonicalURI = canonicalURI.concat( ::rtl::Uri::encode( stringURI, 243 rtl_UriCharClassUricNoSlash, rtl_UriEncodeCheckEscapes, 244 RTL_TEXTENCODING_ASCII_US ) ); 245 246 if (returnedID == -1) 247 { 248 OSL_TRACE("Creating new storage for %s", 249 ::rtl::OUStringToOString( stringURI, 250 RTL_TEXTENCODING_ASCII_US ).pData->buffer ); 251 returnedID = setupAnyStorage( xSFA, canonicalURI, stringURI ); 252 } 253 else 254 { 255 OSL_TRACE("Using existing storage for %s", 256 ::rtl::OUStringToOString( stringURI, 257 RTL_TEXTENCODING_ASCII_US ).pData->buffer ); 258 } 259 260 // np - removed previous scripting framework security handling 261 // now handled by modification to existing calls in sfx for basic 262 // 263 /* if( displayDialog ) 264 { 265 try 266 { 267 OSL_TRACE("Adding to security mgr for %s", 268 ::rtl::OUStringToOString( stringURI, 269 RTL_TEXTENCODING_ASCII_US ).pData->buffer ); 270 m_securityMgr.addScriptStorage( stringURI, returnedID ); 271 } 272 catch ( RuntimeException & rte ) 273 { 274 throw RuntimeException( 275 OUSTR( "ScriptStorageManager::createScriptStorageWithURI: " ).concat( 276 rte.Message ), Reference< XInterface >() ); 277 } 278 } 279 else 280 { 281 OSL_TRACE("No need to security mgr for %s", 282 ::rtl::OUStringToOString( stringURI, 283 RTL_TEXTENCODING_ASCII_US ).pData->buffer ); 284 }*/ 285 return returnedID; 286 } 287 288 //************************************************************************* 289 Reference < XInterface > SAL_CALL 290 ScriptStorageManager::getScriptStorage( sal_Int32 scriptStorageID ) 291 throw( RuntimeException ) 292 { 293 OSL_TRACE( "** ==> ScriptStorageManager in getStorageInstance\n" ); 294 OSL_TRACE( "** ==> request for id=%d",scriptStorageID ); 295 296 ScriptStorage_map::const_iterator itr = 297 m_ScriptStorageMap.find( scriptStorageID ); 298 299 if ( itr == m_ScriptStorageMap.end() ) 300 { 301 throw RuntimeException( 302 OUSTR( "ScriptStorageManager::getScriptStorage: invalid storage ID" ), 303 Reference< XInterface >() ); 304 } 305 ENSURE_OR_THROW( itr->second.is(), 306 "ScriptStorageManager::getScriptStorage: Cannot get ScriptStorage from ScriptStorageHash" ); 307 return itr->second; 308 } 309 310 //******************************************************************* 311 sal_Int32 SAL_CALL 312 ScriptStorageManager::getScriptStorageID( const ::rtl::OUString& origURI ) 313 throw (::com::sun::star::uno::RuntimeException) 314 { 315 StorageId_hash::const_iterator it = m_StorageIdOrigURIHash.find( origURI ); 316 317 if ( it == m_StorageIdOrigURIHash.end() ) 318 { 319 OUString message = OUSTR( "ScriptStorageManager::getScriptStorageID(): Cannot find storage for " ); 320 if ( origURI.getLength() == 0 ) 321 { 322 message = message.concat( OUSTR("Empty URI") ); 323 } 324 else 325 { 326 message = message.concat( origURI ); 327 } 328 OSL_TRACE( ::rtl::OUStringToOString( message, 329 RTL_TEXTENCODING_ASCII_US ).pData->buffer ); 330 return -1; 331 } 332 333 return it->second; 334 } 335 336 //******************************************************************* 337 void 338 ScriptStorageManager::removeScriptDocURIHashEntry( const OUString & origURI ) 339 { 340 StorageId_hash::iterator it = m_StorageIdOrigURIHash.find( origURI ); 341 if ( it == m_StorageIdOrigURIHash.end() ) 342 { 343 OSL_TRACE( "ScriptStorageManager::removeScriptDocURIHashEntry: no entry to remove" ); 344 return; 345 } 346 347 // remove entry for this doc url from orig uri map. 348 m_StorageIdOrigURIHash.erase( it ); 349 } 350 351 //******************************************************************* 352 void SAL_CALL 353 ScriptStorageManager::refreshScriptStorage( const OUString & stringURI ) 354 throw( RuntimeException ) 355 { 356 OSL_TRACE( "** => ScriptStorageManager in refreshScriptStorage\n" ); 357 OSL_TRACE( "** => refreshing URI: %s\n", 358 ::rtl::OUStringToOString( 359 stringURI, RTL_TEXTENCODING_ASCII_US ).pData->buffer); 360 361 sal_Int32 storageID = getScriptStorageID( stringURI ); 362 363 if ( storageID == -1 ) 364 { 365 OSL_TRACE( "** id was -1, no storage"); 366 // Refreshing noexistent storage - just return 367 return; 368 } 369 370 try 371 { 372 Reference < storage::XScriptStorageRefresh > xSSR( 373 getScriptStorage( storageID ), UNO_QUERY ); 374 375 xSSR->refresh(); 376 } 377 catch ( RuntimeException & e ) 378 { 379 throw RuntimeException( 380 OUSTR( "ScriptStorageManager::refreshScriptStorage: " ).concat( 381 e.Message ), Reference< XInterface >() ); 382 } 383 catch ( Exception & e ) 384 { 385 throw RuntimeException( 386 OUSTR( "ScriptStorageManager::refreshScriptStorage: " ).concat( 387 e.Message ), Reference< XInterface >() ); 388 } 389 } 390 391 //************************************************************************* 392 void SAL_CALL 393 ScriptStorageManager::checkPermission( const OUString & 394 scriptStorageURI, const OUString & permissionRequest ) 395 throw ( RuntimeException, lang::IllegalArgumentException, css::security::AccessControlException ) 396 { 397 try 398 { 399 m_securityMgr.checkPermission( scriptStorageURI, permissionRequest ); 400 } 401 catch ( css::security::AccessControlException & e ) 402 { 403 throw css::security::AccessControlException( 404 OUSTR( "ScriptStorageManager::checkPermission: AccessControlException: " ).concat( 405 e.Message ), Reference< XInterface >(), e.LackingPermission ); 406 } 407 catch ( lang::IllegalArgumentException & e ) 408 { 409 throw lang::IllegalArgumentException( 410 OUSTR( "ScriptStorageManager::checkPermission: IllegalArgumentException: " ).concat( 411 e.Message ), Reference< XInterface >(), e.ArgumentPosition ); 412 } 413 catch ( RuntimeException & e ) 414 { 415 throw RuntimeException( 416 OUSTR( "ScriptStorageManager::checkPermission: RuntimeException: " ).concat( 417 e.Message ), Reference< XInterface >() ); 418 } 419 } 420 421 //************************************************************************* 422 OUString SAL_CALL 423 ScriptStorageManager::getImplementationName( ) 424 throw( RuntimeException ) 425 { 426 return s_implName; 427 } 428 429 //************************************************************************* 430 sal_Bool SAL_CALL 431 ScriptStorageManager::supportsService( const OUString& serviceName ) 432 throw( RuntimeException ) 433 { 434 OUString const * pNames = s_serviceNames.getConstArray(); 435 for ( sal_Int32 nPos = s_serviceNames.getLength(); nPos--; ) 436 { 437 if ( serviceName.equals( pNames[ nPos ] ) ) 438 { 439 return sal_True; 440 } 441 } 442 return sal_False; 443 } 444 445 //************************************************************************* 446 Sequence< OUString > SAL_CALL 447 ScriptStorageManager::getSupportedServiceNames( ) 448 throw( RuntimeException ) 449 { 450 return s_serviceNames; 451 } 452 453 //************************************************************************* 454 void SAL_CALL 455 ScriptStorageManager::disposing( const ::com::sun::star::lang::EventObject& Source ) 456 throw ( ::com::sun::star::uno::RuntimeException ) 457 { 458 OSL_TRACE( "ScriptStorageManager::disposing started" ); 459 OSL_TRACE( "event object type=%s", 460 ::rtl::OUStringToOString( getCppuType( &Source ).getTypeName(), 461 RTL_TEXTENCODING_ASCII_US ).pData->buffer ); 462 OUString storageURI; 463 bool removeSecurityPermission = true; 464 try 465 { 466 Reference< XInterface > xInterface = Source.Source; 467 // no UNO_QUERY_THROW since we want a 2nd change to query if it's 468 // not a document being disposed 469 Reference< frame::XModel > xModel = Reference< frame::XModel > ( xInterface, UNO_QUERY ); 470 if( xModel.is() ) 471 { 472 storageURI = xModel->getURL(); 473 } 474 else 475 { 476 // UNO_QURY_THROW here since it's supposed to be either a doc 477 // or a XScriptInfo (in the case of a filesys script) 478 Reference< storage::XScriptInfo > xScriptInfo = Reference< storage::XScriptInfo > ( xInterface, UNO_QUERY_THROW ); 479 storageURI = xScriptInfo->getParcelURI().concat( xScriptInfo->getFunctionName() ); 480 // to save the user seeing the security dialogs every time they 481 // run the script we hang on to the permission for a given script 482 // for the lifetime of the Office 483 removeSecurityPermission = false; 484 // possibly need to encode it?? 485 } 486 if ( storageURI.getLength() > 0 ) 487 { 488 OSL_TRACE( "URI disposing is ... %s", 489 ::rtl::OUStringToOString( storageURI, 490 RTL_TEXTENCODING_ASCII_US ).pData->buffer ); 491 } 492 } 493 catch ( RuntimeException& e ) 494 { 495 OUString message = 496 OUSTR( 497 "ScriptStorageManager::disposing: can't get script context, reason = " ); 498 message = message.concat( e.Message ); 499 OSL_TRACE( ::rtl::OUStringToOString( message, 500 RTL_TEXTENCODING_ASCII_US ).pData->buffer ); 501 return; 502 } 503 504 505 // grab storage id. 506 sal_Int32 scriptStorageID = getScriptStorageID( storageURI ); 507 508 // no need to do anything if there's no doc storage 509 if( scriptStorageID == -1 ) 510 { 511 return; 512 } 513 514 OSL_TRACE( "disposing storageID = %d", scriptStorageID ); 515 516 // attempt to get the storage from the hash to ensure that we have a 517 // valid storageID 518 ScriptStorage_map::const_iterator itr = 519 m_ScriptStorageMap.find( scriptStorageID ); 520 521 if ( itr == m_ScriptStorageMap.end() ) 522 { 523 OSL_TRACE( "Entry for storage id %d doesn't exist in map", scriptStorageID ); 524 return; 525 } 526 527 // erase the entry from the hash 528 m_ScriptStorageMap.erase( scriptStorageID ); 529 removeScriptDocURIHashEntry( storageURI ); 530 if ( removeSecurityPermission ) 531 { 532 m_securityMgr.removePermissionSettings ( storageURI ); 533 } 534 } 535 } // Namespace 536 537 namespace scripting_runtimemgr 538 { 539 //************************************************************************* 540 Reference< XInterface > SAL_CALL 541 ssm_create( 542 const Reference< XComponentContext > & xCompC ) 543 { 544 return ( cppu::OWeakObject * ) new ::scripting_impl::ScriptStorageManager( xCompC ); 545 } 546 547 //************************************************************************* 548 Sequence< OUString > 549 ssm_getSupportedServiceNames( ) 550 SAL_THROW( () ) 551 { 552 return ::scripting_impl::s_serviceNames; 553 } 554 555 //************************************************************************* 556 OUString 557 ssm_getImplementationName( ) 558 SAL_THROW( () ) 559 { 560 return ::scripting_impl::s_implName; 561 } 562 } 563