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