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
ScriptStorageManager(const Reference<XComponentContext> & xContext)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( "${$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
setupAppStorage(const Reference<util::XMacroExpander> & xME,const OUString & storageStr,const OUString & appStr)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
setupAnyStorage(const Reference<ucb::XSimpleFileAccess> & xSFA,const OUString & storageStr,const OUString & origStringURI)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
~ScriptStorageManager()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
createScriptStorage(const Reference<ucb::XSimpleFileAccess> & xSFA)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
createScriptStorageWithURI(const Reference<ucb::XSimpleFileAccess> & xSFA,const OUString & cStringURI)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
getScriptStorage(sal_Int32 scriptStorageID)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
getScriptStorageID(const::rtl::OUString & origURI)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
removeScriptDocURIHashEntry(const OUString & origURI)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
refreshScriptStorage(const OUString & stringURI)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
checkPermission(const OUString & scriptStorageURI,const OUString & permissionRequest)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
getImplementationName()419 ScriptStorageManager::getImplementationName( )
420 throw( RuntimeException )
421 {
422 return s_implName;
423 }
424
425 //*************************************************************************
426 sal_Bool SAL_CALL
supportsService(const OUString & serviceName)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
getSupportedServiceNames()443 ScriptStorageManager::getSupportedServiceNames( )
444 throw( RuntimeException )
445 {
446 return s_serviceNames;
447 }
448
449 //*************************************************************************
450 void SAL_CALL
disposing(const::com::sun::star::lang::EventObject & Source)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
ssm_create(const Reference<XComponentContext> & xCompC)537 ssm_create(
538 const Reference< XComponentContext > & xCompC )
539 {
540 return ( cppu::OWeakObject * ) new ::scripting_impl::ScriptStorageManager( xCompC );
541 }
542
543 //*************************************************************************
544 Sequence< OUString >
ssm_getSupportedServiceNames()545 ssm_getSupportedServiceNames( )
546 SAL_THROW( () )
547 {
548 return ::scripting_impl::s_serviceNames;
549 }
550
551 //*************************************************************************
552 OUString
ssm_getImplementationName()553 ssm_getImplementationName( )
554 SAL_THROW( () )
555 {
556 return ::scripting_impl::s_implName;
557 }
558 }
559