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