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