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