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 )
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 {
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
setupAnyStorage(const Reference<ucb::XSimpleFileAccess> & xSFA,const OUString & storageStr,const OUString & origStringURI)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
~ScriptStorageManager()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
createScriptStorage(const Reference<ucb::XSimpleFileAccess> & xSFA)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
createScriptStorageWithURI(const Reference<ucb::XSimpleFileAccess> & xSFA,const OUString & cStringURI)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
getScriptStorage(sal_Int32 scriptStorageID)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
getScriptStorageID(const::rtl::OUString & origURI)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
removeScriptDocURIHashEntry(const OUString & origURI)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
refreshScriptStorage(const OUString & stringURI)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
checkPermission(const OUString & scriptStorageURI,const OUString & permissionRequest)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
getImplementationName()411 ScriptStorageManager::getImplementationName( )
412 {
413 return s_implName;
414 }
415
416 //*************************************************************************
417 sal_Bool SAL_CALL
supportsService(const OUString & serviceName)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
getSupportedServiceNames()433 ScriptStorageManager::getSupportedServiceNames( )
434 {
435 return s_serviceNames;
436 }
437
438 //*************************************************************************
439 void SAL_CALL
disposing(const::com::sun::star::lang::EventObject & Source)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
ssm_create(const Reference<XComponentContext> & xCompC)525 ssm_create(
526 const Reference< XComponentContext > & xCompC )
527 {
528 return ( cppu::OWeakObject * ) new ::scripting_impl::ScriptStorageManager( xCompC );
529 }
530
531 //*************************************************************************
532 Sequence< OUString >
ssm_getSupportedServiceNames()533 ssm_getSupportedServiceNames( )
534 SAL_THROW( () )
535 {
536 return ::scripting_impl::s_serviceNames;
537 }
538
539 //*************************************************************************
540 OUString
ssm_getImplementationName()541 ssm_getImplementationName( )
542 SAL_THROW( () )
543 {
544 return ::scripting_impl::s_implName;
545 }
546 }
547