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