File: | home/maarten/src/libreoffice/core/basic/source/uno/scriptcont.cxx |
Warning: | line 333, column 1 Potential leak of memory pointed to by 'xStorage.pObj' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ | |||
2 | /* | |||
3 | * This file is part of the LibreOffice project. | |||
4 | * | |||
5 | * This Source Code Form is subject to the terms of the Mozilla Public | |||
6 | * License, v. 2.0. If a copy of the MPL was not distributed with this | |||
7 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. | |||
8 | * | |||
9 | * This file incorporates work covered by the following license notice: | |||
10 | * | |||
11 | * Licensed to the Apache Software Foundation (ASF) under one or more | |||
12 | * contributor license agreements. See the NOTICE file distributed | |||
13 | * with this work for additional information regarding copyright | |||
14 | * ownership. The ASF licenses this file to you under the Apache | |||
15 | * License, Version 2.0 (the "License"); you may not use this file | |||
16 | * except in compliance with the License. You may obtain a copy of | |||
17 | * the License at http://www.apache.org/licenses/LICENSE-2.0 . | |||
18 | */ | |||
19 | ||||
20 | #include <scriptcont.hxx> | |||
21 | #include <com/sun/star/packages/WrongPasswordException.hpp> | |||
22 | #include <com/sun/star/xml/sax/Parser.hpp> | |||
23 | #include <com/sun/star/xml/sax/InputSource.hpp> | |||
24 | #include <com/sun/star/xml/sax/Writer.hpp> | |||
25 | #include <com/sun/star/io/XTruncate.hpp> | |||
26 | #include <com/sun/star/embed/ElementModes.hpp> | |||
27 | #include <com/sun/star/embed/XEncryptionProtectedSource.hpp> | |||
28 | #include <com/sun/star/beans/XPropertySet.hpp> | |||
29 | #include <com/sun/star/embed/XTransactedObject.hpp> | |||
30 | #include <com/sun/star/task/ErrorCodeIOException.hpp> | |||
31 | #include <com/sun/star/script/ModuleType.hpp> | |||
32 | #include <com/sun/star/lang/XMultiServiceFactory.hpp> | |||
33 | #include <comphelper/storagehelper.hxx> | |||
34 | #include <unotools/ucbstreamhelper.hxx> | |||
35 | #include <sal/log.hxx> | |||
36 | #include <sot/storage.hxx> | |||
37 | ||||
38 | // For password functionality | |||
39 | #include <tools/urlobj.hxx> | |||
40 | ||||
41 | ||||
42 | #include <svtools/sfxecode.hxx> | |||
43 | #include <svtools/ehdl.hxx> | |||
44 | #include <basic/basmgr.hxx> | |||
45 | #include <basic/sbmod.hxx> | |||
46 | #include <basic/modsizeexceeded.hxx> | |||
47 | #include <xmlscript/xmlmod_imexp.hxx> | |||
48 | #include <com/sun/star/util/VetoException.hpp> | |||
49 | #include <memory> | |||
50 | ||||
51 | namespace basic | |||
52 | { | |||
53 | ||||
54 | using namespace com::sun::star::document; | |||
55 | using namespace com::sun::star::container; | |||
56 | using namespace com::sun::star::io; | |||
57 | using namespace com::sun::star::uno; | |||
58 | using namespace com::sun::star::ucb; | |||
59 | using namespace com::sun::star::lang; | |||
60 | using namespace com::sun::star::script; | |||
61 | using namespace com::sun::star::xml::sax; | |||
62 | using namespace com::sun::star; | |||
63 | using namespace cppu; | |||
64 | using namespace osl; | |||
65 | ||||
66 | ||||
67 | // Implementation class SfxScriptLibraryContainer | |||
68 | ||||
69 | const char* SfxScriptLibraryContainer::getInfoFileName() const { return "script"; } | |||
70 | const char* SfxScriptLibraryContainer::getOldInfoFileName() const { return "script"; } | |||
71 | const char* SfxScriptLibraryContainer::getLibElementFileExtension() const { return "xba"; } | |||
72 | const char* SfxScriptLibraryContainer::getLibrariesDir() const { return "Basic"; } | |||
73 | ||||
74 | // OldBasicPassword interface | |||
75 | void SfxScriptLibraryContainer::setLibraryPassword( const OUString& rLibraryName, const OUString& rPassword ) | |||
76 | { | |||
77 | try | |||
78 | { | |||
79 | SfxLibrary* pImplLib = getImplLib( rLibraryName ); | |||
80 | if( !rPassword.isEmpty() ) | |||
81 | { | |||
82 | pImplLib->mbDoc50Password = true; | |||
83 | pImplLib->mbPasswordProtected = true; | |||
84 | pImplLib->maPassword = rPassword; | |||
85 | SfxScriptLibrary *const pSL(dynamic_cast<SfxScriptLibrary *>(pImplLib)); | |||
86 | if (pSL && pSL->mbLoaded) | |||
87 | { | |||
88 | pSL->mbLoadedSource = true; // must store source code now! | |||
89 | } | |||
90 | } | |||
91 | } | |||
92 | catch(const NoSuchElementException& ) {} | |||
93 | } | |||
94 | ||||
95 | // Ctor for service | |||
96 | SfxScriptLibraryContainer::SfxScriptLibraryContainer() | |||
97 | { | |||
98 | // all initialisation has to be done | |||
99 | // by calling XInitialization::initialize | |||
100 | } | |||
101 | ||||
102 | SfxScriptLibraryContainer::SfxScriptLibraryContainer( const uno::Reference< embed::XStorage >& xStorage ) | |||
103 | { | |||
104 | init( OUString(), xStorage ); | |||
105 | } | |||
106 | ||||
107 | // Methods to get library instances of the correct type | |||
108 | SfxLibrary* SfxScriptLibraryContainer::implCreateLibrary( const OUString& ) | |||
109 | { | |||
110 | SfxLibrary* pRet = new SfxScriptLibrary( maModifiable, mxSFI ); | |||
111 | return pRet; | |||
112 | } | |||
113 | ||||
114 | SfxLibrary* SfxScriptLibraryContainer::implCreateLibraryLink( const OUString&, | |||
115 | const OUString& aLibInfoFileURL, | |||
116 | const OUString& StorageURL, | |||
117 | bool ReadOnly ) | |||
118 | { | |||
119 | SfxLibrary* pRet = new SfxScriptLibrary( maModifiable, mxSFI, | |||
120 | aLibInfoFileURL, StorageURL, ReadOnly ); | |||
121 | return pRet; | |||
122 | } | |||
123 | ||||
124 | Any SfxScriptLibraryContainer::createEmptyLibraryElement() | |||
125 | { | |||
126 | Any aRetAny; | |||
127 | aRetAny <<= OUString(); | |||
128 | return aRetAny; | |||
129 | } | |||
130 | ||||
131 | bool SfxScriptLibraryContainer::isLibraryElementValid(const Any& rElement) const | |||
132 | { | |||
133 | return SfxScriptLibrary::containsValidModule(rElement); | |||
134 | } | |||
135 | ||||
136 | void SfxScriptLibraryContainer::writeLibraryElement( const Reference < XNameContainer >& xLib, | |||
137 | const OUString& aElementName, | |||
138 | const Reference< XOutputStream >& xOutput) | |||
139 | { | |||
140 | // Create sax writer | |||
141 | Reference< XWriter > xWriter = xml::sax::Writer::create(mxContext); | |||
142 | ||||
143 | Reference< XTruncate > xTruncate( xOutput, UNO_QUERY ); | |||
144 | OSL_ENSURE( xTruncate.is(), "Currently only the streams that can be truncated are expected!" )do { if (true && (!(xTruncate.is()))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/basic/source/uno/scriptcont.cxx" ":" "144" ": "), "%s", "Currently only the streams that can be truncated are expected!" ); } } while (false); | |||
145 | if ( xTruncate.is() ) | |||
146 | { | |||
147 | xTruncate->truncate(); | |||
148 | } | |||
149 | xWriter->setOutputStream( xOutput ); | |||
150 | ||||
151 | xmlscript::ModuleDescriptor aMod; | |||
152 | aMod.aName = aElementName; | |||
153 | aMod.aLanguage = "StarBasic"; | |||
154 | Any aElement = xLib->getByName( aElementName ); | |||
155 | aElement >>= aMod.aCode; | |||
156 | ||||
157 | Reference< script::vba::XVBAModuleInfo > xModInfo( xLib, UNO_QUERY ); | |||
158 | if( xModInfo.is() && xModInfo->hasModuleInfo( aElementName ) ) | |||
159 | { | |||
160 | script::ModuleInfo aModInfo = xModInfo->getModuleInfo( aElementName ); | |||
161 | switch( aModInfo.ModuleType ) | |||
162 | { | |||
163 | case ModuleType::NORMAL: | |||
164 | aMod.aModuleType = "normal"; | |||
165 | break; | |||
166 | case ModuleType::CLASS: | |||
167 | aMod.aModuleType ="class"; | |||
168 | break; | |||
169 | case ModuleType::FORM: | |||
170 | aMod.aModuleType = "form"; | |||
171 | break; | |||
172 | case ModuleType::DOCUMENT: | |||
173 | aMod.aModuleType = "document"; | |||
174 | break; | |||
175 | case ModuleType::UNKNOWN: | |||
176 | // nothing | |||
177 | break; | |||
178 | } | |||
179 | } | |||
180 | ||||
181 | xmlscript::exportScriptModule( xWriter, aMod ); | |||
182 | } | |||
183 | ||||
184 | ||||
185 | Any SfxScriptLibraryContainer::importLibraryElement | |||
186 | ( const Reference < XNameContainer >& xLib, | |||
187 | const OUString& aElementName, const OUString& aFile, | |||
188 | const uno::Reference< io::XInputStream >& xInStream ) | |||
189 | { | |||
190 | Any aRetAny; | |||
191 | ||||
192 | Reference< XParser > xParser = xml::sax::Parser::create( mxContext ); | |||
193 | ||||
194 | // Read from storage? | |||
195 | bool bStorage = xInStream.is(); | |||
196 | Reference< XInputStream > xInput; | |||
197 | ||||
198 | if( bStorage ) | |||
199 | { | |||
200 | xInput = xInStream; | |||
201 | } | |||
202 | else | |||
203 | { | |||
204 | try | |||
205 | { | |||
206 | xInput = mxSFI->openFileRead( aFile ); | |||
207 | } | |||
208 | catch(const Exception& ) | |||
209 | //catch( Exception& e ) | |||
210 | { | |||
211 | // TODO: | |||
212 | //throw WrappedTargetException( e ); | |||
213 | } | |||
214 | } | |||
215 | ||||
216 | if( !xInput.is() ) | |||
217 | return aRetAny; | |||
218 | ||||
219 | InputSource source; | |||
220 | source.aInputStream = xInput; | |||
221 | source.sSystemId = aFile; | |||
222 | ||||
223 | // start parsing | |||
224 | xmlscript::ModuleDescriptor aMod; | |||
225 | ||||
226 | try | |||
227 | { | |||
228 | xParser->setDocumentHandler( ::xmlscript::importScriptModule( aMod ) ); | |||
229 | xParser->parseStream( source ); | |||
230 | } | |||
231 | catch(const Exception& ) | |||
232 | { | |||
233 | SfxErrorContext aEc( ERRCTX_SFX_LOADBASIC80, aFile ); | |||
234 | ErrorHandler::HandleError( ERRCODE_IO_GENERALErrCode( ErrCodeArea::Io, ErrCodeClass::General, 13 ) ); | |||
235 | } | |||
236 | ||||
237 | aRetAny <<= aMod.aCode; | |||
238 | ||||
239 | // TODO: Check language | |||
240 | // aMod.aLanguage | |||
241 | // aMod.aName ignored | |||
242 | if( !aMod.aModuleType.isEmpty() ) | |||
243 | { | |||
244 | /* If in VBA compatibility mode, force creation of the VBA Globals | |||
245 | object. Each application will create an instance of its own | |||
246 | implementation and store it in its Basic manager. Implementations | |||
247 | will do all necessary additional initialization, such as | |||
248 | registering the global "This***Doc" UNO constant, starting the | |||
249 | document events processor etc. | |||
250 | */ | |||
251 | if( getVBACompatibilityMode() ) try | |||
252 | { | |||
253 | Reference< frame::XModel > xModel( mxOwnerDocument ); // weak-ref -> ref | |||
254 | Reference< XMultiServiceFactory > xFactory( xModel, UNO_QUERY_THROW ); | |||
255 | xFactory->createInstance("ooo.vba.VBAGlobals"); | |||
256 | } | |||
257 | catch(const Exception& ) | |||
258 | { | |||
259 | } | |||
260 | ||||
261 | script::ModuleInfo aModInfo; | |||
262 | aModInfo.ModuleType = ModuleType::UNKNOWN; | |||
263 | if( aMod.aModuleType == "normal" ) | |||
264 | { | |||
265 | aModInfo.ModuleType = ModuleType::NORMAL; | |||
266 | } | |||
267 | else if( aMod.aModuleType == "class" ) | |||
268 | { | |||
269 | aModInfo.ModuleType = ModuleType::CLASS; | |||
270 | } | |||
271 | else if( aMod.aModuleType == "form" ) | |||
272 | { | |||
273 | aModInfo.ModuleType = ModuleType::FORM; | |||
274 | aModInfo.ModuleObject = mxOwnerDocument; | |||
275 | } | |||
276 | else if( aMod.aModuleType == "document" ) | |||
277 | { | |||
278 | aModInfo.ModuleType = ModuleType::DOCUMENT; | |||
279 | ||||
280 | // #163691# use the same codename access instance for all document modules | |||
281 | if( !mxCodeNameAccess.is() ) try | |||
282 | { | |||
283 | Reference<frame::XModel > xModel( mxOwnerDocument ); | |||
284 | Reference< XMultiServiceFactory> xSF( xModel, UNO_QUERY_THROW ); | |||
285 | mxCodeNameAccess.set( xSF->createInstance("ooo.vba.VBAObjectModuleObjectProvider"), UNO_QUERY ); | |||
286 | } | |||
287 | catch(const Exception& ) {} | |||
288 | ||||
289 | if( mxCodeNameAccess.is() ) | |||
290 | { | |||
291 | try | |||
292 | { | |||
293 | aModInfo.ModuleObject.set( mxCodeNameAccess->getByName( aElementName), uno::UNO_QUERY ); | |||
294 | } | |||
295 | catch(const uno::Exception&) | |||
296 | { | |||
297 | SAL_WARN("basic", "Failed to get document object for " << aElementName )do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN , "basic")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case SAL_DETAIL_LOG_ACTION_LOG : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "Failed to get document object for " << aElementName ) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("basic" ), ("/home/maarten/src/libreoffice/core/basic/source/uno/scriptcont.cxx" ":" "297" ": "), ::sal::detail::unwrapStream( ::sal::detail:: StreamStart() << "Failed to get document object for " << aElementName), 0); } else { ::std::ostringstream sal_detail_stream ; sal_detail_stream << "Failed to get document object for " << aElementName; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN ), ("basic"), ("/home/maarten/src/libreoffice/core/basic/source/uno/scriptcont.cxx" ":" "297" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "Failed to get document object for " << aElementName ) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("basic" ), ("/home/maarten/src/libreoffice/core/basic/source/uno/scriptcont.cxx" ":" "297" ": "), ::sal::detail::unwrapStream( ::sal::detail:: StreamStart() << "Failed to get document object for " << aElementName), 0); } else { ::std::ostringstream sal_detail_stream ; sal_detail_stream << "Failed to get document object for " << aElementName; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN ), ("basic"), ("/home/maarten/src/libreoffice/core/basic/source/uno/scriptcont.cxx" ":" "297" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false); | |||
298 | } | |||
299 | } | |||
300 | } | |||
301 | ||||
302 | Reference< script::vba::XVBAModuleInfo > xVBAModuleInfo( xLib, UNO_QUERY ); | |||
303 | if( xVBAModuleInfo.is() ) | |||
304 | { | |||
305 | if( xVBAModuleInfo->hasModuleInfo( aElementName ) ) | |||
306 | { | |||
307 | xVBAModuleInfo->removeModuleInfo( aElementName ); | |||
308 | } | |||
309 | xVBAModuleInfo->insertModuleInfo( aElementName, aModInfo ); | |||
310 | } | |||
311 | } | |||
312 | ||||
313 | return aRetAny; | |||
314 | } | |||
315 | ||||
316 | SfxLibraryContainer* SfxScriptLibraryContainer::createInstanceImpl() | |||
317 | { | |||
318 | return new SfxScriptLibraryContainer(); | |||
319 | } | |||
320 | ||||
321 | void SfxScriptLibraryContainer::importFromOldStorage( const OUString& aFile ) | |||
322 | { | |||
323 | // TODO: move loading from old storage to binary filters? | |||
324 | auto xStorage = tools::make_ref<SotStorage>( false, aFile ); | |||
| ||||
325 | if( xStorage->GetError() == ERRCODE_NONEErrCode(0) ) | |||
326 | { | |||
327 | std::unique_ptr<BasicManager> pBasicManager(new BasicManager( *xStorage, aFile )); | |||
328 | ||||
329 | // Set info | |||
330 | LibraryContainerInfo aInfo( this, nullptr, static_cast< OldBasicPassword* >( this ) ); | |||
331 | pBasicManager->SetLibraryContainerInfo( aInfo ); | |||
332 | } | |||
333 | } | |||
| ||||
334 | ||||
335 | ||||
336 | // Storing with password encryption | |||
337 | ||||
338 | // Methods XLibraryContainerPassword | |||
339 | sal_Bool SAL_CALL SfxScriptLibraryContainer::isLibraryPasswordProtected( const OUString& Name ) | |||
340 | { | |||
341 | LibraryContainerMethodGuard aGuard( *this ); | |||
342 | SfxLibrary* pImplLib = getImplLib( Name ); | |||
343 | bool bRet = pImplLib->mbPasswordProtected; | |||
344 | return bRet; | |||
345 | } | |||
346 | ||||
347 | sal_Bool SAL_CALL SfxScriptLibraryContainer::isLibraryPasswordVerified( const OUString& Name ) | |||
348 | { | |||
349 | LibraryContainerMethodGuard aGuard( *this ); | |||
350 | SfxLibrary* pImplLib = getImplLib( Name ); | |||
351 | if( !pImplLib->mbPasswordProtected ) | |||
352 | { | |||
353 | throw IllegalArgumentException(); | |||
354 | } | |||
355 | bool bRet = pImplLib->mbPasswordVerified; | |||
356 | return bRet; | |||
357 | } | |||
358 | ||||
359 | sal_Bool SAL_CALL SfxScriptLibraryContainer::verifyLibraryPassword | |||
360 | ( const OUString& Name, const OUString& Password ) | |||
361 | { | |||
362 | LibraryContainerMethodGuard aGuard( *this ); | |||
363 | SfxLibrary* pImplLib = getImplLib( Name ); | |||
364 | if( !pImplLib->mbPasswordProtected || pImplLib->mbPasswordVerified ) | |||
365 | { | |||
366 | throw IllegalArgumentException(); | |||
367 | } | |||
368 | // Test password | |||
369 | bool bSuccess = false; | |||
370 | if( pImplLib->mbDoc50Password ) | |||
371 | { | |||
372 | bSuccess = ( Password == pImplLib->maPassword ); | |||
373 | if( bSuccess ) | |||
374 | { | |||
375 | pImplLib->mbPasswordVerified = true; | |||
376 | } | |||
377 | } | |||
378 | else | |||
379 | { | |||
380 | pImplLib->maPassword = Password; | |||
381 | bSuccess = implLoadPasswordLibrary( pImplLib, Name, true ); | |||
382 | if( bSuccess ) | |||
383 | { | |||
384 | // The library gets modified by verifying the password, because other- | |||
385 | // wise for saving the storage would be copied and that doesn't work | |||
386 | // with mtg's storages when the password is verified | |||
387 | pImplLib->implSetModified( true ); | |||
388 | pImplLib->mbPasswordVerified = true; | |||
389 | ||||
390 | // Reload library to get source | |||
391 | if( pImplLib->mbLoaded ) | |||
392 | { | |||
393 | implLoadPasswordLibrary( pImplLib, Name ); | |||
394 | } | |||
395 | } | |||
396 | } | |||
397 | return bSuccess; | |||
398 | } | |||
399 | ||||
400 | void SAL_CALL SfxScriptLibraryContainer::changeLibraryPassword( const OUString& Name, | |||
401 | const OUString& OldPassword, | |||
402 | const OUString& NewPassword ) | |||
403 | { | |||
404 | LibraryContainerMethodGuard aGuard( *this ); | |||
405 | SfxLibrary* pImplLib = getImplLib( Name ); | |||
406 | if( OldPassword == NewPassword ) | |||
407 | { | |||
408 | return; | |||
409 | } | |||
410 | bool bOldPassword = !OldPassword.isEmpty(); | |||
411 | bool bNewPassword = !NewPassword.isEmpty(); | |||
412 | bool bStorage = mxStorage.is() && !pImplLib->mbLink; | |||
413 | ||||
414 | if( pImplLib->mbReadOnly || (bOldPassword && !pImplLib->mbPasswordProtected) ) | |||
415 | { | |||
416 | throw IllegalArgumentException(); | |||
417 | } | |||
418 | // Library must be loaded | |||
419 | loadLibrary( Name ); | |||
420 | ||||
421 | bool bKillCryptedFiles = false; | |||
422 | bool bKillUnencryptedFiles = false; | |||
423 | ||||
424 | // Remove or change password? | |||
425 | if( bOldPassword ) | |||
426 | { | |||
427 | if( isLibraryPasswordVerified( Name ) ) | |||
428 | { | |||
429 | if( pImplLib->maPassword != OldPassword ) | |||
430 | { | |||
431 | throw IllegalArgumentException(); | |||
432 | } | |||
433 | } | |||
434 | else | |||
435 | { | |||
436 | if( !verifyLibraryPassword( Name, OldPassword ) ) | |||
437 | { | |||
438 | throw IllegalArgumentException(); | |||
439 | } | |||
440 | // Reload library to get source | |||
441 | // Should be done in verifyLibraryPassword loadLibrary( Name ); | |||
442 | } | |||
443 | ||||
444 | if( !bNewPassword ) | |||
445 | { | |||
446 | pImplLib->mbPasswordProtected = false; | |||
447 | pImplLib->mbPasswordVerified = false; | |||
448 | pImplLib->maPassword.clear(); | |||
449 | ||||
450 | maModifiable.setModified( true ); | |||
451 | pImplLib->implSetModified( true ); | |||
452 | ||||
453 | if( !bStorage && !pImplLib->mbDoc50Password ) | |||
454 | { | |||
455 | // Store application basic unencrypted | |||
456 | uno::Reference< embed::XStorage > xStorage; | |||
457 | storeLibraries_Impl( xStorage, false ); | |||
458 | bKillCryptedFiles = true; | |||
459 | } | |||
460 | } | |||
461 | } | |||
462 | ||||
463 | // Set new password? | |||
464 | if( bNewPassword ) | |||
465 | { | |||
466 | pImplLib->mbPasswordProtected = true; | |||
467 | pImplLib->mbPasswordVerified = true; | |||
468 | pImplLib->maPassword = NewPassword; | |||
469 | SfxScriptLibrary *const pSL(dynamic_cast<SfxScriptLibrary *>(pImplLib)); | |||
470 | if (pSL && pSL->mbLoaded) | |||
471 | { | |||
472 | pSL->mbLoadedSource = true; // must store source code now! | |||
473 | } | |||
474 | ||||
475 | maModifiable.setModified( true ); | |||
476 | pImplLib->implSetModified( true ); | |||
477 | ||||
478 | if( !bStorage && !pImplLib->mbDoc50Password ) | |||
479 | { | |||
480 | // Store application basic crypted | |||
481 | uno::Reference< embed::XStorage > xStorage; | |||
482 | storeLibraries_Impl( xStorage, false ); | |||
483 | bKillUnencryptedFiles = true; | |||
484 | } | |||
485 | } | |||
486 | ||||
487 | if( !(bKillCryptedFiles || bKillUnencryptedFiles) ) | |||
488 | return; | |||
489 | ||||
490 | Sequence< OUString > aElementNames = pImplLib->getElementNames(); | |||
491 | sal_Int32 nNameCount = aElementNames.getLength(); | |||
492 | const OUString* pNames = aElementNames.getConstArray(); | |||
493 | OUString aLibDirPath = createAppLibraryFolder( pImplLib, Name ); | |||
494 | try | |||
495 | { | |||
496 | for( sal_Int32 i = 0 ; i < nNameCount ; i++ ) | |||
497 | { | |||
498 | OUString aElementName = pNames[ i ]; | |||
499 | ||||
500 | INetURLObject aElementInetObj( aLibDirPath ); | |||
501 | aElementInetObj.insertName( aElementName, false, | |||
502 | INetURLObject::LAST_SEGMENT, | |||
503 | INetURLObject::EncodeMechanism::All ); | |||
504 | if( bKillUnencryptedFiles ) | |||
505 | { | |||
506 | aElementInetObj.setExtension( maLibElementFileExtension ); | |||
507 | } | |||
508 | else | |||
509 | { | |||
510 | aElementInetObj.setExtension( "pba" ); | |||
511 | } | |||
512 | OUString aElementPath( aElementInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ); | |||
513 | ||||
514 | if( mxSFI->exists( aElementPath ) ) | |||
515 | { | |||
516 | mxSFI->kill( aElementPath ); | |||
517 | } | |||
518 | } | |||
519 | } | |||
520 | catch(const Exception& ) {} | |||
521 | } | |||
522 | ||||
523 | ||||
524 | static void setStreamKey( const uno::Reference< io::XStream >& xStream, const OUString& aPass ) | |||
525 | { | |||
526 | uno::Reference< embed::XEncryptionProtectedSource > xEncrStream( xStream, uno::UNO_QUERY ); | |||
527 | if ( xEncrStream.is() ) | |||
528 | { | |||
529 | xEncrStream->setEncryptionPassword( aPass ); | |||
530 | } | |||
531 | } | |||
532 | ||||
533 | ||||
534 | // Impl methods | |||
535 | bool SfxScriptLibraryContainer::implStorePasswordLibrary( SfxLibrary* pLib, | |||
536 | const OUString& aName, | |||
537 | const uno::Reference< embed::XStorage >& xStorage, | |||
538 | const css::uno::Reference< css::task::XInteractionHandler >& xHandler ) | |||
539 | { | |||
540 | Reference< XSimpleFileAccess3 > xDummySFA; | |||
541 | return implStorePasswordLibrary( pLib, aName, xStorage, OUString(), xDummySFA, xHandler ); | |||
542 | } | |||
543 | ||||
544 | bool SfxScriptLibraryContainer::implStorePasswordLibrary( SfxLibrary* pLib, const OUString& aName, | |||
545 | const css::uno::Reference< css::embed::XStorage >& xStorage, | |||
546 | const OUString& aTargetURL, | |||
547 | const Reference< XSimpleFileAccess3 >& rToUseSFI, | |||
548 | const css::uno::Reference< css::task::XInteractionHandler >& xHandler ) | |||
549 | { | |||
550 | bool bExport = !aTargetURL.isEmpty(); | |||
551 | ||||
552 | BasicManager* pBasicMgr = getBasicManager(); | |||
553 | OSL_ENSURE( pBasicMgr, "SfxScriptLibraryContainer::implStorePasswordLibrary: cannot do this without a BasicManager!" )do { if (true && (!(pBasicMgr))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/basic/source/uno/scriptcont.cxx" ":" "553" ": "), "%s", "SfxScriptLibraryContainer::implStorePasswordLibrary: cannot do this without a BasicManager!" ); } } while (false); | |||
554 | if ( !pBasicMgr ) | |||
555 | { | |||
556 | return false; | |||
557 | } | |||
558 | // Only need to handle the export case here, | |||
559 | // save/saveas etc are handled in sfxbasemodel::storeSelf & | |||
560 | // sfxbasemodel::impl_store | |||
561 | std::vector<OUString> aNames; | |||
562 | if ( bExport && pBasicMgr->LegacyPsswdBinaryLimitExceeded(aNames) ) | |||
563 | { | |||
564 | if ( xHandler.is() ) | |||
565 | { | |||
566 | ModuleSizeExceeded* pReq = new ModuleSizeExceeded( aNames ); | |||
567 | uno::Reference< task::XInteractionRequest > xReq( pReq ); | |||
568 | xHandler->handle( xReq ); | |||
569 | if ( pReq->isAbort() ) | |||
570 | { | |||
571 | throw util::VetoException(); | |||
572 | } | |||
573 | } | |||
574 | } | |||
575 | ||||
576 | StarBASIC* pBasicLib = pBasicMgr->GetLib( aName ); | |||
577 | if( !pBasicLib ) | |||
578 | { | |||
579 | return false; | |||
580 | } | |||
581 | Sequence< OUString > aElementNames = pLib->getElementNames(); | |||
582 | sal_Int32 nNameCount = aElementNames.getLength(); | |||
583 | const OUString* pNames = aElementNames.getConstArray(); | |||
584 | ||||
585 | bool bLink = pLib->mbLink; | |||
586 | bool bStorage = xStorage.is() && !bLink; | |||
587 | if( bStorage ) | |||
588 | { | |||
589 | for( sal_Int32 i = 0 ; i < nNameCount ; i++ ) | |||
590 | { | |||
591 | OUString aElementName = pNames[ i ]; | |||
592 | ||||
593 | // Write binary image stream | |||
594 | SbModule* pMod = pBasicLib->FindModule( aElementName ); | |||
595 | if( pMod ) | |||
596 | { | |||
597 | OUString aCodeStreamName = aElementName + ".bin"; | |||
598 | try | |||
599 | { | |||
600 | uno::Reference< io::XStream > xCodeStream = xStorage->openStreamElement( | |||
601 | aCodeStreamName, | |||
602 | embed::ElementModes::READWRITE | embed::ElementModes::TRUNCATE ); | |||
603 | ||||
604 | if ( !xCodeStream.is() ) | |||
605 | { | |||
606 | throw uno::RuntimeException("null returned from openStreamElement"); | |||
607 | } | |||
608 | SvMemoryStream aMemStream; | |||
609 | /*sal_Bool bStore = */pMod->StoreBinaryData( aMemStream ); | |||
610 | ||||
611 | sal_Int32 const nSize = aMemStream.Tell(); | |||
612 | if (nSize < 0) { abort(); } | |||
613 | Sequence< sal_Int8 > aBinSeq( nSize ); | |||
614 | sal_Int8* pData = aBinSeq.getArray(); | |||
615 | memcpy( pData, aMemStream.GetData(), nSize ); | |||
616 | ||||
617 | Reference< XOutputStream > xOut = xCodeStream->getOutputStream(); | |||
618 | if ( !xOut.is() ) | |||
619 | { | |||
620 | throw io::IOException(); // access denied because the stream is readonly | |||
621 | } | |||
622 | xOut->writeBytes( aBinSeq ); | |||
623 | xOut->closeOutput(); | |||
624 | } | |||
625 | catch(const uno::Exception& ) | |||
626 | { | |||
627 | // TODO: handle error | |||
628 | } | |||
629 | } | |||
630 | ||||
631 | if( pLib->mbPasswordVerified || pLib->mbDoc50Password ) | |||
632 | { | |||
633 | if( !isLibraryElementValid( pLib->getByName( aElementName ) ) ) | |||
634 | { | |||
635 | SAL_WARN( "basic", "invalid library element '" << aElementName << "'.")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN , "basic")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case SAL_DETAIL_LOG_ACTION_LOG : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "invalid library element '" << aElementName << "'.") == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN ), ("basic"), ("/home/maarten/src/libreoffice/core/basic/source/uno/scriptcont.cxx" ":" "635" ": "), ::sal::detail::unwrapStream( ::sal::detail:: StreamStart() << "invalid library element '" << aElementName << "'."), 0); } else { ::std::ostringstream sal_detail_stream ; sal_detail_stream << "invalid library element '" << aElementName << "'."; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN ), ("basic"), ("/home/maarten/src/libreoffice/core/basic/source/uno/scriptcont.cxx" ":" "635" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "invalid library element '" << aElementName << "'.") == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN ), ("basic"), ("/home/maarten/src/libreoffice/core/basic/source/uno/scriptcont.cxx" ":" "635" ": "), ::sal::detail::unwrapStream( ::sal::detail:: StreamStart() << "invalid library element '" << aElementName << "'."), 0); } else { ::std::ostringstream sal_detail_stream ; sal_detail_stream << "invalid library element '" << aElementName << "'."; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN ), ("basic"), ("/home/maarten/src/libreoffice/core/basic/source/uno/scriptcont.cxx" ":" "635" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false); | |||
636 | continue; | |||
637 | } | |||
638 | ||||
639 | OUString aSourceStreamName = aElementName + ".xml"; | |||
640 | try | |||
641 | { | |||
642 | uno::Reference< io::XStream > xSourceStream = xStorage->openStreamElement( | |||
643 | aSourceStreamName, | |||
644 | embed::ElementModes::READWRITE ); | |||
645 | uno::Reference< beans::XPropertySet > xProps( xSourceStream, uno::UNO_QUERY_THROW ); | |||
646 | xProps->setPropertyValue("MediaType", uno::Any( OUString( "text/xml" ) ) ); | |||
647 | ||||
648 | // Set encryption key | |||
649 | setStreamKey( xSourceStream, pLib->maPassword ); | |||
650 | ||||
651 | Reference< XOutputStream > xOutput = xSourceStream->getOutputStream(); | |||
652 | Reference< XNameContainer > xLib( pLib ); | |||
653 | writeLibraryElement( xLib, aElementName, xOutput ); | |||
654 | } | |||
655 | catch(const uno::Exception& ) | |||
656 | { | |||
657 | OSL_FAIL( "Problem on storing of password library!" )do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/basic/source/uno/scriptcont.cxx" ":" "657" ": "), "%s", "Problem on storing of password library!" ); } } while (false); | |||
658 | // TODO: error handling | |||
659 | } | |||
660 | } | |||
661 | else // !mbPasswordVerified | |||
662 | { | |||
663 | // TODO | |||
664 | // What to do if not verified?! In any case it's already loaded here | |||
665 | } | |||
666 | } | |||
667 | ||||
668 | } | |||
669 | // Application libraries have only to be saved if the password | |||
670 | // is verified because otherwise they can't be modified | |||
671 | else if( pLib->mbPasswordVerified || bExport ) | |||
672 | { | |||
673 | try | |||
674 | { | |||
675 | Reference< XSimpleFileAccess3 > xSFI = mxSFI; | |||
676 | if( rToUseSFI.is() ) | |||
677 | { | |||
678 | xSFI = rToUseSFI; | |||
679 | } | |||
680 | OUString aLibDirPath; | |||
681 | if( bExport ) | |||
682 | { | |||
683 | INetURLObject aInetObj( aTargetURL ); | |||
684 | aInetObj.insertName( aName, true, INetURLObject::LAST_SEGMENT, | |||
685 | INetURLObject::EncodeMechanism::All ); | |||
686 | aLibDirPath = aInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ); | |||
687 | ||||
688 | if( !xSFI->isFolder( aLibDirPath ) ) | |||
689 | { | |||
690 | xSFI->createFolder( aLibDirPath ); | |||
691 | } | |||
692 | } | |||
693 | else | |||
694 | { | |||
695 | aLibDirPath = createAppLibraryFolder( pLib, aName ); | |||
696 | } | |||
697 | ||||
698 | for( sal_Int32 i = 0 ; i < nNameCount ; i++ ) | |||
699 | { | |||
700 | OUString aElementName = pNames[ i ]; | |||
701 | ||||
702 | INetURLObject aElementInetObj( aLibDirPath ); | |||
703 | aElementInetObj.insertName( aElementName, false, | |||
704 | INetURLObject::LAST_SEGMENT, | |||
705 | INetURLObject::EncodeMechanism::All ); | |||
706 | aElementInetObj.setExtension( "pba" ); | |||
707 | OUString aElementPath = aElementInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ); | |||
708 | ||||
709 | if( !isLibraryElementValid( pLib->getByName( aElementName ) ) ) | |||
710 | { | |||
711 | SAL_WARN( "basic", "invalid library element '" << aElementName << "'.")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN , "basic")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case SAL_DETAIL_LOG_ACTION_LOG : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "invalid library element '" << aElementName << "'.") == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN ), ("basic"), ("/home/maarten/src/libreoffice/core/basic/source/uno/scriptcont.cxx" ":" "711" ": "), ::sal::detail::unwrapStream( ::sal::detail:: StreamStart() << "invalid library element '" << aElementName << "'."), 0); } else { ::std::ostringstream sal_detail_stream ; sal_detail_stream << "invalid library element '" << aElementName << "'."; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN ), ("basic"), ("/home/maarten/src/libreoffice/core/basic/source/uno/scriptcont.cxx" ":" "711" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "invalid library element '" << aElementName << "'.") == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN ), ("basic"), ("/home/maarten/src/libreoffice/core/basic/source/uno/scriptcont.cxx" ":" "711" ": "), ::sal::detail::unwrapStream( ::sal::detail:: StreamStart() << "invalid library element '" << aElementName << "'."), 0); } else { ::std::ostringstream sal_detail_stream ; sal_detail_stream << "invalid library element '" << aElementName << "'."; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN ), ("basic"), ("/home/maarten/src/libreoffice/core/basic/source/uno/scriptcont.cxx" ":" "711" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false); | |||
712 | continue; | |||
713 | } | |||
714 | ||||
715 | try | |||
716 | { | |||
717 | uno::Reference< embed::XStorage > xElementRootStorage = | |||
718 | ::comphelper::OStorageHelper::GetStorageFromURL( | |||
719 | aElementPath, | |||
720 | embed::ElementModes::READWRITE ); | |||
721 | if ( !xElementRootStorage.is() ) | |||
722 | { | |||
723 | throw uno::RuntimeException("null returned from GetStorageFromURL"); | |||
724 | } | |||
725 | // Write binary image stream | |||
726 | SbModule* pMod = pBasicLib->FindModule( aElementName ); | |||
727 | if( pMod ) | |||
728 | { | |||
729 | uno::Reference< io::XStream > xCodeStream = xElementRootStorage->openStreamElement( | |||
730 | "code.bin", | |||
731 | embed::ElementModes::WRITE | embed::ElementModes::TRUNCATE ); | |||
732 | ||||
733 | SvMemoryStream aMemStream; | |||
734 | /*sal_Bool bStore = */pMod->StoreBinaryData( aMemStream ); | |||
735 | ||||
736 | sal_Int32 const nSize = aMemStream.Tell(); | |||
737 | if (nSize < 0) { abort(); } | |||
738 | Sequence< sal_Int8 > aBinSeq( nSize ); | |||
739 | sal_Int8* pData = aBinSeq.getArray(); | |||
740 | memcpy( pData, aMemStream.GetData(), nSize ); | |||
741 | ||||
742 | Reference< XOutputStream > xOut = xCodeStream->getOutputStream(); | |||
743 | if ( xOut.is() ) | |||
744 | { | |||
745 | xOut->writeBytes( aBinSeq ); | |||
746 | xOut->closeOutput(); | |||
747 | } | |||
748 | } | |||
749 | ||||
750 | // Write encrypted source stream | |||
751 | OUString aSourceStreamName( "source.xml" ); | |||
752 | ||||
753 | uno::Reference< io::XStream > xSourceStream; | |||
754 | try | |||
755 | { | |||
756 | xSourceStream = xElementRootStorage->openStreamElement( | |||
757 | aSourceStreamName, | |||
758 | embed::ElementModes::WRITE | embed::ElementModes::TRUNCATE ); | |||
759 | ||||
760 | // #87671 Allow encryption | |||
761 | uno::Reference< embed::XEncryptionProtectedSource > xEncr( xSourceStream, uno::UNO_QUERY_THROW ); | |||
762 | xEncr->setEncryptionPassword( pLib->maPassword ); | |||
763 | } | |||
764 | catch(const css::packages::WrongPasswordException& ) | |||
765 | { | |||
766 | xSourceStream = xElementRootStorage->openEncryptedStreamElement( | |||
767 | aSourceStreamName, | |||
768 | embed::ElementModes::WRITE | embed::ElementModes::TRUNCATE, | |||
769 | pLib->maPassword ); | |||
770 | } | |||
771 | ||||
772 | uno::Reference< beans::XPropertySet > xProps( xSourceStream, uno::UNO_QUERY_THROW ); | |||
773 | xProps->setPropertyValue("MediaType", uno::Any( OUString( "text/xml" ) ) ); | |||
774 | ||||
775 | Reference< XOutputStream > xOut = xSourceStream->getOutputStream(); | |||
776 | Reference< XNameContainer > xLib( pLib ); | |||
777 | writeLibraryElement( xLib, aElementName, xOut ); | |||
778 | // i50568: sax writer already closes stream | |||
779 | // xOut->closeOutput(); | |||
780 | ||||
781 | uno::Reference< embed::XTransactedObject > xTransact( xElementRootStorage, uno::UNO_QUERY_THROW ); | |||
782 | xTransact->commit(); | |||
783 | } | |||
784 | catch(const uno::Exception& ) | |||
785 | { | |||
786 | // TODO: handle error | |||
787 | } | |||
788 | ||||
789 | } | |||
790 | } | |||
791 | catch(const Exception& ) | |||
792 | { | |||
793 | } | |||
794 | } | |||
795 | return true; | |||
796 | } | |||
797 | ||||
798 | bool SfxScriptLibraryContainer::implLoadPasswordLibrary | |||
799 | ( SfxLibrary* pLib, const OUString& Name, bool bVerifyPasswordOnly ) | |||
800 | { | |||
801 | bool bRet = true; | |||
802 | ||||
803 | bool bLink = pLib->mbLink; | |||
804 | bool bStorage = mxStorage.is() && !bLink; | |||
805 | ||||
806 | // Already loaded? Then only verifiedPassword can change something | |||
807 | SfxScriptLibrary* pScriptLib = static_cast< SfxScriptLibrary* >( pLib ); | |||
808 | if( pScriptLib->mbLoaded ) | |||
809 | { | |||
810 | if( pScriptLib->mbLoadedBinary && !bVerifyPasswordOnly && | |||
811 | (pScriptLib->mbLoadedSource || !pLib->mbPasswordVerified) ) | |||
812 | { | |||
813 | return false; | |||
814 | } | |||
815 | } | |||
816 | ||||
817 | StarBASIC* pBasicLib = nullptr; | |||
818 | bool bLoadBinary = false; | |||
819 | if( !pScriptLib->mbLoadedBinary && !bVerifyPasswordOnly && !pLib->mbPasswordVerified ) | |||
820 | { | |||
821 | BasicManager* pBasicMgr = getBasicManager(); | |||
822 | OSL_ENSURE( pBasicMgr, "SfxScriptLibraryContainer::implLoadPasswordLibrary: cannot do this without a BasicManager!" )do { if (true && (!(pBasicMgr))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/basic/source/uno/scriptcont.cxx" ":" "822" ": "), "%s", "SfxScriptLibraryContainer::implLoadPasswordLibrary: cannot do this without a BasicManager!" ); } } while (false); | |||
823 | bool bLoaded = pScriptLib->mbLoaded; | |||
824 | pScriptLib->mbLoaded = true; // Necessary to get lib | |||
825 | pBasicLib = pBasicMgr ? pBasicMgr->GetLib( Name ) : nullptr; | |||
826 | pScriptLib->mbLoaded = bLoaded; // Restore flag | |||
827 | if( !pBasicLib ) | |||
828 | { | |||
829 | return false; | |||
830 | } | |||
831 | bLoadBinary = true; | |||
832 | pScriptLib->mbLoadedBinary = true; | |||
833 | } | |||
834 | ||||
835 | bool bLoadSource = false; | |||
836 | if( !pScriptLib->mbLoadedSource && pLib->mbPasswordVerified && !bVerifyPasswordOnly ) | |||
837 | { | |||
838 | bLoadSource = true; | |||
839 | pScriptLib->mbLoadedSource = true; | |||
840 | } | |||
841 | ||||
842 | Sequence< OUString > aElementNames = pLib->getElementNames(); | |||
843 | sal_Int32 nNameCount = aElementNames.getLength(); | |||
844 | const OUString* pNames = aElementNames.getConstArray(); | |||
845 | ||||
846 | if( bStorage ) | |||
847 | { | |||
848 | uno::Reference< embed::XStorage > xLibrariesStor; | |||
849 | uno::Reference< embed::XStorage > xLibraryStor; | |||
850 | try { | |||
851 | xLibrariesStor = mxStorage->openStorageElement( maLibrariesDir, embed::ElementModes::READ ); | |||
852 | if ( !xLibrariesStor.is() ) | |||
853 | { | |||
854 | throw uno::RuntimeException("null returned from openStorageElement"); | |||
855 | } | |||
856 | xLibraryStor = xLibrariesStor->openStorageElement( Name, embed::ElementModes::READ ); | |||
857 | if ( !xLibraryStor.is() ) | |||
858 | { | |||
859 | throw uno::RuntimeException("null returned from openStorageElement"); | |||
860 | } | |||
861 | } | |||
862 | catch(const uno::Exception& ) | |||
863 | { | |||
864 | OSL_FAIL( "### couldn't open sub storage for library" )do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/basic/source/uno/scriptcont.cxx" ":" "864" ": "), "%s", "### couldn't open sub storage for library" ); } } while (false); | |||
865 | return false; | |||
866 | } | |||
867 | ||||
868 | for( sal_Int32 i = 0 ; i < nNameCount ; i++ ) | |||
869 | { | |||
870 | OUString aElementName = pNames[ i ]; | |||
871 | ||||
872 | // Load binary | |||
873 | if( bLoadBinary ) | |||
874 | { | |||
875 | SbModule* pMod = pBasicLib->FindModule( aElementName ); | |||
876 | if( !pMod ) | |||
877 | { | |||
878 | pMod = pBasicLib->MakeModule( aElementName, OUString() ); | |||
879 | pBasicLib->SetModified( false ); | |||
880 | } | |||
881 | ||||
882 | OUString aCodeStreamName= aElementName + ".bin"; | |||
883 | try | |||
884 | { | |||
885 | uno::Reference< io::XStream > xCodeStream = xLibraryStor->openStreamElement( | |||
886 | aCodeStreamName, | |||
887 | embed::ElementModes::READ ); | |||
888 | if ( !xCodeStream.is() ) | |||
889 | { | |||
890 | throw uno::RuntimeException("null returned from openStreamElement"); | |||
891 | } | |||
892 | std::unique_ptr<SvStream> pStream(::utl::UcbStreamHelper::CreateStream( xCodeStream )); | |||
893 | if ( !pStream || pStream->GetError() ) | |||
894 | { | |||
895 | sal_uInt32 nError = sal_uInt32(pStream ? pStream->GetError() : ERRCODE_IO_GENERALErrCode( ErrCodeArea::Io, ErrCodeClass::General, 13 )); | |||
896 | throw task::ErrorCodeIOException( | |||
897 | ("utl::UcbStreamHelper::CreateStream failed for \"" | |||
898 | + aCodeStreamName + "\": 0x" | |||
899 | + OUString::number(nError, 16)), | |||
900 | uno::Reference< uno::XInterface >(), nError); | |||
901 | } | |||
902 | ||||
903 | /*sal_Bool bRet = */pMod->LoadBinaryData( *pStream ); | |||
904 | // TODO: Check return value | |||
905 | } | |||
906 | catch(const uno::Exception& ) | |||
907 | { | |||
908 | // TODO: error handling | |||
909 | } | |||
910 | } | |||
911 | ||||
912 | // Load source | |||
913 | if( bLoadSource || bVerifyPasswordOnly ) | |||
914 | { | |||
915 | // Access encrypted source stream | |||
916 | OUString aSourceStreamName = aElementName + ".xml"; | |||
917 | try | |||
918 | { | |||
919 | uno::Reference< io::XStream > xSourceStream = xLibraryStor->openEncryptedStreamElement( | |||
920 | aSourceStreamName, | |||
921 | embed::ElementModes::READ, | |||
922 | pLib->maPassword ); | |||
923 | if ( !xSourceStream.is() ) | |||
924 | { | |||
925 | throw uno::RuntimeException("null returned from openEncryptedStreamElement"); | |||
926 | } | |||
927 | // if this point is reached then the password is correct | |||
928 | if ( !bVerifyPasswordOnly ) | |||
929 | { | |||
930 | uno::Reference< io::XInputStream > xInStream = xSourceStream->getInputStream(); | |||
931 | if ( !xInStream.is() ) | |||
932 | { | |||
933 | throw io::IOException(); // read access denied, seems to be impossible | |||
934 | } | |||
935 | Reference< XNameContainer > xLib( pLib ); | |||
936 | Any aAny = importLibraryElement( xLib, | |||
937 | aElementName, aSourceStreamName, | |||
938 | xInStream ); | |||
939 | if( pLib->hasByName( aElementName ) ) | |||
940 | { | |||
941 | if( aAny.hasValue() ) | |||
942 | { | |||
943 | pLib->maNameContainer->replaceByName( aElementName, aAny ); | |||
944 | } | |||
945 | } | |||
946 | else | |||
947 | { | |||
948 | pLib->maNameContainer->insertByName( aElementName, aAny ); | |||
949 | } | |||
950 | } | |||
951 | } | |||
952 | catch(const uno::Exception& ) | |||
953 | { | |||
954 | bRet = false; | |||
955 | } | |||
956 | } | |||
957 | } | |||
958 | } | |||
959 | else | |||
960 | { | |||
961 | try | |||
962 | { | |||
963 | OUString aLibDirPath = createAppLibraryFolder( pLib, Name ); | |||
964 | ||||
965 | for( sal_Int32 i = 0 ; i < nNameCount ; i++ ) | |||
966 | { | |||
967 | OUString aElementName = pNames[ i ]; | |||
968 | ||||
969 | INetURLObject aElementInetObj( aLibDirPath ); | |||
970 | aElementInetObj.insertName( aElementName, false, | |||
971 | INetURLObject::LAST_SEGMENT, INetURLObject::EncodeMechanism::All ); | |||
972 | aElementInetObj.setExtension( "pba" ); | |||
973 | OUString aElementPath = aElementInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ); | |||
974 | ||||
975 | uno::Reference< embed::XStorage > xElementRootStorage; | |||
976 | try | |||
977 | { | |||
978 | xElementRootStorage = ::comphelper::OStorageHelper::GetStorageFromURL( | |||
979 | aElementPath, | |||
980 | embed::ElementModes::READ ); | |||
981 | } catch(const uno::Exception& ) | |||
982 | { | |||
983 | // TODO: error handling | |||
984 | } | |||
985 | ||||
986 | if ( xElementRootStorage.is() ) | |||
987 | { | |||
988 | // Load binary | |||
989 | if( bLoadBinary ) | |||
990 | { | |||
991 | SbModule* pMod = pBasicLib->FindModule( aElementName ); | |||
992 | if( !pMod ) | |||
993 | { | |||
994 | pMod = pBasicLib->MakeModule( aElementName, OUString() ); | |||
995 | pBasicLib->SetModified( false ); | |||
996 | } | |||
997 | ||||
998 | try | |||
999 | { | |||
1000 | uno::Reference< io::XStream > xCodeStream = xElementRootStorage->openStreamElement( | |||
1001 | "code.bin", | |||
1002 | embed::ElementModes::READ ); | |||
1003 | ||||
1004 | std::unique_ptr<SvStream> pStream(::utl::UcbStreamHelper::CreateStream( xCodeStream )); | |||
1005 | if ( !pStream || pStream->GetError() ) | |||
1006 | { | |||
1007 | sal_uInt32 nError = sal_uInt32(pStream ? pStream->GetError() : ERRCODE_IO_GENERALErrCode( ErrCodeArea::Io, ErrCodeClass::General, 13 )); | |||
1008 | throw task::ErrorCodeIOException( | |||
1009 | ("utl::UcbStreamHelper::CreateStream failed" | |||
1010 | " for code.bin: 0x" | |||
1011 | + OUString::number(nError, 16)), | |||
1012 | uno::Reference< uno::XInterface >(), | |||
1013 | nError); | |||
1014 | } | |||
1015 | ||||
1016 | /*sal_Bool bRet = */pMod->LoadBinaryData( *pStream ); | |||
1017 | // TODO: Check return value | |||
1018 | } | |||
1019 | catch(const uno::Exception& ) | |||
1020 | { | |||
1021 | // TODO: error handling | |||
1022 | } | |||
1023 | } | |||
1024 | ||||
1025 | // Load source | |||
1026 | if( bLoadSource || bVerifyPasswordOnly ) | |||
1027 | { | |||
1028 | // Access encrypted source stream | |||
1029 | try | |||
1030 | { | |||
1031 | OUString aSourceStreamName( "source.xml" ); | |||
1032 | uno::Reference< io::XStream > xSourceStream = xElementRootStorage->openEncryptedStreamElement( | |||
1033 | aSourceStreamName, | |||
1034 | embed::ElementModes::READ, | |||
1035 | pLib->maPassword ); | |||
1036 | if ( !xSourceStream.is() ) | |||
1037 | { | |||
1038 | throw uno::RuntimeException("null returned from openEncryptedStreamElement"); | |||
1039 | } | |||
1040 | if ( !bVerifyPasswordOnly ) | |||
1041 | { | |||
1042 | uno::Reference< io::XInputStream > xInStream = xSourceStream->getInputStream(); | |||
1043 | if ( !xInStream.is() ) | |||
1044 | { | |||
1045 | throw io::IOException(); // read access denied, seems to be impossible | |||
1046 | } | |||
1047 | Reference< XNameContainer > xLib( pLib ); | |||
1048 | Any aAny = importLibraryElement( xLib, | |||
1049 | aElementName, | |||
1050 | aSourceStreamName, | |||
1051 | xInStream ); | |||
1052 | if( pLib->hasByName( aElementName ) ) | |||
1053 | { | |||
1054 | if( aAny.hasValue() ) | |||
1055 | { | |||
1056 | pLib->maNameContainer->replaceByName( aElementName, aAny ); | |||
1057 | } | |||
1058 | } | |||
1059 | else | |||
1060 | { | |||
1061 | pLib->maNameContainer->insertByName( aElementName, aAny ); | |||
1062 | } | |||
1063 | } | |||
1064 | } | |||
1065 | catch (const uno::Exception& ) | |||
1066 | { | |||
1067 | bRet = false; | |||
1068 | } | |||
1069 | } | |||
1070 | } | |||
1071 | } | |||
1072 | } | |||
1073 | catch(const Exception& ) | |||
1074 | { | |||
1075 | // TODO | |||
1076 | //throw e; | |||
1077 | } | |||
1078 | } | |||
1079 | ||||
1080 | return bRet; | |||
1081 | } | |||
1082 | ||||
1083 | ||||
1084 | void SfxScriptLibraryContainer::onNewRootStorage() | |||
1085 | { | |||
1086 | } | |||
1087 | ||||
1088 | sal_Bool SAL_CALL SfxScriptLibraryContainer:: HasExecutableCode( const OUString& Library ) | |||
1089 | { | |||
1090 | BasicManager* pBasicMgr = getBasicManager(); | |||
1091 | OSL_ENSURE( pBasicMgr, "we need a basicmanager, really we do" )do { if (true && (!(pBasicMgr))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/basic/source/uno/scriptcont.cxx" ":" "1091" ": "), "%s", "we need a basicmanager, really we do" ); } } while (false); | |||
1092 | if ( pBasicMgr ) | |||
1093 | { | |||
1094 | return pBasicMgr->HasExeCode( Library ); // need to change this to take name | |||
1095 | } | |||
1096 | // default to it has code if we can't decide | |||
1097 | return true; | |||
1098 | } | |||
1099 | ||||
1100 | ||||
1101 | // Service | |||
1102 | OUString SAL_CALL SfxScriptLibraryContainer::getImplementationName( ) | |||
1103 | { | |||
1104 | return "com.sun.star.comp.sfx2.ScriptLibraryContainer"; | |||
1105 | } | |||
1106 | ||||
1107 | Sequence< OUString > SAL_CALL SfxScriptLibraryContainer::getSupportedServiceNames( ) | |||
1108 | { | |||
1109 | return {"com.sun.star.script.DocumentScriptLibraryContainer", | |||
1110 | "com.sun.star.script.ScriptLibraryContainer"}; // for compatibility | |||
1111 | } | |||
1112 | ||||
1113 | // Implementation class SfxScriptLibrary | |||
1114 | ||||
1115 | // Ctor | |||
1116 | SfxScriptLibrary::SfxScriptLibrary( ModifiableHelper& _rModifiable, | |||
1117 | const Reference< XSimpleFileAccess3 >& xSFI ) | |||
1118 | : SfxLibrary( _rModifiable, cppu::UnoType<OUString>::get(), xSFI ) | |||
1119 | , mbLoadedSource( false ) | |||
1120 | , mbLoadedBinary( false ) | |||
1121 | { | |||
1122 | } | |||
1123 | ||||
1124 | SfxScriptLibrary::SfxScriptLibrary( ModifiableHelper& _rModifiable, | |||
1125 | const Reference< XSimpleFileAccess3 >& xSFI, | |||
1126 | const OUString& aLibInfoFileURL, | |||
1127 | const OUString& aStorageURL, | |||
1128 | bool ReadOnly ) | |||
1129 | : SfxLibrary( _rModifiable, cppu::UnoType<OUString>::get(), xSFI, | |||
1130 | aLibInfoFileURL, aStorageURL, ReadOnly) | |||
1131 | , mbLoadedSource( false ) | |||
1132 | , mbLoadedBinary( false ) | |||
1133 | { | |||
1134 | } | |||
1135 | ||||
1136 | bool SfxScriptLibrary::isLoadedStorable() | |||
1137 | { | |||
1138 | // note: mbLoadedSource can only be true for password-protected lib! | |||
1139 | return SfxLibrary::isLoadedStorable() && (!mbPasswordProtected || mbLoadedSource); | |||
1140 | } | |||
1141 | ||||
1142 | // Provide modify state including resources | |||
1143 | bool SfxScriptLibrary::isModified() | |||
1144 | { | |||
1145 | return implIsModified(); // No resources | |||
1146 | } | |||
1147 | ||||
1148 | void SfxScriptLibrary::storeResources() | |||
1149 | { | |||
1150 | // No resources | |||
1151 | } | |||
1152 | ||||
1153 | void SfxScriptLibrary::storeResourcesToURL( const OUString&, | |||
1154 | const Reference< task::XInteractionHandler >& ) | |||
1155 | {} | |||
1156 | ||||
1157 | void SfxScriptLibrary::storeResourcesAsURL | |||
1158 | ( const OUString&, const OUString& ) | |||
1159 | {} | |||
1160 | ||||
1161 | void SfxScriptLibrary::storeResourcesToStorage( const css::uno::Reference | |||
1162 | < css::embed::XStorage >& ) | |||
1163 | { | |||
1164 | // No resources | |||
1165 | } | |||
1166 | ||||
1167 | bool SfxScriptLibrary::containsValidModule(const Any& rElement) | |||
1168 | { | |||
1169 | OUString sModuleText; | |||
1170 | rElement >>= sModuleText; | |||
1171 | return ( !sModuleText.isEmpty() ); | |||
1172 | } | |||
1173 | ||||
1174 | bool SfxScriptLibrary::isLibraryElementValid(const css::uno::Any& rElement) const | |||
1175 | { | |||
1176 | return SfxScriptLibrary::containsValidModule(rElement); | |||
1177 | } | |||
1178 | ||||
1179 | IMPLEMENT_FORWARD_XINTERFACE2( SfxScriptLibrary, SfxLibrary, SfxScriptLibrary_BASE )void SfxScriptLibrary::acquire() throw() { SfxLibrary::acquire (); } void SfxScriptLibrary::release() throw() { SfxLibrary:: release(); } css::uno::Any SfxScriptLibrary::queryInterface( const css::uno::Type& _rType ) { css::uno::Any aReturn = SfxLibrary ::queryInterface( _rType ); if ( !aReturn.hasValue() ) aReturn = SfxScriptLibrary_BASE::queryInterface( _rType ); return aReturn ; }; | |||
1180 | IMPLEMENT_FORWARD_XTYPEPROVIDER2( SfxScriptLibrary, SfxLibrary, SfxScriptLibrary_BASE )css::uno::Sequence< css::uno::Type > SfxScriptLibrary:: getTypes( ) { return ::comphelper::concatSequences( SfxLibrary ::getTypes(), SfxScriptLibrary_BASE::getTypes() ); } css::uno ::Sequence< sal_Int8 > SfxScriptLibrary::getImplementationId ( ) { return css::uno::Sequence<sal_Int8>(); }; | |||
1181 | ||||
1182 | script::ModuleInfo SAL_CALL SfxScriptLibrary::getModuleInfo( const OUString& ModuleName ) | |||
1183 | { | |||
1184 | if ( !hasModuleInfo( ModuleName ) ) | |||
1185 | { | |||
1186 | throw NoSuchElementException(); | |||
1187 | } | |||
1188 | return mModuleInfo[ ModuleName ]; | |||
1189 | } | |||
1190 | ||||
1191 | sal_Bool SAL_CALL SfxScriptLibrary::hasModuleInfo( const OUString& ModuleName ) | |||
1192 | { | |||
1193 | bool bRes = false; | |||
1194 | ModuleInfoMap::iterator it = mModuleInfo.find( ModuleName ); | |||
1195 | ||||
1196 | if ( it != mModuleInfo.end() ) | |||
1197 | { | |||
1198 | bRes = true; | |||
1199 | } | |||
1200 | return bRes; | |||
1201 | } | |||
1202 | ||||
1203 | void SAL_CALL SfxScriptLibrary::insertModuleInfo( const OUString& ModuleName, const script::ModuleInfo& ModuleInfo ) | |||
1204 | { | |||
1205 | if ( hasModuleInfo( ModuleName ) ) | |||
1206 | { | |||
1207 | throw ElementExistException(); | |||
1208 | } | |||
1209 | mModuleInfo[ ModuleName ] = ModuleInfo; | |||
1210 | } | |||
1211 | ||||
1212 | void SAL_CALL SfxScriptLibrary::removeModuleInfo( const OUString& ModuleName ) | |||
1213 | { | |||
1214 | // #FIXME add NoSuchElementException to the spec | |||
1215 | if ( mModuleInfo.erase( ModuleName ) == 0 ) | |||
1216 | throw NoSuchElementException(); | |||
1217 | } | |||
1218 | ||||
1219 | } // namespace basic | |||
1220 | ||||
1221 | ||||
1222 | extern "C" SAL_DLLPUBLIC_EXPORT__attribute__ ((visibility("default"))) css::uno::XInterface* | |||
1223 | com_sun_star_comp_sfx2_ScriptLibraryContainer_get_implementation(css::uno::XComponentContext*, | |||
1224 | css::uno::Sequence<css::uno::Any> const &) | |||
1225 | { | |||
1226 | return cppu::acquire(new basic::SfxScriptLibraryContainer()); | |||
1227 | } | |||
1228 | ||||
1229 | ||||
1230 | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |
1 | /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
2 | /* |
3 | * This file is part of the LibreOffice project. |
4 | * |
5 | * This Source Code Form is subject to the terms of the Mozilla Public |
6 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
7 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
8 | * |
9 | * This file incorporates work covered by the following license notice: |
10 | * |
11 | * Licensed to the Apache Software Foundation (ASF) under one or more |
12 | * contributor license agreements. See the NOTICE file distributed |
13 | * with this work for additional information regarding copyright |
14 | * ownership. The ASF licenses this file to you under the Apache |
15 | * License, Version 2.0 (the "License"); you may not use this file |
16 | * except in compliance with the License. You may obtain a copy of |
17 | * the License at http://www.apache.org/licenses/LICENSE-2.0 . |
18 | */ |
19 | #ifndef INCLUDED_TOOLS_REF_HXX |
20 | #define INCLUDED_TOOLS_REF_HXX |
21 | |
22 | #include <sal/config.h> |
23 | #include <cassert> |
24 | #include <tools/toolsdllapi.h> |
25 | #include <utility> |
26 | |
27 | /** |
28 | This implements similar functionality to boost::intrusive_ptr |
29 | */ |
30 | |
31 | namespace tools { |
32 | |
33 | /** T must be a class that extends SvRefBase */ |
34 | template<typename T> class SAL_DLLPUBLIC_RTTI__attribute__ ((type_visibility("default"))) SvRef final { |
35 | public: |
36 | SvRef(): pObj(nullptr) {} |
37 | |
38 | SvRef(SvRef&& rObj) noexcept |
39 | { |
40 | pObj = rObj.pObj; |
41 | rObj.pObj = nullptr; |
42 | } |
43 | |
44 | SvRef(SvRef const & rObj): pObj(rObj.pObj) |
45 | { |
46 | if (pObj != nullptr) pObj->AddNextRef(); |
47 | } |
48 | |
49 | SvRef(T * pObjP): pObj(pObjP) |
50 | { |
51 | if (pObj != nullptr) pObj->AddFirstRef(); |
52 | } |
53 | |
54 | ~SvRef() |
55 | { |
56 | if (pObj != nullptr) pObj->ReleaseRef(); |
57 | } |
58 | |
59 | void clear() |
60 | { |
61 | if (pObj != nullptr) { |
62 | T * pRefObj = pObj; |
63 | pObj = nullptr; |
64 | pRefObj->ReleaseRef(); |
65 | } |
66 | } |
67 | |
68 | SvRef & operator =(SvRef const & rObj) |
69 | { |
70 | if (rObj.pObj != nullptr) { |
71 | rObj.pObj->AddNextRef(); |
72 | } |
73 | T * pRefObj = pObj; |
74 | pObj = rObj.pObj; |
75 | if (pRefObj != nullptr) { |
76 | pRefObj->ReleaseRef(); |
77 | } |
78 | return *this; |
79 | } |
80 | |
81 | SvRef & operator =(SvRef && rObj) |
82 | { |
83 | if (pObj != nullptr) { |
84 | pObj->ReleaseRef(); |
85 | } |
86 | pObj = rObj.pObj; |
87 | rObj.pObj = nullptr; |
88 | return *this; |
89 | } |
90 | |
91 | bool is() const { return pObj != nullptr; } |
92 | |
93 | explicit operator bool() const { return is(); } |
94 | |
95 | T * get() const { return pObj; } |
96 | |
97 | T * operator ->() const { assert(pObj != nullptr)(static_cast <bool> (pObj != nullptr) ? void (0) : __assert_fail ("pObj != nullptr", "/home/maarten/src/libreoffice/core/include/tools/ref.hxx" , 97, __extension__ __PRETTY_FUNCTION__)); return pObj; } |
98 | |
99 | T & operator *() const { assert(pObj != nullptr)(static_cast <bool> (pObj != nullptr) ? void (0) : __assert_fail ("pObj != nullptr", "/home/maarten/src/libreoffice/core/include/tools/ref.hxx" , 99, __extension__ __PRETTY_FUNCTION__)); return *pObj; } |
100 | |
101 | bool operator ==(const SvRef<T> &rhs) const { return pObj == rhs.pObj; } |
102 | bool operator !=(const SvRef<T> &rhs) const { return !(*this == rhs); } |
103 | |
104 | private: |
105 | T * pObj; |
106 | }; |
107 | |
108 | /** |
109 | * This implements similar functionality to std::make_shared. |
110 | */ |
111 | template<typename T, typename... Args> |
112 | SvRef<T> make_ref(Args&& ... args) |
113 | { |
114 | return SvRef<T>(new T(std::forward<Args>(args)...)); |
115 | } |
116 | |
117 | } |
118 | |
119 | /** Classes that want to be referenced-counted via SvRef<T>, should extend this base class */ |
120 | class TOOLS_DLLPUBLIC__attribute__ ((visibility("default"))) SvRefBase |
121 | { |
122 | // work around a clang 3.5 optimization bug: if the bNoDelete is *first* |
123 | // it mis-compiles "if (--nRefCount == 0)" and never deletes any object |
124 | unsigned int nRefCount : 31; |
125 | // the only reason this is not bool is because MSVC cannot handle mixed type bitfields |
126 | unsigned int bNoDelete : 1; |
127 | |
128 | protected: |
129 | virtual ~SvRefBase() COVERITY_NOEXCEPT_FALSE; |
130 | |
131 | public: |
132 | SvRefBase() : nRefCount(0), bNoDelete(1) {} |
133 | SvRefBase(const SvRefBase &) : nRefCount(0), bNoDelete(1) {} |
134 | |
135 | SvRefBase & operator=(const SvRefBase &) { return *this; } |
136 | |
137 | void RestoreNoDelete() |
138 | { bNoDelete = 1; } |
139 | |
140 | void AddNextRef() |
141 | { |
142 | assert( nRefCount < (1 << 30) && "Do not add refs to dead objects" )(static_cast <bool> (nRefCount < (1 << 30) && "Do not add refs to dead objects") ? void (0) : __assert_fail ("nRefCount < (1 << 30) && \"Do not add refs to dead objects\"" , "/home/maarten/src/libreoffice/core/include/tools/ref.hxx", 142, __extension__ __PRETTY_FUNCTION__)); |
143 | ++nRefCount; |
144 | } |
145 | |
146 | void AddFirstRef() |
147 | { |
148 | assert( nRefCount < (1 << 30) && "Do not add refs to dead objects" )(static_cast <bool> (nRefCount < (1 << 30) && "Do not add refs to dead objects") ? void (0) : __assert_fail ("nRefCount < (1 << 30) && \"Do not add refs to dead objects\"" , "/home/maarten/src/libreoffice/core/include/tools/ref.hxx", 148, __extension__ __PRETTY_FUNCTION__)); |
149 | if( bNoDelete ) |
150 | bNoDelete = 0; |
151 | ++nRefCount; |
152 | } |
153 | |
154 | void ReleaseRef() |
155 | { |
156 | assert( nRefCount >= 1)(static_cast <bool> (nRefCount >= 1) ? void (0) : __assert_fail ("nRefCount >= 1", "/home/maarten/src/libreoffice/core/include/tools/ref.hxx" , 156, __extension__ __PRETTY_FUNCTION__)); |
157 | if( --nRefCount == 0 && !bNoDelete) |
158 | { |
159 | // I'm not sure about the original purpose of this line, but right now |
160 | // it serves the purpose that anything that attempts to do an AddRef() |
161 | // after an object is deleted will trip an assert. |
162 | nRefCount = 1 << 30; |
163 | delete this; |
164 | } |
165 | } |
166 | |
167 | unsigned int GetRefCount() const |
168 | { return nRefCount; } |
169 | }; |
170 | |
171 | template<typename T> |
172 | class SvCompatWeakBase; |
173 | |
174 | /** SvCompatWeakHdl acts as an intermediary between SvCompatWeakRef<T> and T. |
175 | */ |
176 | template<typename T> |
177 | class SvCompatWeakHdl final : public SvRefBase |
178 | { |
179 | friend class SvCompatWeakBase<T>; |
180 | T* _pObj; |
181 | |
182 | SvCompatWeakHdl( T* pObj ) : _pObj( pObj ) {} |
183 | |
184 | public: |
185 | void ResetWeakBase( ) { _pObj = nullptr; } |
186 | T* GetObj() { return _pObj; } |
187 | }; |
188 | |
189 | /** We only have one place that extends this, in include/sfx2/frame.hxx, class SfxFrame. |
190 | Its function is to notify the SvCompatWeakHdl when an SfxFrame object is deleted. |
191 | */ |
192 | template<typename T> |
193 | class SvCompatWeakBase |
194 | { |
195 | tools::SvRef< SvCompatWeakHdl<T> > _xHdl; |
196 | |
197 | public: |
198 | /** Does not use initializer due to compiler warnings, |
199 | because the lifetime of the _xHdl object can exceed the lifetime of this class. |
200 | */ |
201 | SvCompatWeakBase( T* pObj ) { _xHdl = new SvCompatWeakHdl<T>( pObj ); } |
202 | |
203 | ~SvCompatWeakBase() { _xHdl->ResetWeakBase(); } |
204 | |
205 | SvCompatWeakHdl<T>* GetHdl() { return _xHdl.get(); } |
206 | }; |
207 | |
208 | /** We only have one weak reference in LO, in include/sfx2/frame.hxx, class SfxFrameWeak. |
209 | */ |
210 | template<typename T> |
211 | class SAL_WARN_UNUSED__attribute__((warn_unused)) SvCompatWeakRef |
212 | { |
213 | tools::SvRef< SvCompatWeakHdl<T> > _xHdl; |
214 | public: |
215 | SvCompatWeakRef( ) {} |
216 | SvCompatWeakRef( T* pObj ) |
217 | { if( pObj ) _xHdl = pObj->GetHdl(); } |
218 | #if defined(__COVERITY__) |
219 | ~SvCompatWeakRef() COVERITY_NOEXCEPT_FALSE {} |
220 | #endif |
221 | SvCompatWeakRef& operator = ( T * pObj ) |
222 | { _xHdl = pObj ? pObj->GetHdl() : nullptr; return *this; } |
223 | bool is() const |
224 | { return _xHdl.is() && _xHdl->GetObj(); } |
225 | explicit operator bool() const { return is(); } |
226 | T* operator -> () const |
227 | { return _xHdl.is() ? _xHdl->GetObj() : nullptr; } |
228 | operator T* () const |
229 | { return _xHdl.is() ? _xHdl->GetObj() : nullptr; } |
230 | }; |
231 | |
232 | #endif |
233 | |
234 | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |