Line data Source code
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 <config_features.h>
21 :
22 : #include <sal/config.h>
23 :
24 : #include <cassert>
25 :
26 : #include <vcl/msgbox.hxx>
27 : #include <svl/eitem.hxx>
28 : #include <svl/stritem.hxx>
29 : #include <svl/intitem.hxx>
30 : #include <com/sun/star/frame/theGlobalEventBroadcaster.hpp>
31 : #include <com/sun/star/frame/XStorable.hpp>
32 : #include <com/sun/star/frame/XModel.hpp>
33 : #include <com/sun/star/frame/XFrame.hpp>
34 : #include <com/sun/star/document/XFilter.hpp>
35 : #include <com/sun/star/document/XImporter.hpp>
36 : #include <com/sun/star/document/XExporter.hpp>
37 : #include <com/sun/star/document/XInteractionFilterOptions.hpp>
38 : #include <com/sun/star/packages/zip/ZipIOException.hpp>
39 : #include <com/sun/star/task/XInteractionHandler.hpp>
40 : #include <com/sun/star/task/XInteractionAskLater.hpp>
41 : #include <com/sun/star/task/InteractionClassification.hpp>
42 : #include <com/sun/star/lang/XInitialization.hpp>
43 : #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
44 : #include <com/sun/star/document/MacroExecMode.hpp>
45 : #include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp>
46 : #include <com/sun/star/ui/dialogs/XFilePickerControlAccess.hpp>
47 : #include <com/sun/star/ui/dialogs/XFilePicker.hpp>
48 : #include <com/sun/star/beans/XPropertySetInfo.hpp>
49 : #include <com/sun/star/lang/XMultiServiceFactory.hpp>
50 : #include <com/sun/star/beans/XPropertyAccess.hpp>
51 : #include <com/sun/star/beans/PropertyValue.hpp>
52 : #include <com/sun/star/beans/XPropertySet.hpp>
53 : #include <com/sun/star/container/XNameAccess.hpp>
54 : #include <com/sun/star/container/XSet.hpp>
55 : #include <com/sun/star/embed/ElementModes.hpp>
56 : #include <com/sun/star/embed/EmbedStates.hpp>
57 : #include <com/sun/star/embed/Aspects.hpp>
58 : #include <com/sun/star/embed/XTransactedObject.hpp>
59 : #include <com/sun/star/embed/XEmbedPersist.hpp>
60 : #include <com/sun/star/embed/XLinkageSupport.hpp>
61 : #include <com/sun/star/embed/EntryInitModes.hpp>
62 : #include <com/sun/star/embed/XOptimizedStorage.hpp>
63 : #include <com/sun/star/embed/XEncryptionProtectedStorage.hpp>
64 : #include <com/sun/star/io/XTruncate.hpp>
65 : #include <com/sun/star/util/XModifiable.hpp>
66 : #include <com/sun/star/security/DocumentDigitalSignatures.hpp>
67 : #include <com/sun/star/text/XTextRange.hpp>
68 : #include <com/sun/star/xml/crypto/CipherID.hpp>
69 : #include <com/sun/star/xml/crypto/DigestID.hpp>
70 :
71 : #include <com/sun/star/document/XDocumentProperties.hpp>
72 : #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
73 : #include <comphelper/processfactory.hxx>
74 : #include <comphelper/interaction.hxx>
75 : #include <svtools/sfxecode.hxx>
76 : #include <unotools/securityoptions.hxx>
77 : #include <cppuhelper/weak.hxx>
78 : #include <unotools/streamwrap.hxx>
79 :
80 : #include <unotools/saveopt.hxx>
81 : #include <unotools/useroptions.hxx>
82 : #include <unotools/pathoptions.hxx>
83 : #include <tools/urlobj.hxx>
84 : #include <tools/diagnose_ex.h>
85 : #include <unotools/localfilehelper.hxx>
86 : #include <unotools/ucbhelper.hxx>
87 : #include <unotools/tempfile.hxx>
88 : #include <unotools/docinfohelper.hxx>
89 : #include <ucbhelper/content.hxx>
90 : #include <sot/storage.hxx>
91 : #include <sot/storinfo.hxx>
92 : #include <sot/exchange.hxx>
93 : #include <sot/formats.hxx>
94 : #include <comphelper/storagehelper.hxx>
95 : #include <comphelper/seqstream.hxx>
96 : #include <comphelper/documentconstants.hxx>
97 : #include <comphelper/string.hxx>
98 : #include <vcl/bitmapex.hxx>
99 : #include <svtools/embedhlp.hxx>
100 : #include <basic/modsizeexceeded.hxx>
101 : #include <officecfg/Office/Common.hxx>
102 : #include <osl/file.hxx>
103 :
104 : #include <sfx2/signaturestate.hxx>
105 : #include <sfx2/app.hxx>
106 : #include <sfx2/objsh.hxx>
107 : #include <sfx2/childwin.hxx>
108 : #include <sfx2/request.hxx>
109 : #include <sfx2/sfxresid.hxx>
110 : #include <sfx2/docfile.hxx>
111 : #include <sfx2/fcontnr.hxx>
112 : #include <sfx2/docfilt.hxx>
113 : #include <sfx2/docfac.hxx>
114 : #include "appopen.hxx"
115 : #include "objshimp.hxx"
116 : #include "sfxtypes.hxx"
117 : #include "doc.hrc"
118 : #include <sfx2/sfxsids.hrc>
119 : #include <sfx2/module.hxx>
120 : #include <sfx2/dispatch.hxx>
121 : #include "openflag.hxx"
122 : #include "helper.hxx"
123 : #include <sfx2/event.hxx>
124 : #include "fltoptint.hxx"
125 : #include <sfx2/viewfrm.hxx>
126 : #include "graphhelp.hxx"
127 : #include "appbaslib.hxx"
128 : #include "appdata.hxx"
129 : #include <objstor.hxx>
130 :
131 : #include "../appl/app.hrc"
132 :
133 : using namespace ::com::sun::star;
134 : using namespace ::com::sun::star::container;
135 : using namespace ::com::sun::star::lang;
136 : using namespace ::com::sun::star::ui::dialogs;
137 : using namespace ::com::sun::star::uno;
138 : using namespace ::com::sun::star::beans;
139 : using namespace ::com::sun::star::ucb;
140 : using namespace ::com::sun::star::task;
141 : using namespace ::com::sun::star::document;
142 : using namespace ::cppu;
143 :
144 :
145 4117 : void impl_addToModelCollection(const css::uno::Reference< css::frame::XModel >& xModel)
146 : {
147 4117 : if (!xModel.is())
148 4117 : return;
149 :
150 4117 : css::uno::Reference< css::uno::XComponentContext > xContext = ::comphelper::getProcessComponentContext();
151 : css::uno::Reference< css::frame::XGlobalEventBroadcaster > xModelCollection =
152 8234 : css::frame::theGlobalEventBroadcaster::get(xContext);
153 : try
154 : {
155 4117 : xModelCollection->insert(css::uno::makeAny(xModel));
156 : }
157 0 : catch ( uno::Exception& )
158 : {
159 : SAL_WARN( "sfx.doc", "The document seems to be in the collection already!\n" );
160 4117 : }
161 : }
162 :
163 :
164 :
165 0 : bool SfxObjectShell::Save()
166 : {
167 0 : return SaveChildren();
168 : }
169 :
170 :
171 :
172 673 : bool SfxObjectShell::SaveAs( SfxMedium& rMedium )
173 : {
174 673 : return SaveAsChildren( rMedium );
175 : }
176 :
177 :
178 :
179 1 : bool SfxObjectShell::QuerySlotExecutable( sal_uInt16 /*nSlotId*/ )
180 : {
181 1 : return true;
182 : }
183 :
184 :
185 :
186 2967 : bool GetEncryptionData_Impl( const SfxItemSet* pSet, uno::Sequence< beans::NamedValue >& o_rEncryptionData )
187 : {
188 2967 : bool bResult = false;
189 2967 : if ( pSet )
190 : {
191 2967 : SFX_ITEMSET_ARG( pSet, pEncryptionDataItem, SfxUnoAnyItem, SID_ENCRYPTIONDATA, false);
192 2967 : if ( pEncryptionDataItem )
193 : {
194 7 : pEncryptionDataItem->GetValue() >>= o_rEncryptionData;
195 7 : bResult = true;
196 : }
197 : else
198 : {
199 2960 : SFX_ITEMSET_ARG( pSet, pPasswordItem, SfxStringItem, SID_PASSWORD, false);
200 2960 : if ( pPasswordItem )
201 : {
202 4 : OUString aPassword = pPasswordItem->GetValue();
203 4 : o_rEncryptionData = ::comphelper::OStorageHelper::CreatePackageEncryptionData( aPassword );
204 4 : bResult = true;
205 : }
206 : }
207 : }
208 :
209 2967 : return bResult;
210 : }
211 :
212 :
213 0 : bool SfxObjectShell::PutURLContentsToVersionStream_Impl(
214 : const OUString& aURL,
215 : const uno::Reference< embed::XStorage >& xDocStorage,
216 : const OUString& aStreamName )
217 : {
218 0 : bool bResult = false;
219 : try
220 : {
221 0 : uno::Reference< embed::XStorage > xVersion = xDocStorage->openStorageElement(
222 : OUString("Versions"),
223 0 : embed::ElementModes::READWRITE );
224 :
225 : DBG_ASSERT( xVersion.is(),
226 : "The method must throw an exception if the storage can not be opened!\n" );
227 0 : if ( !xVersion.is() )
228 0 : throw uno::RuntimeException();
229 :
230 0 : uno::Reference< io::XStream > xVerStream = xVersion->openStreamElement(
231 : aStreamName,
232 0 : embed::ElementModes::READWRITE );
233 : DBG_ASSERT( xVerStream.is(), "The method must throw an exception if the storage can not be opened!\n" );
234 0 : if ( !xVerStream.is() )
235 0 : throw uno::RuntimeException();
236 :
237 0 : uno::Reference< io::XOutputStream > xOutStream = xVerStream->getOutputStream();
238 0 : uno::Reference< io::XTruncate > xTrunc( xOutStream, uno::UNO_QUERY );
239 :
240 : DBG_ASSERT( xTrunc.is(), "The output stream must exist and implement XTruncate interface!\n" );
241 0 : if ( !xTrunc.is() )
242 0 : throw RuntimeException();
243 :
244 : uno::Reference< io::XInputStream > xTmpInStream =
245 : ::comphelper::OStorageHelper::GetInputStreamFromURL(
246 0 : aURL, comphelper::getProcessComponentContext() );
247 : assert( xTmpInStream.is() );
248 :
249 0 : xTrunc->truncate();
250 0 : ::comphelper::OStorageHelper::CopyInputToOutput( xTmpInStream, xOutStream );
251 0 : xOutStream->closeOutput();
252 :
253 0 : uno::Reference< embed::XTransactedObject > xTransact( xVersion, uno::UNO_QUERY );
254 : DBG_ASSERT( xTransact.is(), "The storage must implement XTransacted interface!\n" );
255 0 : if ( xTransact.is() )
256 0 : xTransact->commit();
257 :
258 0 : bResult = true;
259 : }
260 0 : catch( uno::Exception& )
261 : {
262 : // TODO/LATER: handle the error depending on exception
263 0 : SetError( ERRCODE_IO_GENERAL, OUString( OSL_LOG_PREFIX ) );
264 : }
265 :
266 0 : return bResult;
267 : }
268 :
269 :
270 0 : OUString SfxObjectShell::CreateTempCopyOfStorage_Impl( const uno::Reference< embed::XStorage >& xStorage )
271 : {
272 0 : OUString aTempURL = ::utl::TempFile().GetURL();
273 :
274 : DBG_ASSERT( !aTempURL.isEmpty(), "Can't create a temporary file!\n" );
275 0 : if ( !aTempURL.isEmpty() )
276 : {
277 : try
278 : {
279 : uno::Reference< embed::XStorage > xTempStorage =
280 0 : ::comphelper::OStorageHelper::GetStorageFromURL( aTempURL, embed::ElementModes::READWRITE );
281 :
282 : // the password will be transferred from the xStorage to xTempStorage by storage implementation
283 0 : xStorage->copyToStorage( xTempStorage );
284 :
285 : // the temporary storage was committed by the previous method and it will die by refcount
286 : }
287 0 : catch ( uno::Exception& )
288 : {
289 : SAL_WARN( "sfx.doc", "Creation of a storage copy is failed!" );
290 0 : ::utl::UCBContentHelper::Kill( aTempURL );
291 :
292 0 : aTempURL.clear();
293 :
294 : // TODO/LATER: may need error code setting based on exception
295 0 : SetError( ERRCODE_IO_GENERAL, OUString( OSL_LOG_PREFIX ) );
296 : }
297 : }
298 :
299 0 : return aTempURL;
300 : }
301 :
302 :
303 0 : SvGlobalName SfxObjectShell::GetClassName() const
304 : {
305 0 : return GetFactory().GetClassId();
306 : }
307 :
308 : namespace {
309 :
310 : /**
311 : * Chart2 does not have an Object shell, so handle this here for now
312 : * If we ever implement a full scale object shell in chart2 move it there
313 : */
314 0 : SotClipboardFormatId GetChartVersion( sal_Int32 nVersion, bool bTemplate )
315 : {
316 0 : if( nVersion == SOFFICE_FILEFORMAT_60)
317 : {
318 0 : return SotClipboardFormatId::STARCHART_60;
319 : }
320 0 : else if( nVersion == SOFFICE_FILEFORMAT_8)
321 : {
322 0 : if (bTemplate)
323 : {
324 : SAL_WARN("sfx", "no chart template support yet");
325 0 : return SotClipboardFormatId::STARCHART_8;
326 : }
327 : else
328 0 : return SotClipboardFormatId::STARCHART_8;
329 : }
330 :
331 : SAL_WARN("sfx", "unsupported version");
332 0 : return SotClipboardFormatId::NONE;
333 : }
334 :
335 : }
336 :
337 :
338 4741 : void SfxObjectShell::SetupStorage( const uno::Reference< embed::XStorage >& xStorage,
339 : sal_Int32 nVersion, bool bTemplate, bool bChart ) const
340 : {
341 4741 : uno::Reference< beans::XPropertySet > xProps( xStorage, uno::UNO_QUERY );
342 :
343 4741 : if ( xProps.is() )
344 : {
345 4741 : SvGlobalName aName;
346 9482 : OUString aFullTypeName, aShortTypeName, aAppName;
347 4741 : SotClipboardFormatId nClipFormat = SotClipboardFormatId::NONE;
348 :
349 4741 : if(!bChart)
350 4741 : FillClass( &aName, &nClipFormat, &aAppName, &aFullTypeName, &aShortTypeName, nVersion, bTemplate );
351 : else
352 0 : nClipFormat = GetChartVersion(nVersion, bTemplate);
353 :
354 4741 : if ( nClipFormat != SotClipboardFormatId::NONE )
355 : {
356 : // basic doesn't have a ClipFormat
357 : // without MediaType the storage is not really usable, but currently the BasicIDE still
358 : // is an SfxObjectShell and so we can't take this as an error
359 4741 : datatransfer::DataFlavor aDataFlavor;
360 4741 : SotExchange::GetFormatDataFlavor( nClipFormat, aDataFlavor );
361 4741 : if ( !aDataFlavor.MimeType.isEmpty() )
362 : {
363 : try
364 : {
365 4741 : xProps->setPropertyValue("MediaType", uno::makeAny( aDataFlavor.MimeType ) );
366 : }
367 0 : catch( uno::Exception& )
368 : {
369 0 : const_cast<SfxObjectShell*>( this )->SetError( ERRCODE_IO_GENERAL, OUString( OSL_LOG_PREFIX ) );
370 : }
371 :
372 4741 : SvtSaveOptions aSaveOpt;
373 4741 : SvtSaveOptions::ODFDefaultVersion nDefVersion = aSaveOpt.GetODFDefaultVersion();
374 :
375 9482 : uno::Sequence< beans::NamedValue > aEncryptionAlgs( 3 );
376 4741 : aEncryptionAlgs[0].Name = "StartKeyGenerationAlgorithm";
377 4741 : aEncryptionAlgs[1].Name = "EncryptionAlgorithm";
378 4741 : aEncryptionAlgs[2].Name = "ChecksumAlgorithm";
379 : // the default values, that should be used for ODF1.1 and older formats
380 4741 : aEncryptionAlgs[0].Value <<= xml::crypto::DigestID::SHA1;
381 4741 : aEncryptionAlgs[1].Value <<= xml::crypto::CipherID::BLOWFISH_CFB_8;
382 4741 : aEncryptionAlgs[2].Value <<= xml::crypto::DigestID::SHA1_1K;
383 :
384 4741 : if ( nDefVersion >= SvtSaveOptions::ODFVER_012 )
385 : {
386 : try
387 : {
388 : // older versions can not have this property set, it exists only starting from ODF1.2
389 4741 : xProps->setPropertyValue("Version", uno::makeAny<OUString>( ODFVER_012_TEXT ) );
390 : }
391 0 : catch( uno::Exception& )
392 : {
393 : }
394 :
395 4741 : if ( !aSaveOpt.IsUseSHA1InODF12() && nDefVersion != SvtSaveOptions::ODFVER_012_EXT_COMPAT )
396 : {
397 4741 : aEncryptionAlgs[0].Value <<= xml::crypto::DigestID::SHA256;
398 4741 : aEncryptionAlgs[2].Value <<= xml::crypto::DigestID::SHA256_1K;
399 : }
400 4741 : if ( !aSaveOpt.IsUseBlowfishInODF12() && nDefVersion != SvtSaveOptions::ODFVER_012_EXT_COMPAT )
401 4741 : aEncryptionAlgs[1].Value <<= xml::crypto::CipherID::AES_CBC_W3C_PADDING;
402 : }
403 :
404 : try
405 : {
406 : // set the encryption algorithms accordingly;
407 : // the setting does not trigger encryption,
408 : // it just provides the format for the case that contents should be encrypted
409 4741 : uno::Reference< embed::XEncryptionProtectedStorage > xEncr( xStorage, uno::UNO_QUERY_THROW );
410 3597 : xEncr->setEncryptionAlgorithms( aEncryptionAlgs );
411 : }
412 1144 : catch( uno::Exception& )
413 : {
414 1144 : const_cast<SfxObjectShell*>( this )->SetError( ERRCODE_IO_GENERAL, OUString( OSL_LOG_PREFIX ) );
415 4741 : }
416 :
417 4741 : }
418 4741 : }
419 4741 : }
420 4741 : }
421 :
422 :
423 0 : void SfxObjectShell::PrepareSecondTryLoad_Impl()
424 : {
425 : // only for internal use
426 0 : pImp->m_xDocStorage = uno::Reference< embed::XStorage >();
427 0 : pImp->m_bIsInit = false;
428 0 : ResetError();
429 0 : }
430 :
431 :
432 4119 : bool SfxObjectShell::GeneralInit_Impl( const uno::Reference< embed::XStorage >& xStorage,
433 : bool bTypeMustBeSetAlready )
434 : {
435 4119 : if ( pImp->m_bIsInit )
436 1 : return false;
437 :
438 4118 : pImp->m_bIsInit = true;
439 4118 : if ( xStorage.is() )
440 : {
441 : // no notification is required the storage is set the first time
442 496 : pImp->m_xDocStorage = xStorage;
443 :
444 : try {
445 496 : uno::Reference < beans::XPropertySet > xPropSet( xStorage, uno::UNO_QUERY_THROW );
446 992 : Any a = xPropSet->getPropertyValue("MediaType");
447 992 : OUString aMediaType;
448 496 : if ( !(a>>=aMediaType) || aMediaType.isEmpty() )
449 : {
450 0 : if ( bTypeMustBeSetAlready )
451 : {
452 0 : SetError( ERRCODE_IO_BROKENPACKAGE, OUString( OSL_LOG_PREFIX ) );
453 0 : return false;
454 : }
455 :
456 0 : SetupStorage( xStorage, SOFFICE_FILEFORMAT_CURRENT, false, false );
457 496 : }
458 : }
459 0 : catch ( uno::Exception& )
460 : {
461 : SAL_WARN( "sfx.doc", "Can't check storage's mediatype!" );
462 : }
463 : }
464 : else
465 3622 : pImp->m_bCreateTempStor = true;
466 :
467 4118 : return true;
468 : }
469 :
470 :
471 3623 : bool SfxObjectShell::InitNew( const uno::Reference< embed::XStorage >& xStorage )
472 : {
473 3623 : return GeneralInit_Impl( xStorage, false );
474 : }
475 :
476 :
477 496 : bool SfxObjectShell::Load( SfxMedium& rMedium )
478 : {
479 496 : return GeneralInit_Impl( rMedium.GetStorage(), true );
480 : }
481 :
482 204 : bool SfxObjectShell::DoInitUnitTest()
483 : {
484 204 : pMedium = new SfxMedium;
485 204 : return true; // always a success!
486 : }
487 :
488 1151 : bool SfxObjectShell::DoInitNew( SfxMedium* pMed )
489 : /* [Description]
490 :
491 : This from SvPersist inherited virtual method is called to initialize
492 : the SfxObjectShell instance from a storage (PStore! = 0) or (PStore == 0)
493 :
494 : Like with all Do...-methods there is a from a control, the actual
495 : implementation is done by the virtual method in which also the
496 : InitNew(SvStorate *) from the SfxObjectShell-Subclass is implemented.
497 :
498 : For pStore == 0 the SfxObjectShell-instance is connected to an empty
499 : SfxMedium, otherwise a SfxMedium, which refers to the SotStorage
500 : passed as a parameter.
501 :
502 : The object is only initialized correctly after InitNew() or Load().
503 :
504 : [Return value]
505 : true The object has been initialized.
506 : false The object could not be initialized
507 : */
508 :
509 : {
510 1151 : ModifyBlocker_Impl aBlock( this );
511 1151 : pMedium = pMed;
512 1151 : if ( !pMedium )
513 : {
514 1146 : pMedium = new SfxMedium;
515 : }
516 :
517 1151 : pMedium->CanDisposeStorage_Impl( true );
518 :
519 1151 : if ( InitNew( pMed ? pMed->GetStorage() : uno::Reference < embed::XStorage >() ) )
520 : {
521 : // empty documents always get their macros from the user, so there is no reason to restrict access
522 1150 : pImp->aMacroMode.allowMacroExecution();
523 1150 : if ( SfxObjectCreateMode::EMBEDDED == eCreateMode )
524 318 : SetTitle(SfxResId(STR_NONAME).toString());
525 :
526 1150 : uno::Reference< frame::XModel > xModel ( GetModel(), uno::UNO_QUERY );
527 1150 : if ( xModel.is() )
528 : {
529 1150 : SfxItemSet *pSet = GetMedium()->GetItemSet();
530 1150 : uno::Sequence< beans::PropertyValue > aArgs;
531 1150 : TransformItems( SID_OPENDOC, *pSet, aArgs );
532 1150 : sal_Int32 nLength = aArgs.getLength();
533 1150 : aArgs.realloc( nLength + 1 );
534 1150 : aArgs[nLength].Name = "Title";
535 1150 : aArgs[nLength].Value <<= OUString( GetTitle( SFX_TITLE_DETECT ) );
536 1150 : xModel->attachResource( OUString(), aArgs );
537 1150 : impl_addToModelCollection(xModel);
538 : }
539 :
540 1150 : SetInitialized_Impl( true );
541 1150 : return true;
542 : }
543 :
544 1 : return false;
545 : }
546 :
547 :
548 :
549 0 : bool SfxObjectShell::ImportFromGeneratedStream_Impl(
550 : const uno::Reference< io::XStream >& xStream,
551 : const uno::Sequence< beans::PropertyValue >& rMediaDescr )
552 : {
553 0 : if ( !xStream.is() )
554 0 : return false;
555 :
556 0 : if ( pMedium && pMedium->HasStorage_Impl() )
557 0 : pMedium->CloseStorage();
558 :
559 0 : bool bResult = false;
560 :
561 : try
562 : {
563 : uno::Reference< embed::XStorage > xStorage =
564 0 : ::comphelper::OStorageHelper::GetStorageFromStream( xStream, embed::ElementModes::READWRITE );
565 :
566 0 : if ( !xStorage.is() )
567 0 : throw uno::RuntimeException();
568 :
569 0 : if ( !pMedium )
570 0 : pMedium = new SfxMedium( xStorage, OUString() );
571 : else
572 0 : pMedium->SetStorage_Impl( xStorage );
573 :
574 0 : SfxAllItemSet aSet( SfxGetpApp()->GetPool() );
575 0 : TransformParameters( SID_OPENDOC, rMediaDescr, aSet );
576 0 : pMedium->GetItemSet()->Put( aSet );
577 0 : pMedium->CanDisposeStorage_Impl( false );
578 0 : uno::Reference<text::XTextRange> xInsertTextRange;
579 0 : for (sal_Int32 i = 0; i < rMediaDescr.getLength(); ++i)
580 : {
581 0 : if (rMediaDescr[i].Name == "TextInsertModeRange")
582 : {
583 0 : rMediaDescr[i].Value >>= xInsertTextRange;
584 : }
585 : }
586 :
587 0 : if (xInsertTextRange.is())
588 : {
589 0 : bResult = InsertGeneratedStream(*pMedium, xInsertTextRange);
590 : }
591 : else
592 : {
593 :
594 : // allow the subfilter to reinit the model
595 0 : if ( pImp->m_bIsInit )
596 0 : pImp->m_bIsInit = false;
597 :
598 0 : if ( LoadOwnFormat( *pMedium ) )
599 : {
600 0 : bHasName = true;
601 0 : if ( !IsReadOnly() && IsLoadReadonly() )
602 0 : SetReadOnlyUI();
603 :
604 0 : bResult = true;
605 : OSL_ENSURE( pImp->m_xDocStorage == xStorage, "Wrong storage is used!\n" );
606 : }
607 : }
608 :
609 : // now the medium can be disconnected from the storage
610 : // the medium is not allowed to dispose the storage so CloseStorage() can be used
611 0 : pMedium->CloseStorage();
612 : }
613 0 : catch( uno::Exception& )
614 : {
615 : }
616 :
617 0 : return bResult;
618 : }
619 :
620 :
621 :
622 2969 : bool SfxObjectShell::DoLoad( SfxMedium *pMed )
623 : {
624 2969 : ModifyBlocker_Impl aBlock( this );
625 :
626 2969 : pMedium = pMed;
627 2969 : pMedium->CanDisposeStorage_Impl( true );
628 :
629 2969 : bool bOk = false;
630 2969 : const SfxFilter* pFilter = pMed->GetFilter();
631 2969 : SfxItemSet* pSet = pMedium->GetItemSet();
632 2969 : if( !pImp->nEventId )
633 : {
634 2965 : SFX_ITEMSET_ARG(
635 : pSet, pTemplateItem, SfxBoolItem,
636 : SID_TEMPLATE, false);
637 : SetActivateEvent_Impl(
638 49 : ( pTemplateItem && pTemplateItem->GetValue() )
639 3014 : ? SFX_EVENT_CREATEDOC : SFX_EVENT_OPENDOC );
640 : }
641 :
642 :
643 2969 : SFX_ITEMSET_ARG( pSet, pBaseItem, SfxStringItem,
644 : SID_BASEURL, false);
645 5938 : OUString aBaseURL;
646 2969 : SFX_ITEMSET_ARG( pMedium->GetItemSet(), pSalvageItem, SfxStringItem, SID_DOC_SALVAGE, false);
647 2969 : if( pBaseItem )
648 0 : aBaseURL = pBaseItem->GetValue();
649 : else
650 : {
651 2969 : if ( pSalvageItem )
652 : {
653 0 : OUString aName( pMed->GetPhysicalName() );
654 0 : ::utl::LocalFileHelper::ConvertPhysicalNameToURL( aName, aBaseURL );
655 : }
656 : else
657 2969 : aBaseURL = pMed->GetBaseURL();
658 : }
659 2969 : pMed->GetItemSet()->Put( SfxStringItem( SID_DOC_BASEURL, aBaseURL ) );
660 :
661 2969 : pImp->nLoadedFlags = SfxLoadedFlags::NONE;
662 2969 : pImp->bModelInitialized = false;
663 :
664 : //TODO/LATER: make a clear strategy how to handle "UsesStorage" etc.
665 2969 : bool bOwnStorageFormat = IsOwnStorageFormat_Impl( *pMedium );
666 2969 : bool bHasStorage = IsPackageStorageFormat_Impl( *pMedium );
667 2969 : if ( pMedium->GetFilter() )
668 : {
669 2964 : sal_uInt32 nError = HandleFilter( pMedium, this );
670 2964 : if ( nError != ERRCODE_NONE )
671 0 : SetError( nError, OUString( OSL_LOG_PREFIX ) );
672 :
673 2964 : if (pMedium->GetFilter()->GetFilterFlags() & SfxFilterFlags::STARTPRESENTATION)
674 0 : pSet->Put( SfxBoolItem( SID_DOC_STARTPRESENTATION, true) );
675 : }
676 :
677 2969 : EnableSetModified( false );
678 :
679 2969 : pMedium->LockOrigFileOnDemand( true, false );
680 2969 : if ( GetError() == ERRCODE_NONE && bOwnStorageFormat && ( !pFilter || !( pFilter->GetFilterFlags() & SfxFilterFlags::STARONEFILTER ) ) )
681 : {
682 497 : uno::Reference< embed::XStorage > xStorage;
683 497 : if ( pMedium->GetError() == ERRCODE_NONE )
684 497 : xStorage = pMedium->GetStorage();
685 :
686 497 : if( xStorage.is() && pMedium->GetLastStorageCreationState() == ERRCODE_NONE )
687 : {
688 : DBG_ASSERT( pFilter, "No filter for storage found!" );
689 :
690 : try
691 : {
692 496 : bool bWarnMediaTypeFallback = false;
693 496 : SFX_ITEMSET_ARG( pMedium->GetItemSet(), pRepairPackageItem, SfxBoolItem, SID_REPAIRPACKAGE, false);
694 :
695 : // treat the package as broken if the mediatype was retrieved as a fallback
696 496 : uno::Reference< beans::XPropertySet > xStorProps( xStorage, uno::UNO_QUERY_THROW );
697 496 : xStorProps->getPropertyValue("MediaTypeFallbackUsed")
698 496 : >>= bWarnMediaTypeFallback;
699 :
700 496 : if ( pRepairPackageItem && pRepairPackageItem->GetValue() )
701 : {
702 : // the macros in repaired documents should be disabled
703 0 : pMedium->GetItemSet()->Put( SfxUInt16Item( SID_MACROEXECMODE, document::MacroExecMode::NEVER_EXECUTE ) );
704 :
705 : // the mediatype was retrieved by using fallback solution but this is a repairing mode
706 : // so it is acceptable to open the document if there is no contents that required manifest.xml
707 0 : bWarnMediaTypeFallback = false;
708 : }
709 :
710 496 : if ( bWarnMediaTypeFallback || !xStorage->getElementNames().getLength() )
711 0 : SetError( ERRCODE_IO_BROKENPACKAGE, OUString( OSL_LOG_PREFIX ) );
712 : }
713 0 : catch( uno::Exception& )
714 : {
715 : // TODO/LATER: may need error code setting based on exception
716 0 : SetError( ERRCODE_IO_GENERAL, OUString( OSL_LOG_PREFIX ) );
717 : }
718 :
719 : // Load
720 496 : if ( !GetError() )
721 : {
722 496 : pImp->nLoadedFlags = SfxLoadedFlags::NONE;
723 496 : pImp->bModelInitialized = false;
724 496 : bOk = xStorage.is() && LoadOwnFormat( *pMed );
725 496 : if ( bOk )
726 : {
727 : // the document loaded from template has no name
728 495 : SFX_ITEMSET_ARG( pMedium->GetItemSet(), pTemplateItem, SfxBoolItem, SID_TEMPLATE, false);
729 495 : if ( !pTemplateItem || !pTemplateItem->GetValue() )
730 491 : bHasName = true;
731 : }
732 : else
733 1 : SetError( ERRCODE_ABORT, OUString( OSL_LOG_PREFIX ) );
734 : }
735 : }
736 : else
737 1 : SetError( pMed->GetLastStorageCreationState(), OUString( OSL_LOG_PREFIX ) );
738 : }
739 2472 : else if ( GetError() == ERRCODE_NONE && InitNew(0) )
740 : {
741 : // Name vor ConvertFrom setzen, damit GetSbxObject() schon funktioniert
742 2472 : bHasName = true;
743 2472 : SetName( SfxResId(STR_NONAME).toString() );
744 :
745 2472 : if( !bHasStorage )
746 2303 : pMedium->GetInStream();
747 : else
748 169 : pMedium->GetStorage();
749 :
750 2472 : if ( GetError() == ERRCODE_NONE )
751 : {
752 2472 : pImp->nLoadedFlags = SfxLoadedFlags::NONE;
753 2472 : pImp->bModelInitialized = false;
754 2472 : if ( pMedium->GetFilter() && ( pMedium->GetFilter()->GetFilterFlags() & SfxFilterFlags::STARONEFILTER ) )
755 : {
756 2191 : uno::Reference < beans::XPropertySet > xSet( GetModel(), uno::UNO_QUERY );
757 4382 : OUString sLockUpdates("LockUpdates");
758 2191 : bool bSetProperty = true;
759 : try
760 : {
761 2277 : xSet->setPropertyValue( sLockUpdates, makeAny( true ) );
762 : }
763 172 : catch(const beans::UnknownPropertyException& )
764 : {
765 86 : bSetProperty = false;
766 : }
767 2191 : bOk = ImportFrom(*pMedium, 0);
768 2191 : if(bSetProperty)
769 : {
770 : try
771 : {
772 2105 : xSet->setPropertyValue( sLockUpdates, makeAny( false ) );
773 : }
774 0 : catch(const beans::UnknownPropertyException& )
775 : {}
776 : }
777 2191 : UpdateLinks();
778 4382 : FinishedLoading( SfxLoadedFlags::ALL );
779 : }
780 : else
781 : {
782 281 : bOk = ConvertFrom(*pMedium);
783 281 : InitOwnModel_Impl();
784 : }
785 : }
786 : }
787 :
788 2969 : if ( bOk )
789 : {
790 2955 : if ( IsReadOnlyMedium() || IsLoadReadonly() )
791 462 : SetReadOnlyUI();
792 :
793 : try
794 : {
795 3009 : ::ucbhelper::Content aContent( pMedium->GetName(), com::sun::star::uno::Reference < XCommandEnvironment >(), comphelper::getProcessComponentContext() );
796 5802 : com::sun::star::uno::Reference < XPropertySetInfo > xProps = aContent.getProperties();
797 2901 : if ( xProps.is() )
798 : {
799 2901 : OUString aAuthor( "Author" );
800 5802 : OUString aKeywords( "Keywords" );
801 5802 : OUString aSubject( "Subject" );
802 5802 : Any aAny;
803 5802 : OUString aValue;
804 : uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
805 5802 : GetModel(), uno::UNO_QUERY_THROW);
806 : uno::Reference<document::XDocumentProperties> xDocProps
807 5802 : = xDPS->getDocumentProperties();
808 2901 : if ( xProps->hasPropertyByName( aAuthor ) )
809 : {
810 0 : aAny = aContent.getPropertyValue( aAuthor );
811 0 : if ( ( aAny >>= aValue ) )
812 0 : xDocProps->setAuthor(aValue);
813 : }
814 2901 : if ( xProps->hasPropertyByName( aKeywords ) )
815 : {
816 0 : aAny = aContent.getPropertyValue( aKeywords );
817 0 : if ( ( aAny >>= aValue ) )
818 0 : xDocProps->setKeywords(
819 0 : ::comphelper::string::convertCommaSeparated(aValue));
820 : ;
821 : }
822 2901 : if ( xProps->hasPropertyByName( aSubject ) )
823 : {
824 0 : aAny = aContent.getPropertyValue( aSubject );
825 0 : if ( ( aAny >>= aValue ) ) {
826 0 : xDocProps->setSubject(aValue);
827 : }
828 2901 : }
829 2901 : }
830 : }
831 54 : catch( Exception& )
832 : {
833 : }
834 :
835 : // If not loaded asynchronously call FinishedLoading
836 2975 : if ( !( pImp->nLoadedFlags & SfxLoadedFlags::MAINDOCUMENT ) &&
837 15 : ( !pMedium->GetFilter() || pMedium->GetFilter()->UsesStorage() )
838 : )
839 10 : FinishedLoading( SfxLoadedFlags::MAINDOCUMENT );
840 :
841 2955 : if( IsOwnStorageFormat_Impl(*pMed) && pMed->GetFilter() )
842 : {
843 : }
844 2955 : Broadcast( SfxSimpleHint(SFX_HINT_NAMECHANGED) );
845 :
846 2955 : if ( SfxObjectCreateMode::EMBEDDED != eCreateMode )
847 : {
848 2478 : SFX_ITEMSET_ARG( pMedium->GetItemSet(), pAsTempItem, SfxBoolItem, SID_TEMPLATE, false);
849 2478 : SFX_ITEMSET_ARG( pMedium->GetItemSet(), pPreviewItem, SfxBoolItem, SID_PREVIEW, false);
850 2478 : SFX_ITEMSET_ARG( pMedium->GetItemSet(), pHiddenItem, SfxBoolItem, SID_HIDDEN, false);
851 4956 : if( bOk && !pMedium->GetOrigURL().isEmpty()
852 2440 : && !( pAsTempItem && pAsTempItem->GetValue() )
853 2440 : && !( pPreviewItem && pPreviewItem->GetValue() )
854 4918 : && !( pHiddenItem && pHiddenItem->GetValue() ) )
855 : {
856 2417 : AddToRecentlyUsedList();
857 : }
858 : }
859 :
860 : const SfxBoolItem* pDdeReconnectItem = static_cast<const SfxBoolItem*>(
861 2955 : SfxRequest::GetItem(pMedium->GetItemSet(), SID_DDE_RECONNECT_ONLOAD, false, TYPE(SfxBoolItem)));
862 :
863 2955 : bool bReconnectDde = true; // by default, we try to auto-connect DDE connections.
864 2955 : if (pDdeReconnectItem)
865 0 : bReconnectDde = pDdeReconnectItem->GetValue();
866 :
867 2955 : if (bReconnectDde)
868 2955 : ReconnectDdeLinks(*this);
869 : }
870 :
871 5938 : return bOk;
872 : }
873 :
874 0 : bool SfxObjectShell::DoLoadExternal( SfxMedium *pMed )
875 : {
876 0 : pMedium = pMed;
877 0 : return LoadExternal(*pMedium);
878 : }
879 :
880 2964 : sal_uInt32 SfxObjectShell::HandleFilter( SfxMedium* pMedium, SfxObjectShell* pDoc )
881 : {
882 2964 : sal_uInt32 nError = ERRCODE_NONE;
883 2964 : SfxItemSet* pSet = pMedium->GetItemSet();
884 2964 : SFX_ITEMSET_ARG( pSet, pOptions, SfxStringItem, SID_FILE_FILTEROPTIONS, false );
885 2964 : SFX_ITEMSET_ARG( pSet, pData, SfxUnoAnyItem, SID_FILTER_DATA, false );
886 2964 : if ( !pData && !pOptions )
887 : {
888 2956 : com::sun::star::uno::Reference< XMultiServiceFactory > xServiceManager = ::comphelper::getProcessServiceFactory();
889 5912 : com::sun::star::uno::Reference< XNameAccess > xFilterCFG;
890 2956 : if( xServiceManager.is() )
891 : {
892 5912 : xFilterCFG = com::sun::star::uno::Reference< XNameAccess >(
893 2956 : xServiceManager->createInstance("com.sun.star.document.FilterFactory"),
894 2956 : UNO_QUERY );
895 : }
896 :
897 2956 : if( xFilterCFG.is() )
898 : {
899 : try {
900 2956 : bool bAbort = false;
901 2956 : const SfxFilter* pFilter = pMedium->GetFilter();
902 2956 : Sequence < PropertyValue > aProps;
903 5912 : Any aAny = xFilterCFG->getByName( pFilter->GetName() );
904 2956 : if ( aAny >>= aProps )
905 : {
906 2956 : sal_Int32 nPropertyCount = aProps.getLength();
907 32516 : for( sal_Int32 nProperty=0; nProperty < nPropertyCount; ++nProperty )
908 32516 : if( aProps[nProperty].Name == "UIComponent" )
909 : {
910 2956 : OUString aServiceName;
911 2956 : aProps[nProperty].Value >>= aServiceName;
912 2956 : if( !aServiceName.isEmpty() )
913 : {
914 9 : com::sun::star::uno::Reference< XInteractionHandler > rHandler = pMedium->GetInteractionHandler();
915 9 : if( rHandler.is() )
916 : {
917 : // we need some properties in the media descriptor, so we have to make sure that they are in
918 0 : Any aStreamAny;
919 0 : aStreamAny <<= pMedium->GetInputStream();
920 0 : if ( pSet->GetItemState( SID_INPUTSTREAM ) < SfxItemState::SET )
921 0 : pSet->Put( SfxUnoAnyItem( SID_INPUTSTREAM, aStreamAny ) );
922 0 : if ( pSet->GetItemState( SID_FILE_NAME ) < SfxItemState::SET )
923 0 : pSet->Put( SfxStringItem( SID_FILE_NAME, pMedium->GetName() ) );
924 0 : if ( pSet->GetItemState( SID_FILTER_NAME ) < SfxItemState::SET )
925 0 : pSet->Put( SfxStringItem( SID_FILTER_NAME, pFilter->GetName() ) );
926 :
927 0 : Sequence< PropertyValue > rProperties;
928 0 : TransformItems( SID_OPENDOC, *pSet, rProperties, NULL );
929 0 : RequestFilterOptions* pFORequest = new RequestFilterOptions( pDoc->GetModel(), rProperties );
930 :
931 0 : com::sun::star::uno::Reference< XInteractionRequest > rRequest( pFORequest );
932 0 : rHandler->handle( rRequest );
933 :
934 0 : if ( !pFORequest->isAbort() )
935 : {
936 0 : SfxAllItemSet aNewParams( pDoc->GetPool() );
937 : TransformParameters( SID_OPENDOC,
938 : pFORequest->getFilterOptions(),
939 : aNewParams,
940 0 : NULL );
941 :
942 0 : SFX_ITEMSET_ARG( &aNewParams,
943 : pFilterOptions,
944 : SfxStringItem,
945 : SID_FILE_FILTEROPTIONS,
946 : false );
947 0 : if ( pFilterOptions )
948 0 : pSet->Put( *pFilterOptions );
949 :
950 0 : SFX_ITEMSET_ARG( &aNewParams,
951 : pFilterData,
952 : SfxUnoAnyItem,
953 : SID_FILTER_DATA,
954 : false );
955 0 : if ( pFilterData )
956 0 : pSet->Put( *pFilterData );
957 : }
958 : else
959 0 : bAbort = true;
960 9 : }
961 : }
962 :
963 2956 : break;
964 : }
965 : }
966 :
967 2956 : if( bAbort )
968 : {
969 : // filter options were not entered
970 0 : nError = ERRCODE_ABORT;
971 2956 : }
972 : }
973 0 : catch( NoSuchElementException& )
974 : {
975 : // the filter name is unknown
976 0 : nError = ERRCODE_IO_INVALIDPARAMETER;
977 : }
978 0 : catch( Exception& )
979 : {
980 0 : nError = ERRCODE_ABORT;
981 : }
982 2956 : }
983 : }
984 :
985 2964 : return nError;
986 : }
987 :
988 :
989 :
990 10595 : bool SfxObjectShell::IsOwnStorageFormat_Impl(const SfxMedium &rMedium) const
991 : {
992 22973 : return !rMedium.GetFilter() || // Embedded
993 12393 : ( rMedium.GetFilter()->IsOwnFormat() &&
994 3607 : rMedium.GetFilter()->UsesStorage() &&
995 12378 : rMedium.GetFilter()->GetVersion() >= SOFFICE_FILEFORMAT_60 );
996 : }
997 :
998 :
999 :
1000 6269 : bool SfxObjectShell::IsPackageStorageFormat_Impl(const SfxMedium &rMedium) const
1001 : {
1002 14544 : return !rMedium.GetFilter() || // Embedded
1003 8527 : ( rMedium.GetFilter()->UsesStorage() &&
1004 8543 : rMedium.GetFilter()->GetVersion() >= SOFFICE_FILEFORMAT_60 );
1005 : }
1006 :
1007 :
1008 :
1009 0 : bool SfxObjectShell::DoSave()
1010 : // DoSave is only invoked for OLE. Save your own documents in the SFX through
1011 : // DoSave_Impl order to allow for the creation of backups.
1012 : // Save in your own format again.
1013 : {
1014 0 : bool bOk = false ;
1015 : {
1016 0 : ModifyBlocker_Impl aBlock( this );
1017 :
1018 0 : pImp->bIsSaving = true;
1019 :
1020 0 : uno::Sequence< beans::NamedValue > aEncryptionData;
1021 0 : if ( IsPackageStorageFormat_Impl( *GetMedium() ) )
1022 : {
1023 0 : if ( GetEncryptionData_Impl( GetMedium()->GetItemSet(), aEncryptionData ) )
1024 : {
1025 : try
1026 : {
1027 : //TODO/MBA: GetOutputStorage?! Special mode, because it's "Save"?!
1028 0 : ::comphelper::OStorageHelper::SetCommonStorageEncryptionData( GetMedium()->GetStorage(), aEncryptionData );
1029 0 : bOk = true;
1030 : }
1031 0 : catch( uno::Exception& )
1032 : {
1033 0 : SetError( ERRCODE_IO_GENERAL, OUString( OSL_LOG_PREFIX ) );
1034 : }
1035 :
1036 : DBG_ASSERT( bOk, "The root storage must allow to set common password!\n" );
1037 : }
1038 : else
1039 0 : bOk = true;
1040 : #if HAVE_FEATURE_SCRIPTING
1041 0 : if ( HasBasic() )
1042 : {
1043 : try
1044 : {
1045 : // The basic and dialogs related contents are still not able to proceed with save operation ( saveTo only )
1046 : // so since the document storage is locked a workaround has to be used
1047 :
1048 0 : uno::Reference< embed::XStorage > xTmpStorage = ::comphelper::OStorageHelper::GetTemporaryStorage();
1049 : DBG_ASSERT( xTmpStorage.is(), "If a storage can not be created an exception must be thrown!\n" );
1050 0 : if ( !xTmpStorage.is() )
1051 0 : throw uno::RuntimeException();
1052 :
1053 0 : OUString aBasicStorageName( "Basic" );
1054 0 : OUString aDialogsStorageName( "Dialogs" );
1055 0 : if ( GetMedium()->GetStorage()->hasByName( aBasicStorageName ) )
1056 0 : GetMedium()->GetStorage()->copyElementTo( aBasicStorageName, xTmpStorage, aBasicStorageName );
1057 0 : if ( GetMedium()->GetStorage()->hasByName( aDialogsStorageName ) )
1058 0 : GetMedium()->GetStorage()->copyElementTo( aDialogsStorageName, xTmpStorage, aDialogsStorageName );
1059 :
1060 0 : GetBasicManager();
1061 :
1062 : // disconnect from the current storage
1063 0 : pImp->aBasicManager.setStorage( xTmpStorage );
1064 :
1065 : // store to the current storage
1066 0 : pImp->aBasicManager.storeLibrariesToStorage( GetMedium()->GetStorage() );
1067 :
1068 : // connect to the current storage back
1069 0 : pImp->aBasicManager.setStorage( GetMedium()->GetStorage() );
1070 : }
1071 0 : catch( uno::Exception& )
1072 : {
1073 0 : SetError( ERRCODE_IO_GENERAL, OUString( OSL_LOG_PREFIX ) );
1074 0 : bOk = false;
1075 : }
1076 : }
1077 : #endif
1078 : }
1079 :
1080 0 : if (bOk)
1081 0 : bOk = Save();
1082 :
1083 0 : if (bOk)
1084 0 : bOk = pMedium->Commit();
1085 : }
1086 :
1087 0 : return bOk;
1088 : }
1089 :
1090 1662 : void Lock_Impl( SfxObjectShell* pDoc, bool bLock )
1091 : {
1092 1662 : SfxViewFrame *pFrame= SfxViewFrame::GetFirst( pDoc );
1093 4678 : while ( pFrame )
1094 : {
1095 1354 : pFrame->GetDispatcher()->Lock( bLock );
1096 1354 : pFrame->Enable( !bLock );
1097 1354 : pFrame = SfxViewFrame::GetNext( *pFrame, pDoc );
1098 : }
1099 :
1100 1662 : }
1101 :
1102 :
1103 :
1104 831 : bool SfxObjectShell::SaveTo_Impl
1105 : (
1106 : SfxMedium &rMedium, // Medium, in which it will be stored
1107 : const SfxItemSet* pSet
1108 : )
1109 :
1110 : /* [Description]
1111 :
1112 : Writes the current contents to the medium rMedium. If the target medium is
1113 : no storage, then saving to a temporary storage, or directly if the medium
1114 : is transacted, if we ourselves have opened it, and if we are a server
1115 : either the container a transacted storage provides or created a
1116 : temporary storage by one self.
1117 : */
1118 :
1119 : {
1120 : SAL_INFO( "sfx.doc", "saving \"" << rMedium.GetName() << "\"" );
1121 :
1122 831 : UpdateDocInfoForSave();
1123 :
1124 831 : AddLog( OUString( OSL_LOG_PREFIX "Begin" ) );
1125 :
1126 831 : ModifyBlocker_Impl aMod(this);
1127 :
1128 831 : const SfxFilter *pFilter = rMedium.GetFilter();
1129 831 : if ( !pFilter )
1130 : {
1131 : // if no filter was set, use the default filter
1132 : // this should be changed in the feature, it should be an error!
1133 : SAL_WARN( "sfx.doc","No filter set!");
1134 0 : pFilter = GetFactory().GetFilterContainer()->GetAnyFilter( SfxFilterFlags::IMPORT | SfxFilterFlags::EXPORT );
1135 0 : rMedium.SetFilter(pFilter);
1136 : }
1137 :
1138 831 : bool bStorageBasedSource = IsPackageStorageFormat_Impl( *pMedium );
1139 831 : bool bStorageBasedTarget = IsPackageStorageFormat_Impl( rMedium );
1140 831 : bool bOwnSource = IsOwnStorageFormat_Impl( *pMedium );
1141 831 : bool bOwnTarget = IsOwnStorageFormat_Impl( rMedium );
1142 :
1143 : // Examine target format to determine whether to query if any password
1144 : // protected libraries exceed the size we can handler
1145 831 : if ( bOwnTarget && !QuerySaveSizeExceededModules_Impl( rMedium.GetInteractionHandler() ) )
1146 : {
1147 0 : SetError( ERRCODE_IO_ABORT, OUString( OSL_LOG_PREFIX ) );
1148 0 : return false;
1149 : }
1150 :
1151 831 : bool bNeedsDisconnectionOnFail = false;
1152 :
1153 831 : bool bStoreToSameLocation = false;
1154 :
1155 : // the detection whether the script is changed should be done before saving
1156 831 : bool bTryToPreserveScriptSignature = false;
1157 : // no way to detect whether a filter is oasis format, have to wait for saving process
1158 831 : bool bNoPreserveForOasis = false;
1159 831 : if ( bOwnSource && bOwnTarget
1160 96 : && ( pImp->nScriptingSignatureState == SignatureState::OK
1161 96 : || pImp->nScriptingSignatureState == SignatureState::NOTVALIDATED
1162 96 : || pImp->nScriptingSignatureState == SignatureState::INVALID ) )
1163 : {
1164 0 : AddLog( OUString( OSL_LOG_PREFIX "MacroSignaturePreserving" ) );
1165 :
1166 : // the checking of the library modified state iterates over the libraries, should be done only when required
1167 : // currently the check is commented out since it is broken, we have to check the signature every time we save
1168 : // TODO/LATER: let isAnyContainerModified() work!
1169 0 : bTryToPreserveScriptSignature = true; // !pImp->pBasicManager->isAnyContainerModified();
1170 0 : if ( bTryToPreserveScriptSignature )
1171 : {
1172 : // check that the storage format stays the same
1173 0 : SvtSaveOptions aSaveOpt;
1174 0 : SvtSaveOptions::ODFDefaultVersion nVersion = aSaveOpt.GetODFDefaultVersion();
1175 :
1176 0 : OUString aODFVersion;
1177 : try
1178 : {
1179 0 : uno::Reference < beans::XPropertySet > xPropSet( GetStorage(), uno::UNO_QUERY_THROW );
1180 0 : xPropSet->getPropertyValue("Version") >>= aODFVersion;
1181 : }
1182 0 : catch( uno::Exception& )
1183 : {}
1184 :
1185 : // preserve only if the same filter has been used
1186 0 : bTryToPreserveScriptSignature = pMedium->GetFilter() && pFilter && pMedium->GetFilter()->GetFilterName() == pFilter->GetFilterName();
1187 :
1188 : bNoPreserveForOasis = (
1189 0 : (aODFVersion == ODFVER_012_TEXT && nVersion == SvtSaveOptions::ODFVER_011) ||
1190 0 : (aODFVersion.isEmpty() && nVersion >= SvtSaveOptions::ODFVER_012)
1191 0 : );
1192 : }
1193 : }
1194 :
1195 831 : bool bCopyTo = false;
1196 831 : SfxItemSet *pMedSet = rMedium.GetItemSet();
1197 831 : if( pMedSet )
1198 : {
1199 831 : SFX_ITEMSET_ARG( pMedSet, pSaveToItem, SfxBoolItem, SID_SAVETO, false );
1200 1624 : bCopyTo = GetCreateMode() == SfxObjectCreateMode::EMBEDDED ||
1201 1505 : (pSaveToItem && pSaveToItem->GetValue());
1202 : }
1203 :
1204 : // use UCB for case sensitive/insensitive file name comparison
1205 1662 : if ( !pMedium->GetName().equalsIgnoreAsciiCase("private:stream")
1206 831 : && !rMedium.GetName().equalsIgnoreAsciiCase("private:stream")
1207 1660 : && ::utl::UCBContentHelper::EqualURLs( pMedium->GetName(), rMedium.GetName() ) )
1208 : {
1209 2 : bStoreToSameLocation = true;
1210 2 : AddLog( OUString( OSL_LOG_PREFIX "Save" ) );
1211 :
1212 2 : if ( pMedium->DocNeedsFileDateCheck() )
1213 2 : rMedium.CheckFileDate( pMedium->GetInitFileDate( false ) );
1214 :
1215 2 : if ( bCopyTo && GetCreateMode() != SfxObjectCreateMode::EMBEDDED )
1216 : {
1217 : // export to the same location is forbidden
1218 0 : SetError( ERRCODE_IO_CANTWRITE, OUString( OSL_LOG_PREFIX ) );
1219 : }
1220 : else
1221 : {
1222 : // before we overwrite the original file, we will make a backup if there is a demand for that
1223 : // if the backup is not created here it will be created internally and will be removed in case of successful saving
1224 2 : const bool bDoBackup = SvtSaveOptions().IsBackup();
1225 2 : if ( bDoBackup )
1226 : {
1227 0 : AddLog( OUString( OSL_LOG_PREFIX "DoBackup" ) );
1228 0 : rMedium.DoBackup_Impl();
1229 0 : if ( rMedium.GetError() )
1230 : {
1231 0 : SetError( rMedium.GetErrorCode(), OUString( OSL_LOG_PREFIX ) );
1232 0 : rMedium.ResetError();
1233 : }
1234 : }
1235 :
1236 2 : if ( bStorageBasedSource && bStorageBasedTarget )
1237 : {
1238 : // The active storage must be switched. The simple saving is not enough.
1239 : // The problem is that the target medium contains target MediaDescriptor.
1240 :
1241 : // In future the switch of the persistence could be done on stream level:
1242 : // a new wrapper service will be implemented that allows to exchange
1243 : // persistence on the fly. So the real persistence will be set
1244 : // to that stream only after successful commit of the storage.
1245 : // TODO/LATER:
1246 : // create wrapper stream based on the URL
1247 : // create a new storage based on this stream
1248 : // store to this new storage
1249 : // commit the new storage
1250 : // call saveCompleted based with this new storage ( get rid of old storage and "frees" URL )
1251 : // commit the wrapper stream ( the stream will connect the URL only on commit, after that it will hold it )
1252 : // if the last step is failed the stream should stay to be transacted and should be committed on any flush
1253 : // so we can forget the stream in any way and the next storage commit will flush it
1254 :
1255 1 : AddLog( OUString( OSL_LOG_PREFIX "Save: Own to Own" ) );
1256 :
1257 : bNeedsDisconnectionOnFail = DisconnectStorage_Impl(
1258 1 : *pMedium, rMedium );
1259 4 : if ( bNeedsDisconnectionOnFail
1260 2 : || ConnectTmpStorage_Impl( pMedium->GetStorage(), pMedium ) )
1261 : {
1262 1 : pMedium->CloseAndRelease();
1263 :
1264 : // TODO/LATER: for now the medium must be closed since it can already contain streams from old medium
1265 : // in future those streams should not be copied in case a valid target url is provided,
1266 : // if the url is not provided ( means the document is based on a stream ) this code is not
1267 : // reachable.
1268 1 : rMedium.CloseAndRelease();
1269 1 : rMedium.GetOutputStorage();
1270 : }
1271 : }
1272 1 : else if ( !bStorageBasedSource && !bStorageBasedTarget )
1273 : {
1274 : // the source and the target formats are alien
1275 : // just disconnect the stream from the source format
1276 : // so that the target medium can use it
1277 :
1278 1 : AddLog( OUString( OSL_LOG_PREFIX "Save: Alien to Alien" ) );
1279 :
1280 1 : pMedium->CloseAndRelease();
1281 1 : rMedium.CloseAndRelease();
1282 1 : rMedium.CreateTempFileNoCopy();
1283 1 : rMedium.GetOutStream();
1284 : }
1285 0 : else if ( !bStorageBasedSource && bStorageBasedTarget )
1286 : {
1287 : // the source format is an alien one but the target
1288 : // format is an own one so just disconnect the source
1289 : // medium
1290 :
1291 0 : AddLog( OUString( OSL_LOG_PREFIX "Save: Alien to Own" ) );
1292 :
1293 0 : pMedium->CloseAndRelease();
1294 0 : rMedium.CloseAndRelease();
1295 0 : rMedium.GetOutputStorage();
1296 : }
1297 : else // means if ( bStorageBasedSource && !bStorageBasedTarget )
1298 : {
1299 : // the source format is an own one but the target is
1300 : // an alien format, just connect the source to temporary
1301 : // storage
1302 :
1303 0 : AddLog( OUString( OSL_LOG_PREFIX "Save: Own to Alien" ) );
1304 :
1305 : bNeedsDisconnectionOnFail = DisconnectStorage_Impl(
1306 0 : *pMedium, rMedium );
1307 0 : if ( bNeedsDisconnectionOnFail
1308 0 : || ConnectTmpStorage_Impl( pMedium->GetStorage(), pMedium ) )
1309 : {
1310 0 : pMedium->CloseAndRelease();
1311 0 : rMedium.CloseAndRelease();
1312 0 : rMedium.CreateTempFileNoCopy();
1313 0 : rMedium.GetOutStream();
1314 : }
1315 : }
1316 : }
1317 : }
1318 : else
1319 : {
1320 : // This is SaveAs or export action, prepare the target medium
1321 : // the alien filters still might write directly to the file, that is of course a bug,
1322 : // but for now the framework has to be ready for it
1323 : // TODO/LATER: let the medium be prepared for alien formats as well
1324 :
1325 829 : AddLog( OUString( OSL_LOG_PREFIX "SaveAs/Export" ) );
1326 :
1327 829 : rMedium.CloseAndRelease();
1328 829 : if ( bStorageBasedTarget )
1329 : {
1330 100 : rMedium.GetOutputStorage();
1331 : }
1332 : }
1333 :
1334 : // TODO/LATER: error handling
1335 831 : if( rMedium.GetErrorCode() || pMedium->GetErrorCode() || GetErrorCode() )
1336 0 : return false;
1337 :
1338 831 : AddLog( OUString( OSL_LOG_PREFIX "Locking" ) );
1339 :
1340 831 : rMedium.LockOrigFileOnDemand( false, false );
1341 :
1342 831 : if ( bStorageBasedTarget )
1343 : {
1344 101 : if ( rMedium.GetErrorCode() )
1345 0 : return false;
1346 :
1347 : // If the filter is a "cross export" filter ( f.e. a filter for exporting an impress document from
1348 : // a draw document ), the ClassId of the destination storage is different from the ClassId of this
1349 : // document. It can be retrieved from the default filter for the desired target format
1350 101 : SotClipboardFormatId nFormat = rMedium.GetFilter()->GetFormat();
1351 101 : SfxFilterMatcher& rMatcher = SfxGetpApp()->GetFilterMatcher();
1352 101 : const SfxFilter *pFilt = rMatcher.GetFilter4ClipBoardId( nFormat );
1353 101 : if ( pFilt )
1354 : {
1355 101 : if ( pFilt->GetServiceName() != rMedium.GetFilter()->GetServiceName() )
1356 : {
1357 25 : datatransfer::DataFlavor aDataFlavor;
1358 25 : SotExchange::GetFormatDataFlavor( nFormat, aDataFlavor );
1359 :
1360 : try
1361 : {
1362 25 : uno::Reference< beans::XPropertySet > xProps( rMedium.GetStorage(), uno::UNO_QUERY );
1363 : DBG_ASSERT( xProps.is(), "The storage implementation must implement XPropertySet!" );
1364 25 : if ( !xProps.is() )
1365 0 : throw uno::RuntimeException();
1366 :
1367 25 : xProps->setPropertyValue("MediaType",
1368 25 : uno::makeAny( aDataFlavor.MimeType ) );
1369 : }
1370 0 : catch( uno::Exception& )
1371 : {
1372 25 : }
1373 : }
1374 : }
1375 : }
1376 :
1377 : // TODO/LATER: error handling
1378 831 : if( rMedium.GetErrorCode() || pMedium->GetErrorCode() || GetErrorCode() )
1379 0 : return false;
1380 :
1381 831 : bool bOldStat = pImp->bForbidReload;
1382 831 : pImp->bForbidReload = true;
1383 :
1384 : // lock user interface while saving the document
1385 831 : Lock_Impl( this, true );
1386 :
1387 831 : bool bOk = false;
1388 : // TODO/LATER: get rid of bOk
1389 831 : if (bOwnTarget && pFilter && !(pFilter->GetFilterFlags() & SfxFilterFlags::STARONEFILTER))
1390 : {
1391 101 : AddLog( OUString( OSL_LOG_PREFIX "Storing in own format." ) );
1392 101 : uno::Reference< embed::XStorage > xMedStorage = rMedium.GetStorage();
1393 101 : if ( !xMedStorage.is() )
1394 : {
1395 : // no saving without storage, unlock UI and return
1396 0 : Lock_Impl( this, false );
1397 0 : pImp->bForbidReload = bOldStat;
1398 0 : AddLog( OUString( OSL_LOG_PREFIX "Storing failed, still no error set." ) );
1399 0 : return false;
1400 : }
1401 :
1402 : // transfer password from the parameters to the storage
1403 202 : uno::Sequence< beans::NamedValue > aEncryptionData;
1404 101 : bool bPasswdProvided = false;
1405 101 : if ( GetEncryptionData_Impl( rMedium.GetItemSet(), aEncryptionData ) )
1406 : {
1407 1 : bPasswdProvided = true;
1408 : try {
1409 1 : ::comphelper::OStorageHelper::SetCommonStorageEncryptionData( xMedStorage, aEncryptionData );
1410 1 : bOk = true;
1411 : }
1412 0 : catch( uno::Exception& )
1413 : {
1414 : SAL_WARN( "sfx.doc", "Setting of common encryption key failed!" );
1415 0 : SetError( ERRCODE_IO_GENERAL, OUString( OSL_LOG_PREFIX ) );
1416 : }
1417 : }
1418 : else
1419 100 : bOk = true;
1420 :
1421 101 : pFilter = rMedium.GetFilter();
1422 :
1423 202 : const SfxStringItem *pVersionItem = ( !rMedium.IsInCheckIn( ) && pSet )
1424 1 : ? static_cast<const SfxStringItem*>( SfxRequest::GetItem( pSet, SID_DOCINFO_COMMENTS, false, TYPE(SfxStringItem) ) )
1425 102 : : NULL;
1426 202 : OUString aTmpVersionURL;
1427 :
1428 101 : if ( bOk )
1429 : {
1430 101 : bOk = false;
1431 : // currently the case that the storage is the same should be impossible
1432 101 : if ( xMedStorage == GetStorage() )
1433 : {
1434 : OSL_ENSURE( !pVersionItem, "This scenario is impossible currently!\n" );
1435 0 : AddLog( OUString( OSL_LOG_PREFIX "Should be impossible." ) );
1436 : // usual save procedure
1437 0 : bOk = Save();
1438 : }
1439 : else
1440 : {
1441 : // save to target
1442 101 : AddLog( OUString( OSL_LOG_PREFIX "Save as own format." ) );
1443 101 : bOk = SaveAsOwnFormat( rMedium );
1444 101 : if ( bOk && pVersionItem )
1445 : {
1446 0 : AddLog( OUString( OSL_LOG_PREFIX "pVersionItem != NULL" ) );
1447 0 : aTmpVersionURL = CreateTempCopyOfStorage_Impl( xMedStorage );
1448 0 : bOk = !aTmpVersionURL.isEmpty();
1449 : }
1450 : }
1451 : }
1452 :
1453 : //fdo#61320: only store thumbnail image if the corresponding option is enabled in the configuration
1454 202 : if ( bOk && officecfg::Office::Common::Save::Document::GenerateThumbnail::get()
1455 202 : && GetCreateMode() != SfxObjectCreateMode::EMBEDDED && !bPasswdProvided )
1456 : {
1457 : // store the thumbnail representation image
1458 : // the thumbnail is not stored in case of encrypted document
1459 73 : AddLog( OUString( OSL_LOG_PREFIX "Thumbnail creation." ) );
1460 73 : if ( !GenerateAndStoreThumbnail( bPasswdProvided,
1461 73 : pFilter->IsOwnTemplateFormat(),
1462 73 : xMedStorage ) )
1463 : {
1464 : // TODO: error handling
1465 : SAL_WARN( "sfx.doc", "Couldn't store thumbnail representation!" );
1466 : }
1467 : }
1468 :
1469 101 : if ( bOk )
1470 : {
1471 101 : if ( pImp->bIsSaving || pImp->bPreserveVersions )
1472 : {
1473 101 : AddLog( OUString( OSL_LOG_PREFIX "Preserve versions." ) );
1474 : try
1475 : {
1476 101 : Sequence < util::RevisionTag > aVersions = rMedium.GetVersionList();
1477 101 : if ( aVersions.getLength() )
1478 : {
1479 : // copy the version streams
1480 0 : OUString aVersionsName( "Versions" );
1481 0 : uno::Reference< embed::XStorage > xNewVerStor = xMedStorage->openStorageElement(
1482 : aVersionsName,
1483 0 : embed::ElementModes::READWRITE );
1484 0 : uno::Reference< embed::XStorage > xOldVerStor = GetStorage()->openStorageElement(
1485 : aVersionsName,
1486 0 : embed::ElementModes::READ );
1487 0 : if ( !xNewVerStor.is() || !xOldVerStor.is() )
1488 0 : throw uno::RuntimeException();
1489 :
1490 0 : for ( sal_Int32 n=0; n<aVersions.getLength(); n++ )
1491 : {
1492 0 : if ( xOldVerStor->hasByName( aVersions[n].Identifier ) )
1493 0 : xOldVerStor->copyElementTo( aVersions[n].Identifier, xNewVerStor, aVersions[n].Identifier );
1494 : }
1495 :
1496 0 : uno::Reference< embed::XTransactedObject > xTransact( xNewVerStor, uno::UNO_QUERY );
1497 0 : if ( xTransact.is() )
1498 0 : xTransact->commit();
1499 101 : }
1500 : }
1501 0 : catch( uno::Exception& )
1502 : {
1503 0 : AddLog( OUString( OSL_LOG_PREFIX "Preserve versions has failed." ) );
1504 : SAL_WARN( "sfx.doc", "Couldn't copy versions!" );
1505 0 : bOk = false;
1506 : // TODO/LATER: a specific error could be set
1507 : }
1508 : }
1509 :
1510 101 : if ( bOk && pVersionItem && !rMedium.IsInCheckIn() )
1511 : {
1512 : // store a version also
1513 : const SfxStringItem *pAuthorItem = pSet
1514 0 : ? static_cast<const SfxStringItem*>( SfxRequest::GetItem( pSet, SID_DOCINFO_AUTHOR, false, TYPE(SfxStringItem) ) )
1515 0 : : NULL;
1516 :
1517 : // version comment
1518 0 : util::RevisionTag aInfo;
1519 0 : aInfo.Comment = pVersionItem->GetValue();
1520 :
1521 : // version author
1522 0 : if ( pAuthorItem )
1523 0 : aInfo.Author = pAuthorItem->GetValue();
1524 : else
1525 : // if not transferred as a parameter, get it from user settings
1526 0 : aInfo.Author = SvtUserOptions().GetFullName();
1527 :
1528 0 : DateTime aTime( DateTime::SYSTEM );
1529 0 : aInfo.TimeStamp.Day = aTime.GetDay();
1530 0 : aInfo.TimeStamp.Month = aTime.GetMonth();
1531 0 : aInfo.TimeStamp.Year = aTime.GetYear();
1532 0 : aInfo.TimeStamp.Hours = aTime.GetHour();
1533 0 : aInfo.TimeStamp.Minutes = aTime.GetMin();
1534 0 : aInfo.TimeStamp.Seconds = aTime.GetSec();
1535 :
1536 0 : if ( bOk )
1537 : {
1538 : // add new version information into the versionlist and save the versionlist
1539 : // the version list must have been transferred from the "old" medium before
1540 0 : rMedium.AddVersion_Impl( aInfo );
1541 0 : rMedium.SaveVersionList_Impl( true );
1542 0 : bOk = PutURLContentsToVersionStream_Impl( aTmpVersionURL, xMedStorage, aInfo.Identifier );
1543 0 : }
1544 : }
1545 101 : else if ( bOk && ( pImp->bIsSaving || pImp->bPreserveVersions ) )
1546 : {
1547 101 : rMedium.SaveVersionList_Impl( true );
1548 : }
1549 : }
1550 :
1551 101 : if ( !aTmpVersionURL.isEmpty() )
1552 101 : ::utl::UCBContentHelper::Kill( aTmpVersionURL );
1553 : }
1554 : else
1555 : {
1556 730 : AddLog( OUString( OSL_LOG_PREFIX "Storing in alien format." ) );
1557 : // it's a "SaveAs" in an alien format
1558 730 : if ( rMedium.GetFilter() && ( rMedium.GetFilter()->GetFilterFlags() & SfxFilterFlags::STARONEFILTER ) )
1559 659 : bOk = ExportTo( rMedium );
1560 : else
1561 71 : bOk = ConvertTo( rMedium );
1562 :
1563 : // after saving the document, the temporary object storage must be updated
1564 : // if the old object storage was not a temporary one, it will be updated also, because it will be used
1565 : // as a source for copying the objects into the new temporary storage that will be created below
1566 : // updating means: all child objects must be stored into it
1567 : // ( same as on loading, where these objects are copied to the temporary storage )
1568 : // but don't commit these changes, because in the case when the old object storage is not a temporary one,
1569 : // all changes will be written into the original file !
1570 :
1571 730 : if( bOk && !bCopyTo )
1572 : // we also don't touch any graphical replacements here
1573 3 : bOk = SaveChildren( true );
1574 : }
1575 :
1576 831 : if ( bOk )
1577 : {
1578 : // if ODF version of oasis format changes on saving the signature should not be preserved
1579 831 : if ( bOk && bTryToPreserveScriptSignature && bNoPreserveForOasis )
1580 0 : bTryToPreserveScriptSignature = ( SotStorage::GetVersion( rMedium.GetStorage() ) == SOFFICE_FILEFORMAT_60 );
1581 :
1582 831 : uno::Reference< security::XDocumentDigitalSignatures > xDDSigns;
1583 831 : if ( bOk && bTryToPreserveScriptSignature )
1584 : {
1585 0 : AddLog( OUString( OSL_LOG_PREFIX "Copying scripting signature." ) );
1586 :
1587 : // if the scripting code was not changed and it is signed the signature should be preserved
1588 : // unfortunately at this point we have only information whether the basic code has changed or not
1589 : // so the only way is to check the signature if the basic was not changed
1590 : try
1591 : {
1592 : // get the ODF version of the new medium
1593 0 : OUString aVersion;
1594 : try
1595 : {
1596 0 : uno::Reference < beans::XPropertySet > xPropSet( rMedium.GetStorage(), uno::UNO_QUERY_THROW );
1597 0 : xPropSet->getPropertyValue("Version") >>= aVersion;
1598 : }
1599 0 : catch( uno::Exception& )
1600 : {
1601 : }
1602 :
1603 0 : xDDSigns = security::DocumentDigitalSignatures::createWithVersion(comphelper::getProcessComponentContext(), aVersion);
1604 :
1605 0 : OUString aScriptSignName = xDDSigns->getScriptingContentSignatureDefaultStreamName();
1606 :
1607 0 : if ( !aScriptSignName.isEmpty() )
1608 : {
1609 0 : pMedium->Close();
1610 :
1611 : // target medium is still not committed, it should not be closed
1612 : // commit the package storage and close it, but leave the streams open
1613 0 : rMedium.StorageCommit_Impl();
1614 0 : rMedium.CloseStorage();
1615 :
1616 0 : uno::Reference< embed::XStorage > xReadOrig = pMedium->GetZipStorageToSign_Impl();
1617 0 : if ( !xReadOrig.is() )
1618 0 : throw uno::RuntimeException();
1619 0 : uno::Reference< embed::XStorage > xMetaInf = xReadOrig->openStorageElement(
1620 : OUString( "META-INF" ),
1621 0 : embed::ElementModes::READ );
1622 :
1623 0 : uno::Reference< embed::XStorage > xTarget = rMedium.GetZipStorageToSign_Impl( false );
1624 0 : if ( !xTarget.is() )
1625 0 : throw uno::RuntimeException();
1626 0 : uno::Reference< embed::XStorage > xTargetMetaInf = xTarget->openStorageElement(
1627 : OUString( "META-INF" ),
1628 0 : embed::ElementModes::READWRITE );
1629 :
1630 0 : if ( xMetaInf.is() && xTargetMetaInf.is() )
1631 : {
1632 0 : xMetaInf->copyElementTo( aScriptSignName, xTargetMetaInf, aScriptSignName );
1633 :
1634 0 : uno::Reference< embed::XTransactedObject > xTransact( xTargetMetaInf, uno::UNO_QUERY );
1635 0 : if ( xTransact.is() )
1636 0 : xTransact->commit();
1637 :
1638 0 : xTargetMetaInf->dispose();
1639 :
1640 : // now check the copied signature
1641 : uno::Sequence< security::DocumentSignatureInformation > aInfos =
1642 0 : xDDSigns->verifyScriptingContentSignatures( xTarget,
1643 0 : uno::Reference< io::XInputStream >() );
1644 0 : SignatureState nState = ImplCheckSignaturesInformation( aInfos );
1645 0 : if ( nState == SignatureState::OK || nState == SignatureState::NOTVALIDATED
1646 0 : || nState == SignatureState::PARTIAL_OK)
1647 : {
1648 0 : rMedium.SetCachedSignatureState_Impl( nState );
1649 :
1650 : // commit the ZipStorage from target medium
1651 0 : xTransact.set( xTarget, uno::UNO_QUERY );
1652 0 : if ( xTransact.is() )
1653 0 : xTransact->commit();
1654 : }
1655 : else
1656 : {
1657 : // it should not happen, the copies signature is invalid!
1658 : // throw the changes away
1659 : SAL_WARN( "sfx.doc", "An invalid signature was copied!" );
1660 0 : }
1661 0 : }
1662 0 : }
1663 : }
1664 0 : catch( uno::Exception& )
1665 : {
1666 : }
1667 :
1668 0 : pMedium->Close();
1669 0 : rMedium.CloseZipStorage_Impl();
1670 : }
1671 :
1672 831 : AddLog( OUString( OSL_LOG_PREFIX "Medium commit." ) );
1673 :
1674 1662 : OUString sName( rMedium.GetName( ) );
1675 831 : bOk = rMedium.Commit();
1676 1662 : OUString sNewName( rMedium.GetName( ) );
1677 :
1678 831 : if ( sName != sNewName )
1679 0 : GetMedium( )->SwitchDocumentToFile( sNewName );
1680 :
1681 831 : if ( bOk )
1682 : {
1683 831 : AddLog( OUString( OSL_LOG_PREFIX "Storing is successful." ) );
1684 :
1685 : // if the target medium is an alien format and the "old" medium was an own format and the "old" medium
1686 : // has a name, the object storage must be exchanged, because now we need a new temporary storage
1687 : // as object storage
1688 831 : if ( !bCopyTo && bStorageBasedSource && !bStorageBasedTarget )
1689 : {
1690 1 : if ( bStoreToSameLocation )
1691 : {
1692 : // if the old medium already disconnected from document storage, the storage still must
1693 : // be switched if backup file is used
1694 0 : if ( bNeedsDisconnectionOnFail )
1695 0 : ConnectTmpStorage_Impl( pImp->m_xDocStorage, NULL );
1696 : }
1697 2 : else if (!pMedium->GetName().isEmpty()
1698 1 : || ( pMedium->HasStorage_Impl() && pMedium->WillDisposeStorageOnClose_Impl() ) )
1699 : {
1700 : OSL_ENSURE(!pMedium->GetName().isEmpty(), "Fallback is used, the medium without name should not dispose the storage!\n");
1701 : // copy storage of old medium to new temporary storage and take this over
1702 0 : if( !ConnectTmpStorage_Impl( pMedium->GetStorage(), pMedium ) )
1703 : {
1704 0 : AddLog( OUString( OSL_LOG_PREFIX "Process after storing has failed." ) );
1705 0 : bOk = false;
1706 : }
1707 : }
1708 : }
1709 : }
1710 : else
1711 : {
1712 0 : AddLog( OUString( OSL_LOG_PREFIX "Storing has failed." ) );
1713 :
1714 : // in case the document storage was connected to backup temporarely it must be disconnected now
1715 0 : if ( bNeedsDisconnectionOnFail )
1716 0 : ConnectTmpStorage_Impl( pImp->m_xDocStorage, NULL );
1717 831 : }
1718 : }
1719 :
1720 : // unlock user interface
1721 831 : Lock_Impl( this, false );
1722 831 : pImp->bForbidReload = bOldStat;
1723 :
1724 831 : if ( bOk )
1725 : {
1726 : try
1727 : {
1728 833 : ::ucbhelper::Content aContent( rMedium.GetName(), com::sun::star::uno::Reference < XCommandEnvironment >(), comphelper::getProcessComponentContext() );
1729 1658 : com::sun::star::uno::Reference < XPropertySetInfo > xProps = aContent.getProperties();
1730 829 : if ( xProps.is() )
1731 : {
1732 829 : OUString aAuthor( "Author" );
1733 1658 : OUString aKeywords( "Keywords" );
1734 1658 : OUString aSubject( "Subject" );
1735 1658 : Any aAny;
1736 :
1737 : uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
1738 1658 : GetModel(), uno::UNO_QUERY_THROW);
1739 : uno::Reference<document::XDocumentProperties> xDocProps
1740 1658 : = xDPS->getDocumentProperties();
1741 :
1742 829 : if ( xProps->hasPropertyByName( aAuthor ) )
1743 : {
1744 0 : aAny <<= xDocProps->getAuthor();
1745 0 : aContent.setPropertyValue( aAuthor, aAny );
1746 : }
1747 829 : if ( xProps->hasPropertyByName( aKeywords ) )
1748 : {
1749 0 : aAny <<= ::comphelper::string::convertCommaSeparated(
1750 0 : xDocProps->getKeywords());
1751 0 : aContent.setPropertyValue( aKeywords, aAny );
1752 : }
1753 829 : if ( xProps->hasPropertyByName( aSubject ) )
1754 : {
1755 0 : aAny <<= xDocProps->getSubject();
1756 0 : aContent.setPropertyValue( aSubject, aAny );
1757 829 : }
1758 829 : }
1759 : }
1760 2 : catch( Exception& )
1761 : {
1762 : }
1763 : }
1764 :
1765 831 : return bOk;
1766 : }
1767 :
1768 :
1769 1 : bool SfxObjectShell::DisconnectStorage_Impl( SfxMedium& rSrcMedium, SfxMedium& rTargetMedium )
1770 : {
1771 : // this method disconnects the storage from source medium, and attaches it to the backup created by the target medium
1772 :
1773 1 : uno::Reference< embed::XStorage > xStorage = rSrcMedium.GetStorage();
1774 :
1775 1 : bool bResult = false;
1776 1 : if ( xStorage == pImp->m_xDocStorage )
1777 : {
1778 : try
1779 : {
1780 1 : uno::Reference< embed::XOptimizedStorage > xOptStorage( xStorage, uno::UNO_QUERY_THROW );
1781 2 : OUString aBackupURL = rTargetMedium.GetBackup_Impl();
1782 1 : if ( aBackupURL.isEmpty() )
1783 : {
1784 : // the backup could not be created, try to disconnect the storage and close the source SfxMedium
1785 : // in this case the optimization is not possible, connect storage to a temporary file
1786 0 : rTargetMedium.ResetError();
1787 0 : xOptStorage->writeAndAttachToStream( uno::Reference< io::XStream >() );
1788 0 : rSrcMedium.CanDisposeStorage_Impl( false );
1789 0 : rSrcMedium.Close();
1790 :
1791 : // now try to create the backup
1792 0 : rTargetMedium.GetBackup_Impl();
1793 : }
1794 : else
1795 : {
1796 : // the following call will only compare stream sizes
1797 : // TODO/LATER: this is a very risky part, since if the URL contents are different from the storage
1798 : // contents, the storag will be broken
1799 1 : xOptStorage->attachToURL( aBackupURL, sal_True );
1800 :
1801 : // the storage is successfully attached to backup, thus it is owned by the document not by the medium
1802 1 : rSrcMedium.CanDisposeStorage_Impl( false );
1803 1 : bResult = true;
1804 1 : }
1805 : }
1806 0 : catch ( uno::Exception& )
1807 : {}
1808 : }
1809 :
1810 1 : return bResult;
1811 : }
1812 :
1813 :
1814 :
1815 0 : bool SfxObjectShell::ConnectTmpStorage_Impl(
1816 : const uno::Reference< embed::XStorage >& xStorage,
1817 : SfxMedium* pMediumArg )
1818 :
1819 : /* [Description]
1820 :
1821 : If the application operates on a temporary storage, then it may not take
1822 : the temporary storage from the SaveCompleted. Therefore the new storage
1823 : is connected already here in this case and SaveCompleted then does nothing.
1824 : */
1825 :
1826 : {
1827 0 : bool bResult = false;
1828 :
1829 0 : if ( xStorage.is() )
1830 : {
1831 : try
1832 : {
1833 : // the empty argument means that the storage will create temporary stream itself
1834 0 : uno::Reference< embed::XOptimizedStorage > xOptStorage( xStorage, uno::UNO_QUERY_THROW );
1835 0 : xOptStorage->writeAndAttachToStream( uno::Reference< io::XStream >() );
1836 :
1837 : // the storage is successfully disconnected from the original sources, thus the medium must not dispose it
1838 0 : if ( pMediumArg )
1839 0 : pMediumArg->CanDisposeStorage_Impl( false );
1840 :
1841 0 : bResult = true;
1842 : }
1843 0 : catch( uno::Exception& )
1844 : {
1845 : }
1846 :
1847 : // if switching of the storage does not work for any reason ( nonroot storage for example ) use the old method
1848 0 : if ( !bResult ) try
1849 : {
1850 0 : uno::Reference< embed::XStorage > xTmpStorage = ::comphelper::OStorageHelper::GetTemporaryStorage();
1851 :
1852 : DBG_ASSERT( xTmpStorage.is(), "If a storage can not be created an exception must be thrown!\n" );
1853 0 : if ( !xTmpStorage.is() )
1854 0 : throw uno::RuntimeException();
1855 :
1856 : // TODO/LATER: may be it should be done in SwitchPersistence also
1857 : // TODO/LATER: find faster way to copy storage; perhaps sharing with backup?!
1858 0 : xStorage->copyToStorage( xTmpStorage );
1859 0 : bResult = SaveCompleted( xTmpStorage );
1860 :
1861 0 : if ( bResult )
1862 : {
1863 0 : pImp->aBasicManager.setStorage( xTmpStorage );
1864 :
1865 : // Get rid of this workaround after issue i113914 is fixed
1866 : try
1867 : {
1868 0 : uno::Reference< script::XStorageBasedLibraryContainer > xBasicLibraries( pImp->xBasicLibraries, uno::UNO_QUERY_THROW );
1869 0 : xBasicLibraries->setRootStorage( xTmpStorage );
1870 : }
1871 0 : catch( uno::Exception& )
1872 : {}
1873 : try
1874 : {
1875 0 : uno::Reference< script::XStorageBasedLibraryContainer > xDialogLibraries( pImp->xDialogLibraries, uno::UNO_QUERY_THROW );
1876 0 : xDialogLibraries->setRootStorage( xTmpStorage );
1877 : }
1878 0 : catch( uno::Exception& )
1879 : {}
1880 0 : }
1881 : }
1882 0 : catch( uno::Exception& )
1883 : {}
1884 :
1885 0 : if ( !bResult )
1886 : {
1887 : // TODO/LATER: may need error code setting based on exception
1888 0 : SetError( ERRCODE_IO_GENERAL, OUString( OSL_LOG_PREFIX ) );
1889 : }
1890 : }
1891 :
1892 0 : return bResult;
1893 : }
1894 :
1895 :
1896 :
1897 572 : bool SfxObjectShell::DoSaveObjectAs( SfxMedium& rMedium, bool bCommit )
1898 : {
1899 572 : bool bOk = false;
1900 :
1901 572 : ModifyBlocker_Impl aBlock( this );
1902 :
1903 1144 : uno::Reference < embed::XStorage > xNewStor = rMedium.GetStorage();
1904 572 : if ( !xNewStor.is() )
1905 0 : return false;
1906 :
1907 1144 : uno::Reference < beans::XPropertySet > xPropSet( xNewStor, uno::UNO_QUERY );
1908 572 : if ( !xPropSet.is() )
1909 0 : return false;
1910 :
1911 1144 : Any a = xPropSet->getPropertyValue("MediaType");
1912 1144 : OUString aMediaType;
1913 572 : if ( !(a>>=aMediaType) || aMediaType.isEmpty() )
1914 : {
1915 : SAL_WARN( "sfx.doc", "The mediatype must be set already!" );
1916 0 : SetupStorage( xNewStor, SOFFICE_FILEFORMAT_CURRENT, false, false );
1917 : }
1918 :
1919 572 : pImp->bIsSaving = false;
1920 572 : bOk = SaveAsOwnFormat( rMedium );
1921 :
1922 572 : if ( bCommit )
1923 : {
1924 : try {
1925 572 : uno::Reference< embed::XTransactedObject > xTransact( xNewStor, uno::UNO_QUERY_THROW );
1926 572 : xTransact->commit();
1927 : }
1928 0 : catch( uno::Exception& )
1929 : {
1930 : SAL_WARN( "sfx.doc", "The strotage was not committed on DoSaveAs!" );
1931 : }
1932 : }
1933 :
1934 1144 : return bOk;
1935 : }
1936 :
1937 :
1938 : // TODO/LATER: may be the call must be removed completelly
1939 129 : bool SfxObjectShell::DoSaveAs( SfxMedium& rMedium )
1940 : {
1941 : // here only root storages are included, which are stored via temp file
1942 129 : rMedium.CreateTempFileNoCopy();
1943 129 : SetError(rMedium.GetErrorCode(), OUString( OSL_LOG_PREFIX ) );
1944 129 : if ( GetError() )
1945 0 : return false;
1946 :
1947 : // copy version list from "old" medium to target medium, so it can be used on saving
1948 129 : if ( pImp->bPreserveVersions )
1949 129 : rMedium.TransferVersionList_Impl( *pMedium );
1950 :
1951 129 : bool bRet = SaveTo_Impl( rMedium, NULL );
1952 129 : if ( !bRet )
1953 0 : SetError(rMedium.GetErrorCode(), OUString( OSL_LOG_PREFIX ) );
1954 129 : return bRet;
1955 : }
1956 :
1957 :
1958 :
1959 1866 : bool SfxObjectShell::DoSaveCompleted( SfxMedium* pNewMed )
1960 : {
1961 1866 : bool bOk = true;
1962 1866 : bool bMedChanged = pNewMed && pNewMed!=pMedium;
1963 :
1964 : DBG_ASSERT( !pNewMed || pNewMed->GetError() == ERRCODE_NONE, "DoSaveCompleted: Medium has error!" );
1965 :
1966 : // delete Medium (and Storage!) after all notifications
1967 1866 : SfxMedium* pOld = pMedium;
1968 1866 : if ( bMedChanged )
1969 : {
1970 609 : pMedium = pNewMed;
1971 609 : pMedium->CanDisposeStorage_Impl( true );
1972 : }
1973 :
1974 1866 : const SfxFilter *pFilter = pMedium ? pMedium->GetFilter() : 0;
1975 1866 : if ( pNewMed )
1976 : {
1977 609 : if( bMedChanged )
1978 : {
1979 609 : if (!pNewMed->GetName().isEmpty())
1980 39 : bHasName = true;
1981 609 : Broadcast( SfxSimpleHint(SFX_HINT_NAMECHANGED) );
1982 609 : EnableSetModified(false);
1983 1218 : getDocProperties()->setGenerator(
1984 609 : ::utl::DocInfoHelper::GetGeneratorString() );
1985 609 : EnableSetModified(true);
1986 : }
1987 :
1988 609 : uno::Reference< embed::XStorage > xStorage;
1989 609 : if ( !pFilter || IsPackageStorageFormat_Impl( *pMedium ) )
1990 : {
1991 605 : uno::Reference < embed::XStorage > xOld = GetStorage();
1992 :
1993 : // when the package based medium is broken and has no storage or if the storage
1994 : // is the same as the document storage the current document storage should be preserved
1995 605 : xStorage = pMedium->GetStorage();
1996 605 : bOk = SaveCompleted( xStorage );
1997 2115 : if ( bOk && xStorage.is() && xOld != xStorage
1998 2120 : && (!pOld || !pOld->HasStorage_Impl() || xOld != pOld->GetStorage() ) )
1999 : {
2000 : // old own storage was not controlled by old Medium -> dispose it
2001 : try {
2002 300 : xOld->dispose();
2003 0 : } catch( uno::Exception& )
2004 : {
2005 : // the storage is disposed already
2006 : // can happen during reload scenario when the medium has
2007 : // disposed it during the closing
2008 : // will be fixed in one of the next milestones
2009 : }
2010 605 : }
2011 : }
2012 : else
2013 : {
2014 4 : if( pMedium->GetOpenMode() & StreamMode::WRITE )
2015 4 : pMedium->GetInStream();
2016 4 : xStorage = GetStorage();
2017 : }
2018 :
2019 : // TODO/LATER: may be this code will be replaced, but not sure
2020 : // Set storage in document library containers
2021 609 : pImp->aBasicManager.setStorage( xStorage );
2022 :
2023 : // Get rid of this workaround after issue i113914 is fixed
2024 : try
2025 : {
2026 609 : uno::Reference< script::XStorageBasedLibraryContainer > xBasicLibraries( pImp->xBasicLibraries, uno::UNO_QUERY_THROW );
2027 608 : xBasicLibraries->setRootStorage( xStorage );
2028 : }
2029 1 : catch( uno::Exception& )
2030 : {}
2031 : try
2032 : {
2033 609 : uno::Reference< script::XStorageBasedLibraryContainer > xDialogLibraries( pImp->xDialogLibraries, uno::UNO_QUERY_THROW );
2034 604 : xDialogLibraries->setRootStorage( xStorage );
2035 : }
2036 5 : catch( uno::Exception& )
2037 609 : {}
2038 : }
2039 : else
2040 : {
2041 1257 : if( pMedium )
2042 : {
2043 1257 : if( pFilter && !IsPackageStorageFormat_Impl( *pMedium ) && (pMedium->GetOpenMode() & StreamMode::WRITE ))
2044 : {
2045 561 : pMedium->ReOpen();
2046 561 : bOk = SaveCompletedChildren( false );
2047 : }
2048 : else
2049 696 : bOk = SaveCompleted( NULL );
2050 : }
2051 : // either Save or ConvertTo
2052 : else
2053 0 : bOk = SaveCompleted( NULL );
2054 : }
2055 :
2056 1866 : if ( bOk && pNewMed )
2057 : {
2058 609 : if( bMedChanged )
2059 : {
2060 609 : delete pOld;
2061 :
2062 609 : uno::Reference< frame::XModel > xModel = GetModel();
2063 609 : if ( xModel.is() )
2064 : {
2065 609 : OUString aURL = pNewMed->GetOrigURL();
2066 1218 : uno::Sequence< beans::PropertyValue > aMediaDescr;
2067 609 : TransformItems( SID_OPENDOC, *pNewMed->GetItemSet(), aMediaDescr );
2068 : try
2069 : {
2070 609 : xModel->attachResource( aURL, aMediaDescr );
2071 : }
2072 0 : catch( uno::Exception& )
2073 609 : {}
2074 : }
2075 :
2076 : // before the title regenerated the document must lose the signatures
2077 609 : pImp->nDocumentSignatureState = SignatureState::NOSIGNATURES;
2078 609 : pImp->nScriptingSignatureState = pNewMed->GetCachedSignatureState_Impl();
2079 : OSL_ENSURE( pImp->nScriptingSignatureState != SignatureState::BROKEN, "The signature must not be broken at this place" );
2080 609 : pImp->bSignatureErrorIsShown = false;
2081 :
2082 : // TODO/LATER: in future the medium must control own signature state, not the document
2083 609 : pNewMed->SetCachedSignatureState_Impl( SignatureState::NOSIGNATURES ); // set the default value back
2084 :
2085 : // Set new title
2086 609 : if (!pNewMed->GetName().isEmpty() && SfxObjectCreateMode::EMBEDDED != eCreateMode)
2087 38 : InvalidateName();
2088 609 : SetModified(false); // reset only by set medium
2089 609 : Broadcast( SfxSimpleHint(SFX_HINT_MODECHANGED) );
2090 :
2091 : // this is the end of the saving process, it is possible that
2092 : // the file was changed
2093 : // between medium commit and this step (attributes change and so on)
2094 : // so get the file date again
2095 609 : if ( pNewMed->DocNeedsFileDateCheck() )
2096 39 : pNewMed->GetInitFileDate( true );
2097 : }
2098 : }
2099 :
2100 1866 : pMedium->ClearBackup_Impl();
2101 1866 : pMedium->LockOrigFileOnDemand( true, false );
2102 :
2103 1866 : AddToRecentlyUsedList();
2104 :
2105 1866 : return bOk;
2106 : }
2107 :
2108 4283 : void SfxObjectShell::AddToRecentlyUsedList()
2109 : {
2110 4283 : INetURLObject aUrl( pMedium->GetOrigURL() );
2111 :
2112 4283 : if ( aUrl.GetProtocol() == INetProtocol::File )
2113 : {
2114 3136 : const SfxFilter* pOrgFilter = pMedium->GetOrigFilter();
2115 : Application::AddToRecentDocumentList( aUrl.GetURLNoPass( INetURLObject::NO_DECODE ),
2116 3136 : (pOrgFilter) ? pOrgFilter->GetMimeType() : OUString(),
2117 6272 : (pOrgFilter) ? pOrgFilter->GetServiceName() : OUString() );
2118 4283 : }
2119 4283 : }
2120 :
2121 :
2122 :
2123 0 : bool SfxObjectShell::ConvertFrom
2124 : (
2125 : SfxMedium& /*rMedium*/ /* <SfxMedium>, which describes the source file
2126 : (for example file name, <SfxFilter>,
2127 : Open-Modi and so on) */
2128 : )
2129 :
2130 : /* [Description]
2131 :
2132 : This method is called for loading of documents over all filters which are
2133 : not SfxFilterFlags::OWN or for which no clipboard format has been registered
2134 : (thus no storage format that is used). In other words, with this method
2135 : it is imported.
2136 :
2137 : Files which are to be opened here should be opened through 'rMedium'
2138 : to guarantee the right open modes. Especially if the format is retained
2139 : (only possible with SfxFilterFlags::SIMULATE or SfxFilterFlags::ONW) file which must
2140 : be opened STREAM_SHARE_DENYWRITE.
2141 :
2142 : [Return value]
2143 :
2144 : bool true
2145 : The document could be loaded.
2146 :
2147 : false
2148 : The document could not be loaded, an error code
2149 : received through <SvMedium::GetError()const>
2150 :
2151 : [Example]
2152 :
2153 : bool DocSh::ConvertFrom( SfxMedium &rMedium )
2154 : {
2155 : SvStreamRef xStream = rMedium.GetInStream();
2156 : if( xStream.is() )
2157 : {
2158 : xStream->SetBufferSize(4096);
2159 : *xStream >> ...;
2160 :
2161 : // Do not call 'rMedium.CloseInStream()'! Keep File locked!
2162 : return SVSTREAM_OK == rMedium.GetError();
2163 : }
2164 :
2165 : return false;
2166 : }
2167 :
2168 : [Cross-references]
2169 :
2170 : <SfxObjectShell::ConvertTo(SfxMedium&)>
2171 : <SfxFilterFlags::REGISTRATION>
2172 : */
2173 : {
2174 0 : return false;
2175 : }
2176 :
2177 2191 : bool SfxObjectShell::ImportFrom(SfxMedium& rMedium,
2178 : css::uno::Reference<css::text::XTextRange> const& xInsertPosition)
2179 : {
2180 2191 : OUString aFilterName( rMedium.GetFilter()->GetFilterName() );
2181 :
2182 4382 : uno::Reference< lang::XMultiServiceFactory > xMan = ::comphelper::getProcessServiceFactory();
2183 : uno::Reference < lang::XMultiServiceFactory > xFilterFact (
2184 4382 : xMan->createInstance( "com.sun.star.document.FilterFactory" ), uno::UNO_QUERY );
2185 :
2186 4382 : uno::Sequence < beans::PropertyValue > aProps;
2187 4382 : uno::Reference < container::XNameAccess > xFilters ( xFilterFact, uno::UNO_QUERY );
2188 2191 : if ( xFilters->hasByName( aFilterName ) )
2189 : {
2190 2191 : xFilters->getByName( aFilterName ) >>= aProps;
2191 2191 : rMedium.GetItemSet()->Put( SfxStringItem( SID_FILTER_NAME, aFilterName ) );
2192 : }
2193 :
2194 4382 : OUString aFilterImplName;
2195 2191 : sal_Int32 nFilterProps = aProps.getLength();
2196 26292 : for ( sal_Int32 nFilterProp = 0; nFilterProp<nFilterProps; nFilterProp++ )
2197 : {
2198 26292 : const beans::PropertyValue& rFilterProp = aProps[nFilterProp];
2199 26292 : if (rFilterProp.Name == "FilterService")
2200 : {
2201 2191 : rFilterProp.Value >>= aFilterImplName;
2202 2191 : break;
2203 : }
2204 : }
2205 :
2206 4382 : uno::Reference< document::XFilter > xLoader;
2207 2191 : if ( !aFilterImplName.isEmpty() )
2208 : {
2209 : try{
2210 4382 : xLoader = uno::Reference< document::XFilter >
2211 4382 : ( xFilterFact->createInstanceWithArguments( aFilterName, uno::Sequence < uno::Any >() ), uno::UNO_QUERY );
2212 0 : }catch(const uno::Exception&)
2213 0 : { xLoader.clear(); }
2214 : }
2215 2191 : if ( xLoader.is() )
2216 : {
2217 : // it happens that xLoader does not support xImporter!
2218 : try{
2219 2191 : uno::Reference< lang::XComponent > xComp( GetModel(), uno::UNO_QUERY_THROW );
2220 4382 : uno::Reference< document::XImporter > xImporter( xLoader, uno::UNO_QUERY_THROW );
2221 2191 : xImporter->setTargetDocument( xComp );
2222 :
2223 4382 : uno::Sequence < beans::PropertyValue > lDescriptor;
2224 2191 : rMedium.GetItemSet()->Put( SfxStringItem( SID_FILE_NAME, rMedium.GetName() ) );
2225 2191 : TransformItems( SID_OPENDOC, *rMedium.GetItemSet(), lDescriptor );
2226 :
2227 4382 : com::sun::star::uno::Sequence < com::sun::star::beans::PropertyValue > aArgs ( lDescriptor.getLength() );
2228 2191 : com::sun::star::beans::PropertyValue * pNewValue = aArgs.getArray();
2229 2191 : const com::sun::star::beans::PropertyValue * pOldValue = lDescriptor.getConstArray();
2230 4382 : const OUString sInputStream ( "InputStream" );
2231 :
2232 2191 : bool bHasInputStream = false;
2233 2191 : bool bHasBaseURL = false;
2234 : sal_Int32 i;
2235 2191 : sal_Int32 nEnd = lDescriptor.getLength();
2236 :
2237 25048 : for ( i = 0; i < nEnd; i++ )
2238 : {
2239 22857 : pNewValue[i] = pOldValue[i];
2240 22857 : if ( pOldValue [i].Name == sInputStream )
2241 2060 : bHasInputStream = true;
2242 20797 : else if ( pOldValue[i].Name == "DocumentBaseURL" )
2243 2191 : bHasBaseURL = true;
2244 : }
2245 :
2246 2191 : if ( !bHasInputStream )
2247 : {
2248 131 : aArgs.realloc ( ++nEnd );
2249 131 : aArgs[nEnd-1].Name = sInputStream;
2250 131 : aArgs[nEnd-1].Value <<= com::sun::star::uno::Reference < com::sun::star::io::XInputStream > ( new utl::OSeekableInputStreamWrapper ( *rMedium.GetInStream() ) );
2251 : }
2252 :
2253 2191 : if ( !bHasBaseURL )
2254 : {
2255 0 : aArgs.realloc ( ++nEnd );
2256 0 : aArgs[nEnd-1].Name = "DocumentBaseURL";
2257 0 : aArgs[nEnd-1].Value <<= rMedium.GetBaseURL();
2258 : }
2259 :
2260 2191 : if (xInsertPosition.is()) {
2261 0 : aArgs.realloc( ++nEnd );
2262 0 : aArgs[nEnd-1].Name = "InsertMode";
2263 0 : aArgs[nEnd-1].Value <<= true;
2264 0 : aArgs.realloc( ++nEnd );
2265 0 : aArgs[nEnd-1].Name = "TextInsertModeRange";
2266 0 : aArgs[nEnd-1].Value <<= xInsertPosition;
2267 : }
2268 :
2269 : // #i119492# During loading, some OLE objects like chart will be set
2270 : // modified flag, so needs to reset the flag to false after loading
2271 2191 : bool bRtn = xLoader->filter( aArgs );
2272 4378 : uno::Sequence < OUString > aNames = GetEmbeddedObjectContainer().GetObjectNames();
2273 3046 : for ( sal_Int32 n = 0; n < aNames.getLength(); ++n )
2274 : {
2275 857 : OUString aName = aNames[n];
2276 1714 : uno::Reference < embed::XEmbeddedObject > xObj = GetEmbeddedObjectContainer().GetEmbeddedObject( aName );
2277 : OSL_ENSURE( xObj.is(), "An empty entry in the embedded objects list!\n" );
2278 857 : if ( xObj.is() )
2279 : {
2280 857 : sal_Int32 nState = xObj->getCurrentState();
2281 857 : if ( nState == embed::EmbedStates::LOADED || nState == embed::EmbedStates::RUNNING ) // means that the object is not active
2282 : {
2283 857 : uno::Reference< util::XModifiable > xModifiable( xObj->getComponent(), uno::UNO_QUERY );
2284 857 : if ( xModifiable.is() )
2285 611 : xModifiable->setModified(sal_False);
2286 : }
2287 : }
2288 857 : }
2289 4380 : return bRtn;
2290 : }
2291 0 : catch (const packages::zip::ZipIOException&)
2292 : {
2293 0 : SetError( ERRCODE_IO_BROKENPACKAGE, "Badness in the underlying package format." );
2294 : }
2295 4 : catch (const lang::WrappedTargetRuntimeException& rWrapped)
2296 : {
2297 2 : io::WrongFormatException e;
2298 2 : if (rWrapped.TargetException >>= e)
2299 : {
2300 : SetError(*new StringErrorInfo(ERRCODE_SFX_FORMAT_ROWCOL,
2301 1 : e.Message, ERRCODE_BUTTON_OK | ERRCODE_MSG_ERROR ), "");
2302 2 : }
2303 : }
2304 0 : catch(...)
2305 : {}
2306 : }
2307 :
2308 2193 : return false;
2309 : }
2310 :
2311 659 : bool SfxObjectShell::ExportTo( SfxMedium& rMedium )
2312 : {
2313 659 : OUString aFilterName( rMedium.GetFilter()->GetFilterName() );
2314 1318 : uno::Reference< document::XExporter > xExporter;
2315 :
2316 : {
2317 659 : uno::Reference< lang::XMultiServiceFactory > xMan = ::comphelper::getProcessServiceFactory();
2318 : uno::Reference < lang::XMultiServiceFactory > xFilterFact (
2319 1318 : xMan->createInstance( "com.sun.star.document.FilterFactory" ), uno::UNO_QUERY );
2320 :
2321 1318 : uno::Sequence < beans::PropertyValue > aProps;
2322 1318 : uno::Reference < container::XNameAccess > xFilters ( xFilterFact, uno::UNO_QUERY );
2323 659 : if ( xFilters->hasByName( aFilterName ) )
2324 659 : xFilters->getByName( aFilterName ) >>= aProps;
2325 :
2326 1318 : OUString aFilterImplName;
2327 659 : sal_Int32 nFilterProps = aProps.getLength();
2328 7908 : for ( sal_Int32 nFilterProp = 0; nFilterProp<nFilterProps; nFilterProp++ )
2329 : {
2330 7908 : const beans::PropertyValue& rFilterProp = aProps[nFilterProp];
2331 7908 : if (rFilterProp.Name == "FilterService")
2332 : {
2333 659 : rFilterProp.Value >>= aFilterImplName;
2334 659 : break;
2335 : }
2336 : }
2337 :
2338 659 : if ( !aFilterImplName.isEmpty() )
2339 : {
2340 : try{
2341 1318 : xExporter = uno::Reference< document::XExporter >
2342 1318 : ( xFilterFact->createInstanceWithArguments( aFilterName, uno::Sequence < uno::Any >() ), uno::UNO_QUERY );
2343 0 : }catch(const uno::Exception&)
2344 0 : { xExporter.clear(); }
2345 659 : }
2346 : }
2347 :
2348 659 : if ( xExporter.is() )
2349 : {
2350 : try{
2351 659 : uno::Reference< lang::XComponent > xComp( GetModel(), uno::UNO_QUERY_THROW );
2352 1318 : uno::Reference< document::XFilter > xFilter( xExporter, uno::UNO_QUERY_THROW );
2353 659 : xExporter->setSourceDocument( xComp );
2354 :
2355 1318 : com::sun::star::uno::Sequence < com::sun::star::beans::PropertyValue > aOldArgs;
2356 659 : SfxItemSet* pItems = rMedium.GetItemSet();
2357 659 : TransformItems( SID_SAVEASDOC, *pItems, aOldArgs );
2358 :
2359 659 : const com::sun::star::beans::PropertyValue * pOldValue = aOldArgs.getConstArray();
2360 1318 : com::sun::star::uno::Sequence < com::sun::star::beans::PropertyValue > aArgs ( aOldArgs.getLength() );
2361 659 : com::sun::star::beans::PropertyValue * pNewValue = aArgs.getArray();
2362 :
2363 : // put in the REAL file name, and copy all PropertyValues
2364 1318 : const OUString sOutputStream ( "OutputStream" );
2365 1318 : const OUString sStream ( "StreamForOutput" );
2366 659 : bool bHasOutputStream = false;
2367 659 : bool bHasStream = false;
2368 659 : bool bHasBaseURL = false;
2369 659 : bool bHasFilterName = false;
2370 : sal_Int32 i;
2371 659 : sal_Int32 nEnd = aOldArgs.getLength();
2372 :
2373 4864 : for ( i = 0; i < nEnd; i++ )
2374 : {
2375 4205 : pNewValue[i] = pOldValue[i];
2376 4205 : if ( pOldValue[i].Name == "FileName" )
2377 0 : pNewValue[i].Value <<= OUString ( rMedium.GetName() );
2378 4205 : else if ( pOldValue[i].Name == sOutputStream )
2379 0 : bHasOutputStream = true;
2380 4205 : else if ( pOldValue[i].Name == sStream )
2381 0 : bHasStream = true;
2382 4205 : else if ( pOldValue[i].Name == "DocumentBaseURL" )
2383 0 : bHasBaseURL = true;
2384 4205 : else if( pOldValue[i].Name == "FilterName" )
2385 593 : bHasFilterName = true;
2386 : }
2387 :
2388 659 : if ( !bHasOutputStream )
2389 : {
2390 659 : aArgs.realloc ( ++nEnd );
2391 659 : aArgs[nEnd-1].Name = sOutputStream;
2392 659 : aArgs[nEnd-1].Value <<= com::sun::star::uno::Reference < com::sun::star::io::XOutputStream > ( new utl::OOutputStreamWrapper ( *rMedium.GetOutStream() ) );
2393 : }
2394 :
2395 : // add stream as well, for OOX export and maybe others
2396 659 : if ( !bHasStream )
2397 : {
2398 659 : aArgs.realloc ( ++nEnd );
2399 659 : aArgs[nEnd-1].Name = sStream;
2400 659 : aArgs[nEnd-1].Value <<= com::sun::star::uno::Reference < com::sun::star::io::XStream > ( new utl::OStreamWrapper ( *rMedium.GetOutStream() ) );
2401 : }
2402 :
2403 659 : if ( !bHasBaseURL )
2404 : {
2405 659 : aArgs.realloc ( ++nEnd );
2406 659 : aArgs[nEnd-1].Name = "DocumentBaseURL";
2407 659 : aArgs[nEnd-1].Value <<= rMedium.GetBaseURL( true );
2408 : }
2409 :
2410 659 : if( !bHasFilterName )
2411 : {
2412 66 : aArgs.realloc( ++nEnd );
2413 66 : aArgs[nEnd-1].Name = "FilterName";
2414 66 : aArgs[nEnd-1].Value <<= aFilterName;
2415 : }
2416 :
2417 1318 : return xFilter->filter( aArgs );
2418 0 : }catch(const uno::Exception&)
2419 : {}
2420 : }
2421 :
2422 659 : return false;
2423 : }
2424 :
2425 :
2426 :
2427 0 : bool SfxObjectShell::ConvertTo
2428 : (
2429 : SfxMedium& /*rMedium*/ /* <SfxMedium>, which describes the target file
2430 : (for example file name, <SfxFilter>,
2431 : Open-Modi and so on) */
2432 : )
2433 :
2434 : /* [Description]
2435 :
2436 : This method is called for saving of documents over all filters which are
2437 : not SfxFilterFlags::OWN or for which no clipboard format has been registered
2438 : (thus no storage format that is used). In other words, with this method
2439 : it is exported.
2440 :
2441 : Files which are to be opened here should be opened through 'rMedium'
2442 : to guarantee the right open modes. Especially if the format is retained
2443 : (only possible with SfxFilterFlags::SIMULATE or SfxFilterFlags::ONW) file which must
2444 : be opened STREAM_SHARE_DENYWRITE.
2445 :
2446 : [Return value]
2447 :
2448 : bool true
2449 : The document could be saved.
2450 :
2451 : false
2452 : The document could not be saved, an error code is
2453 : received by <SvMedium::GetError()const>
2454 :
2455 :
2456 : [Example]
2457 :
2458 : bool DocSh::ConvertTo( SfxMedium &rMedium )
2459 : {
2460 : SvStreamRef xStream = rMedium.GetOutStream();
2461 : if ( xStream.is() )
2462 : {
2463 : xStream->SetBufferSize(4096);
2464 : *xStream << ...;
2465 :
2466 : rMedium.CloseOutStream(); // opens the InStream automatically
2467 : return SVSTREAM_OK == rMedium.GetError();
2468 : }
2469 : return false ;
2470 : }
2471 :
2472 : [Cross-references]
2473 :
2474 : <SfxObjectShell::ConvertFrom(SfxMedium&)>
2475 : <SfxFilterFlags::REGISTRATION>
2476 : */
2477 :
2478 : {
2479 0 : return false;
2480 : }
2481 :
2482 :
2483 :
2484 2 : bool SfxObjectShell::DoSave_Impl( const SfxItemSet* pArgs )
2485 : {
2486 2 : SfxMedium* pRetrMedium = GetMedium();
2487 2 : const SfxFilter* pFilter = pRetrMedium->GetFilter();
2488 :
2489 : // copy the original itemset, but remove the "version" item, because pMediumTmp
2490 : // is a new medium "from scratch", so no version should be stored into it
2491 2 : SfxItemSet* pSet = new SfxAllItemSet(*pRetrMedium->GetItemSet());
2492 2 : pSet->ClearItem( SID_VERSION );
2493 2 : pSet->ClearItem( SID_DOC_BASEURL );
2494 :
2495 : // copy the version comment and major items for the checkin only
2496 2 : if ( pRetrMedium->IsInCheckIn( ) )
2497 : {
2498 0 : const SfxPoolItem* pMajor = pArgs->GetItem( SID_DOCINFO_MAJOR );
2499 0 : if ( pMajor )
2500 0 : pSet->Put( *pMajor );
2501 :
2502 0 : const SfxPoolItem* pComments = pArgs->GetItem( SID_DOCINFO_COMMENTS );
2503 0 : if ( pComments )
2504 0 : pSet->Put( *pComments );
2505 : }
2506 :
2507 : // create a medium as a copy; this medium is only for writingm, because it
2508 : // uses the same name as the original one writing is done through a copy,
2509 : // that will be transferred to the target (of course after calling HandsOff)
2510 2 : SfxMedium* pMediumTmp = new SfxMedium( pRetrMedium->GetName(), pRetrMedium->GetOpenMode(), pFilter, pSet );
2511 2 : pMediumTmp->SetInCheckIn( pRetrMedium->IsInCheckIn( ) );
2512 2 : pMediumTmp->SetLongName( pRetrMedium->GetLongName() );
2513 2 : if ( pMediumTmp->GetErrorCode() != ERRCODE_NONE )
2514 : {
2515 0 : SetError( pMediumTmp->GetError(), OUString( OSL_LOG_PREFIX ) );
2516 0 : delete pMediumTmp;
2517 0 : return false;
2518 : }
2519 :
2520 : // copy version list from "old" medium to target medium, so it can be used on saving
2521 2 : pMediumTmp->TransferVersionList_Impl( *pRetrMedium );
2522 :
2523 : // an interaction handler here can acquire only in case of GUI Saving
2524 : // and should be removed after the saving is done
2525 2 : com::sun::star::uno::Reference< XInteractionHandler > xInteract;
2526 2 : SFX_ITEMSET_ARG( pArgs, pxInteractionItem, SfxUnoAnyItem, SID_INTERACTIONHANDLER, false );
2527 2 : if ( pxInteractionItem && ( pxInteractionItem->GetValue() >>= xInteract ) && xInteract.is() )
2528 1 : pMediumTmp->GetItemSet()->Put( SfxUnoAnyItem( SID_INTERACTIONHANDLER, makeAny( xInteract ) ) );
2529 :
2530 2 : bool bSaved = false;
2531 2 : if( !GetError() && SaveTo_Impl( *pMediumTmp, pArgs ) )
2532 : {
2533 2 : bSaved = true;
2534 :
2535 2 : if( pMediumTmp->GetItemSet() )
2536 : {
2537 2 : pMediumTmp->GetItemSet()->ClearItem( SID_INTERACTIONHANDLER );
2538 2 : pMediumTmp->GetItemSet()->ClearItem( SID_PROGRESS_STATUSBAR_CONTROL );
2539 : }
2540 :
2541 2 : SetError(pMediumTmp->GetErrorCode(), OUString( OSL_LOG_PREFIX ) );
2542 :
2543 2 : bool bOpen( false );
2544 2 : bOpen = DoSaveCompleted( pMediumTmp );
2545 :
2546 : DBG_ASSERT(bOpen,"Error handling for DoSaveCompleted not implemented");
2547 : (void)bOpen;
2548 : }
2549 : else
2550 : {
2551 : // transfer error code from medium to objectshell
2552 0 : SetError( pMediumTmp->GetError(), OUString( OSL_LOG_PREFIX ) );
2553 :
2554 : // reconnect to object storage
2555 0 : DoSaveCompleted( 0 );
2556 :
2557 0 : if( pRetrMedium->GetItemSet() )
2558 : {
2559 0 : pRetrMedium->GetItemSet()->ClearItem( SID_INTERACTIONHANDLER );
2560 0 : pRetrMedium->GetItemSet()->ClearItem( SID_PROGRESS_STATUSBAR_CONTROL );
2561 : }
2562 :
2563 0 : delete pMediumTmp;
2564 : }
2565 :
2566 2 : SetModified( !bSaved );
2567 2 : return bSaved;
2568 : }
2569 :
2570 :
2571 :
2572 2 : bool SfxObjectShell::Save_Impl( const SfxItemSet* pSet )
2573 : {
2574 2 : if ( IsReadOnly() )
2575 : {
2576 0 : SetError( ERRCODE_SFX_DOCUMENTREADONLY, OUString( OSL_LOG_PREFIX ) );
2577 0 : return false;
2578 : }
2579 :
2580 :
2581 2 : pImp->bIsSaving = true;
2582 2 : bool bSaved = false;
2583 2 : SFX_ITEMSET_ARG( GetMedium()->GetItemSet(), pSalvageItem, SfxStringItem, SID_DOC_SALVAGE, false);
2584 2 : if ( pSalvageItem )
2585 : {
2586 0 : SFX_ITEMSET_ARG( GetMedium()->GetItemSet(), pFilterItem, SfxStringItem, SID_FILTER_NAME, false);
2587 0 : OUString aFilterName;
2588 0 : const SfxFilter *pFilter = NULL;
2589 0 : if ( pFilterItem )
2590 0 : pFilter = SfxFilterMatcher( OUString::createFromAscii( GetFactory().GetShortName()) ).GetFilter4FilterName( aFilterName );
2591 :
2592 : SfxMedium *pMed = new SfxMedium(
2593 0 : pSalvageItem->GetValue(), STREAM_READWRITE | StreamMode::SHARE_DENYWRITE | StreamMode::TRUNC, pFilter );
2594 :
2595 0 : SFX_ITEMSET_ARG( GetMedium()->GetItemSet(), pPasswordItem, SfxStringItem, SID_PASSWORD, false );
2596 0 : if ( pPasswordItem )
2597 0 : pMed->GetItemSet()->Put( *pPasswordItem );
2598 :
2599 0 : bSaved = DoSaveAs( *pMed );
2600 0 : if ( bSaved )
2601 0 : bSaved = DoSaveCompleted( pMed );
2602 : else
2603 0 : delete pMed;
2604 : }
2605 : else
2606 2 : bSaved = DoSave_Impl( pSet );
2607 2 : return bSaved;
2608 : }
2609 :
2610 :
2611 :
2612 700 : bool SfxObjectShell::CommonSaveAs_Impl
2613 : (
2614 : const INetURLObject& aURL,
2615 : const OUString& aFilterName,
2616 : SfxItemSet* aParams
2617 : )
2618 : {
2619 700 : if( aURL.HasError() )
2620 : {
2621 0 : SetError( ERRCODE_IO_INVALIDPARAMETER, OUString( OSL_LOG_PREFIX ) );
2622 0 : return false;
2623 : }
2624 :
2625 700 : if ( aURL != INetURLObject( OUString( "private:stream" ) ) )
2626 : {
2627 : // Is there already a Document with this name?
2628 698 : SfxObjectShell* pDoc = 0;
2629 1392 : for ( SfxObjectShell* pTmp = SfxObjectShell::GetFirst();
2630 694 : pTmp && !pDoc;
2631 : pTmp = SfxObjectShell::GetNext(*pTmp) )
2632 : {
2633 694 : if( ( pTmp != this ) && pTmp->GetMedium() )
2634 : {
2635 18 : INetURLObject aCompare( pTmp->GetMedium()->GetName() );
2636 18 : if ( aCompare == aURL )
2637 0 : pDoc = pTmp;
2638 : }
2639 : }
2640 698 : if ( pDoc )
2641 : {
2642 : // Then error message: "already opened"
2643 0 : SetError(ERRCODE_SFX_ALREADYOPEN, OUString( OSL_LOG_PREFIX ));
2644 0 : return false;
2645 : }
2646 : }
2647 :
2648 : DBG_ASSERT( aURL.GetProtocol() != INetProtocol::NotValid, "Illegal URL!" );
2649 : DBG_ASSERT( aParams->Count() != 0, "Incorrect Parameter");
2650 :
2651 700 : SFX_ITEMSET_ARG( aParams, pSaveToItem, SfxBoolItem, SID_SAVETO, false );
2652 700 : bool bSaveTo = pSaveToItem && pSaveToItem->GetValue();
2653 :
2654 700 : const SfxFilter* pFilter = GetFactory().GetFilterContainer()->GetFilter4FilterName( aFilterName );
2655 700 : if ( !pFilter
2656 700 : || !pFilter->CanExport()
2657 1400 : || (!bSaveTo && !pFilter->CanImport()) )
2658 : {
2659 0 : SetError( ERRCODE_IO_INVALIDPARAMETER, OUString( OSL_LOG_PREFIX ) );
2660 0 : return false;
2661 : }
2662 :
2663 700 : SFX_ITEMSET_ARG( aParams, pCopyStreamItem, SfxBoolItem, SID_COPY_STREAM_IF_POSSIBLE, false );
2664 700 : if ( bSaveTo && pCopyStreamItem && pCopyStreamItem->GetValue() && !IsModified() )
2665 : {
2666 0 : if ( pMedium->TryDirectTransfer( aURL.GetMainURL( INetURLObject::NO_DECODE ), *aParams ) )
2667 0 : return true;
2668 : }
2669 700 : aParams->ClearItem( SID_COPY_STREAM_IF_POSSIBLE );
2670 :
2671 700 : pImp->bPasswd = SfxItemState::SET == aParams->GetItemState(SID_PASSWORD);
2672 :
2673 700 : SfxMedium *pActMed = GetMedium();
2674 700 : const INetURLObject aActName(pActMed->GetName());
2675 :
2676 700 : bool bWasReadonly = IsReadOnly();
2677 :
2678 1400 : if ( aURL == aActName && aURL != INetURLObject( OUString("private:stream") )
2679 1400 : && IsReadOnly() )
2680 : {
2681 0 : SetError(ERRCODE_SFX_DOCUMENTREADONLY, OUString( OSL_LOG_PREFIX ));
2682 0 : return false;
2683 : }
2684 :
2685 700 : if( SfxItemState::SET != aParams->GetItemState(SID_UNPACK) && SvtSaveOptions().IsSaveUnpacked() )
2686 0 : aParams->Put( SfxBoolItem( SID_UNPACK, false ) );
2687 :
2688 1400 : OUString aTempFileURL;
2689 700 : if ( IsDocShared() )
2690 0 : aTempFileURL = pMedium->GetURLObject().GetMainURL( INetURLObject::NO_DECODE );
2691 :
2692 700 : if ( PreDoSaveAs_Impl(aURL.GetMainURL( INetURLObject::NO_DECODE ),aFilterName,aParams))
2693 : {
2694 : // Update Data on media
2695 700 : SfxItemSet *pSet = GetMedium()->GetItemSet();
2696 700 : pSet->ClearItem( SID_INTERACTIONHANDLER );
2697 700 : pSet->ClearItem( SID_PROGRESS_STATUSBAR_CONTROL );
2698 700 : pSet->ClearItem( SID_STANDARD_DIR );
2699 700 : pSet->ClearItem( SID_PATH );
2700 :
2701 700 : if ( !bSaveTo )
2702 : {
2703 15 : pSet->ClearItem( SID_REFERER );
2704 15 : pSet->ClearItem( SID_POSTDATA );
2705 15 : pSet->ClearItem( SID_TEMPLATE );
2706 15 : pSet->ClearItem( SID_DOC_READONLY );
2707 15 : pSet->ClearItem( SID_CONTENTTYPE );
2708 15 : pSet->ClearItem( SID_CHARSET );
2709 15 : pSet->ClearItem( SID_FILTER_NAME );
2710 15 : pSet->ClearItem( SID_OPTIONS );
2711 15 : pSet->ClearItem( SID_VERSION );
2712 15 : pSet->ClearItem( SID_EDITDOC );
2713 15 : pSet->ClearItem( SID_OVERWRITE );
2714 15 : pSet->ClearItem( SID_DEFAULTFILEPATH );
2715 15 : pSet->ClearItem( SID_DEFAULTFILENAME );
2716 :
2717 15 : SFX_ITEMSET_GET( (*aParams), pFilterItem, SfxStringItem, SID_FILTER_NAME, false );
2718 15 : if ( pFilterItem )
2719 15 : pSet->Put( *pFilterItem );
2720 :
2721 15 : SFX_ITEMSET_GET( (*aParams), pOptionsItem, SfxStringItem, SID_OPTIONS, false );
2722 15 : if ( pOptionsItem )
2723 0 : pSet->Put( *pOptionsItem );
2724 :
2725 15 : SFX_ITEMSET_GET( (*aParams), pFilterOptItem, SfxStringItem, SID_FILE_FILTEROPTIONS, false );
2726 15 : if ( pFilterOptItem )
2727 0 : pSet->Put( *pFilterOptItem );
2728 :
2729 : #if HAVE_FEATURE_MULTIUSER_ENVIRONMENT
2730 15 : if ( IsDocShared() && !aTempFileURL.isEmpty() )
2731 : {
2732 : // this is a shared document that has to be disconnected from the old location
2733 0 : FreeSharedFile( aTempFileURL );
2734 :
2735 0 : if ( pFilter->IsOwnFormat()
2736 0 : && pFilter->UsesStorage()
2737 0 : && pFilter->GetVersion() >= SOFFICE_FILEFORMAT_60 )
2738 : {
2739 : // the target format is the own format
2740 : // the target document must be shared
2741 0 : SwitchToShared( true, false );
2742 : }
2743 : }
2744 : #endif
2745 : }
2746 :
2747 700 : if ( bWasReadonly && !bSaveTo )
2748 0 : Broadcast( SfxSimpleHint(SFX_HINT_MODECHANGED) );
2749 :
2750 700 : return true;
2751 : }
2752 : else
2753 700 : return false;
2754 : }
2755 :
2756 :
2757 :
2758 700 : bool SfxObjectShell::PreDoSaveAs_Impl
2759 : (
2760 : const OUString& rFileName,
2761 : const OUString& aFilterName,
2762 : SfxItemSet* pParams
2763 : )
2764 : {
2765 : // copy all items stored in the itemset of the current medium
2766 700 : SfxAllItemSet* pMergedParams = new SfxAllItemSet( *pMedium->GetItemSet() );
2767 :
2768 : // in "SaveAs" title and password will be cleared ( maybe the new itemset contains new values, otherwise they will be empty )
2769 700 : pMergedParams->ClearItem( SID_ENCRYPTIONDATA );
2770 700 : pMergedParams->ClearItem( SID_PASSWORD );
2771 : // #i119366# - As the SID_ENCRYPTIONDATA and SID_PASSWORD are using for setting password together, we need to clear them both.
2772 : // Also, ( maybe the new itemset contains new values, otherwise they will be empty )
2773 700 : pMergedParams->ClearItem( SID_ENCRYPTIONDATA );
2774 700 : pMergedParams->ClearItem( SID_DOCINFO_TITLE );
2775 :
2776 700 : pMergedParams->ClearItem( SID_INPUTSTREAM );
2777 700 : pMergedParams->ClearItem( SID_STREAM );
2778 700 : pMergedParams->ClearItem( SID_CONTENT );
2779 700 : pMergedParams->ClearItem( SID_DOC_READONLY );
2780 700 : pMergedParams->ClearItem( SID_DOC_BASEURL );
2781 :
2782 700 : pMergedParams->ClearItem( SID_REPAIRPACKAGE );
2783 :
2784 : // "SaveAs" will never store any version information - it's a complete new file !
2785 700 : pMergedParams->ClearItem( SID_VERSION );
2786 :
2787 : // merge the new parameters into the copy
2788 : // all values present in both itemsets will be overwritten by the new parameters
2789 700 : if( pParams )
2790 700 : pMergedParams->Put( *pParams );
2791 :
2792 : #ifdef DBG_UTIL
2793 : if ( pMergedParams->GetItemState( SID_DOC_SALVAGE) >= SfxItemState::SET )
2794 : SAL_WARN( "sfx.doc","Salvage item present in Itemset, check the parameters!");
2795 : #endif
2796 :
2797 : // should be unnecessary - too hot to handle!
2798 700 : pMergedParams->ClearItem( SID_DOC_SALVAGE );
2799 :
2800 : // take over the new merged itemset
2801 700 : pParams = pMergedParams;
2802 :
2803 : // create a medium for the target URL
2804 700 : SfxMedium *pNewFile = new SfxMedium( rFileName, STREAM_READWRITE | StreamMode::SHARE_DENYWRITE | StreamMode::TRUNC, 0, pParams );
2805 :
2806 : // set filter; if no filter is given, take the default filter of the factory
2807 700 : if ( !aFilterName.isEmpty() )
2808 700 : pNewFile->SetFilter( GetFactory().GetFilterContainer()->GetFilter4FilterName( aFilterName ) );
2809 : else
2810 0 : pNewFile->SetFilter( GetFactory().GetFilterContainer()->GetAnyFilter( SfxFilterFlags::IMPORT | SfxFilterFlags::EXPORT ) );
2811 :
2812 700 : if ( pNewFile->GetErrorCode() != ERRCODE_NONE )
2813 : {
2814 : // creating temporary file failed ( f.e. floppy disk not inserted! )
2815 0 : SetError( pNewFile->GetError(), OUString( OSL_LOG_PREFIX ) );
2816 0 : delete pNewFile;
2817 0 : return false;
2818 : }
2819 :
2820 : // check if a "SaveTo" is wanted, no "SaveAs"
2821 700 : SFX_ITEMSET_ARG( pParams, pSaveToItem, SfxBoolItem, SID_SAVETO, false );
2822 700 : bool bCopyTo = GetCreateMode() == SfxObjectCreateMode::EMBEDDED || (pSaveToItem && pSaveToItem->GetValue());
2823 :
2824 : // distinguish between "Save" and "SaveAs"
2825 700 : pImp->bIsSaving = false;
2826 :
2827 : // copy version list from "old" medium to target medium, so it can be used on saving
2828 700 : if ( pImp->bPreserveVersions )
2829 700 : pNewFile->TransferVersionList_Impl( *pMedium );
2830 :
2831 : // Save the document ( first as temporary file, then transfer to the target URL by committing the medium )
2832 700 : bool bOk = false;
2833 700 : if ( !pNewFile->GetErrorCode() && SaveTo_Impl( *pNewFile, NULL ) )
2834 : {
2835 700 : bOk = true;
2836 :
2837 : // transfer a possible error from the medium to the document
2838 700 : SetError( pNewFile->GetErrorCode(), OUString( OSL_LOG_PREFIX ) );
2839 :
2840 : // notify the document that saving was done successfully
2841 700 : if ( !bCopyTo )
2842 : {
2843 15 : bOk = DoSaveCompleted( pNewFile );
2844 : }
2845 : else
2846 685 : bOk = DoSaveCompleted(0);
2847 :
2848 700 : if( bOk )
2849 : {
2850 700 : if( !bCopyTo )
2851 15 : SetModified( false );
2852 : }
2853 : else
2854 : {
2855 : // TODO/LATER: the code below must be dead since the storage commit makes all the stuff
2856 : // and the DoSaveCompleted call should not be able to fail in general
2857 :
2858 : DBG_ASSERT( !bCopyTo, "Error while reconnecting to medium, can't be handled!");
2859 0 : SetError( pNewFile->GetErrorCode(), OUString( OSL_LOG_PREFIX ) );
2860 :
2861 0 : if ( !bCopyTo )
2862 : {
2863 : // reconnect to the old medium
2864 0 : bool bRet( false );
2865 0 : bRet = DoSaveCompleted( pMedium );
2866 : DBG_ASSERT( bRet, "Error in DoSaveCompleted, can't be handled!");
2867 : (void)bRet;
2868 : }
2869 :
2870 : // TODO/LATER: disconnect the new file from the storage for the case when pure saving is done
2871 : // if storing has corrupted the file, probably it must be restored either here or
2872 : // by the storage
2873 0 : DELETEZ( pNewFile );
2874 : }
2875 : }
2876 : else
2877 : {
2878 0 : SetError( pNewFile->GetErrorCode(), OUString( OSL_LOG_PREFIX ) );
2879 :
2880 : // reconnect to the old storage
2881 0 : DoSaveCompleted( 0 );
2882 :
2883 0 : DELETEZ( pNewFile );
2884 : }
2885 :
2886 700 : if ( bCopyTo )
2887 685 : DELETEZ( pNewFile );
2888 15 : else if( !bOk )
2889 0 : SetModified( true );
2890 :
2891 700 : return bOk;
2892 : }
2893 :
2894 :
2895 :
2896 0 : bool SfxObjectShell::LoadFrom( SfxMedium& /*rMedium*/ )
2897 : {
2898 : SAL_WARN( "sfx.doc", "Base implementation, must not be called in general!" );
2899 0 : return true;
2900 : }
2901 :
2902 :
2903 0 : bool SfxObjectShell::IsInformationLost()
2904 : {
2905 0 : Sequence< PropertyValue > aProps = GetModel()->getArgs();
2906 0 : OUString aFilterName;
2907 0 : OUString aPreusedFilterName;
2908 0 : for ( sal_Int32 nInd = 0; nInd < aProps.getLength(); nInd++ )
2909 : {
2910 0 : if ( aProps[nInd].Name == "FilterName" )
2911 0 : aProps[nInd].Value >>= aFilterName;
2912 0 : else if ( aProps[nInd].Name == "PreusedFilterName" )
2913 0 : aProps[nInd].Value >>= aPreusedFilterName;
2914 : }
2915 :
2916 : // if current filter can lead to information loss and it was used
2917 : // for the latest store then the user should be asked to store in own format
2918 0 : if ( !aFilterName.isEmpty() && aFilterName.equals( aPreusedFilterName ) )
2919 : {
2920 0 : const SfxFilter *pFilt = GetMedium()->GetFilter();
2921 : DBG_ASSERT( pFilt && aFilterName.equals( pFilt->GetName() ), "MediaDescriptor contains wrong filter!\n" );
2922 0 : return ( pFilt && pFilt->IsAlienFormat() );
2923 : }
2924 :
2925 0 : return false;
2926 : }
2927 :
2928 :
2929 0 : bool SfxObjectShell::CanReload_Impl()
2930 :
2931 : /* [Description]
2932 :
2933 : Internal method for determining whether a reload of the document
2934 : (as RevertToSaved or last known version) is possible.
2935 : */
2936 :
2937 : {
2938 0 : return pMedium && HasName() && !IsInModalMode() && !pImp->bForbidReload;
2939 : }
2940 :
2941 :
2942 :
2943 0 : HiddenInformation SfxObjectShell::GetHiddenInformationState( HiddenInformation nStates )
2944 : {
2945 0 : HiddenInformation nState = HiddenInformation::NONE;
2946 0 : if ( nStates & HiddenInformation::DOCUMENTVERSIONS )
2947 : {
2948 0 : if ( GetMedium()->GetVersionList().getLength() )
2949 0 : nState |= HiddenInformation::DOCUMENTVERSIONS;
2950 : }
2951 :
2952 0 : return nState;
2953 : }
2954 :
2955 1 : sal_Int16 SfxObjectShell::QueryHiddenInformation( HiddenWarningFact eFact, vcl::Window* pParent )
2956 : {
2957 1 : sal_Int16 nRet = RET_YES;
2958 1 : sal_uInt16 nResId = sal_uInt16();
2959 1 : SvtSecurityOptions::EOption eOption = SvtSecurityOptions::EOption();
2960 :
2961 1 : switch ( eFact )
2962 : {
2963 : case HiddenWarningFact::WhenSaving :
2964 : {
2965 1 : nResId = STR_HIDDENINFO_CONTINUE_SAVING;
2966 1 : eOption = SvtSecurityOptions::E_DOCWARN_SAVEORSEND;
2967 1 : break;
2968 : }
2969 : case HiddenWarningFact::WhenPrinting :
2970 : {
2971 0 : nResId = STR_HIDDENINFO_CONTINUE_PRINTING;
2972 0 : eOption = SvtSecurityOptions::E_DOCWARN_PRINT;
2973 0 : break;
2974 : }
2975 : case HiddenWarningFact::WhenSigning :
2976 : {
2977 0 : nResId = STR_HIDDENINFO_CONTINUE_SIGNING;
2978 0 : eOption = SvtSecurityOptions::E_DOCWARN_SIGNING;
2979 0 : break;
2980 : }
2981 : case HiddenWarningFact::WhenCreatingPDF :
2982 : {
2983 0 : nResId = STR_HIDDENINFO_CONTINUE_CREATEPDF;
2984 0 : eOption = SvtSecurityOptions::E_DOCWARN_CREATEPDF;
2985 0 : break;
2986 : }
2987 : default:
2988 : assert(false); // this cannot happen
2989 : }
2990 :
2991 1 : if ( SvtSecurityOptions().IsOptionSet( eOption ) )
2992 : {
2993 0 : OUString sMessage( SfxResId(STR_HIDDENINFO_CONTAINS).toString() );
2994 0 : HiddenInformation nWantedStates = HiddenInformation::RECORDEDCHANGES | HiddenInformation::NOTES;
2995 0 : if ( eFact != HiddenWarningFact::WhenPrinting )
2996 0 : nWantedStates |= HiddenInformation::DOCUMENTVERSIONS;
2997 0 : HiddenInformation nStates = GetHiddenInformationState( nWantedStates );
2998 0 : bool bWarning = false;
2999 :
3000 0 : if ( nStates & HiddenInformation::RECORDEDCHANGES )
3001 : {
3002 0 : sMessage += SfxResId(STR_HIDDENINFO_RECORDCHANGES).toString();
3003 0 : sMessage += "\n";
3004 0 : bWarning = true;
3005 : }
3006 0 : if ( nStates & HiddenInformation::NOTES )
3007 : {
3008 0 : sMessage += SfxResId(STR_HIDDENINFO_NOTES).toString();
3009 0 : sMessage += "\n";
3010 0 : bWarning = true;
3011 : }
3012 0 : if ( nStates & HiddenInformation::DOCUMENTVERSIONS )
3013 : {
3014 0 : sMessage += SfxResId(STR_HIDDENINFO_DOCVERSIONS).toString();
3015 0 : sMessage += "\n";
3016 0 : bWarning = true;
3017 : }
3018 :
3019 0 : if ( bWarning )
3020 : {
3021 0 : sMessage += "\n";
3022 0 : sMessage += SfxResId(nResId).toString();
3023 0 : ScopedVclPtrInstance< WarningBox > aWBox(pParent, WB_YES_NO | WB_DEF_NO, sMessage);
3024 0 : nRet = aWBox->Execute();
3025 0 : }
3026 : }
3027 :
3028 1 : return nRet;
3029 : }
3030 :
3031 0 : bool SfxObjectShell::IsSecurityOptOpenReadOnly() const
3032 : {
3033 0 : return IsLoadReadonly();
3034 : }
3035 :
3036 0 : void SfxObjectShell::SetSecurityOptOpenReadOnly( bool _b )
3037 : {
3038 0 : SetLoadReadonly( _b );
3039 0 : }
3040 :
3041 496 : bool SfxObjectShell::LoadOwnFormat( SfxMedium& rMedium )
3042 : {
3043 : SAL_INFO( "sfx.doc", "loading \" " << rMedium.GetName() << "\"" );
3044 :
3045 496 : uno::Reference< embed::XStorage > xStorage = rMedium.GetStorage();
3046 496 : if ( xStorage.is() )
3047 : {
3048 : // Password
3049 496 : SFX_ITEMSET_ARG( rMedium.GetItemSet(), pPasswdItem, SfxStringItem, SID_PASSWORD, false );
3050 496 : if ( pPasswdItem || ERRCODE_IO_ABORT != CheckPasswd_Impl( this, SfxGetpApp()->GetPool(), pMedium ) )
3051 : {
3052 496 : uno::Sequence< beans::NamedValue > aEncryptionData;
3053 496 : if ( GetEncryptionData_Impl(pMedium->GetItemSet(), aEncryptionData) )
3054 : {
3055 : try
3056 : {
3057 : // the following code must throw an exception in case of failure
3058 4 : ::comphelper::OStorageHelper::SetCommonStorageEncryptionData( xStorage, aEncryptionData );
3059 : }
3060 0 : catch( uno::Exception& )
3061 : {
3062 : // TODO/LATER: handle the error code
3063 : }
3064 : }
3065 :
3066 : // load document
3067 496 : return Load( rMedium );
3068 : }
3069 0 : return false;
3070 : }
3071 : else
3072 0 : return false;
3073 : }
3074 :
3075 673 : bool SfxObjectShell::SaveAsOwnFormat( SfxMedium& rMedium )
3076 : {
3077 673 : uno::Reference< embed::XStorage > xStorage = rMedium.GetStorage();
3078 673 : if( xStorage.is() )
3079 : {
3080 673 : sal_Int32 nVersion = rMedium.GetFilter()->GetVersion();
3081 :
3082 : // OASIS templates have own mediatypes ( SO7 also actually, but it is to late to use them here )
3083 673 : const bool bTemplate = rMedium.GetFilter()->IsOwnTemplateFormat()
3084 673 : && nVersion > SOFFICE_FILEFORMAT_60;
3085 :
3086 673 : const SfxFilter* pFilter = rMedium.GetFilter();
3087 673 : bool bChart = false;
3088 673 : if(pFilter->GetName() == "chart8")
3089 0 : bChart = true;
3090 :
3091 673 : SetupStorage( xStorage, nVersion, bTemplate, bChart );
3092 : #if HAVE_FEATURE_SCRIPTING
3093 673 : if ( HasBasic() )
3094 : {
3095 : // Initialize Basic
3096 653 : GetBasicManager();
3097 :
3098 : // Save dialog/script container
3099 653 : pImp->aBasicManager.storeLibrariesToStorage( xStorage );
3100 : }
3101 : #endif
3102 673 : return SaveAs( rMedium );
3103 : }
3104 0 : else return false;
3105 : }
3106 :
3107 39022 : uno::Reference< embed::XStorage > SfxObjectShell::GetStorage()
3108 : {
3109 39022 : if ( !pImp->m_xDocStorage.is() )
3110 : {
3111 : OSL_ENSURE( pImp->m_bCreateTempStor, "The storage must exist already!\n" );
3112 : try {
3113 : // no notification is required the storage is set the first time
3114 3849 : pImp->m_xDocStorage = ::comphelper::OStorageHelper::GetTemporaryStorage();
3115 : OSL_ENSURE( pImp->m_xDocStorage.is(), "The method must either return storage or throw an exception!" );
3116 :
3117 3496 : SetupStorage( pImp->m_xDocStorage, SOFFICE_FILEFORMAT_CURRENT, false, false );
3118 3496 : pImp->m_bCreateTempStor = false;
3119 3496 : SfxGetpApp()->NotifyEvent( SfxEventHint( SFX_EVENT_STORAGECHANGED, GlobalEventConfig::GetEventName(GlobalEventId::STORAGECHANGED), this ) );
3120 : }
3121 353 : catch( uno::Exception& )
3122 : {
3123 : // TODO/LATER: error handling?
3124 : DBG_UNHANDLED_EXCEPTION();
3125 : }
3126 : }
3127 :
3128 : OSL_ENSURE( pImp->m_xDocStorage.is(), "The document storage must be created!" );
3129 39022 : return pImp->m_xDocStorage;
3130 : }
3131 :
3132 :
3133 3 : bool SfxObjectShell::SaveChildren( bool bObjectsOnly )
3134 : {
3135 3 : bool bResult = true;
3136 3 : if ( pImp->mpObjectContainer )
3137 : {
3138 1 : bool bOasis = ( SotStorage::GetVersion( GetStorage() ) > SOFFICE_FILEFORMAT_60 );
3139 1 : GetEmbeddedObjectContainer().StoreChildren(bOasis,bObjectsOnly);
3140 : }
3141 :
3142 3 : return bResult;
3143 : }
3144 :
3145 673 : bool SfxObjectShell::SaveAsChildren( SfxMedium& rMedium )
3146 : {
3147 673 : bool bResult = true;
3148 :
3149 673 : uno::Reference < embed::XStorage > xStorage = rMedium.GetStorage();
3150 673 : if ( !xStorage.is() )
3151 0 : return false;
3152 :
3153 673 : if ( xStorage == GetStorage() )
3154 0 : return SaveChildren();
3155 :
3156 673 : if ( pImp->mpObjectContainer )
3157 : {
3158 12 : bool bOasis = ( SotStorage::GetVersion( xStorage ) > SOFFICE_FILEFORMAT_60 );
3159 12 : GetEmbeddedObjectContainer().StoreAsChildren(bOasis,SfxObjectCreateMode::EMBEDDED == eCreateMode,xStorage);
3160 : }
3161 :
3162 673 : if ( bResult )
3163 673 : bResult = CopyStoragesOfUnknownMediaType( GetStorage(), xStorage );
3164 :
3165 673 : return bResult;
3166 : }
3167 :
3168 1257 : bool SfxObjectShell::SaveCompletedChildren( bool bSuccess )
3169 : {
3170 1257 : bool bResult = true;
3171 :
3172 1257 : if ( pImp->mpObjectContainer )
3173 : {
3174 545 : uno::Sequence < OUString > aNames = GetEmbeddedObjectContainer().GetObjectNames();
3175 871 : for ( sal_Int32 n=0; n<aNames.getLength(); n++ )
3176 : {
3177 326 : uno::Reference < embed::XEmbeddedObject > xObj = GetEmbeddedObjectContainer().GetEmbeddedObject( aNames[n] );
3178 : OSL_ENSURE( xObj.is(), "An empty entry in the embedded objects list!\n" );
3179 326 : if ( xObj.is() )
3180 : {
3181 326 : uno::Reference< embed::XEmbedPersist > xPersist( xObj, uno::UNO_QUERY );
3182 326 : if ( xPersist.is() )
3183 : {
3184 : try
3185 : {
3186 323 : xPersist->saveCompleted( bSuccess );
3187 : }
3188 0 : catch( uno::Exception& )
3189 : {
3190 : // TODO/LATER: error handling
3191 0 : bResult = false;
3192 0 : break;
3193 : }
3194 326 : }
3195 : }
3196 871 : }
3197 : }
3198 :
3199 1257 : return bResult;
3200 : }
3201 :
3202 1171 : bool SfxObjectShell::SwitchChildrenPersistance( const uno::Reference< embed::XStorage >& xStorage,
3203 : bool bForceNonModified )
3204 : {
3205 1171 : if ( !xStorage.is() )
3206 : {
3207 : // TODO/LATER: error handling
3208 0 : return false;
3209 : }
3210 :
3211 1171 : bool bResult = true;
3212 :
3213 1171 : if ( pImp->mpObjectContainer )
3214 0 : pImp->mpObjectContainer->SetPersistentEntries(xStorage,bForceNonModified);
3215 :
3216 1171 : return bResult;
3217 : }
3218 :
3219 : // Never call this method directly, always use the DoSaveCompleted call
3220 1301 : bool SfxObjectShell::SaveCompleted( const uno::Reference< embed::XStorage >& xStorage )
3221 : {
3222 1301 : bool bResult = false;
3223 1301 : bool bSendNotification = false;
3224 1301 : uno::Reference< embed::XStorage > xOldStorageHolder;
3225 :
3226 : #ifdef DBG_UTIL
3227 : // check for wrong creation of object container
3228 : bool bHasContainer = ( pImp->mpObjectContainer != 0 );
3229 : #endif
3230 :
3231 1301 : if ( !xStorage.is() || xStorage == GetStorage() )
3232 : {
3233 : // no persistence change
3234 696 : bResult = SaveCompletedChildren( false );
3235 : }
3236 : else
3237 : {
3238 605 : if ( pImp->mpObjectContainer )
3239 0 : GetEmbeddedObjectContainer().SwitchPersistence( xStorage );
3240 :
3241 605 : bResult = SwitchChildrenPersistance( xStorage, true );
3242 : }
3243 :
3244 1301 : if ( bResult )
3245 : {
3246 1301 : if ( xStorage.is() && pImp->m_xDocStorage != xStorage )
3247 : {
3248 : // make sure that until the storage is assigned the object
3249 : // container is not created by accident!
3250 : DBG_ASSERT( bHasContainer == (pImp->mpObjectContainer != 0), "Wrong storage in object container!" );
3251 605 : xOldStorageHolder = pImp->m_xDocStorage;
3252 605 : pImp->m_xDocStorage = xStorage;
3253 605 : bSendNotification = true;
3254 :
3255 605 : if ( IsEnableSetModified() )
3256 605 : SetModified( false );
3257 : }
3258 : }
3259 : else
3260 : {
3261 0 : if ( pImp->mpObjectContainer )
3262 0 : GetEmbeddedObjectContainer().SwitchPersistence( pImp->m_xDocStorage );
3263 :
3264 : // let already successfully connected objects be switched back
3265 0 : SwitchChildrenPersistance( pImp->m_xDocStorage, true );
3266 : }
3267 :
3268 1301 : if ( bSendNotification )
3269 : {
3270 605 : SfxGetpApp()->NotifyEvent( SfxEventHint( SFX_EVENT_STORAGECHANGED, GlobalEventConfig::GetEventName(GlobalEventId::STORAGECHANGED), this ) );
3271 : }
3272 :
3273 1301 : return bResult;
3274 : }
3275 :
3276 : #if OSL_DEBUG_LEVEL > 0
3277 : bool StoragesOfUnknownMediaTypeAreCopied_Impl( const uno::Reference< embed::XStorage >& xSource,
3278 : const uno::Reference< embed::XStorage >& xTarget )
3279 : {
3280 : OSL_ENSURE( xSource.is() && xTarget.is(), "Source and/or target storages are not available!\n" );
3281 : if ( !xSource.is() || !xTarget.is() || xSource == xTarget )
3282 : return true;
3283 :
3284 : try
3285 : {
3286 : uno::Sequence< OUString > aSubElements = xSource->getElementNames();
3287 : for ( sal_Int32 nInd = 0; nInd < aSubElements.getLength(); nInd++ )
3288 : {
3289 : if ( xSource->isStorageElement( aSubElements[nInd] ) )
3290 : {
3291 : OUString aMediaType;
3292 : OUString aMediaTypePropName( "MediaType" );
3293 : bool bGotMediaType = false;
3294 :
3295 : try
3296 : {
3297 : uno::Reference< embed::XOptimizedStorage > xOptStorage( xSource, uno::UNO_QUERY_THROW );
3298 : bGotMediaType =
3299 : ( xOptStorage->getElementPropertyValue( aSubElements[nInd], aMediaTypePropName ) >>= aMediaType );
3300 : }
3301 : catch( uno::Exception& )
3302 : {}
3303 :
3304 : if ( !bGotMediaType )
3305 : {
3306 : uno::Reference< embed::XStorage > xSubStorage;
3307 : try {
3308 : xSubStorage = xSource->openStorageElement( aSubElements[nInd], embed::ElementModes::READ );
3309 : } catch( uno::Exception& )
3310 : {}
3311 :
3312 : if ( !xSubStorage.is() )
3313 : {
3314 : xSubStorage = ::comphelper::OStorageHelper::GetTemporaryStorage();
3315 : xSource->copyStorageElementLastCommitTo( aSubElements[nInd], xSubStorage );
3316 : }
3317 :
3318 : uno::Reference< beans::XPropertySet > xProps( xSubStorage, uno::UNO_QUERY_THROW );
3319 : bGotMediaType = ( xProps->getPropertyValue( aMediaTypePropName ) >>= aMediaType );
3320 : }
3321 :
3322 : // TODO/LATER: there should be a way to detect whether an object with such a MediaType can exist
3323 : // probably it should be placed in the MimeType-ClassID table or in standalone table
3324 : if ( !aMediaType.isEmpty()
3325 : && aMediaType != "application/vnd.sun.star.oleobject" )
3326 : {
3327 : ::com::sun::star::datatransfer::DataFlavor aDataFlavor;
3328 : aDataFlavor.MimeType = aMediaType;
3329 : SotClipboardFormatId nFormat = SotExchange::GetFormat( aDataFlavor );
3330 :
3331 : switch ( nFormat )
3332 : {
3333 : case SotClipboardFormatId::STARWRITER_60 :
3334 : case SotClipboardFormatId::STARWRITERWEB_60 :
3335 : case SotClipboardFormatId::STARWRITERGLOB_60 :
3336 : case SotClipboardFormatId::STARDRAW_60 :
3337 : case SotClipboardFormatId::STARIMPRESS_60 :
3338 : case SotClipboardFormatId::STARCALC_60 :
3339 : case SotClipboardFormatId::STARCHART_60 :
3340 : case SotClipboardFormatId::STARMATH_60 :
3341 : case SotClipboardFormatId::STARWRITER_8:
3342 : case SotClipboardFormatId::STARWRITERWEB_8:
3343 : case SotClipboardFormatId::STARWRITERGLOB_8:
3344 : case SotClipboardFormatId::STARDRAW_8:
3345 : case SotClipboardFormatId::STARIMPRESS_8:
3346 : case SotClipboardFormatId::STARCALC_8:
3347 : case SotClipboardFormatId::STARCHART_8:
3348 : case SotClipboardFormatId::STARMATH_8:
3349 : break;
3350 :
3351 : default:
3352 : {
3353 : if ( !xTarget->hasByName( aSubElements[nInd] ) )
3354 : return false;
3355 : }
3356 : }
3357 : }
3358 : }
3359 : }
3360 : }
3361 : catch( uno::Exception& )
3362 : {
3363 : SAL_WARN( "sfx.doc", "Can not check storage consistency!" );
3364 : }
3365 :
3366 : return true;
3367 : }
3368 : #endif
3369 :
3370 566 : bool SfxObjectShell::SwitchPersistance( const uno::Reference< embed::XStorage >& xStorage )
3371 : {
3372 566 : bool bResult = false;
3373 : #ifdef DBG_UTIL
3374 : // check for wrong creation of object container
3375 : bool bHasContainer = ( pImp->mpObjectContainer != 0 );
3376 : #endif
3377 566 : if ( xStorage.is() )
3378 : {
3379 566 : if ( pImp->mpObjectContainer )
3380 0 : GetEmbeddedObjectContainer().SwitchPersistence( xStorage );
3381 566 : bResult = SwitchChildrenPersistance( xStorage );
3382 :
3383 : // TODO/LATER: substorages that have unknown mimetypes probably should be copied to the target storage here
3384 : OSL_ENSURE( StoragesOfUnknownMediaTypeAreCopied_Impl( pImp->m_xDocStorage, xStorage ),
3385 : "Some of substorages with unknown mimetypes is lost!" );
3386 : }
3387 :
3388 566 : if ( bResult )
3389 : {
3390 : // make sure that until the storage is assigned the object container is not created by accident!
3391 : DBG_ASSERT( bHasContainer == (pImp->mpObjectContainer != 0), "Wrong storage in object container!" );
3392 566 : if ( pImp->m_xDocStorage != xStorage )
3393 566 : DoSaveCompleted( new SfxMedium( xStorage, GetMedium()->GetBaseURL() ) );
3394 :
3395 566 : if ( IsEnableSetModified() )
3396 566 : SetModified( true ); // ???
3397 : }
3398 :
3399 566 : return bResult;
3400 : }
3401 :
3402 673 : bool SfxObjectShell::CopyStoragesOfUnknownMediaType( const uno::Reference< embed::XStorage >& xSource,
3403 : const uno::Reference< embed::XStorage >& xTarget )
3404 : {
3405 : // This method does not commit the target storage and should not do it
3406 673 : bool bResult = true;
3407 :
3408 : try
3409 : {
3410 673 : uno::Sequence< OUString > aSubElements = xSource->getElementNames();
3411 4130 : for ( sal_Int32 nInd = 0; nInd < aSubElements.getLength(); nInd++ )
3412 : {
3413 3457 : if ( aSubElements[nInd] == "Configurations" )
3414 : {
3415 : // The workaround for compatibility with SO7, "Configurations" substorage must be preserved
3416 0 : if ( xSource->isStorageElement( aSubElements[nInd] ) )
3417 : {
3418 : OSL_ENSURE( !xTarget->hasByName( aSubElements[nInd] ),
3419 : "The target storage is an output storage, the element should not exist in the target!\n" );
3420 :
3421 0 : xSource->copyElementTo( aSubElements[nInd], xTarget, aSubElements[nInd] );
3422 : }
3423 : }
3424 3457 : else if ( xSource->isStorageElement( aSubElements[nInd] ) )
3425 : {
3426 2465 : OUString aMediaType;
3427 4930 : OUString aMediaTypePropName( "MediaType" );
3428 2465 : bool bGotMediaType = false;
3429 :
3430 : try
3431 : {
3432 2465 : uno::Reference< embed::XOptimizedStorage > xOptStorage( xSource, uno::UNO_QUERY_THROW );
3433 : bGotMediaType =
3434 2465 : ( xOptStorage->getElementPropertyValue( aSubElements[nInd], aMediaTypePropName ) >>= aMediaType );
3435 : }
3436 0 : catch( uno::Exception& )
3437 : {}
3438 :
3439 2465 : if ( !bGotMediaType )
3440 : {
3441 0 : uno::Reference< embed::XStorage > xSubStorage;
3442 : try {
3443 0 : xSubStorage = xSource->openStorageElement( aSubElements[nInd], embed::ElementModes::READ );
3444 0 : } catch( uno::Exception& )
3445 : {}
3446 :
3447 0 : if ( !xSubStorage.is() )
3448 : {
3449 : // TODO/LATER: as optimization in future a substorage of target storage could be used
3450 : // instead of the temporary storage; this substorage should be removed later
3451 : // if the MimeType is wrong
3452 0 : xSubStorage = ::comphelper::OStorageHelper::GetTemporaryStorage();
3453 0 : xSource->copyStorageElementLastCommitTo( aSubElements[nInd], xSubStorage );
3454 : }
3455 :
3456 0 : uno::Reference< beans::XPropertySet > xProps( xSubStorage, uno::UNO_QUERY_THROW );
3457 0 : bGotMediaType = ( xProps->getPropertyValue( aMediaTypePropName ) >>= aMediaType );
3458 : }
3459 :
3460 : // TODO/LATER: there should be a way to detect whether an object with such a MediaType can exist
3461 : // probably it should be placed in the MimeType-ClassID table or in standalone table
3462 4930 : if ( !aMediaType.isEmpty()
3463 2465 : && aMediaType != "application/vnd.sun.star.oleobject" )
3464 : {
3465 107 : ::com::sun::star::datatransfer::DataFlavor aDataFlavor;
3466 107 : aDataFlavor.MimeType = aMediaType;
3467 107 : SotClipboardFormatId nFormat = SotExchange::GetFormat( aDataFlavor );
3468 :
3469 107 : switch ( nFormat )
3470 : {
3471 : case SotClipboardFormatId::STARWRITER_60 :
3472 : case SotClipboardFormatId::STARWRITERWEB_60 :
3473 : case SotClipboardFormatId::STARWRITERGLOB_60 :
3474 : case SotClipboardFormatId::STARDRAW_60 :
3475 : case SotClipboardFormatId::STARIMPRESS_60 :
3476 : case SotClipboardFormatId::STARCALC_60 :
3477 : case SotClipboardFormatId::STARCHART_60 :
3478 : case SotClipboardFormatId::STARMATH_60 :
3479 : case SotClipboardFormatId::STARWRITER_8:
3480 : case SotClipboardFormatId::STARWRITERWEB_8:
3481 : case SotClipboardFormatId::STARWRITERGLOB_8:
3482 : case SotClipboardFormatId::STARDRAW_8:
3483 : case SotClipboardFormatId::STARIMPRESS_8:
3484 : case SotClipboardFormatId::STARCALC_8:
3485 : case SotClipboardFormatId::STARCHART_8:
3486 : case SotClipboardFormatId::STARMATH_8:
3487 8 : break;
3488 :
3489 : default:
3490 : {
3491 : OSL_ENSURE( aSubElements[nInd] == "Configurations2" || nFormat == SotClipboardFormatId::STARBASE_8 || !xTarget->hasByName( aSubElements[nInd] ),
3492 : "The target storage is an output storage, the element should not exist in the target!\n" );
3493 :
3494 99 : if ( !xTarget->hasByName( aSubElements[nInd] ) )
3495 : {
3496 98 : xSource->copyElementTo( aSubElements[nInd], xTarget, aSubElements[nInd] );
3497 : }
3498 : }
3499 107 : }
3500 2465 : }
3501 : }
3502 673 : }
3503 : }
3504 0 : catch( uno::Exception& )
3505 : {
3506 0 : bResult = false;
3507 : // TODO/LATER: a specific error could be provided
3508 : }
3509 :
3510 673 : return bResult;
3511 : }
3512 :
3513 73 : bool SfxObjectShell::GenerateAndStoreThumbnail(bool bEncrypted, bool bIsTemplate, const uno::Reference<embed::XStorage>& xStorage)
3514 : {
3515 : //optimize thumbnail generate and store procedure to improve odt saving performance, i120030
3516 73 : bIsInGenerateThumbnail = true;
3517 :
3518 73 : bool bResult = false;
3519 :
3520 : try
3521 : {
3522 73 : uno::Reference<embed::XStorage> xThumbnailStorage = xStorage->openStorageElement(OUString("Thumbnails"), embed::ElementModes::READWRITE);
3523 :
3524 73 : if (xThumbnailStorage.is())
3525 : {
3526 73 : uno::Reference<io::XStream> xStream = xThumbnailStorage->openStreamElement(OUString("thumbnail.png"), embed::ElementModes::READWRITE);
3527 :
3528 73 : if (xStream.is() && WriteThumbnail(bEncrypted, bIsTemplate, xStream))
3529 : {
3530 73 : uno::Reference<embed::XTransactedObject> xTransactedObject(xThumbnailStorage, uno::UNO_QUERY_THROW);
3531 73 : xTransactedObject->commit();
3532 73 : bResult = true;
3533 73 : }
3534 73 : }
3535 : }
3536 0 : catch( uno::Exception& )
3537 : {
3538 : }
3539 :
3540 : //optimize thumbnail generate and store procedure to improve odt saving performance, i120030
3541 73 : bIsInGenerateThumbnail = false;
3542 :
3543 73 : return bResult;
3544 : }
3545 :
3546 73 : bool SfxObjectShell::WriteThumbnail(bool bEncrypted, bool bIsTemplate, const uno::Reference<io::XStream>& xStream)
3547 : {
3548 73 : bool bResult = false;
3549 :
3550 73 : if (!xStream.is())
3551 0 : return false;
3552 :
3553 : try
3554 : {
3555 73 : uno::Reference<io::XTruncate> xTruncate(xStream->getOutputStream(), uno::UNO_QUERY_THROW);
3556 73 : xTruncate->truncate();
3557 :
3558 146 : uno::Reference <beans::XPropertySet> xSet(xStream, uno::UNO_QUERY);
3559 73 : if (xSet.is())
3560 73 : xSet->setPropertyValue("MediaType", uno::makeAny(OUString("image/png")));
3561 73 : if (bEncrypted)
3562 : {
3563 0 : OUString sFactoryName = OUString::createFromAscii(GetFactory().GetShortName());
3564 0 : sal_uInt16 nResID = GraphicHelper::getThumbnailReplacementIDByFactoryName_Impl(sFactoryName, bIsTemplate);
3565 0 : if (nResID)
3566 0 : bResult = GraphicHelper::getThumbnailReplacement_Impl(nResID, xStream);
3567 : }
3568 : else
3569 : {
3570 73 : std::shared_ptr<GDIMetaFile> xMetaFile = GetPreviewMetaFile(false);
3571 73 : if (xMetaFile)
3572 : {
3573 73 : bResult = GraphicHelper::getThumbnailFormatFromGDI_Impl(xMetaFile.get(), xStream);
3574 73 : }
3575 73 : }
3576 : }
3577 0 : catch(uno::Exception&)
3578 : {}
3579 :
3580 73 : return bResult;
3581 : }
3582 :
3583 86 : void SfxObjectShell::UpdateLinks()
3584 : {
3585 86 : }
3586 :
3587 0 : bool SfxObjectShell::LoadExternal( SfxMedium& )
3588 : {
3589 : // Not implemented. It's an error if the code path ever comes here.
3590 : assert(false);
3591 0 : return false;
3592 : }
3593 :
3594 0 : bool SfxObjectShell::InsertGeneratedStream(SfxMedium&,
3595 : uno::Reference<text::XTextRange> const&)
3596 : {
3597 : // Not implemented. It's an error if the code path ever comes here.
3598 : assert(false);
3599 0 : return false;
3600 : }
3601 :
3602 0 : void SfxObjectShell::CheckConfigOptions()
3603 : {
3604 : // not handled. Each app's shell needs to overwrite this method to add handler.
3605 0 : SetConfigOptionsChecked(true);
3606 0 : }
3607 :
3608 502 : bool SfxObjectShell::IsConfigOptionsChecked() const
3609 : {
3610 502 : return pImp->m_bConfigOptionsChecked;
3611 : }
3612 :
3613 296 : void SfxObjectShell::SetConfigOptionsChecked( bool bChecked )
3614 : {
3615 296 : pImp->m_bConfigOptionsChecked = bChecked;
3616 296 : }
3617 :
3618 101 : bool SfxObjectShell::QuerySaveSizeExceededModules_Impl( const uno::Reference< task::XInteractionHandler >& xHandler )
3619 : {
3620 : #if !HAVE_FEATURE_SCRIPTING
3621 : (void) xHandler;
3622 : #else
3623 101 : if ( !HasBasic() )
3624 20 : return true;
3625 :
3626 81 : if ( !pImp->aBasicManager.isValid() )
3627 0 : GetBasicManager();
3628 81 : uno::Sequence< OUString > sModules;
3629 81 : if ( xHandler.is() )
3630 : {
3631 52 : if( pImp->aBasicManager.LegacyPsswdBinaryLimitExceeded( sModules ) )
3632 : {
3633 0 : ModuleSizeExceeded* pReq = new ModuleSizeExceeded( sModules );
3634 0 : uno::Reference< task::XInteractionRequest > xReq( pReq );
3635 0 : xHandler->handle( xReq );
3636 0 : return pReq->isApprove();
3637 : }
3638 : }
3639 : #endif
3640 : // No interaction handler, default is to continue to save
3641 81 : return true;
3642 : }
3643 :
3644 0 : uno::Reference< task::XInteractionHandler > SfxObjectShell::getInteractionHandler() const
3645 : {
3646 0 : uno::Reference< task::XInteractionHandler > xRet;
3647 0 : if ( GetMedium() )
3648 0 : xRet = GetMedium()->GetInteractionHandler();
3649 0 : return xRet;
3650 : }
3651 :
3652 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|