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