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