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