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 ) 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( "${$OOO_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 { 110 try 111 { 112 Reference< ucb::XSimpleFileAccess > xSFA( 113 m_xMgr->createInstanceWithContext( 114 OUString::createFromAscii( "com.sun.star.ucb.SimpleFileAccess" ), 115 m_xContext 116 ), 117 UNO_QUERY_THROW 118 ); 119 120 setupAnyStorage( xSFA, xME->expandMacros( storageStr ), appStr ); 121 } 122 catch ( Exception & e ) 123 { 124 throw RuntimeException( 125 OUSTR( "ScriptStorageManager::setupAppStorage: " ).concat( e.Message ), 126 Reference< XInterface >() ); 127 } 128 } 129 130 //************************************************************************* 131 // ScriptStorageManager setupAnyStorage 132 sal_Int32 133 ScriptStorageManager::setupAnyStorage( 134 const Reference< ucb::XSimpleFileAccess > & xSFA, 135 const OUString & storageStr, 136 const OUString & origStringURI ) 137 { 138 // Required for scope of fnc to protect all access read and writes to m_count 139 ::osl::Guard< ::osl::Mutex > aGuard( m_mutex ); 140 try 141 { 142 143 // create a ScriptingStorage using the SimpleFileAccess, the storageID 144 // (from the count), and the URL to the application's shared area 145 Sequence < Any > aArgs( 3 ); 146 aArgs[ 0 ] <<= xSFA; 147 aArgs[ 1 ] <<= m_count; 148 aArgs[ 2 ] <<= storageStr; 149 150 OSL_TRACE( "creating storage for: %s\n", 151 ::rtl::OUStringToOString( storageStr, 152 RTL_TEXTENCODING_ASCII_US ).pData->buffer ); 153 154 Reference< XInterface > xInterface( 155 m_xMgr->createInstanceWithArgumentsAndContext( 156 OUString::createFromAscii( "drafts.com.sun.star.script.framework.storage.ScriptStorage" ), 157 aArgs, 158 m_xContext 159 ), 160 UNO_QUERY_THROW 161 ); 162 163 // and place it in the hash_map. Increment the counter 164 m_ScriptStorageMap[ m_count++ ] = xInterface; 165 sal_Int32 sid = m_count - 1; 166 167 // create hash of original uri i.e. file:///home/users/docs/mydoc.sxw 168 // and storage id (sid) this will allow us to retrieve 169 // the sid based on the url of the document. 170 m_StorageIdOrigURIHash [ origStringURI ] = sid; 171 OSL_TRACE( "\tcreated with ID=%d\n", m_count - 1 ); 172 173 } 174 catch ( Exception & e ) 175 { 176 throw RuntimeException( 177 OUSTR( "ScriptStorageManager::setupAnyStorage: " ).concat( 178 e.Message ), Reference< XInterface >() ); 179 } 180 181 return m_count -1; 182 } 183 184 //************************************************************************* 185 // ScriptStorageManager Destructor 186 ScriptStorageManager::~ScriptStorageManager() 187 SAL_THROW ( () ) 188 { 189 OSL_TRACE( "< ScriptStorageManager dtor called >\n" ); 190 // s_moduleCount.modCnt.release( &s_moduleCount.modCnt ); 191 } 192 193 //************************************************************************* 194 // This method assumes that the XSimpleFileAccess knows it's on root URL 195 // and can be used with relative URLs 196 sal_Int32 SAL_CALL 197 ScriptStorageManager::createScriptStorage( 198 const Reference< ucb::XSimpleFileAccess >& xSFA ) 199 { 200 OSL_TRACE( "** ==> ScriptStorageManager in createScriptingStorage\n" ); 201 ENSURE_OR_THROW( xSFA.is(), "ScriptStorageManager::createScriptStorage: XSimpleFileAccess is not valid" ); 202 203 return setupAnyStorage( xSFA, ::rtl::OUString::createFromAscii( "" ), 204 ::rtl::OUString::createFromAscii( "" ) ); 205 } 206 207 //************************************************************************* 208 sal_Int32 SAL_CALL 209 ScriptStorageManager::createScriptStorageWithURI( 210 const Reference< ucb::XSimpleFileAccess >& xSFA, const OUString & cStringURI ) 211 { 212 OSL_TRACE( "** ==> ScriptStorageManager in createScriptingStorageWithURI\n" ); 213 ENSURE_OR_THROW( xSFA.is(), "ScriptStorageManager::createScriptStorage: XSimpleFileAccess is not valid" ); 214 215 // related to issue 11866 216 // warning dialog gets launched when adding binding to script in doc 217 // workaround issue: no functionProvider created on doc open 218 // if NODIALOG tag, strip from stringURI, set boolean=true 219 bool displayDialog = true; 220 ::rtl::OUString dialogTag = ::rtl::OUString::createFromAscii( "NoDialog::" ); 221 ::rtl::OUString stringURI = cStringURI; 222 if( stringURI.indexOf( dialogTag ) == 0 ) 223 { 224 OSL_TRACE( "ScriptStorageManager::createScriptStorage: will not display security dialogs" ); 225 stringURI = stringURI.copy( dialogTag.getLength() ); 226 displayDialog = false; 227 } 228 sal_Int32 returnedID = getScriptStorageID(stringURI); 229 230 231 // convert file:///... url to vnd... syntax 232 ::rtl::OUString canonicalURI( 233 ::rtl::OUString::createFromAscii( "vnd.sun.star.pkg://" ) ); 234 canonicalURI = canonicalURI.concat( ::rtl::Uri::encode( stringURI, 235 rtl_UriCharClassUricNoSlash, rtl_UriEncodeCheckEscapes, 236 RTL_TEXTENCODING_ASCII_US ) ); 237 238 if (returnedID == -1) 239 { 240 OSL_TRACE("Creating new storage for %s", 241 ::rtl::OUStringToOString( stringURI, 242 RTL_TEXTENCODING_ASCII_US ).pData->buffer ); 243 returnedID = setupAnyStorage( xSFA, canonicalURI, stringURI ); 244 } 245 else 246 { 247 OSL_TRACE("Using existing storage for %s", 248 ::rtl::OUStringToOString( stringURI, 249 RTL_TEXTENCODING_ASCII_US ).pData->buffer ); 250 } 251 252 // np - removed previous scripting framework security handling 253 // now handled by modification to existing calls in sfx for basic 254 // 255 /* if( displayDialog ) 256 { 257 try 258 { 259 OSL_TRACE("Adding to security mgr for %s", 260 ::rtl::OUStringToOString( stringURI, 261 RTL_TEXTENCODING_ASCII_US ).pData->buffer ); 262 m_securityMgr.addScriptStorage( stringURI, returnedID ); 263 } 264 catch ( RuntimeException & rte ) 265 { 266 throw RuntimeException( 267 OUSTR( "ScriptStorageManager::createScriptStorageWithURI: " ).concat( 268 rte.Message ), Reference< XInterface >() ); 269 } 270 } 271 else 272 { 273 OSL_TRACE("No need to security mgr for %s", 274 ::rtl::OUStringToOString( stringURI, 275 RTL_TEXTENCODING_ASCII_US ).pData->buffer ); 276 }*/ 277 return returnedID; 278 } 279 280 //************************************************************************* 281 Reference < XInterface > SAL_CALL 282 ScriptStorageManager::getScriptStorage( sal_Int32 scriptStorageID ) 283 { 284 OSL_TRACE( "** ==> ScriptStorageManager in getStorageInstance\n" ); 285 OSL_TRACE( "** ==> request for id=%d",scriptStorageID ); 286 287 ScriptStorage_map::const_iterator itr = 288 m_ScriptStorageMap.find( scriptStorageID ); 289 290 if ( itr == m_ScriptStorageMap.end() ) 291 { 292 throw RuntimeException( 293 OUSTR( "ScriptStorageManager::getScriptStorage: invalid storage ID" ), 294 Reference< XInterface >() ); 295 } 296 ENSURE_OR_THROW( itr->second.is(), 297 "ScriptStorageManager::getScriptStorage: Cannot get ScriptStorage from ScriptStorageHash" ); 298 return itr->second; 299 } 300 301 //******************************************************************* 302 sal_Int32 SAL_CALL 303 ScriptStorageManager::getScriptStorageID( const ::rtl::OUString& origURI ) 304 { 305 StorageId_hash::const_iterator it = m_StorageIdOrigURIHash.find( origURI ); 306 307 if ( it == m_StorageIdOrigURIHash.end() ) 308 { 309 OUString message = OUSTR( "ScriptStorageManager::getScriptStorageID(): Cannot find storage for " ); 310 if ( origURI.getLength() == 0 ) 311 { 312 message = message.concat( OUSTR("Empty URI") ); 313 } 314 else 315 { 316 message = message.concat( origURI ); 317 } 318 OSL_TRACE( ::rtl::OUStringToOString( message, 319 RTL_TEXTENCODING_ASCII_US ).pData->buffer ); 320 return -1; 321 } 322 323 return it->second; 324 } 325 326 //******************************************************************* 327 void 328 ScriptStorageManager::removeScriptDocURIHashEntry( const OUString & origURI ) 329 { 330 StorageId_hash::iterator it = m_StorageIdOrigURIHash.find( origURI ); 331 if ( it == m_StorageIdOrigURIHash.end() ) 332 { 333 OSL_TRACE( "ScriptStorageManager::removeScriptDocURIHashEntry: no entry to remove" ); 334 return; 335 } 336 337 // remove entry for this doc url from orig uri map. 338 m_StorageIdOrigURIHash.erase( it ); 339 } 340 341 //******************************************************************* 342 void SAL_CALL 343 ScriptStorageManager::refreshScriptStorage( const OUString & stringURI ) 344 { 345 OSL_TRACE( "** => ScriptStorageManager in refreshScriptStorage\n" ); 346 OSL_TRACE( "** => refreshing URI: %s\n", 347 ::rtl::OUStringToOString( 348 stringURI, RTL_TEXTENCODING_ASCII_US ).pData->buffer); 349 350 sal_Int32 storageID = getScriptStorageID( stringURI ); 351 352 if ( storageID == -1 ) 353 { 354 OSL_TRACE( "** id was -1, no storage"); 355 // Refreshing noexistent storage - just return 356 return; 357 } 358 359 try 360 { 361 Reference < storage::XScriptStorageRefresh > xSSR( 362 getScriptStorage( storageID ), UNO_QUERY ); 363 364 xSSR->refresh(); 365 } 366 catch ( RuntimeException & e ) 367 { 368 throw RuntimeException( 369 OUSTR( "ScriptStorageManager::refreshScriptStorage: " ).concat( 370 e.Message ), Reference< XInterface >() ); 371 } 372 catch ( Exception & e ) 373 { 374 throw RuntimeException( 375 OUSTR( "ScriptStorageManager::refreshScriptStorage: " ).concat( 376 e.Message ), Reference< XInterface >() ); 377 } 378 } 379 380 //************************************************************************* 381 void SAL_CALL 382 ScriptStorageManager::checkPermission( const OUString & 383 scriptStorageURI, const OUString & permissionRequest ) 384 { 385 try 386 { 387 m_securityMgr.checkPermission( scriptStorageURI, permissionRequest ); 388 } 389 catch ( css::security::AccessControlException & e ) 390 { 391 throw css::security::AccessControlException( 392 OUSTR( "ScriptStorageManager::checkPermission: AccessControlException: " ).concat( 393 e.Message ), Reference< XInterface >(), e.LackingPermission ); 394 } 395 catch ( lang::IllegalArgumentException & e ) 396 { 397 throw lang::IllegalArgumentException( 398 OUSTR( "ScriptStorageManager::checkPermission: IllegalArgumentException: " ).concat( 399 e.Message ), Reference< XInterface >(), e.ArgumentPosition ); 400 } 401 catch ( RuntimeException & e ) 402 { 403 throw RuntimeException( 404 OUSTR( "ScriptStorageManager::checkPermission: RuntimeException: " ).concat( 405 e.Message ), Reference< XInterface >() ); 406 } 407 } 408 409 //************************************************************************* 410 OUString SAL_CALL 411 ScriptStorageManager::getImplementationName( ) 412 { 413 return s_implName; 414 } 415 416 //************************************************************************* 417 sal_Bool SAL_CALL 418 ScriptStorageManager::supportsService( const OUString& serviceName ) 419 { 420 OUString const * pNames = s_serviceNames.getConstArray(); 421 for ( sal_Int32 nPos = s_serviceNames.getLength(); nPos--; ) 422 { 423 if ( serviceName.equals( pNames[ nPos ] ) ) 424 { 425 return sal_True; 426 } 427 } 428 return sal_False; 429 } 430 431 //************************************************************************* 432 Sequence< OUString > SAL_CALL 433 ScriptStorageManager::getSupportedServiceNames( ) 434 { 435 return s_serviceNames; 436 } 437 438 //************************************************************************* 439 void SAL_CALL 440 ScriptStorageManager::disposing( const ::com::sun::star::lang::EventObject& Source ) 441 { 442 OSL_TRACE( "ScriptStorageManager::disposing started" ); 443 OSL_TRACE( "event object type=%s", 444 ::rtl::OUStringToOString( getCppuType( &Source ).getTypeName(), 445 RTL_TEXTENCODING_ASCII_US ).pData->buffer ); 446 OUString storageURI; 447 bool removeSecurityPermission = true; 448 try 449 { 450 Reference< XInterface > xInterface = Source.Source; 451 // no UNO_QUERY_THROW since we want a 2nd change to query if it's 452 // not a document being disposed 453 Reference< frame::XModel > xModel = Reference< frame::XModel > ( xInterface, UNO_QUERY ); 454 if( xModel.is() ) 455 { 456 storageURI = xModel->getURL(); 457 } 458 else 459 { 460 // UNO_QURY_THROW here since it's supposed to be either a doc 461 // or a XScriptInfo (in the case of a filesys script) 462 Reference< storage::XScriptInfo > xScriptInfo = Reference< storage::XScriptInfo > ( xInterface, UNO_QUERY_THROW ); 463 storageURI = xScriptInfo->getParcelURI().concat( xScriptInfo->getFunctionName() ); 464 // to save the user seeing the security dialogs every time they 465 // run the script we hang on to the permission for a given script 466 // for the lifetime of the Office 467 removeSecurityPermission = false; 468 // possibly need to encode it?? 469 } 470 if ( storageURI.getLength() > 0 ) 471 { 472 OSL_TRACE( "URI disposing is ... %s", 473 ::rtl::OUStringToOString( storageURI, 474 RTL_TEXTENCODING_ASCII_US ).pData->buffer ); 475 } 476 } 477 catch ( RuntimeException& e ) 478 { 479 OUString message = 480 OUSTR( 481 "ScriptStorageManager::disposing: can't get script context, reason = " ); 482 message = message.concat( e.Message ); 483 OSL_TRACE( ::rtl::OUStringToOString( message, 484 RTL_TEXTENCODING_ASCII_US ).pData->buffer ); 485 return; 486 } 487 488 489 // grab storage id. 490 sal_Int32 scriptStorageID = getScriptStorageID( storageURI ); 491 492 // no need to do anything if there's no doc storage 493 if( scriptStorageID == -1 ) 494 { 495 return; 496 } 497 498 OSL_TRACE( "disposing storageID = %d", scriptStorageID ); 499 500 // attempt to get the storage from the hash to ensure that we have a 501 // valid storageID 502 ScriptStorage_map::const_iterator itr = 503 m_ScriptStorageMap.find( scriptStorageID ); 504 505 if ( itr == m_ScriptStorageMap.end() ) 506 { 507 OSL_TRACE( "Entry for storage id %d doesn't exist in map", scriptStorageID ); 508 return; 509 } 510 511 // erase the entry from the hash 512 m_ScriptStorageMap.erase( scriptStorageID ); 513 removeScriptDocURIHashEntry( storageURI ); 514 if ( removeSecurityPermission ) 515 { 516 m_securityMgr.removePermissionSettings ( storageURI ); 517 } 518 } 519 } // Namespace 520 521 namespace scripting_runtimemgr 522 { 523 //************************************************************************* 524 Reference< XInterface > SAL_CALL 525 ssm_create( 526 const Reference< XComponentContext > & xCompC ) 527 { 528 return ( cppu::OWeakObject * ) new ::scripting_impl::ScriptStorageManager( xCompC ); 529 } 530 531 //************************************************************************* 532 Sequence< OUString > 533 ssm_getSupportedServiceNames( ) 534 SAL_THROW( () ) 535 { 536 return ::scripting_impl::s_serviceNames; 537 } 538 539 //************************************************************************* 540 OUString 541 ssm_getImplementationName( ) 542 SAL_THROW( () ) 543 { 544 return ::scripting_impl::s_implName; 545 } 546 } 547