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