1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: objstor.cxx,v $
10 * $Revision: 1.212.44.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sfx2.hxx"
34 #ifndef _MSGBOX_HXX //autogen
35 #include <vcl/msgbox.hxx>
37 #include <svtools/eitem.hxx>
38 #include <svtools/stritem.hxx>
39 #include <tools/zcodec.hxx>
40 #include <com/sun/star/frame/XStorable.hpp>
41 #include <com/sun/star/frame/XModel.hpp>
42 #include <com/sun/star/frame/XFrame.hpp>
43 #include <com/sun/star/document/XFilter.hpp>
44 #include <com/sun/star/document/XImporter.hpp>
45 #include <com/sun/star/document/XExporter.hpp>
46 #include <com/sun/star/document/FilterOptionsRequest.hpp>
47 #include <com/sun/star/document/XInteractionFilterOptions.hpp>
48 #include <com/sun/star/task/XInteractionHandler.hpp>
49 #include <com/sun/star/task/XInteractionAskLater.hpp>
50 #include <com/sun/star/task/FutureDocumentVersionProductUpdateRequest.hpp>
51 #include <com/sun/star/task/InteractionClassification.hpp>
52 #include <com/sun/star/lang/XInitialization.hpp>
53 #include <com/sun/star/document/MacroExecMode.hpp>
54 #include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp>
55 #include <com/sun/star/ui/dialogs/XFilePickerControlAccess.hpp>
56 #include <com/sun/star/ui/dialogs/XFilePicker.hpp>
57 #include <com/sun/star/beans/XPropertySetInfo.hpp>
58 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
59 #include <com/sun/star/beans/XPropertyAccess.hpp>
60 #include <com/sun/star/beans/PropertyValue.hpp>
61 #include <com/sun/star/beans/XPropertySet.hpp>
62 #include <com/sun/star/container/XNameAccess.hpp>
63 #include <com/sun/star/container/XSet.hpp>
64 #include <com/sun/star/embed/ElementModes.hpp>
65 #include <com/sun/star/embed/EmbedStates.hpp>
66 #include <com/sun/star/embed/Aspects.hpp>
67 #include <com/sun/star/embed/XTransactedObject.hpp>
68 #include <com/sun/star/embed/XEmbedPersist.hpp>
69 #include <com/sun/star/embed/XLinkageSupport.hpp>
70 #include <com/sun/star/embed/EntryInitModes.hpp>
71 #include <com/sun/star/embed/XOptimizedStorage.hpp>
72 #include <com/sun/star/io/XTruncate.hpp>
73 #include <com/sun/star/util/XModifiable.hpp>
74 #include <com/sun/star/security/XDocumentDigitalSignatures.hpp>
76 #include <com/sun/star/document/XDocumentProperties.hpp>
77 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
78 #include <comphelper/processfactory.hxx>
79 #include <comphelper/configurationhelper.hxx>
80 #include <comphelper/interaction.hxx>
81 #include <svtools/sfxecode.hxx>
82 #include <svtools/securityoptions.hxx>
83 #include <cppuhelper/weak.hxx>
84 #include <comphelper/processfactory.hxx>
85 #include <tools/cachestr.hxx>
86 #include <svtools/addxmltostorageoptions.hxx>
87 #include <unotools/streamwrap.hxx>
89 #include <svtools/saveopt.hxx>
90 #include <svtools/useroptions.hxx>
91 #include <svtools/pathoptions.hxx>
92 #include <tools/urlobj.hxx>
93 #include <tools/diagnose_ex.h>
94 #include <unotools/localfilehelper.hxx>
95 #include <unotools/ucbhelper.hxx>
96 #include <unotools/tempfile.hxx>
97 #include <unotools/docinfohelper.hxx>
98 #include <ucbhelper/content.hxx>
99 #include <sot/storinfo.hxx>
100 #include <sot/exchange.hxx>
101 #include <sot/formats.hxx>
102 #include <shell/systemshell.hxx>
103 #include <comphelper/storagehelper.hxx>
104 #include <comphelper/seqstream.hxx>
105 #include <comphelper/documentconstants.hxx>
106 #include <comphelper/string.hxx>
107 #include <vcl/bitmapex.hxx>
108 #include <svtools/embedhlp.hxx>
109 #include <rtl/logfile.hxx>
110 #include <basic/modsizeexceeded.hxx>
111 #include <osl/file.hxx>
112 #include <com/sun/star/util/XMacroExpander.hpp>
113 #include <osl/process.h>
114 #include <osl/thread.hxx>
116 #include <sfx2/signaturestate.hxx>
117 #include <sfx2/app.hxx>
118 #include <sfx2/objsh.hxx>
119 #include <sfx2/childwin.hxx>
120 #include <sfx2/request.hxx>
121 #include "sfxresid.hxx"
122 #include <sfx2/docfile.hxx>
123 #include "fltfnc.hxx"
124 #include <sfx2/docfilt.hxx>
125 #include <sfx2/docfac.hxx>
126 #include "objshimp.hxx"
127 #include "sfxtypes.hxx"
129 #include <sfx2/sfxsids.hrc>
130 #include <sfx2/module.hxx>
131 #include <sfx2/dispatch.hxx>
132 #include "openflag.hxx"
133 #include "helper.hxx"
134 #include <sfx2/filedlghelper.hxx>
135 #include <sfx2/event.hxx>
136 #include "fltoptint.hxx"
137 #include <sfx2/viewfrm.hxx>
138 #include "graphhelp.hxx"
139 #include "appbaslib.hxx"
140 #include "appdata.hxx"
142 #include "../appl/app.hrc"
144 extern sal_uInt32
CheckPasswd_Impl( SfxObjectShell
*, SfxItemPool
&, SfxMedium
* );
146 using namespace ::com::sun::star
;
147 using namespace ::com::sun::star::container
;
148 using namespace ::com::sun::star::lang
;
149 using namespace ::com::sun::star::ui::dialogs
;
150 using namespace ::com::sun::star::uno
;
151 using namespace ::com::sun::star::beans
;
152 using namespace ::com::sun::star::ucb
;
153 using namespace ::com::sun::star::task
;
154 using namespace ::com::sun::star::document
;
155 using namespace ::rtl
;
156 using namespace ::cppu
;
158 namespace css
= ::com::sun::star
;
160 class StatusThread
: public osl::Thread
162 oslFileHandle m_handle
;
165 int volatile progressTicks
;
167 StatusThread(oslFileHandle handle
) :
168 osl::Thread(), m_handle(handle
), progressTicks(0)
173 virtual void SAL_CALL
run() {
177 oslFileError err
=osl_readFile(m_handle
, buf
, sizeof(buf
)-1, &nRead
);
178 if (err
!=osl_File_E_None
|| nRead
<=0) {
188 static sal_Bool
invokeExternalApp(String aAppName
, ::rtl::OUString sourceParam
, ::rtl::OUString targetParam
, uno::Reference
< ::com::sun::star::task::XStatusIndicator
> xStatusIndicator
)
190 static const char EXPAND_WILDCARD_CONST
[] ="vnd.sun.star.expand:";
191 static const char SOURCE_WILDCARD_CONST
[]="%source%";
192 static const char TARGET_WILDCARD_CONST
[]="%target%";
193 // get macro expansion
194 uno::Reference
< XMultiServiceFactory
> xMS(::comphelper::getProcessServiceFactory(), UNO_QUERY
);
195 uno::Reference
< beans::XPropertySet
> xProps(xMS
, UNO_QUERY
);
196 uno::Reference
< XComponentContext
> xContext(xProps
->getPropertyValue(rtl::OUString::createFromAscii("DefaultContext")), UNO_QUERY
);
197 uno::Reference
< util::XMacroExpander
> xExpander(xContext
->getValueByName(::rtl::OUString::createFromAscii("/singletons/com.sun.star.util.theMacroExpander")), UNO_QUERY
);
199 // parse preprocessing arguments
200 int c
=aAppName
.GetQuotedTokenCount('\"',',');
201 if (c
<1) return sal_False
;
202 rtl_uString
**args
=new rtl_uString
*[c
];
203 for(int i
=0;i
<c
;i
++) {
204 String aArg
=aAppName
.GetQuotedToken(i
,'\"',',');
205 if (aArg
.EqualsIgnoreCaseAscii(EXPAND_WILDCARD_CONST
, 0, strlen(EXPAND_WILDCARD_CONST
))) {
206 rtl::OUString
argStr(aArg
.GetBuffer()+strlen(EXPAND_WILDCARD_CONST
));
207 aArg
=xExpander
->expandMacros(argStr
);
208 } else if (aArg
.EqualsIgnoreCaseAscii(SOURCE_WILDCARD_CONST
, 0, strlen(SOURCE_WILDCARD_CONST
))) {
210 } else if (aArg
.EqualsIgnoreCaseAscii(TARGET_WILDCARD_CONST
, 0, strlen(TARGET_WILDCARD_CONST
))) {
213 args
[i
]=rtl::OUString(aArg
).pData
;
214 rtl_uString_acquire(args
[i
]);
217 sal_Bool bOk
=sal_False
;
220 for (int p
=0;p
<c
;p
++) {
221 rtl::OString aOString
= ::rtl::OUStringToOString (args
[p
], RTL_TEXTENCODING_UTF8
);
222 printf("args[%i]=\"%s\"\n", p
, aOString
.getStr());
225 // invoke processing step
226 oslProcess pProcess
=NULL
;
227 oslFileHandle handle
=NULL
;
228 oslProcessError error
=osl_executeProcess_WithRedirectedIO(
232 /*osl_Process_NORMAL*/ osl_Process_HIDDEN
,
243 if (error
==osl_Process_E_None
) {
244 static const int MAXBARTICKS
=1000;
245 StatusThread
statusThread(handle
);
246 statusThread
.create();
247 if (xStatusIndicator
.is()) {
248 xStatusIndicator
->start(::rtl::OUString::createFromAscii("waiting for external application..."), MAXBARTICKS
);
251 TimeValue wait
= {1, 0};
252 error
=osl_joinProcessWithTimeout( pProcess
, &wait
);
253 if (xStatusIndicator
.is()) {
254 xStatusIndicator
->setValue(statusThread
.progressTicks
%MAXBARTICKS
);
256 } while (error
==osl_Process_E_TimedOut
);
257 if (xStatusIndicator
.is()) {
258 xStatusIndicator
->end();
260 if (error
==osl_Process_E_None
) {
261 oslProcessInfo aProcessInfo
;
262 aProcessInfo
.Size
= sizeof(aProcessInfo
);
263 error
= osl_getProcessInfo( pProcess
, osl_Process_EXITCODE
, &aProcessInfo
);
264 if (error
==osl_Process_E_None
&& aProcessInfo
.Code
== 0) {
270 osl_freeProcessHandle(pProcess
);
272 for(int i
=0;i
<c
;i
++) {
273 rtl_uString_release(args
[i
]);
280 //=========================================================================
281 void impl_addToModelCollection(const css::uno::Reference
< css::frame::XModel
>& xModel
)
286 css::uno::Reference
< css::lang::XMultiServiceFactory
> xSMGR
= ::comphelper::getProcessServiceFactory();
287 css::uno::Reference
< css::container::XSet
> xModelCollection(
288 xSMGR
->createInstance(::rtl::OUString::createFromAscii("com.sun.star.frame.GlobalEventBroadcaster")),
289 css::uno::UNO_QUERY
);
290 if (xModelCollection
.is())
294 xModelCollection
->insert(css::uno::makeAny(xModel
));
296 catch ( uno::Exception
& )
298 OSL_ENSURE( sal_False
, "The document seems to be in the collection already!\n" );
303 //=========================================================================
305 sal_Bool
SfxObjectShell::Save()
307 return SaveChildren();
310 //--------------------------------------------------------------------------
312 sal_Bool
SfxObjectShell::SaveAs( SfxMedium
& rMedium
)
314 return SaveAsChildren( rMedium
);
317 //-------------------------------------------------------------------------
319 sal_Bool
GetPasswd_Impl( const SfxItemSet
* pSet
, ::rtl::OUString
& rPasswd
)
321 const SfxPoolItem
* pItem
= NULL
;
322 if ( pSet
&& SFX_ITEM_SET
== pSet
->GetItemState( SID_PASSWORD
, sal_True
, &pItem
) )
324 DBG_ASSERT( pItem
->IsA( TYPE(SfxStringItem
) ), "wrong item type" );
325 rPasswd
= ( (const SfxStringItem
*)pItem
)->GetValue();
331 //-------------------------------------------------------------------------
332 sal_Bool
SfxObjectShell::NoDependencyFromManifest_Impl( const uno::Reference
< embed::XStorage
>& xStorage
)
334 uno::Sequence
< ::rtl::OUString
> aElements
= xStorage
->getElementNames();
335 for ( sal_Int32 nInd
= 0; nInd
< aElements
.getLength(); nInd
++ )
337 if ( xStorage
->isStorageElement( aElements
[nInd
] ) )
339 // if there are other standard elements that do not need manifest.xml the following
340 // list can be extended
341 if ( !aElements
[nInd
].equals( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Pictures" ) ) )
342 && !aElements
[nInd
].equals( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Configurations" ) ) )
343 && !aElements
[nInd
].equals( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Configurations2" ) ) )
344 && !aElements
[nInd
].equals( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Thumbnails" ) ) )
345 && !aElements
[nInd
].equals( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Basic" ) ) ) )
347 // the substorage is not know as one that does not need manifest.xml
356 //-------------------------------------------------------------------------
357 sal_Bool
SfxObjectShell::PutURLContentsToVersionStream_Impl(
358 ::rtl::OUString aURL
,
359 const uno::Reference
< embed::XStorage
>& xDocStorage
,
360 ::rtl::OUString aStreamName
)
362 sal_Bool bResult
= sal_False
;
365 uno::Reference
< embed::XStorage
> xVersion
= xDocStorage
->openStorageElement(
366 ::rtl::OUString::createFromAscii( "Versions" ),
367 embed::ElementModes::READWRITE
);
369 DBG_ASSERT( xVersion
.is(),
370 "The method must throw an exception if the storage can not be opened!\n" );
371 if ( !xVersion
.is() )
372 throw uno::RuntimeException();
374 uno::Reference
< io::XStream
> xVerStream
= xVersion
->openStreamElement(
376 embed::ElementModes::READWRITE
);
377 DBG_ASSERT( xVerStream
.is(), "The method must throw an exception if the storage can not be opened!\n" );
378 if ( !xVerStream
.is() )
379 throw uno::RuntimeException();
381 uno::Reference
< io::XOutputStream
> xOutStream
= xVerStream
->getOutputStream();
382 uno::Reference
< io::XTruncate
> xTrunc( xOutStream
, uno::UNO_QUERY
);
384 DBG_ASSERT( xTrunc
.is(), "The output stream must exist and implement XTruncate interface!\n" );
386 throw RuntimeException();
388 uno::Reference
< io::XInputStream
> xTmpInStream
=
389 ::comphelper::OStorageHelper::GetInputStreamFromURL( aURL
);
390 DBG_ASSERT( xTmpInStream
.is(), "The method must create the stream or throw an exception!\n" );
391 if ( !xTmpInStream
.is() )
392 throw uno::RuntimeException();
395 ::comphelper::OStorageHelper::CopyInputToOutput( xTmpInStream
, xOutStream
);
396 xOutStream
->closeOutput();
398 uno::Reference
< embed::XTransactedObject
> xTransact( xVersion
, uno::UNO_QUERY
);
399 DBG_ASSERT( xTransact
.is(), "The storage must implement XTransacted interface!\n" );
400 if ( xTransact
.is() )
405 catch( uno::Exception
& )
407 // TODO/LATER: handle the error depending on exception
408 SetError( ERRCODE_IO_GENERAL
, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
) ) );
414 //-------------------------------------------------------------------------
415 ::rtl::OUString
SfxObjectShell::CreateTempCopyOfStorage_Impl( const uno::Reference
< embed::XStorage
>& xStorage
)
417 ::rtl::OUString aTempURL
= ::utl::TempFile().GetURL();
419 DBG_ASSERT( aTempURL
.getLength(), "Can't create a temporary file!\n" );
420 if ( aTempURL
.getLength() )
424 uno::Reference
< embed::XStorage
> xTempStorage
=
425 ::comphelper::OStorageHelper::GetStorageFromURL( aTempURL
, embed::ElementModes::READWRITE
);
427 // the password will be transfered from the xStorage to xTempStorage by storage implemetation
428 xStorage
->copyToStorage( xTempStorage
);
430 // the temporary storage was commited by the previous method and it will die by refcount
432 catch ( uno::Exception
& )
434 DBG_ERROR( "Creation of a storage copy is failed!" );
435 ::utl::UCBContentHelper::Kill( aTempURL
);
437 aTempURL
= ::rtl::OUString();
439 // TODO/LATER: may need error code setting based on exception
440 SetError( ERRCODE_IO_GENERAL
, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
) ) );
447 //-------------------------------------------------------------------------
448 SvGlobalName
SfxObjectShell::GetClassName() const
450 return GetFactory().GetClassId();
453 //-------------------------------------------------------------------------
454 void SfxObjectShell::SetupStorage( const uno::Reference
< embed::XStorage
>& xStorage
,
456 sal_Bool bTemplate
) const
458 uno::Reference
< beans::XPropertySet
> xProps( xStorage
, uno::UNO_QUERY
);
463 String aFullTypeName
, aShortTypeName
, aAppName
;
464 sal_uInt32 nClipFormat
=0;
466 FillClass( &aName
, &nClipFormat
, &aAppName
, &aFullTypeName
, &aShortTypeName
, nVersion
, bTemplate
);
469 // basic doesn't have a ClipFormat
470 // without MediaType the storage is not really usable, but currently the BasicIDE still
471 // is an SfxObjectShell and so we can't take this as an error
472 datatransfer::DataFlavor aDataFlavor
;
473 SotExchange::GetFormatDataFlavor( nClipFormat
, aDataFlavor
);
474 if ( aDataFlavor
.MimeType
.getLength() )
478 xProps
->setPropertyValue( ::rtl::OUString::createFromAscii( "MediaType" ), uno::makeAny( aDataFlavor
.MimeType
) );
480 catch( uno::Exception
& )
482 const_cast<SfxObjectShell
*>( this )->SetError( ERRCODE_IO_GENERAL
, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
) ) );
485 ::rtl::OUString aVersion
;
486 SvtSaveOptions aSaveOpt
;
487 SvtSaveOptions::ODFDefaultVersion nDefVersion
= aSaveOpt
.GetODFDefaultVersion();
489 // older versions can not have this property set, it exists only starting from ODF1.2
490 if ( nDefVersion
== SvtSaveOptions::ODFVER_012
)
491 aVersion
= ODFVER_012_TEXT
;
493 if ( aVersion
.getLength() )
497 xProps
->setPropertyValue( ::rtl::OUString::createFromAscii( "Version" ), uno::makeAny( aVersion
) );
499 catch( uno::Exception
& )
508 //-------------------------------------------------------------------------
509 void SfxObjectShell::PrepareSecondTryLoad_Impl()
511 // only for internal use
512 pImp
->m_xDocStorage
= uno::Reference
< embed::XStorage
>();
513 pImp
->m_bIsInit
= sal_False
;
517 //-------------------------------------------------------------------------
518 sal_Bool
SfxObjectShell::GeneralInit_Impl( const uno::Reference
< embed::XStorage
>& xStorage
,
519 sal_Bool bTypeMustBeSetAlready
)
521 if ( pImp
->m_bIsInit
)
524 pImp
->m_bIsInit
= sal_True
;
527 // no notification is required the storage is set the first time
528 pImp
->m_xDocStorage
= xStorage
;
531 uno::Reference
< beans::XPropertySet
> xPropSet( xStorage
, uno::UNO_QUERY_THROW
);
532 Any a
= xPropSet
->getPropertyValue( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "MediaType" ) ) );
533 ::rtl::OUString aMediaType
;
534 if ( !(a
>>=aMediaType
) || !aMediaType
.getLength() )
536 if ( bTypeMustBeSetAlready
)
538 SetError( ERRCODE_IO_BROKENPACKAGE
, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
) ) );
542 SetupStorage( xStorage
, SOFFICE_FILEFORMAT_CURRENT
, sal_False
);
545 catch ( uno::Exception
& )
547 OSL_ENSURE( sal_False
, "Can't check storage's mediatype!\n" );
551 pImp
->m_bCreateTempStor
= sal_True
;
556 //-------------------------------------------------------------------------
557 sal_Bool
SfxObjectShell::InitNew( const uno::Reference
< embed::XStorage
>& xStorage
)
559 return GeneralInit_Impl( xStorage
, sal_False
);
562 //-------------------------------------------------------------------------
563 sal_Bool
SfxObjectShell::Load( SfxMedium
& rMedium
)
565 return GeneralInit_Impl( rMedium
.GetStorage(), sal_True
);
568 //-------------------------------------------------------------------------
569 sal_Bool
SfxObjectShell::DoInitNew_Impl( const ::rtl::OUString
& rName
)
575 if ( rName
.getLength() )
577 DBG_ERROR( "This code is intended to be removed, the caller part must be checked!\n" );
585 sal_Bool
SfxObjectShell::DoInitNew( SfxMedium
* pMed
)
588 Diese von SvPersist geerbte virtuelle Methode wird gerufen, um
589 die SfxObjectShell-Instanz aus einem Storage (pStor != 0) bzw.
590 (pStor == 0) ganz neu zu initialisieren.
592 Wie alle Do...-Methoden liegt hier eine Steuerung vor, die eigentliche
593 Implementierung erfolgt, indem die ebenfalls virtuellen Methode
594 InitNew(SvStorate*) von der SfxObjectShell-Subclass implementiert wird.
596 F"ur pStor == 0 wird ein die SfxObjectShell-Instanz mit einem leeren
597 SfxMedium verbunden, sonst mit einem SfxMedium, welches auf den
598 als Parameter "ubergeben SvStorage verweist.
600 Erst nach InitNew() oder Load() ist das Objekt korrekt initialisiert.
603 sal_True Das Objekt wurde initialisiert.
604 sal_False Das Objekt konnte nicht initialisiert werden
608 ModifyBlocker_Impl
aBlock( this );
613 pMedium
= new SfxMedium
;
616 pMedium
->CanDisposeStorage_Impl( sal_True
);
618 if ( InitNew( pMed
? pMed
->GetStorage() : uno::Reference
< embed::XStorage
>() ) )
620 // empty documents always get their macros from the user, so there is no reason to restrict access
621 pImp
->aMacroMode
.allowMacroExecution();
622 if ( SFX_CREATE_MODE_EMBEDDED
== eCreateMode
)
623 SetTitle( String( SfxResId( STR_NONAME
) ));
625 uno::Reference
< frame::XModel
> xModel ( GetModel(), uno::UNO_QUERY
);
628 SfxItemSet
*pSet
= GetMedium()->GetItemSet();
629 uno::Sequence
< beans::PropertyValue
> aArgs
;
630 TransformItems( SID_OPENDOC
, *pSet
, aArgs
);
631 sal_Int32 nLength
= aArgs
.getLength();
632 aArgs
.realloc( nLength
+ 1 );
633 aArgs
[nLength
].Name
= DEFINE_CONST_UNICODE("Title");
634 aArgs
[nLength
].Value
<<= ::rtl::OUString( GetTitle( SFX_TITLE_DETECT
) );
635 xModel
->attachResource( ::rtl::OUString(), aArgs
);
636 impl_addToModelCollection(xModel
);
639 pImp
->bInitialized
= sal_True
;
640 SetActivateEvent_Impl( SFX_EVENT_CREATEDOC
);
641 SFX_APP()->NotifyEvent( SfxEventHint( SFX_EVENT_DOCCREATED
, this ) );
648 //-------------------------------------------------------------------------
650 sal_Bool
SfxObjectShell::ImportFromGeneratedStream_Impl(
651 const uno::Reference
< io::XStream
>& xStream
,
652 const uno::Sequence
< beans::PropertyValue
>& aMediaDescr
)
657 if ( pMedium
&& pMedium
->HasStorage_Impl() )
658 pMedium
->CloseStorage();
660 sal_Bool bResult
= sal_False
;
664 uno::Reference
< embed::XStorage
> xStorage
=
665 ::comphelper::OStorageHelper::GetStorageFromStream( xStream
, embed::ElementModes::READWRITE
);
667 if ( !xStorage
.is() )
668 throw uno::RuntimeException();
671 pMedium
= new SfxMedium( xStorage
, String() );
673 pMedium
->SetStorage_Impl( xStorage
);
675 SfxAllItemSet
aSet( SFX_APP()->GetPool() );
676 TransformParameters( SID_OPENDOC
, aMediaDescr
, aSet
);
677 pMedium
->GetItemSet()->Put( aSet
);
678 pMedium
->CanDisposeStorage_Impl( sal_False
);
680 // allow the subfilter to reinit the model
681 if ( pImp
->m_bIsInit
)
682 pImp
->m_bIsInit
= sal_False
;
684 if ( LoadOwnFormat( *pMedium
) )
687 if ( !IsReadOnly() && IsLoadReadonly() )
691 OSL_ENSURE( pImp
->m_xDocStorage
== xStorage
, "Wrong storage is used!\n" );
694 // now the medium can be disconnected from the storage
695 // the medium is not allowed to dispose the storage so CloseStorage() can be used
696 pMedium
->CloseStorage();
698 catch( uno::Exception
& )
705 //-------------------------------------------------------------------------
707 sal_Bool
SfxObjectShell::DoLoad( SfxMedium
*pMed
)
709 ModifyBlocker_Impl
aBlock( this );
711 if ( SFX_CREATE_MODE_EMBEDDED
!= eCreateMode
)
712 GetpApp()->ShowStatusText( SfxResId(STR_DOC_LOADING
) );
715 pMedium
->CanDisposeStorage_Impl( sal_True
);
717 sal_Bool bOk
= sal_False
;
718 const SfxFilter
* pFilter
= pMed
->GetFilter();
719 SfxItemSet
* pSet
= pMedium
->GetItemSet();
720 if( !pImp
->nEventId
)
723 pSet
, pTemplateItem
, SfxBoolItem
,
724 SID_TEMPLATE
, sal_False
);
725 SetActivateEvent_Impl(
726 ( pTemplateItem
&& pTemplateItem
->GetValue() )
727 ? SFX_EVENT_CREATEDOC
: SFX_EVENT_OPENDOC
);
731 SFX_ITEMSET_ARG( pSet
, pBaseItem
, SfxStringItem
,
732 SID_BASEURL
, sal_False
);
734 SFX_ITEMSET_ARG( pMedium
->GetItemSet(), pSalvageItem
, SfxStringItem
, SID_DOC_SALVAGE
, sal_False
);
736 aBaseURL
= pBaseItem
->GetValue();
741 String
aName( pMed
->GetPhysicalName() );
742 ::utl::LocalFileHelper::ConvertPhysicalNameToURL( aName
, aBaseURL
);
745 aBaseURL
= pMed
->GetBaseURL();
747 pMed
->GetItemSet()->Put( SfxStringItem( SID_DOC_BASEURL
, aBaseURL
) );
749 pImp
->nLoadedFlags
= 0;
750 pImp
->bModelInitialized
= sal_False
;
752 //TODO/LATER: make a clear strategy how to handle "UsesStorage" etc.
753 sal_Bool bOwnStorageFormat
= IsOwnStorageFormat_Impl( *pMedium
);
754 sal_Bool bHasStorage
= IsPackageStorageFormat_Impl( *pMedium
);
755 if ( pMedium
->GetFilter() )
757 sal_uInt32 nError
= HandleFilter( pMedium
, this );
758 if ( nError
!= ERRCODE_NONE
)
759 SetError( nError
, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
) ) );
761 if (pMedium
->GetFilter()->GetFilterFlags() & SFX_FILTER_STARTPRESENTATION
)
762 pSet
->Put( SfxBoolItem( SID_DOC_STARTPRESENTATION
, TRUE
) );
765 EnableSetModified( sal_False
);
767 pMedium
->LockOrigFileOnDemand( sal_True
, sal_False
);
768 if ( GetError() == ERRCODE_NONE
&& bOwnStorageFormat
&& ( !pFilter
|| !( pFilter
->GetFilterFlags() & SFX_FILTER_STARONEFILTER
) ) )
770 uno::Reference
< embed::XStorage
> xStorage
;
771 if ( pMedium
->GetError() == ERRCODE_NONE
)
772 xStorage
= pMedium
->GetStorage();
774 if( xStorage
.is() && pMedium
->GetLastStorageCreationState() == ERRCODE_NONE
)
776 DBG_ASSERT( pFilter
, "No filter for storage found!" );
780 sal_Bool bWarnMediaTypeFallback
= sal_False
;
781 SFX_ITEMSET_ARG( pMedium
->GetItemSet(), pRepairPackageItem
, SfxBoolItem
, SID_REPAIRPACKAGE
, sal_False
);
783 // treat the package as broken if the mediatype was retrieved as a fallback
784 uno::Reference
< beans::XPropertySet
> xStorProps( xStorage
, uno::UNO_QUERY_THROW
);
785 xStorProps
->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "MediaTypeFallbackUsed" ) ) )
786 >>= bWarnMediaTypeFallback
;
788 if ( bWarnMediaTypeFallback
&& pRepairPackageItem
&& pRepairPackageItem
->GetValue() )
790 // the mediatype was retrieved by using fallback solution but this is a repairing mode
791 // so it is acceptable to open the document if there is no contents that required manifest.xml
792 bWarnMediaTypeFallback
= sal_False
; //!NoDependencyFromManifest_Impl( xStorage );
795 if ( bWarnMediaTypeFallback
|| !xStorage
->getElementNames().getLength() )
796 SetError( ERRCODE_IO_BROKENPACKAGE
, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
) ) );
798 catch( uno::Exception
& )
800 // TODO/LATER: may need error code setting based on exception
801 SetError( ERRCODE_IO_GENERAL
, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
) ) );
807 pImp
->nLoadedFlags
= 0;
808 pImp
->bModelInitialized
= sal_False
;
809 int end
, pos
= STRING_NOTFOUND
;
811 static const char PREPROCESS_CONST
[]="Preprocess=<";
813 aUserData
=pFilter
->GetUserData();
814 // check whether a prepocessing step is requested in the configuration
815 pos
=aUserData
.Search(::rtl::OUString::createFromAscii(PREPROCESS_CONST
).getStr(), 0);
816 end
=aUserData
.Search( '>', pos
+strlen(PREPROCESS_CONST
));
818 if (pos
!=STRING_NOTFOUND
&& end
!=STRING_NOTFOUND
) {
819 String
aAppName(aUserData
, pos
+strlen(PREPROCESS_CONST
), end
-(pos
+strlen(PREPROCESS_CONST
)));
822 SfxItemSet
*pSet
= pMed
->GetItemSet();
823 const SfxUnoAnyItem
*pItem
=NULL
;
824 SfxItemState ret
=pSet
->GetItemState( SID_PROGRESS_STATUSBAR_CONTROL
, TRUE
, (const SfxPoolItem
**)&pItem
);
825 uno::Reference
< ::com::sun::star::task::XStatusIndicator
> xStatusIndicator
;
826 if (ret
==SFX_ITEM_SET
&& pItem
!=NULL
)
828 pItem
->GetValue() >>= xStatusIndicator
;
831 SfxMedium
myMed(*pMed
, sal_False
);
832 ::utl::TempFile aTempFile
;
833 myMed
.SetName(aTempFile
.GetURL(), sal_True
);
834 myMed
.SetPhysicalName_Impl(aTempFile
.GetFileName());
836 myMed
.CloseStorage();
837 myMed
.CloseInStream();
838 myMed
.SetTemporary(sal_True
);
840 bOk
= invokeExternalApp(aAppName
, ::rtl::OUString(pMed
->GetPhysicalName()), ::rtl::OUString(myMed
.GetPhysicalName()), xStatusIndicator
);
844 bOk
= xStorage
.is() && LoadOwnFormat( myMed
);
847 // We process only errors from invokeExternalApp at this point
848 // The errors from the above LoadOwnFormat are processed later
849 SetError( ERRCODE_IO_CANTREAD
, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
) ) );
852 bOk
= xStorage
.is() && LoadOwnFormat( *pMed
);
856 // the document loaded from template has no name
857 SFX_ITEMSET_ARG( pMedium
->GetItemSet(), pTemplateItem
, SfxBoolItem
, SID_TEMPLATE
, sal_False
);
858 if ( !pTemplateItem
|| !pTemplateItem
->GetValue() )
861 if ( !IsReadOnly() && IsLoadReadonly() )
865 SetError( ERRCODE_ABORT
, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
) ) );
869 SetError( pMed
->GetLastStorageCreationState(), ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
) ) );
871 else if ( GetError() == ERRCODE_NONE
&& InitNew(0) )
873 // Name vor ConvertFrom setzen, damit GetSbxObject() schon funktioniert
875 SetName( SfxResId( STR_NONAME
) );
878 pMedium
->GetInStream();
880 pMedium
->GetStorage();
882 if ( GetError() == ERRCODE_NONE
)
884 pImp
->nLoadedFlags
= 0;
885 pImp
->bModelInitialized
= sal_False
;
886 if ( pMedium
->GetFilter() && ( pMedium
->GetFilter()->GetFilterFlags() & SFX_FILTER_STARONEFILTER
) )
888 uno::Reference
< beans::XPropertySet
> xSet( GetModel(), uno::UNO_QUERY
);
889 ::rtl::OUString
sLockUpdates(::rtl::OUString::createFromAscii("LockUpdates"));
890 bool bSetProperty
= true;
893 xSet
->setPropertyValue( sLockUpdates
, makeAny( (sal_Bool
) sal_True
) );
895 catch(const beans::UnknownPropertyException
& )
897 bSetProperty
= false;
899 bOk
= ImportFrom(*pMedium
);
904 xSet
->setPropertyValue( sLockUpdates
, makeAny( (sal_Bool
) sal_False
) );
906 catch(const beans::UnknownPropertyException
& )
910 FinishedLoading( SFX_LOADED_ALL
);
914 bOk
= ConvertFrom(*pMedium
);
924 ::ucbhelper::Content
aContent( pMedium
->GetName(), com::sun::star::uno::Reference
< XCommandEnvironment
>() );
925 com::sun::star::uno::Reference
< XPropertySetInfo
> xProps
= aContent
.getProperties();
928 ::rtl::OUString
aAuthor( RTL_CONSTASCII_USTRINGPARAM("Author") );
929 ::rtl::OUString
aKeywords( RTL_CONSTASCII_USTRINGPARAM("Keywords") );
930 ::rtl::OUString
aSubject( RTL_CONSTASCII_USTRINGPARAM("Subject") );
932 ::rtl::OUString aValue
;
933 uno::Reference
<document::XDocumentPropertiesSupplier
> xDPS(
934 GetModel(), uno::UNO_QUERY_THROW
);
935 uno::Reference
<document::XDocumentProperties
> xDocProps
936 = xDPS
->getDocumentProperties();
937 if ( xProps
->hasPropertyByName( aAuthor
) )
939 aAny
= aContent
.getPropertyValue( aAuthor
);
940 if ( ( aAny
>>= aValue
) )
941 xDocProps
->setAuthor(aValue
);
943 if ( xProps
->hasPropertyByName( aKeywords
) )
945 aAny
= aContent
.getPropertyValue( aKeywords
);
946 if ( ( aAny
>>= aValue
) )
947 xDocProps
->setKeywords(
948 ::comphelper::string::convertCommaSeparated(aValue
));
951 if ( xProps
->hasPropertyByName( aSubject
) )
953 aAny
= aContent
.getPropertyValue( aSubject
);
954 if ( ( aAny
>>= aValue
) ) {
955 xDocProps
->setSubject(aValue
);
964 // Falls nicht asynchron geladen wird selbst FinishedLoading aufrufen
965 if ( !( pImp
->nLoadedFlags
& SFX_LOADED_MAINDOCUMENT
) &&
966 ( !pMedium
->GetFilter() || pMedium
->GetFilter()->UsesStorage() )
968 FinishedLoading( SFX_LOADED_MAINDOCUMENT
);
970 if( IsOwnStorageFormat_Impl(*pMed
) && pMed
->GetFilter() )
972 //???? dv DirEntry aDirEntry( pMed->GetPhysicalName() );
973 //???? dv SetFileName( aDirEntry.GetFull() );
975 Broadcast( SfxSimpleHint(SFX_HINT_NAMECHANGED
) );
977 if ( SFX_CREATE_MODE_EMBEDDED
!= eCreateMode
)
979 GetpApp()->HideStatusText();
981 SFX_ITEMSET_ARG( pMedium
->GetItemSet(), pAsTempItem
, SfxBoolItem
, SID_TEMPLATE
, sal_False
);
982 SFX_ITEMSET_ARG( pMedium
->GetItemSet(), pPreviewItem
, SfxBoolItem
, SID_PREVIEW
, sal_False
);
983 SFX_ITEMSET_ARG( pMedium
->GetItemSet(), pHiddenItem
, SfxBoolItem
, SID_HIDDEN
, sal_False
);
984 if( bOk
&& pMedium
->GetOrigURL().Len()
985 && !( pAsTempItem
&& pAsTempItem
->GetValue() )
986 && !( pPreviewItem
&& pPreviewItem
->GetValue() )
987 && !( pHiddenItem
&& pHiddenItem
->GetValue() ) )
989 INetURLObject
aUrl( pMedium
->GetOrigURL() );
991 if ( aUrl
.GetProtocol() == INET_PROT_FILE
)
993 const SfxFilter
* pOrgFilter
= pMedium
->GetOrigFilter();
994 SystemShell::AddToRecentDocumentList(
995 aUrl
.GetURLNoPass( INetURLObject::NO_DECODE
),
996 (pOrgFilter
) ? pOrgFilter
->GetMimeType() : String() );
1002 if ( pMedium
->HasStorage_Impl() )
1004 uno::Reference
< XInteractionHandler
> xHandler( pMedium
->GetInteractionHandler() );
1005 if ( xHandler
.is() && !SFX_APP()->Get_Impl()->bODFVersionWarningLater
)
1007 uno::Reference
<beans::XPropertySet
> xStorageProps( pMedium
->GetStorage(), uno::UNO_QUERY_THROW
);
1008 ::rtl::OUString sVersion
;
1011 xStorageProps
->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Version" ) ) ) >>= sVersion
;
1013 catch( const uno::Exception
& )
1015 // Custom Property "ODFVersion" does not exist
1018 if ( sVersion
.getLength() )
1020 double nVersion
= sVersion
.toDouble();
1021 if ( nVersion
> 1.20001 && SfxObjectShell_Impl::NeedsOfficeUpdateDialog() )
1022 // ODF version greater than 1.2 - added some decimal places to be safe against floating point conversion errors (hack)
1024 ::rtl::OUString
sDocumentURL( pMedium
->GetOrigURL() );
1025 ::rtl::OUString aSystemFileURL
;
1026 if ( osl::FileBase::getSystemPathFromFileURL( sDocumentURL
, aSystemFileURL
) == osl::FileBase::E_None
)
1027 sDocumentURL
= aSystemFileURL
;
1029 FutureDocumentVersionProductUpdateRequest aUpdateRequest
;
1030 aUpdateRequest
.Classification
= InteractionClassification_QUERY
;
1031 aUpdateRequest
.DocumentURL
= sDocumentURL
;
1033 ::rtl::Reference
< ::comphelper::OInteractionRequest
> pRequest
= new ::comphelper::OInteractionRequest( makeAny( aUpdateRequest
) );
1034 pRequest
->addContinuation( new ::comphelper::OInteractionApprove
);
1035 pRequest
->addContinuation( new ::comphelper::OInteractionDisapprove
);
1037 typedef ::comphelper::OInteraction
< XInteractionAskLater
> OInteractionAskLater
;
1038 OInteractionAskLater
* pLater
= new OInteractionAskLater
;
1039 pRequest
->addContinuation( pLater
);
1043 xHandler
->handle( pRequest
.get() );
1045 catch( const Exception
& )
1047 DBG_UNHANDLED_EXCEPTION();
1049 if ( pLater
->wasSelected() )
1050 SFX_APP()->Get_Impl()->bODFVersionWarningLater
= true;
1058 GetpApp()->HideStatusText();
1063 sal_uInt32
SfxObjectShell::HandleFilter( SfxMedium
* pMedium
, SfxObjectShell
* pDoc
)
1065 sal_uInt32 nError
= ERRCODE_NONE
;
1066 SfxItemSet
* pSet
= pMedium
->GetItemSet();
1067 SFX_ITEMSET_ARG( pSet
, pOptions
, SfxStringItem
, SID_FILE_FILTEROPTIONS
, sal_False
);
1068 SFX_ITEMSET_ARG( pSet
, pData
, SfxUnoAnyItem
, SID_FILTER_DATA
, sal_False
);
1069 if ( !pData
&& !pOptions
)
1071 com::sun::star::uno::Reference
< XMultiServiceFactory
> xServiceManager
= ::comphelper::getProcessServiceFactory();
1072 com::sun::star::uno::Reference
< XNameAccess
> xFilterCFG
;
1073 if( xServiceManager
.is() )
1075 xFilterCFG
= com::sun::star::uno::Reference
< XNameAccess
>(
1076 xServiceManager
->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.document.FilterFactory" ) ),
1080 if( xFilterCFG
.is() )
1082 BOOL bAbort
= FALSE
;
1084 const SfxFilter
* pFilter
= pMedium
->GetFilter();
1085 Sequence
< PropertyValue
> aProps
;
1086 Any aAny
= xFilterCFG
->getByName( pFilter
->GetName() );
1087 if ( aAny
>>= aProps
)
1089 sal_Int32 nPropertyCount
= aProps
.getLength();
1090 for( sal_Int32 nProperty
=0; nProperty
< nPropertyCount
; ++nProperty
)
1091 if( aProps
[nProperty
].Name
.equals( ::rtl::OUString::createFromAscii("UIComponent")) )
1093 ::rtl::OUString aServiceName
;
1094 aProps
[nProperty
].Value
>>= aServiceName
;
1095 if( aServiceName
.getLength() )
1097 com::sun::star::uno::Reference
< XInteractionHandler
> rHandler
= pMedium
->GetInteractionHandler();
1100 // we need some properties in the media descriptor, so we have to make sure that they are in
1102 aStreamAny
<<= pMedium
->GetInputStream();
1103 if ( pSet
->GetItemState( SID_INPUTSTREAM
) < SFX_ITEM_SET
)
1104 pSet
->Put( SfxUnoAnyItem( SID_INPUTSTREAM
, aStreamAny
) );
1105 if ( pSet
->GetItemState( SID_FILE_NAME
) < SFX_ITEM_SET
)
1106 pSet
->Put( SfxStringItem( SID_FILE_NAME
, pMedium
->GetName() ) );
1107 if ( pSet
->GetItemState( SID_FILTER_NAME
) < SFX_ITEM_SET
)
1108 pSet
->Put( SfxStringItem( SID_FILTER_NAME
, pFilter
->GetName() ) );
1110 Sequence
< PropertyValue
> rProperties
;
1111 TransformItems( SID_OPENDOC
, *pSet
, rProperties
, NULL
);
1112 RequestFilterOptions
* pFORequest
= new RequestFilterOptions( pDoc
->GetModel(), rProperties
);
1114 com::sun::star::uno::Reference
< XInteractionRequest
> rRequest( pFORequest
);
1115 rHandler
->handle( rRequest
);
1117 if ( !pFORequest
->isAbort() )
1119 SfxAllItemSet
aNewParams( pDoc
->GetPool() );
1120 TransformParameters( SID_OPENDOC
,
1121 pFORequest
->getFilterOptions(),
1125 SFX_ITEMSET_ARG( &aNewParams
,
1128 SID_FILE_FILTEROPTIONS
,
1130 if ( pFilterOptions
)
1131 pSet
->Put( *pFilterOptions
);
1133 SFX_ITEMSET_ARG( &aNewParams
,
1139 pSet
->Put( *pFilterData
);
1152 // filter options were not entered
1153 nError
= ERRCODE_ABORT
;
1156 catch( NoSuchElementException
& )
1158 // the filter name is unknown
1159 nError
= ERRCODE_IO_INVALIDPARAMETER
;
1163 nError
= ERRCODE_ABORT
;
1171 //-------------------------------------------------------------------------
1173 sal_Bool
SfxObjectShell::IsOwnStorageFormat_Impl(const SfxMedium
&rMedium
) const
1175 return !rMedium
.GetFilter() || // Embedded
1176 ( rMedium
.GetFilter()->IsOwnFormat() &&
1177 rMedium
.GetFilter()->UsesStorage() &&
1178 rMedium
.GetFilter()->GetVersion() >= SOFFICE_FILEFORMAT_60
);
1181 //-------------------------------------------------------------------------
1183 sal_Bool
SfxObjectShell::IsPackageStorageFormat_Impl(const SfxMedium
&rMedium
) const
1185 return !rMedium
.GetFilter() || // Embedded
1186 ( rMedium
.GetFilter()->UsesStorage() &&
1187 rMedium
.GetFilter()->GetVersion() >= SOFFICE_FILEFORMAT_60
);
1190 //-------------------------------------------------------------------------
1192 sal_Bool
SfxObjectShell::DoSave()
1193 // DoSave wird nur noch ueber OLE aufgerufen. Sichern eigener Dokumente im SFX
1194 // laeuft uber DoSave_Impl, um das Anlegen von Backups zu ermoeglichen.
1195 // Save in eigenes Format jetzt auch wieder Hierueber
1197 sal_Bool bOk
= sal_False
;
1199 ModifyBlocker_Impl
aBlock( this );
1201 pImp
->bIsSaving
= sal_True
;
1203 ::rtl::OUString aPasswd
;
1204 if ( IsPackageStorageFormat_Impl( *GetMedium() ) )
1206 if ( GetPasswd_Impl( GetMedium()->GetItemSet(), aPasswd
) )
1210 //TODO/MBA: GetOutputStorage?! Special mode, because it's "Save"?!
1211 ::comphelper::OStorageHelper::SetCommonStoragePassword( GetMedium()->GetStorage(), aPasswd
);
1214 catch( uno::Exception
& )
1216 SetError( ERRCODE_IO_GENERAL
, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
) ) );
1219 DBG_ASSERT( bOk
, "The root storage must allow to set common password!\n" );
1228 // The basic and dialogs related contents are still not able to proceed with save operation ( saveTo only )
1229 // so since the document storage is locked a workaround has to be used
1231 uno::Reference
< embed::XStorage
> xTmpStorage
= ::comphelper::OStorageHelper::GetTemporaryStorage();
1232 DBG_ASSERT( xTmpStorage
.is(), "If a storage can not be created an exception must be thrown!\n" );
1233 if ( !xTmpStorage
.is() )
1234 throw uno::RuntimeException();
1236 ::rtl::OUString
aBasicStorageName( RTL_CONSTASCII_USTRINGPARAM( "Basic" ) );
1237 ::rtl::OUString
aDialogsStorageName( RTL_CONSTASCII_USTRINGPARAM( "Dialogs" ) );
1238 if ( GetMedium()->GetStorage()->hasByName( aBasicStorageName
) )
1239 GetMedium()->GetStorage()->copyElementTo( aBasicStorageName
, xTmpStorage
, aBasicStorageName
);
1240 if ( GetMedium()->GetStorage()->hasByName( aDialogsStorageName
) )
1241 GetMedium()->GetStorage()->copyElementTo( aDialogsStorageName
, xTmpStorage
, aDialogsStorageName
);
1245 // disconnect from the current storage
1246 pImp
->pBasicManager
->setStorage( xTmpStorage
);
1248 // store to the current storage
1249 pImp
->pBasicManager
->storeLibrariesToStorage( GetMedium()->GetStorage() );
1251 // connect to the current storage back
1252 pImp
->pBasicManager
->setStorage( GetMedium()->GetStorage() );
1254 catch( uno::Exception
& )
1256 SetError( ERRCODE_IO_GENERAL
, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
) ) );
1265 bOk
= pMedium
->Commit();
1270 // SetModified( sal_False );
1274 void Lock_Impl( SfxObjectShell
* pDoc
, BOOL bLock
)
1276 SfxViewFrame
*pFrame
= SfxViewFrame::GetFirst( pDoc
);
1279 pFrame
->GetDispatcher()->Lock( bLock
);
1280 pFrame
->Enable( !bLock
);
1281 pFrame
= SfxViewFrame::GetNext( *pFrame
, pDoc
);
1287 //-------------------------------------------------------------------------
1289 sal_Bool
SfxObjectShell::SaveTo_Impl
1291 SfxMedium
&rMedium
, // Medium, in das gespeichert werden soll
1292 const SfxItemSet
* pSet
1297 Schreibt den aktuellen Inhalt in das Medium rMedium.
1298 Ist das Zielmedium kein Storage, so wird ueber ein temporaeres
1299 Medium gespeichert, sonst direkt, da das Medium transacted
1300 geschaltet ist, wenn wir es selbst geoeffnet haben und falls wir
1301 Server sind entweder der Container einen transacted Storage zur
1302 Verfuegung stellt oder selbst einen temporaeren Storage erzeugt hat.
1306 RTL_LOGFILE_PRODUCT_CONTEXT( aLog
, "PERFORMANCE SfxObjectShell::SaveTo_Impl" );
1307 if( RTL_LOGFILE_HASLOGFILE() )
1309 ByteString
aString( rMedium
.GetName(), RTL_TEXTENCODING_ASCII_US
);
1310 RTL_LOGFILE_PRODUCT_CONTEXT_TRACE1( aLog
, "saving \"%s\"", aString
.GetBuffer() );
1313 AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
"Begin" ) ) );
1315 ModifyBlocker_Impl
aMod(this);
1317 const SfxFilter
*pFilter
= rMedium
.GetFilter();
1320 // if no filter was set, use the default filter
1321 // this should be changed in the feature, it should be an error!
1322 DBG_ERROR("No filter set!");
1323 pFilter
= GetFactory().GetFilterContainer()->GetAnyFilter( SFX_FILTER_IMPORT
| SFX_FILTER_EXPORT
);
1324 rMedium
.SetFilter(pFilter
);
1327 sal_Bool bStorageBasedSource
= IsPackageStorageFormat_Impl( *pMedium
);
1328 sal_Bool bStorageBasedTarget
= IsPackageStorageFormat_Impl( rMedium
);
1329 sal_Bool bOwnSource
= IsOwnStorageFormat_Impl( *pMedium
);
1330 sal_Bool bOwnTarget
= IsOwnStorageFormat_Impl( rMedium
);
1332 // Examine target format to determine whether to query if any password
1333 // protected libraries exceed the size we can handler
1334 if ( bOwnTarget
&& !QuerySaveSizeExceededModules_Impl( rMedium
.GetInteractionHandler() ) )
1336 SetError( ERRCODE_IO_ABORT
, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
) ) );
1340 sal_Bool bNeedsDisconnectionOnFail
= sal_False
;
1342 sal_Bool bStoreToSameLocation
= sal_False
;
1344 // the detection whether the script is changed should be done before saving
1345 sal_Bool bTryToPreservScriptSignature
= sal_False
;
1346 // no way to detect whether a filter is oasis format, have to wait for saving process
1347 sal_Bool bNoPreserveForOasis
= sal_False
;
1348 if ( bOwnSource
&& bOwnTarget
1349 && ( pImp
->nScriptingSignatureState
== SIGNATURESTATE_SIGNATURES_OK
1350 || pImp
->nScriptingSignatureState
== SIGNATURESTATE_SIGNATURES_NOTVALIDATED
1351 || pImp
->nScriptingSignatureState
== SIGNATURESTATE_SIGNATURES_INVALID
) )
1353 AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
"MacroSignaturePreserving" ) ) );
1355 // the checking of the library modified state iterates over the libraries, should be done only when required
1356 bTryToPreservScriptSignature
= !pImp
->pBasicManager
->isAnyContainerModified();
1357 if ( bTryToPreservScriptSignature
)
1359 // check that the storage format stays the same
1360 SvtSaveOptions aSaveOpt
;
1361 SvtSaveOptions::ODFDefaultVersion nVersion
= aSaveOpt
.GetODFDefaultVersion();
1363 ::rtl::OUString aODFVersion
;
1366 uno::Reference
< beans::XPropertySet
> xPropSet( GetStorage(), uno::UNO_QUERY_THROW
);
1367 xPropSet
->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Version" ) ) ) >>= aODFVersion
;
1369 catch( uno::Exception
& )
1372 // preserve only if the same filter has been used
1373 bTryToPreservScriptSignature
= pMedium
->GetFilter() && pFilter
&& pMedium
->GetFilter()->GetFilterName() == pFilter
->GetFilterName();
1375 bNoPreserveForOasis
= (
1376 (aODFVersion
.equals( ODFVER_012_TEXT
) && nVersion
== SvtSaveOptions::ODFVER_011
) ||
1377 (!aODFVersion
.getLength() && nVersion
== SvtSaveOptions::ODFVER_012
)
1382 sal_Bool bCopyTo
= sal_False
;
1383 SfxItemSet
*pMedSet
= rMedium
.GetItemSet();
1386 SFX_ITEMSET_ARG( pMedSet
, pSaveToItem
, SfxBoolItem
, SID_SAVETO
, sal_False
);
1387 bCopyTo
= GetCreateMode() == SFX_CREATE_MODE_EMBEDDED
||
1388 (pSaveToItem
&& pSaveToItem
->GetValue());
1391 // use UCB for case sensitive/insensitive file name comparison
1393 && pMedium
->GetName().CompareIgnoreCaseToAscii( "private:stream", 14 ) != COMPARE_EQUAL
1394 && rMedium
.GetName().CompareIgnoreCaseToAscii( "private:stream", 14 ) != COMPARE_EQUAL
1395 && SfxMedium::EqualURLs( pMedium
->GetName(), rMedium
.GetName() ) )
1397 bStoreToSameLocation
= sal_True
;
1398 AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
"Save" ) ) );
1400 if ( pMedium
->DocNeedsFileDateCheck() )
1401 rMedium
.CheckFileDate( pMedium
->GetInitFileDate( sal_False
) );
1403 if ( bCopyTo
&& GetCreateMode() != SFX_CREATE_MODE_EMBEDDED
)
1405 // export to the same location is vorbidden
1406 SetError( ERRCODE_IO_CANTWRITE
, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
) ) );
1410 // before we overwrite the original file, we will make a backup if there is a demand for that
1411 // if the backup is not created here it will be created internally and will be removed in case of successful saving
1412 const sal_Bool bDoBackup
= SvtSaveOptions().IsBackup();
1415 AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
"DoBackup" ) ) );
1416 rMedium
.DoBackup_Impl();
1417 if ( rMedium
.GetError() )
1419 SetError( rMedium
.GetErrorCode(), ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
) ) );
1420 rMedium
.ResetError();
1424 if ( bStorageBasedSource
&& bStorageBasedTarget
)
1426 // The active storage must be switched. The simple saving is not enough.
1427 // The problem is that the target medium contains target MediaDescriptor.
1429 // In future the switch of the persistance could be done on stream level:
1430 // a new wrapper service will be implemented that allows to exchange
1431 // persistance on the fly. So the real persistance will be set
1432 // to that stream only after successful commit of the storage.
1434 // create wrapper stream based on the URL
1435 // create a new storage based on this stream
1436 // store to this new storage
1437 // commit the new storage
1438 // call saveCompleted based with this new storage ( get rid of old storage and "frees" URL )
1439 // commit the wrapper stream ( the stream will connect the URL only on commit, after that it will hold it )
1440 // if the last step is failed the stream should stay to be transacted and should be commited on any flush
1441 // so we can forget the stream in any way and the next storage commit will flush it
1443 AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
"Save: Own to Own" ) ) );
1445 bNeedsDisconnectionOnFail
= DisconnectStorage_Impl(
1446 *pMedium
, rMedium
);
1447 if ( bNeedsDisconnectionOnFail
1448 || ConnectTmpStorage_Impl( pMedium
->GetStorage(), pMedium
) )
1450 pMedium
->CloseAndRelease();
1452 // TODO/LATER: for now the medium must be closed since it can already contain streams from old medium
1453 // in future those streams should not be copied in case a valid target url is provided,
1454 // if the url is not provided ( means the document is based on a stream ) this code is not
1456 rMedium
.CloseAndRelease();
1457 rMedium
.GetOutputStorage();
1460 else if ( !bStorageBasedSource
&& !bStorageBasedTarget
)
1462 // the source and the target formats are alien
1463 // just disconnect the stream from the source format
1464 // so that the target medium can use it
1466 AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
"Save: Alien to Alien" ) ) );
1468 pMedium
->CloseAndRelease();
1469 rMedium
.CloseAndRelease();
1470 rMedium
.CreateTempFileNoCopy();
1471 rMedium
.GetOutStream();
1473 else if ( !bStorageBasedSource
&& bStorageBasedTarget
)
1475 // the source format is an alien one but the target
1476 // format is an own one so just disconnect the source
1479 AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
"Save: Alien to Own" ) ) );
1481 pMedium
->CloseAndRelease();
1482 rMedium
.CloseAndRelease();
1483 rMedium
.GetOutputStorage();
1485 else // means if ( bStorageBasedSource && !bStorageBasedTarget )
1487 // the source format is an own one but the target is
1488 // an alien format, just connect the source to temporary
1491 AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
"Save: Own to Alien" ) ) );
1493 bNeedsDisconnectionOnFail
= DisconnectStorage_Impl(
1494 *pMedium
, rMedium
);
1495 if ( bNeedsDisconnectionOnFail
1496 || ConnectTmpStorage_Impl( pMedium
->GetStorage(), pMedium
) )
1498 pMedium
->CloseAndRelease();
1499 rMedium
.CloseAndRelease();
1500 rMedium
.CreateTempFileNoCopy();
1501 rMedium
.GetOutStream();
1508 // This is SaveAs or export action, prepare the target medium
1509 // the alien filters still might write directly to the file, that is of course a bug,
1510 // but for now the framework has to be ready for it
1511 // TODO/LATER: let the medium be prepared for alien formats as well
1513 AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
"SaveAs/Export" ) ) );
1515 rMedium
.CloseAndRelease();
1516 if ( bStorageBasedTarget
)
1518 rMedium
.GetOutputStorage();
1522 // TODO/LATER: error handling
1523 if( rMedium
.GetErrorCode() || pMedium
->GetErrorCode() || GetErrorCode() )
1526 AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
"Locking" ) ) );
1528 rMedium
.LockOrigFileOnDemand( sal_False
, sal_False
);
1530 if ( bStorageBasedTarget
)
1532 if ( rMedium
.GetErrorCode() )
1535 // If the filter is a "cross export" filter ( f.e. a filter for exporting an impress document from
1536 // a draw document ), the ClassId of the destination storage is different from the ClassId of this
1537 // document. It can be retrieved from the default filter for the desired target format
1538 long nFormat
= rMedium
.GetFilter()->GetFormat();
1539 SfxFilterMatcher
& rMatcher
= SFX_APP()->GetFilterMatcher();
1540 const SfxFilter
*pFilt
= rMatcher
.GetFilter4ClipBoardId( nFormat
);
1543 if ( pFilt
->GetServiceName() != rMedium
.GetFilter()->GetServiceName() )
1545 //REMOVE rMedium.GetStorage()->SetClass( SvFactory::GetServerName( nFormat ), nFormat, pFilt->GetTypeName() );
1546 datatransfer::DataFlavor aDataFlavor
;
1547 SotExchange::GetFormatDataFlavor( nFormat
, aDataFlavor
);
1551 uno::Reference
< beans::XPropertySet
> xProps( rMedium
.GetStorage(), uno::UNO_QUERY
);
1552 DBG_ASSERT( xProps
.is(), "The storage implementation must implement XPropertySet!" );
1554 throw uno::RuntimeException();
1556 xProps
->setPropertyValue( ::rtl::OUString::createFromAscii( "MediaType" ),
1557 uno::makeAny( aDataFlavor
.MimeType
) );
1559 catch( uno::Exception
& )
1566 // TODO/LATER: error handling
1567 if( rMedium
.GetErrorCode() || pMedium
->GetErrorCode() || GetErrorCode() )
1570 sal_Bool bOldStat
= pImp
->bForbidReload
;
1571 pImp
->bForbidReload
= sal_True
;
1573 // lock user interface while saving the document
1574 Lock_Impl( this, sal_True
);
1576 sal_Bool bOk
= sal_False
;
1577 // TODO/LATER: get rid of bOk
1579 if( bOwnTarget
&& !( pFilter
->GetFilterFlags() & SFX_FILTER_STARONEFILTER
) )
1581 AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
"Storing in own format." ) ) );
1582 uno::Reference
< embed::XStorage
> xMedStorage
= rMedium
.GetStorage();
1583 if ( !xMedStorage
.is() )
1585 // no saving without storage, unlock UI and return
1586 Lock_Impl( this, sal_False
);
1587 pImp
->bForbidReload
= bOldStat
;
1588 AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
"Storing failed, still no error set." ) ) );
1592 // transfer password from the parameters to the storage
1593 ::rtl::OUString aPasswd
;
1594 sal_Bool bPasswdProvided
= sal_False
;
1595 if ( GetPasswd_Impl( rMedium
.GetItemSet(), aPasswd
) )
1597 bPasswdProvided
= sal_True
;
1599 ::comphelper::OStorageHelper::SetCommonStoragePassword( xMedStorage
, aPasswd
);
1602 catch( uno::Exception
& )
1604 DBG_ERROR( "Setting of common encryption key failed!" );
1605 SetError( ERRCODE_IO_GENERAL
, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
) ) );
1611 pFilter
= rMedium
.GetFilter();
1613 const SfxStringItem
*pVersionItem
= pSet
? (const SfxStringItem
*)
1614 SfxRequest::GetItem( pSet
, SID_DOCINFO_COMMENTS
, sal_False
, TYPE(SfxStringItem
) ) : NULL
;
1615 ::rtl::OUString aTmpVersionURL
;
1620 // currently the case that the storage is the same should be impossible
1621 if ( xMedStorage
== GetStorage() )
1623 OSL_ENSURE( !pVersionItem
, "This scenario is impossible currently!\n" );
1624 AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
"Should be impossible." ) ) );
1625 // usual save procedure
1631 AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
"Save as own format." ) ) );
1632 bOk
= SaveAsOwnFormat( rMedium
);
1633 if ( bOk
&& pVersionItem
)
1635 AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
"pVersionItem != NULL" ) ) );
1636 aTmpVersionURL
= CreateTempCopyOfStorage_Impl( xMedStorage
);
1637 bOk
= ( aTmpVersionURL
.getLength() > 0 );
1643 if ( bOk
&& GetCreateMode() != SFX_CREATE_MODE_EMBEDDED
)
1645 // store the thumbnail representation image
1646 AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
"Thumbnail creation." ) ) );
1647 if ( !GenerateAndStoreThumbnail( bPasswdProvided
,
1649 pFilter
->IsOwnTemplateFormat(),
1652 // TODO: error handling
1653 OSL_ENSURE( sal_False
, "Couldn't store thumbnail representation!" );
1659 if ( pImp
->bIsSaving
|| pImp
->bPreserveVersions
)
1661 AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
"Preserve versions." ) ) );
1664 Sequence
< util::RevisionTag
> aVersions
= rMedium
.GetVersionList();
1665 if ( aVersions
.getLength() )
1667 // copy the version streams
1668 ::rtl::OUString
aVersionsName( RTL_CONSTASCII_USTRINGPARAM( "Versions" ) );
1669 uno::Reference
< embed::XStorage
> xNewVerStor
= xMedStorage
->openStorageElement(
1671 embed::ElementModes::READWRITE
);
1672 uno::Reference
< embed::XStorage
> xOldVerStor
= GetStorage()->openStorageElement(
1674 embed::ElementModes::READ
);
1675 if ( !xNewVerStor
.is() || !xOldVerStor
.is() )
1676 throw uno::RuntimeException();
1678 for ( sal_Int32 n
=0; n
<aVersions
.getLength(); n
++ )
1680 if ( xOldVerStor
->hasByName( aVersions
[n
].Identifier
) )
1681 xOldVerStor
->copyElementTo( aVersions
[n
].Identifier
, xNewVerStor
, aVersions
[n
].Identifier
);
1684 uno::Reference
< embed::XTransactedObject
> xTransact( xNewVerStor
, uno::UNO_QUERY
);
1685 if ( xTransact
.is() )
1686 xTransact
->commit();
1689 catch( uno::Exception
& )
1691 AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
"Preserve versions has failed." ) ) );
1692 DBG_ERROR( "Couldn't copy versions!\n" );
1694 // TODO/LATER: a specific error could be set
1698 if ( bOk
&& pVersionItem
)
1700 // store a version also
1701 const SfxStringItem
*pAuthorItem
= pSet
? (const SfxStringItem
*)
1702 SfxRequest::GetItem( pSet
, SID_DOCINFO_AUTHOR
, sal_False
, TYPE(SfxStringItem
) ) : NULL
;
1705 util::RevisionTag aInfo
;
1706 aInfo
.Comment
= pVersionItem
->GetValue();
1711 aInfo
.Author
= pAuthorItem
->GetValue();
1713 // if not transferred as a parameter, get it from user settings
1714 aInfo
.Author
= SvtUserOptions().GetFullName();
1717 aInfo
.TimeStamp
.Day
= aTime
.GetDay();
1718 aInfo
.TimeStamp
.Month
= aTime
.GetMonth();
1719 aInfo
.TimeStamp
.Year
= aTime
.GetYear();
1720 aInfo
.TimeStamp
.Hours
= aTime
.GetHour();
1721 aInfo
.TimeStamp
.Minutes
= aTime
.GetMin();
1722 aInfo
.TimeStamp
.Seconds
= aTime
.GetSec();
1726 // add new version information into the versionlist and save the versionlist
1727 // the version list must have been transferred from the "old" medium before
1728 rMedium
.AddVersion_Impl( aInfo
);
1729 rMedium
.SaveVersionList_Impl( sal_True
);
1730 bOk
= PutURLContentsToVersionStream_Impl( aTmpVersionURL
, xMedStorage
, aInfo
.Identifier
);
1733 else if ( bOk
&& ( pImp
->bIsSaving
|| pImp
->bPreserveVersions
) )
1735 rMedium
.SaveVersionList_Impl( sal_True
);
1739 if ( aTmpVersionURL
.getLength() )
1740 ::utl::UCBContentHelper::Kill( aTmpVersionURL
);
1744 AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
"Storing in alien format." ) ) );
1745 // it's a "SaveAs" in an alien format
1746 if ( rMedium
.GetFilter() && ( rMedium
.GetFilter()->GetFilterFlags() & SFX_FILTER_STARONEFILTER
) )
1747 bOk
= ExportTo( rMedium
);
1749 bOk
= ConvertTo( rMedium
);
1751 // after saving the document, the temporary object storage must be updated
1752 // if the old object storage was not a temporary one, it will be updated also, because it will be used
1753 // as a source for copying the objects into the new temporary storage that will be created below
1754 // updating means: all child objects must be stored into it
1755 // ( same as on loading, where these objects are copied to the temporary storage )
1756 // but don't commit these changes, because in the case when the old object storage is not a temporary one,
1757 // all changes will be written into the original file !
1759 if( bOk
&& !bCopyTo
)
1760 // we also don't touch any graphical replacements here
1761 bOk
= SaveChildren( TRUE
);
1764 // if ODF version of oasis format changes on saving the signature should not be preserved
1765 if ( bOk
&& bTryToPreservScriptSignature
&& bNoPreserveForOasis
)
1766 bTryToPreservScriptSignature
= ( SotStorage::GetVersion( rMedium
.GetStorage() ) == SOFFICE_FILEFORMAT_60
);
1768 uno::Reference
< security::XDocumentDigitalSignatures
> xDDSigns
;
1769 sal_Bool bScriptSignatureIsCopied
= sal_False
;
1770 if ( bOk
&& bTryToPreservScriptSignature
)
1772 // if the scripting code was not changed and it is signed the signature should be preserved
1773 // unfortunately at this point we have only information whether the basic code has changed or not
1774 // so the only way is to check the signature if the basic was not changed
1777 xDDSigns
= uno::Reference
< security::XDocumentDigitalSignatures
>(
1778 comphelper::getProcessServiceFactory()->createInstance(
1780 RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.security.DocumentDigitalSignatures" ) ) ),
1781 uno::UNO_QUERY_THROW
);
1783 ::rtl::OUString aScriptSignName
= xDDSigns
->getScriptingContentSignatureDefaultStreamName();
1785 if ( aScriptSignName
.getLength() )
1787 uno::Reference
< embed::XStorage
> xMetaInf
= GetStorage()->openStorageElement(
1788 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "META-INF" ) ),
1789 embed::ElementModes::READ
);
1790 uno::Reference
< embed::XStorage
> xTargetMetaInf
= rMedium
.GetStorage()->openStorageElement(
1791 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "META-INF" ) ),
1792 embed::ElementModes::WRITE
);
1794 if ( xMetaInf
.is() && xTargetMetaInf
.is() )
1796 xMetaInf
->copyElementTo( aScriptSignName
, xTargetMetaInf
, aScriptSignName
);
1798 // after loading the UseCommonStoragePassword property might be set to true
1799 // set it to false here, since this is a rare case when it must be so
1800 // TODO/LATER: in future it should be done on loading probably
1801 uno::Reference
< beans::XPropertySet
> xTargetSignPropSet(
1802 xTargetMetaInf
->openStreamElement( aScriptSignName
, embed::ElementModes::WRITE
),
1803 uno::UNO_QUERY_THROW
);
1804 xTargetSignPropSet
->setPropertyValue(
1805 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "UseCommonStoragePasswordEncryption" ) ),
1806 uno::makeAny( (sal_Bool
)sal_False
) );
1808 uno::Reference
< embed::XTransactedObject
> xTransact( xTargetMetaInf
, uno::UNO_QUERY
);
1809 if ( xTransact
.is() )
1810 xTransact
->commit();
1811 bScriptSignatureIsCopied
= sal_True
;
1815 catch( uno::Exception
& )
1822 AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
"Medium commit." ) ) );
1824 // transfer data to its destinated location
1825 // the medium commits the storage or the stream it is based on
1826 RegisterTransfer( rMedium
);
1828 if ( bOk
&& bScriptSignatureIsCopied
)
1830 AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
"Script signature check." ) ) );
1831 bOk
= rMedium
.Commit();
1833 // if the script signature was copied it should be checked now
1834 // usually it should be ok, so no additional actions will be done
1835 // but if for any reasong ( f.e. binshell change ) it is broken it should be removed here
1836 // in result the behaviour will work in optimized way in most cases, means in case of signed basic scripts
1837 OSL_ENSURE( !bScriptSignatureIsCopied
|| xDDSigns
.is(), "The signing could not be done without the service!\n" );
1838 if ( xDDSigns
.is() )
1843 ::com::sun::star::uno::Sequence
< security::DocumentSignatureInformation
> aInfos
=
1844 xDDSigns
->verifyScriptingContentSignatures( rMedium
.GetLastCommitReadStorage_Impl(),
1845 uno::Reference
< io::XInputStream
>() );
1846 sal_uInt16 nState
= ImplCheckSignaturesInformation( aInfos
);
1847 if ( nState
== SIGNATURESTATE_SIGNATURES_OK
|| nState
== SIGNATURESTATE_SIGNATURES_NOTVALIDATED
)
1849 rMedium
.SetCachedSignatureState_Impl( nState
);
1854 // the signature is broken, remove it
1855 rMedium
.SetCachedSignatureState_Impl( SIGNATURESTATE_NOSIGNATURES
);
1856 uno::Reference
< embed::XStorage
> xTargetMetaInf
= rMedium
.GetStorage()->openStorageElement(
1857 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "META-INF" ) ),
1858 embed::ElementModes::WRITE
);
1860 if ( xTargetMetaInf
.is() )
1862 xTargetMetaInf
->removeElement( xDDSigns
->getScriptingContentSignatureDefaultStreamName() );
1863 uno::Reference
< embed::XTransactedObject
> xTransact( xTargetMetaInf
, uno::UNO_QUERY
);
1864 if ( xTransact
.is() )
1865 xTransact
->commit();
1870 catch( uno::Exception
)
1872 OSL_ENSURE( sal_False
, "This exception must not happen!" );
1877 if (bOk
) { // commit *before* we do the conversion!
1878 bOk
= rMedium
.Commit();
1881 uno::Reference
< embed::XStorage
> xNewTmpStorage
;
1883 String aUserData
=pFilter
->GetUserData();
1884 // check whether a postprocessing step is requested in the configuration
1885 static const char POSTPROCESS_CONST
[]="Postprocess=<";
1886 int pos
=aUserData
.Search(::rtl::OUString::createFromAscii(POSTPROCESS_CONST
).getStr(), 0);
1887 int end
=aUserData
.Search( '>', pos
+strlen(POSTPROCESS_CONST
));
1888 if (pos
!=STRING_NOTFOUND
&& end
!=STRING_NOTFOUND
) {
1889 String
aAppName(aUserData
, pos
+strlen(POSTPROCESS_CONST
), end
-(pos
+strlen(POSTPROCESS_CONST
)));
1892 SfxItemSet
*pSet
= rMedium
.GetItemSet();
1893 const SfxUnoAnyItem
*pItem
=NULL
;
1894 SfxItemState ret
=pSet
->GetItemState( SID_PROGRESS_STATUSBAR_CONTROL
, TRUE
, (const SfxPoolItem
**)&pItem
);
1895 uno::Reference
< ::com::sun::star::task::XStatusIndicator
> xStatusIndicator
;
1896 if (ret
==SFX_ITEM_SET
&& pItem
!=NULL
)
1898 pItem
->GetValue() >>= xStatusIndicator
;
1902 ::rtl::OUString aTmpVersionURL
= CreateTempCopyOfStorage_Impl( rMedium
.GetStorage() );
1903 rMedium
.CloseAndRelease();
1905 rtl::OUString aSourceFile
;
1906 osl::FileBase::getSystemPathFromFileURL(aTmpVersionURL
, aSourceFile
);
1907 String
aTargetFile(rMedium
.GetPhysicalName());
1909 // remove the current target file after it was copied
1910 // the postprocess might crash and the unprocessed file would confuse users
1911 String aTargetFileURL
;
1912 ::utl::LocalFileHelper::ConvertPhysicalNameToURL( aTargetFile
, aTargetFileURL
);
1913 osl_removeFile(::rtl::OUString(aTargetFileURL
).pData
);
1915 bOk
=invokeExternalApp(aAppName
, aSourceFile
, aTargetFile
, xStatusIndicator
);
1918 // create a new tmp storage
1919 xNewTmpStorage
=::comphelper::OStorageHelper::GetStorageFromURL( aTmpVersionURL
, embed::ElementModes::READWRITE
);
1920 // it does not make sense to reopen the file if it was not saved correctly
1926 if (bOk
&& xNewTmpStorage
.is()) {
1927 rMedium
.SetStorage_Impl(xNewTmpStorage
);
1932 AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
"Storing is successful." ) ) );
1934 // if the target medium is an alien format and the "old" medium was an own format and the "old" medium
1935 // has a name, the object storage must be exchanged, because now we need a new temporary storage
1936 // as object storage
1937 if ( !bCopyTo
&& bStorageBasedSource
&& !bStorageBasedTarget
)
1939 if ( bStoreToSameLocation
)
1941 // if the old medium already disconnected from document storage, the storage still must
1942 // be switched if backup file is used
1943 if ( bNeedsDisconnectionOnFail
)
1944 ConnectTmpStorage_Impl( pImp
->m_xDocStorage
, NULL
);
1946 else if ( pMedium
->GetName().Len()
1947 || ( pMedium
->HasStorage_Impl() && pMedium
->WillDisposeStorageOnClose_Impl() ) )
1949 OSL_ENSURE( pMedium
->GetName().Len(), "Fallback is used, the medium without name should not dispose the storage!\n" );
1950 // copy storage of old medium to new temporary storage and take this over
1951 if( !ConnectTmpStorage_Impl( pMedium
->GetStorage(), pMedium
) )
1953 AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
"Process after storing has failed." ) ) );
1961 AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
"Storing has failed." ) ) );
1963 // in case the document storage was connected to backup temporarely it must be disconnected now
1964 if ( bNeedsDisconnectionOnFail
)
1965 ConnectTmpStorage_Impl( pImp
->m_xDocStorage
, NULL
);
1969 // unlock user interface
1970 Lock_Impl( this, sal_False
);
1971 pImp
->bForbidReload
= bOldStat
;
1977 ::ucbhelper::Content
aContent( rMedium
.GetName(), com::sun::star::uno::Reference
< XCommandEnvironment
>() );
1978 com::sun::star::uno::Reference
< XPropertySetInfo
> xProps
= aContent
.getProperties();
1981 ::rtl::OUString
aAuthor( RTL_CONSTASCII_USTRINGPARAM("Author") );
1982 ::rtl::OUString
aKeywords( RTL_CONSTASCII_USTRINGPARAM("Keywords") );
1983 ::rtl::OUString
aSubject( RTL_CONSTASCII_USTRINGPARAM("Subject") );
1986 uno::Reference
<document::XDocumentPropertiesSupplier
> xDPS(
1987 GetModel(), uno::UNO_QUERY_THROW
);
1988 uno::Reference
<document::XDocumentProperties
> xDocProps
1989 = xDPS
->getDocumentProperties();
1991 if ( xProps
->hasPropertyByName( aAuthor
) )
1993 aAny
<<= xDocProps
->getAuthor();
1994 aContent
.setPropertyValue( aAuthor
, aAny
);
1996 if ( xProps
->hasPropertyByName( aKeywords
) )
1998 aAny
<<= ::comphelper::string::convertCommaSeparated(
1999 xDocProps
->getKeywords());
2000 aContent
.setPropertyValue( aKeywords
, aAny
);
2002 if ( xProps
->hasPropertyByName( aSubject
) )
2004 aAny
<<= xDocProps
->getSubject();
2005 aContent
.setPropertyValue( aSubject
, aAny
);
2017 //------------------------------------------------------------------------
2018 sal_Bool
SfxObjectShell::DisconnectStorage_Impl( SfxMedium
& rSrcMedium
, SfxMedium
& rTargetMedium
)
2020 RTL_LOGFILE_CONTEXT( aLog
, "sfx2 (mv76033) SfxObjectShell::DisconnectStorage_Impl" );
2022 // this method disconnects the storage from source medium, and attaches it to the backup created by the target medium
2024 uno::Reference
< embed::XStorage
> xStorage
= rSrcMedium
.GetStorage();
2026 sal_Bool bResult
= sal_False
;
2027 if ( xStorage
== pImp
->m_xDocStorage
)
2031 uno::Reference
< embed::XOptimizedStorage
> xOptStorage( xStorage
, uno::UNO_QUERY_THROW
);
2032 ::rtl::OUString aBackupURL
= rTargetMedium
.GetBackup_Impl();
2033 if ( aBackupURL
.getLength() )
2035 // the following call will only compare stream sizes
2036 // TODO/LATER: this is a very risky part, since if the URL contents are different from the storage
2037 // contents, the storag will be broken
2038 xOptStorage
->attachToURL( aBackupURL
, sal_True
);
2040 // the storage is successfuly attached to backup, thus it it owned by the document not by the medium
2041 rSrcMedium
.CanDisposeStorage_Impl( sal_False
);
2045 catch ( uno::Exception
& )
2049 OSL_ENSURE( bResult
, "Storage disconnecting has failed - affects performance!" );
2054 //------------------------------------------------------------------------
2056 sal_Bool
SfxObjectShell::ConnectTmpStorage_Impl(
2057 const uno::Reference
< embed::XStorage
>& xStorage
,
2058 SfxMedium
* pMediumArg
)
2062 Arbeitet die Applikation auf einem temporaeren Storage,
2063 so darf der temporaere Storage nicht aus dem SaveCompleted
2064 genommen werden. Daher wird in diesem Fall schon hier an
2065 den neuen Storage connected. SaveCompleted tut dann nichts.
2070 RTL_LOGFILE_CONTEXT( aLog
, "sfx2 (mv76033) SfxObjectShell::ConnectTmpStorage_Impl" );
2072 sal_Bool bResult
= sal_False
;
2074 if ( xStorage
.is() )
2078 // the empty argument means that the storage will create temporary stream itself
2079 uno::Reference
< embed::XOptimizedStorage
> xOptStorage( xStorage
, uno::UNO_QUERY_THROW
);
2080 xOptStorage
->writeAndAttachToStream( uno::Reference
< io::XStream
>() );
2082 // the storage is successfuly disconnected from the original sources, thus the medium must not dispose it
2084 pMediumArg
->CanDisposeStorage_Impl( sal_False
);
2088 catch( uno::Exception
& )
2092 // if switching of the storage does not work for any reason ( nonroot storage for example ) use the old method
2095 uno::Reference
< embed::XStorage
> xTmpStorage
= ::comphelper::OStorageHelper::GetTemporaryStorage();
2097 DBG_ASSERT( xTmpStorage
.is(), "If a storage can not be created an exception must be thrown!\n" );
2098 if ( !xTmpStorage
.is() )
2099 throw uno::RuntimeException();
2101 // TODO/LATER: may be it should be done in SwitchPersistence also
2102 // TODO/LATER: find faster way to copy storage; perhaps sharing with backup?!
2103 xStorage
->copyToStorage( xTmpStorage
);
2104 //CopyStoragesOfUnknownMediaType( xStorage, xTmpStorage );
2105 bResult
= SaveCompleted( xTmpStorage
);
2108 pImp
->pBasicManager
->setStorage( xTmpStorage
);
2110 catch( uno::Exception
& )
2115 // TODO/LATER: may need error code setting based on exception
2116 SetError( ERRCODE_IO_GENERAL
, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
) ) );
2123 //-------------------------------------------------------------------------
2125 sal_Bool
SfxObjectShell::DoSaveObjectAs( SfxMedium
& rMedium
, BOOL bCommit
)
2127 sal_Bool bOk
= sal_False
;
2129 ModifyBlocker_Impl
aBlock( this );
2131 uno::Reference
< embed::XStorage
> xNewStor
= rMedium
.GetStorage();
2132 if ( !xNewStor
.is() )
2135 uno::Reference
< beans::XPropertySet
> xPropSet( xNewStor
, uno::UNO_QUERY
);
2136 if ( xPropSet
.is() )
2138 Any a
= xPropSet
->getPropertyValue( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "MediaType" ) ) );
2139 ::rtl::OUString aMediaType
;
2140 if ( !(a
>>=aMediaType
) || !aMediaType
.getLength() )
2142 OSL_ENSURE( sal_False
, "The mediatype must be set already!\n" );
2143 SetupStorage( xNewStor
, SOFFICE_FILEFORMAT_CURRENT
, sal_False
);
2146 pImp
->bIsSaving
= sal_False
;
2147 bOk
= SaveAsOwnFormat( rMedium
);
2152 uno::Reference
< embed::XTransactedObject
> xTransact( xNewStor
, uno::UNO_QUERY_THROW
);
2153 xTransact
->commit();
2155 catch( uno::Exception
& )
2157 DBG_ERROR( "The strotage was not commited on DoSaveAs!\n" );
2166 //-------------------------------------------------------------------------
2167 // TODO/LATER: may be the call must be removed completelly
2168 sal_Bool
SfxObjectShell::DoSaveAs( SfxMedium
& rMedium
)
2170 // hier kommen nur Root-Storages rein, die via Temp-File gespeichert werden
2171 rMedium
.CreateTempFileNoCopy();
2172 SetError(rMedium
.GetErrorCode(), ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
) ) );
2176 // copy version list from "old" medium to target medium, so it can be used on saving
2177 if ( pImp
->bPreserveVersions
)
2178 rMedium
.TransferVersionList_Impl( *pMedium
);
2180 sal_Bool bRet
= SaveTo_Impl( rMedium
, NULL
);
2182 SetError(rMedium
.GetErrorCode(), ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
) ) );
2186 //-------------------------------------------------------------------------
2188 sal_Bool
SfxObjectShell::DoSaveCompleted( SfxMedium
* pNewMed
)
2190 RTL_LOGFILE_CONTEXT( aLog
, "sfx2 (mv76033) SfxObjectShell::DoSaveCompleted" );
2192 sal_Bool bOk
= sal_True
;
2193 sal_Bool bMedChanged
= pNewMed
&& pNewMed
!=pMedium
;
2194 /* sal_Bool bCreatedTempStor = pNewMed && pMedium &&
2195 IsPackageStorageFormat_Impl(*pMedium) &&
2196 !IsPackageStorageFormat_Impl(*pNewMed) &&
2197 pMedium->GetName().Len();
2199 DBG_ASSERT( !pNewMed
|| pNewMed
->GetError() == ERRCODE_NONE
, "DoSaveCompleted: Medium has error!" );
2201 // delete Medium (and Storage!) after all notifications
2202 SfxMedium
* pOld
= pMedium
;
2206 pMedium
->CanDisposeStorage_Impl( sal_True
);
2209 const SfxFilter
*pFilter
= pMedium
? pMedium
->GetFilter() : 0;
2214 if( pNewMed
->GetName().Len() )
2215 bHasName
= sal_True
;
2216 Broadcast( SfxSimpleHint(SFX_HINT_NAMECHANGED
) );
2217 getDocProperties()->setGenerator(
2218 ::utl::DocInfoHelper::GetGeneratorString() );
2221 uno::Reference
< embed::XStorage
> xStorage
;
2222 if ( !pFilter
|| IsPackageStorageFormat_Impl( *pMedium
) )
2224 uno::Reference
< embed::XStorage
> xOld
= GetStorage();
2226 // when the package based medium is broken and has no storage or if the storage
2227 // is the same as the document storage the current document storage should be preserved
2228 xStorage
= pMedium
->GetStorage();
2229 bOk
= SaveCompleted( xStorage
);
2230 if ( bOk
&& xStorage
.is() && xOld
!= xStorage
2231 && (!pOld
|| !pOld
->HasStorage_Impl() || xOld
!= pOld
->GetStorage() ) )
2233 // old own storage was not controlled by old Medium -> dispose it
2236 } catch( uno::Exception
& )
2238 // the storage is disposed already
2239 // can happen during reload scenario when the medium has disposed it during the closing
2240 // will be fixed in one of the next milestones
2246 //REMOVE if( pFilter->UsesStorage() )
2247 //REMOVE pMedium->GetStorage();
2248 //REMOVE else if( pMedium->GetOpenMode() & STREAM_WRITE )
2249 if( pMedium
->GetOpenMode() & STREAM_WRITE
)
2250 pMedium
->GetInStream();
2251 xStorage
= GetStorage();
2254 // TODO/LATER: may be this code will be replaced, but not sure
2255 // Set storage in document library containers
2256 pImp
->pBasicManager
->setStorage( xStorage
);
2262 if( pFilter
&& !IsPackageStorageFormat_Impl( *pMedium
) && (pMedium
->GetOpenMode() & STREAM_WRITE
))
2265 bOk
= SaveCompletedChildren( sal_False
);
2268 bOk
= SaveCompleted( NULL
);
2270 // entweder Save oder ConvertTo
2272 bOk
= SaveCompleted( NULL
);
2275 if ( bOk
&& pNewMed
)
2281 uno::Reference
< frame::XModel
> xModel
= GetModel();
2284 ::rtl::OUString aURL
= pNewMed
->GetOrigURL();
2285 uno::Sequence
< beans::PropertyValue
> aMediaDescr
;
2286 TransformItems( SID_OPENDOC
, *pNewMed
->GetItemSet(), aMediaDescr
);
2289 xModel
->attachResource( aURL
, aMediaDescr
);
2291 catch( uno::Exception
& )
2295 // before the title regenerated the document must loose the signatures
2296 pImp
->nDocumentSignatureState
= SIGNATURESTATE_NOSIGNATURES
;
2297 pImp
->nScriptingSignatureState
= pNewMed
->GetCachedSignatureState_Impl();
2298 OSL_ENSURE( pImp
->nScriptingSignatureState
!= SIGNATURESTATE_SIGNATURES_BROKEN
, "The signature must not be broken at this place" );
2299 pImp
->bSignatureErrorIsShown
= sal_False
;
2301 // TODO/LATER: in future the medium must control own signature state, not the document
2302 pNewMed
->SetCachedSignatureState_Impl( SIGNATURESTATE_NOSIGNATURES
); // set the default value back
2305 if ( pNewMed
->GetName().Len() && SFX_CREATE_MODE_EMBEDDED
!= eCreateMode
)
2307 SetModified(sal_False
); // nur bei gesetztem Medium zur"ucksetzen
2308 Broadcast( SfxSimpleHint(SFX_HINT_MODECHANGED
) );
2310 // this is the end of the saving process, it is possible that the file was changed
2311 // between medium commit and this step ( attributes change and so on )
2312 // so get the file date again
2313 if ( pNewMed
->DocNeedsFileDateCheck() )
2314 pNewMed
->GetInitFileDate( sal_True
);
2318 pMedium
->ClearBackup_Impl();
2319 pMedium
->LockOrigFileOnDemand( sal_True
, sal_False
);
2324 //-------------------------------------------------------------------------
2326 sal_Bool
SfxObjectShell::ConvertFrom
2328 SfxMedium
& /*rMedium*/ /* <SfxMedium>, welches die Quell-Datei beschreibt
2329 (z.B. Dateiname, <SfxFilter>, Open-Modi etc.) */
2334 Diese Methode wird zum Laden von Dokumenten "uber alle Filter gerufen,
2335 die nicht SFX_FILTER_OWN sind oder f"ur die kein Clipboard-Format
2336 registriert wurde (also kein Storage-Format benutzen). Mit anderen Worten:
2337 mit dieser Methode wird importiert.
2339 Das hier zu "offende File sollte "uber 'rMedium' ge"offnet werden,
2340 um die richtigen Open-Modi zu gew"ahrleisten. Insbesondere wenn das
2341 Format beibehalten wird (nur m"oglich bei SFX_FILTER_SIMULATE oder
2342 SFX_FILTER_ONW) mu\s die Datei STREAM_SHARE_DENYWRITE ge"offnet werden.
2348 Das Dokument konnte geladen werden.
2351 Das Dokument konnte nicht geladen werden, ein
2352 Fehlercode ist mit <SvMedium::GetError()const> zu
2358 sal_Bool DocSh::ConvertFrom( SfxMedium &rMedium )
2360 SvStreamRef xStream = rMedium.GetInStream();
2363 xStream->SetBufferSize(4096);
2366 // NICHT 'rMedium.CloseInStream()' rufen! File gelockt halten!
2367 return SVSTREAM_OK == rMedium.GetError();
2376 <SfxObjectShell::ConvertTo(SfxMedium&)>
2377 <SFX_FILTER_REGISTRATION>
2383 sal_Bool
SfxObjectShell::InsertFrom( SfxMedium
& rMedium
)
2385 ::rtl::OUString
aTypeName( rMedium
.GetFilter()->GetTypeName() );
2386 ::rtl::OUString
aFilterName( rMedium
.GetFilter()->GetFilterName() );
2388 uno::Reference
< lang::XMultiServiceFactory
> xMan
= ::comphelper::getProcessServiceFactory();
2389 uno::Reference
< lang::XMultiServiceFactory
> xFilterFact (
2390 xMan
->createInstance( DEFINE_CONST_UNICODE( "com.sun.star.document.FilterFactory" ) ), uno::UNO_QUERY
);
2392 uno::Sequence
< beans::PropertyValue
> aProps
;
2393 uno::Reference
< container::XNameAccess
> xFilters ( xFilterFact
, uno::UNO_QUERY
);
2394 if ( xFilters
->hasByName( aFilterName
) )
2396 xFilters
->getByName( aFilterName
) >>= aProps
;
2397 rMedium
.GetItemSet()->Put( SfxStringItem( SID_FILTER_NAME
, aFilterName
) );
2400 ::rtl::OUString aFilterImplName
;
2401 sal_Int32 nFilterProps
= aProps
.getLength();
2402 for ( sal_Int32 nFilterProp
= 0; nFilterProp
<nFilterProps
; nFilterProp
++ )
2404 const beans::PropertyValue
& rFilterProp
= aProps
[nFilterProp
];
2405 if ( rFilterProp
.Name
.compareToAscii("FilterService") == COMPARE_EQUAL
)
2407 rFilterProp
.Value
>>= aFilterImplName
;
2412 uno::Reference
< document::XFilter
> xLoader
;
2413 if ( aFilterImplName
.getLength() )
2416 xLoader
= uno::Reference
< document::XFilter
>
2417 ( xFilterFact
->createInstanceWithArguments( aFilterName
, uno::Sequence
< uno::Any
>() ), uno::UNO_QUERY
);
2418 }catch(const uno::Exception
&)
2419 { xLoader
.clear(); }
2423 // #131744#: it happens that xLoader does not support xImporter!
2425 uno::Reference
< lang::XComponent
> xComp( GetModel(), uno::UNO_QUERY_THROW
);
2426 uno::Reference
< document::XImporter
> xImporter( xLoader
, uno::UNO_QUERY_THROW
);
2427 xImporter
->setTargetDocument( xComp
);
2429 uno::Sequence
< beans::PropertyValue
> lDescriptor
;
2430 rMedium
.GetItemSet()->Put( SfxStringItem( SID_FILE_NAME
, rMedium
.GetName() ) );
2431 TransformItems( SID_OPENDOC
, *rMedium
.GetItemSet(), lDescriptor
);
2433 com::sun::star::uno::Sequence
< com::sun::star::beans::PropertyValue
> aArgs ( lDescriptor
.getLength() );
2434 com::sun::star::beans::PropertyValue
* pNewValue
= aArgs
.getArray();
2435 const com::sun::star::beans::PropertyValue
* pOldValue
= lDescriptor
.getConstArray();
2436 const OUString
sInputStream ( RTL_CONSTASCII_USTRINGPARAM ( "InputStream" ) );
2438 sal_Bool bHasInputStream
= sal_False
;
2439 BOOL bHasBaseURL
= FALSE
;
2441 sal_Int32 nEnd
= lDescriptor
.getLength();
2443 for ( i
= 0; i
< nEnd
; i
++ )
2445 pNewValue
[i
] = pOldValue
[i
];
2446 if ( pOldValue
[i
].Name
== sInputStream
)
2447 bHasInputStream
= sal_True
;
2448 else if ( pOldValue
[i
].Name
.equalsAsciiL ( RTL_CONSTASCII_STRINGPARAM ( "DocumentBaseURL" ) ) )
2449 bHasBaseURL
= sal_True
;
2452 if ( !bHasInputStream
)
2454 aArgs
.realloc ( ++nEnd
);
2455 aArgs
[nEnd
-1].Name
= sInputStream
;
2456 aArgs
[nEnd
-1].Value
<<= com::sun::star::uno::Reference
< com::sun::star::io::XInputStream
> ( new utl::OSeekableInputStreamWrapper ( *rMedium
.GetInStream() ) );
2461 aArgs
.realloc ( ++nEnd
);
2462 aArgs
[nEnd
-1].Name
= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "DocumentBaseURL" ) );
2463 aArgs
[nEnd
-1].Value
<<= rMedium
.GetBaseURL();
2466 aArgs
.realloc( ++nEnd
);
2467 aArgs
[nEnd
-1].Name
= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "InsertMode" ) );
2468 aArgs
[nEnd
-1].Value
<<= (sal_Bool
) sal_True
;
2470 return xLoader
->filter( aArgs
);
2471 }catch(const uno::Exception
&)
2478 sal_Bool
SfxObjectShell::ImportFrom( SfxMedium
& rMedium
)
2480 ::rtl::OUString
aTypeName( rMedium
.GetFilter()->GetTypeName() );
2481 ::rtl::OUString
aFilterName( rMedium
.GetFilter()->GetFilterName() );
2483 uno::Reference
< lang::XMultiServiceFactory
> xMan
= ::comphelper::getProcessServiceFactory();
2484 uno::Reference
< lang::XMultiServiceFactory
> xFilterFact (
2485 xMan
->createInstance( DEFINE_CONST_UNICODE( "com.sun.star.document.FilterFactory" ) ), uno::UNO_QUERY
);
2487 uno::Sequence
< beans::PropertyValue
> aProps
;
2488 uno::Reference
< container::XNameAccess
> xFilters ( xFilterFact
, uno::UNO_QUERY
);
2489 if ( xFilters
->hasByName( aFilterName
) )
2491 xFilters
->getByName( aFilterName
) >>= aProps
;
2492 rMedium
.GetItemSet()->Put( SfxStringItem( SID_FILTER_NAME
, aFilterName
) );
2495 ::rtl::OUString aFilterImplName
;
2496 sal_Int32 nFilterProps
= aProps
.getLength();
2497 for ( sal_Int32 nFilterProp
= 0; nFilterProp
<nFilterProps
; nFilterProp
++ )
2499 const beans::PropertyValue
& rFilterProp
= aProps
[nFilterProp
];
2500 if ( rFilterProp
.Name
.compareToAscii("FilterService") == COMPARE_EQUAL
)
2502 rFilterProp
.Value
>>= aFilterImplName
;
2507 uno::Reference
< document::XFilter
> xLoader
;
2508 if ( aFilterImplName
.getLength() )
2511 xLoader
= uno::Reference
< document::XFilter
>
2512 ( xFilterFact
->createInstanceWithArguments( aFilterName
, uno::Sequence
< uno::Any
>() ), uno::UNO_QUERY
);
2513 }catch(const uno::Exception
&)
2514 { xLoader
.clear(); }
2518 // #131744#: it happens that xLoader does not support xImporter!
2520 uno::Reference
< lang::XComponent
> xComp( GetModel(), uno::UNO_QUERY_THROW
);
2521 uno::Reference
< document::XImporter
> xImporter( xLoader
, uno::UNO_QUERY_THROW
);
2522 xImporter
->setTargetDocument( xComp
);
2524 uno::Sequence
< beans::PropertyValue
> lDescriptor
;
2525 rMedium
.GetItemSet()->Put( SfxStringItem( SID_FILE_NAME
, rMedium
.GetName() ) );
2526 TransformItems( SID_OPENDOC
, *rMedium
.GetItemSet(), lDescriptor
);
2528 com::sun::star::uno::Sequence
< com::sun::star::beans::PropertyValue
> aArgs ( lDescriptor
.getLength() );
2529 com::sun::star::beans::PropertyValue
* pNewValue
= aArgs
.getArray();
2530 const com::sun::star::beans::PropertyValue
* pOldValue
= lDescriptor
.getConstArray();
2531 const OUString
sInputStream ( RTL_CONSTASCII_USTRINGPARAM ( "InputStream" ) );
2533 sal_Bool bHasInputStream
= sal_False
;
2534 BOOL bHasBaseURL
= FALSE
;
2536 sal_Int32 nEnd
= lDescriptor
.getLength();
2538 for ( i
= 0; i
< nEnd
; i
++ )
2540 pNewValue
[i
] = pOldValue
[i
];
2541 if ( pOldValue
[i
].Name
== sInputStream
)
2542 bHasInputStream
= sal_True
;
2543 else if ( pOldValue
[i
].Name
.equalsAsciiL ( RTL_CONSTASCII_STRINGPARAM ( "DocumentBaseURL" ) ) )
2544 bHasBaseURL
= sal_True
;
2547 if ( !bHasInputStream
)
2549 aArgs
.realloc ( ++nEnd
);
2550 aArgs
[nEnd
-1].Name
= sInputStream
;
2551 aArgs
[nEnd
-1].Value
<<= com::sun::star::uno::Reference
< com::sun::star::io::XInputStream
> ( new utl::OSeekableInputStreamWrapper ( *rMedium
.GetInStream() ) );
2556 aArgs
.realloc ( ++nEnd
);
2557 aArgs
[nEnd
-1].Name
= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "DocumentBaseURL" ) );
2558 aArgs
[nEnd
-1].Value
<<= rMedium
.GetBaseURL();
2561 return xLoader
->filter( aArgs
);
2562 }catch(const uno::Exception
&)
2569 sal_Bool
SfxObjectShell::ExportTo( SfxMedium
& rMedium
)
2571 ::rtl::OUString
aTypeName( rMedium
.GetFilter()->GetTypeName() );
2572 ::rtl::OUString
aFilterName( rMedium
.GetFilter()->GetFilterName() );
2573 uno::Reference
< document::XExporter
> xExporter
;
2576 uno::Reference
< lang::XMultiServiceFactory
> xMan
= ::comphelper::getProcessServiceFactory();
2577 uno::Reference
< lang::XMultiServiceFactory
> xFilterFact (
2578 xMan
->createInstance( DEFINE_CONST_UNICODE( "com.sun.star.document.FilterFactory" ) ), uno::UNO_QUERY
);
2580 uno::Sequence
< beans::PropertyValue
> aProps
;
2581 uno::Reference
< container::XNameAccess
> xFilters ( xFilterFact
, uno::UNO_QUERY
);
2582 if ( xFilters
->hasByName( aFilterName
) )
2583 xFilters
->getByName( aFilterName
) >>= aProps
;
2585 ::rtl::OUString aFilterImplName
;
2586 sal_Int32 nFilterProps
= aProps
.getLength();
2587 for ( sal_Int32 nFilterProp
= 0; nFilterProp
<nFilterProps
; nFilterProp
++ )
2589 const beans::PropertyValue
& rFilterProp
= aProps
[nFilterProp
];
2590 if ( rFilterProp
.Name
.compareToAscii("FilterService") == COMPARE_EQUAL
)
2592 rFilterProp
.Value
>>= aFilterImplName
;
2597 if ( aFilterImplName
.getLength() )
2600 xExporter
= uno::Reference
< document::XExporter
>
2601 ( xFilterFact
->createInstanceWithArguments( aFilterName
, uno::Sequence
< uno::Any
>() ), uno::UNO_QUERY
);
2602 }catch(const uno::Exception
&)
2603 { xExporter
.clear(); }
2607 if ( xExporter
.is() )
2610 uno::Reference
< lang::XComponent
> xComp( GetModel(), uno::UNO_QUERY_THROW
);
2611 uno::Reference
< document::XFilter
> xFilter( xExporter
, uno::UNO_QUERY_THROW
);
2612 xExporter
->setSourceDocument( xComp
);
2614 com::sun::star::uno::Sequence
< com::sun::star::beans::PropertyValue
> aOldArgs
;
2615 SfxItemSet
* pItems
= rMedium
.GetItemSet();
2616 TransformItems( SID_SAVEASDOC
, *pItems
, aOldArgs
);
2618 const com::sun::star::beans::PropertyValue
* pOldValue
= aOldArgs
.getConstArray();
2619 com::sun::star::uno::Sequence
< com::sun::star::beans::PropertyValue
> aArgs ( aOldArgs
.getLength() );
2620 com::sun::star::beans::PropertyValue
* pNewValue
= aArgs
.getArray();
2622 // put in the REAL file name, and copy all PropertyValues
2623 const OUString
sOutputStream ( RTL_CONSTASCII_USTRINGPARAM ( "OutputStream" ) );
2624 const OUString
sStream ( RTL_CONSTASCII_USTRINGPARAM ( "StreamForOutput" ) );
2625 BOOL bHasOutputStream
= FALSE
;
2626 BOOL bHasStream
= FALSE
;
2627 BOOL bHasBaseURL
= FALSE
;
2629 sal_Int32 nEnd
= aOldArgs
.getLength();
2631 for ( i
= 0; i
< nEnd
; i
++ )
2633 pNewValue
[i
] = pOldValue
[i
];
2634 if ( pOldValue
[i
].Name
.equalsAsciiL ( RTL_CONSTASCII_STRINGPARAM ( "FileName" ) ) )
2635 pNewValue
[i
].Value
<<= OUString ( rMedium
.GetName() );
2636 else if ( pOldValue
[i
].Name
== sOutputStream
)
2637 bHasOutputStream
= sal_True
;
2638 else if ( pOldValue
[i
].Name
== sStream
)
2639 bHasStream
= sal_True
;
2640 else if ( pOldValue
[i
].Name
.equalsAsciiL ( RTL_CONSTASCII_STRINGPARAM ( "DocumentBaseURL" ) ) )
2641 bHasBaseURL
= sal_True
;
2644 if ( !bHasOutputStream
)
2646 aArgs
.realloc ( ++nEnd
);
2647 aArgs
[nEnd
-1].Name
= sOutputStream
;
2648 aArgs
[nEnd
-1].Value
<<= com::sun::star::uno::Reference
< com::sun::star::io::XOutputStream
> ( new utl::OOutputStreamWrapper ( *rMedium
.GetOutStream() ) );
2651 // add stream as well, for OOX export and maybe others
2654 aArgs
.realloc ( ++nEnd
);
2655 aArgs
[nEnd
-1].Name
= sStream
;
2656 aArgs
[nEnd
-1].Value
<<= com::sun::star::uno::Reference
< com::sun::star::io::XStream
> ( new utl::OStreamWrapper ( *rMedium
.GetOutStream() ) );
2661 aArgs
.realloc ( ++nEnd
);
2662 aArgs
[nEnd
-1].Name
= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "DocumentBaseURL" ) );
2663 aArgs
[nEnd
-1].Value
<<= rMedium
.GetBaseURL( sal_True
);
2666 return xFilter
->filter( aArgs
);
2667 }catch(const uno::Exception
&)
2674 //-------------------------------------------------------------------------
2676 sal_Bool
SfxObjectShell::ConvertTo
2678 SfxMedium
& /*rMedium*/ /* <SfxMedium>, welches die Ziel-Datei beschreibt
2679 (z.B. Dateiname, <SfxFilter>, Open-Modi etc.) */
2684 Diese Methode wird zum Speichern von Dokumenten "uber alle Filter gerufen,
2685 die nicht SFX_FILTER_OWN sind oder f"ur die kein Clipboard-Format
2686 registriert wurde (also kein Storage-Format benutzen). Mit anderen Worten:
2687 mit dieser Methode wird exportiert.
2689 Das hier zu "offende File sollte "uber 'rMedium' ge"offnet werden,
2690 um die richtigen Open-Modi zu gew"ahrleisten. Insbesondere wenn das
2691 Format beibehalten wird (nur m"oglich bei SFX_FILTER_SIMULATE oder
2692 SFX_FILTER_ONW) mu\s die Datei auch nach dem Speichern im Modus
2693 STREAM_SHARE_DENYWRITE ge"offnet bleiben.
2699 Das Dokument konnte gespeichert werden.
2702 Das Dokument konnte nicht gespeichert werden, ein
2703 Fehlercode ist mit <SvMedium::GetError()const> zu
2709 sal_Bool DocSh::ConvertTo( SfxMedium &rMedium )
2711 SvStreamRef xStream = rMedium.GetOutStream();
2714 xStream->SetBufferSize(4096);
2717 rMedium.CloseOutStream(); // "offnet automatisch wieder den InStream
2718 return SVSTREAM_OK == rMedium.GetError();
2726 <SfxObjectShell::ConvertFrom(SfxMedium&)>
2727 <SFX_FILTER_REGISTRATION>
2734 //-------------------------------------------------------------------------
2736 sal_Bool
SfxObjectShell::DoSave_Impl( const SfxItemSet
* pArgs
)
2738 SfxMedium
* pRetrMedium
= GetMedium();
2739 const SfxFilter
* pFilter
= pRetrMedium
->GetFilter();
2741 // copy the original itemset, but remove the "version" item, because pMediumTmp
2742 // is a new medium "from scratch", so no version should be stored into it
2743 SfxItemSet
* pSet
= new SfxAllItemSet(*pRetrMedium
->GetItemSet());
2744 pSet
->ClearItem( SID_VERSION
);
2746 // create a medium as a copy; this medium is only for writingm, because it uses the same name as the original one
2747 // writing is done through a copy, that will be transferred to the target ( of course after calling HandsOff )
2748 SfxMedium
* pMediumTmp
= new SfxMedium( pRetrMedium
->GetName(), pRetrMedium
->GetOpenMode(), pRetrMedium
->IsDirect(), pFilter
, pSet
);
2749 pMediumTmp
->SetLongName( pRetrMedium
->GetLongName() );
2750 // pMediumTmp->CreateTempFileNoCopy();
2751 if ( pMediumTmp
->GetErrorCode() != ERRCODE_NONE
)
2753 SetError( pMediumTmp
->GetError(), ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
) ) );
2758 // copy version list from "old" medium to target medium, so it can be used on saving
2759 pMediumTmp
->TransferVersionList_Impl( *pRetrMedium
);
2761 if ( pFilter && ( pFilter->GetFilterFlags() & SFX_FILTER_PACKED ) )
2762 SetError( GetMedium()->Unpack_Impl( pRetrMedium->GetPhysicalName() ), ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
2765 // an interaction handler here can aquire only in case of GUI Saving
2766 // and should be removed after the saving is done
2767 com::sun::star::uno::Reference
< XInteractionHandler
> xInteract
;
2768 SFX_ITEMSET_ARG( pArgs
, pxInteractionItem
, SfxUnoAnyItem
, SID_INTERACTIONHANDLER
, sal_False
);
2769 if ( pxInteractionItem
&& ( pxInteractionItem
->GetValue() >>= xInteract
) && xInteract
.is() )
2770 pMediumTmp
->GetItemSet()->Put( SfxUnoAnyItem( SID_INTERACTIONHANDLER
, makeAny( xInteract
) ) );
2772 sal_Bool bSaved
= sal_False
;
2773 if( !GetError() && SaveTo_Impl( *pMediumTmp
, pArgs
) )
2777 if( pMediumTmp
->GetItemSet() )
2779 pMediumTmp
->GetItemSet()->ClearItem( SID_INTERACTIONHANDLER
);
2780 pMediumTmp
->GetItemSet()->ClearItem( SID_PROGRESS_STATUSBAR_CONTROL
);
2783 SetError(pMediumTmp
->GetErrorCode(), ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
) ) );
2785 //REMOVE if ( !IsHandsOff() )
2786 //REMOVE pMediumTmp->Close();
2788 sal_Bool
bOpen( sal_False
);
2789 bOpen
= DoSaveCompleted( pMediumTmp
);
2790 DBG_ASSERT(bOpen
,"Fehlerbehandlung fuer DoSaveCompleted nicht implementiert");
2794 // transfer error code from medium to objectshell
2795 SetError( pMediumTmp
->GetError(), ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
) ) );
2797 // reconnect to object storage
2798 //REMOVE if ( IsHandsOff() )
2800 //REMOVE if ( !DoSaveCompleted( pRetrMedium ) )
2801 //REMOVE DBG_ERROR("Case not handled - no way to get a storage!");
2804 DoSaveCompleted( 0 );
2806 if( pRetrMedium
->GetItemSet() )
2808 pRetrMedium
->GetItemSet()->ClearItem( SID_INTERACTIONHANDLER
);
2809 pRetrMedium
->GetItemSet()->ClearItem( SID_PROGRESS_STATUSBAR_CONTROL
);
2815 SetModified( !bSaved
);
2819 //-------------------------------------------------------------------------
2821 sal_Bool
SfxObjectShell::Save_Impl( const SfxItemSet
* pSet
)
2825 SetError( ERRCODE_SFX_DOCUMENTREADONLY
, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
) ) );
2829 DBG_CHKTHIS(SfxObjectShell
, 0);
2831 pImp
->bIsSaving
= sal_True
;
2832 sal_Bool bSaved
= FALSE
;
2833 SFX_ITEMSET_ARG( GetMedium()->GetItemSet(), pSalvageItem
, SfxStringItem
, SID_DOC_SALVAGE
, sal_False
);
2836 SFX_ITEMSET_ARG( GetMedium()->GetItemSet(), pFilterItem
, SfxStringItem
, SID_FILTER_NAME
, sal_False
);
2838 const SfxFilter
*pFilter
= NULL
;
2840 pFilter
= SfxFilterMatcher( String::CreateFromAscii( GetFactory().GetShortName()) ).GetFilter4FilterName( aFilterName
);
2842 SfxMedium
*pMed
= new SfxMedium(
2843 pSalvageItem
->GetValue(), STREAM_READWRITE
| STREAM_SHARE_DENYWRITE
| STREAM_TRUNC
, sal_False
, pFilter
);
2845 SFX_ITEMSET_ARG( GetMedium()->GetItemSet(), pPasswordItem
, SfxStringItem
, SID_PASSWORD
, sal_False
);
2846 if ( pPasswordItem
)
2847 pMed
->GetItemSet()->Put( *pPasswordItem
);
2849 bSaved
= DoSaveAs( *pMed
);
2851 bSaved
= DoSaveCompleted( pMed
);
2856 bSaved
= DoSave_Impl( pSet
);
2860 //-------------------------------------------------------------------------
2862 sal_Bool
SfxObjectShell::CommonSaveAs_Impl
2864 const INetURLObject
& aURL
,
2865 const String
& aFilterName
,
2869 if( aURL
.HasError() )
2871 SetError( ERRCODE_IO_INVALIDPARAMETER
, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
) ) );
2875 if ( aURL
!= INetURLObject( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "private:stream" ) ) ) )
2877 // gibt es schon ein Doc mit dem Namen?
2878 SfxObjectShell
* pDoc
= 0;
2879 for ( SfxObjectShell
* pTmp
= SfxObjectShell::GetFirst();
2881 pTmp
= SfxObjectShell::GetNext(*pTmp
) )
2883 if( ( pTmp
!= this ) && pTmp
->GetMedium() )
2885 INetURLObject
aCompare( pTmp
->GetMedium()->GetName() );
2886 if ( aCompare
== aURL
)
2892 // dann Fehlermeldeung: "schon offen"
2893 SetError(ERRCODE_SFX_ALREADYOPEN
, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
) ));
2898 DBG_ASSERT( aURL
.GetProtocol() != INET_PROT_NOT_VALID
, "Illegal URL!" );
2899 DBG_ASSERT( aParams
->Count() != 0, "fehlerhafte Parameter");
2901 SFX_ITEMSET_ARG( aParams
, pSaveToItem
, SfxBoolItem
, SID_SAVETO
, sal_False
);
2902 sal_Bool bSaveTo
= pSaveToItem
? pSaveToItem
->GetValue() : sal_False
;
2904 const SfxFilter
* pFilter
= GetFactory().GetFilterContainer()->GetFilter4FilterName( aFilterName
);
2906 || !pFilter
->CanExport()
2907 || (!bSaveTo
&& !pFilter
->CanImport()) )
2909 SetError( ERRCODE_IO_INVALIDPARAMETER
, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
) ) );
2913 SFX_ITEMSET_ARG( aParams
, pCopyStreamItem
, SfxBoolItem
, SID_COPY_STREAM_IF_POSSIBLE
, sal_False
);
2914 if ( bSaveTo
&& pCopyStreamItem
&& pCopyStreamItem
->GetValue() && !IsModified() )
2916 if ( pMedium
->TryDirectTransfer( aURL
.GetMainURL( INetURLObject::NO_DECODE
), *aParams
) )
2919 aParams
->ClearItem( SID_COPY_STREAM_IF_POSSIBLE
);
2921 pImp
->bPasswd
= aParams
&& SFX_ITEM_SET
== aParams
->GetItemState(SID_PASSWORD
);
2923 SfxMedium
*pActMed
= GetMedium();
2924 const INetURLObject
aActName(pActMed
->GetName());
2926 BOOL bWasReadonly
= IsReadOnly();
2928 if ( aURL
== aActName
&& aURL
!= INetURLObject( OUString::createFromAscii( "private:stream" ) )
2931 SetError(ERRCODE_SFX_DOCUMENTREADONLY
, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
) ));
2935 // this notification should be already sent by caller in sfxbasemodel
2936 // SFX_APP()->NotifyEvent(SfxEventHint( bSaveTo? SFX_EVENT_SAVETODOC : SFX_EVENT_SAVEASDOC,this));
2938 if( SFX_ITEM_SET
!= aParams
->GetItemState(SID_UNPACK
) && SvtSaveOptions().IsSaveUnpacked() )
2939 aParams
->Put( SfxBoolItem( SID_UNPACK
, sal_False
) );
2941 ::rtl::OUString aTempFileURL
;
2942 if ( IsDocShared() )
2943 aTempFileURL
= pMedium
->GetURLObject().GetMainURL( INetURLObject::NO_DECODE
);
2945 if ( PreDoSaveAs_Impl(aURL
.GetMainURL( INetURLObject::NO_DECODE
),aFilterName
,aParams
))
2947 pImp
->bWaitingForPicklist
= sal_True
;
2949 // Daten am Medium updaten
2950 SfxItemSet
*pSet
= GetMedium()->GetItemSet();
2951 pSet
->ClearItem( SID_INTERACTIONHANDLER
);
2952 pSet
->ClearItem( SID_PROGRESS_STATUSBAR_CONTROL
);
2953 pSet
->ClearItem( SID_STANDARD_DIR
);
2954 pSet
->ClearItem( SID_PATH
);
2958 pSet
->ClearItem( SID_REFERER
);
2959 pSet
->ClearItem( SID_POSTDATA
);
2960 pSet
->ClearItem( SID_TEMPLATE
);
2961 pSet
->ClearItem( SID_DOC_READONLY
);
2962 pSet
->ClearItem( SID_CONTENTTYPE
);
2963 pSet
->ClearItem( SID_CHARSET
);
2964 pSet
->ClearItem( SID_FILTER_NAME
);
2965 pSet
->ClearItem( SID_OPTIONS
);
2966 //pSet->ClearItem( SID_FILE_FILTEROPTIONS );
2967 pSet
->ClearItem( SID_VERSION
);
2968 //pSet->ClearItem( SID_USE_FILTEROPTIONS );
2969 pSet
->ClearItem( SID_EDITDOC
);
2970 pSet
->ClearItem( SID_OVERWRITE
);
2971 pSet
->ClearItem( SID_DEFAULTFILEPATH
);
2972 pSet
->ClearItem( SID_DEFAULTFILENAME
);
2974 SFX_ITEMSET_GET( (*aParams
), pFilterItem
, SfxStringItem
, SID_FILTER_NAME
, sal_False
);
2976 pSet
->Put( *pFilterItem
);
2978 SFX_ITEMSET_GET( (*aParams
), pOptionsItem
, SfxStringItem
, SID_OPTIONS
, sal_False
);
2980 pSet
->Put( *pOptionsItem
);
2982 SFX_ITEMSET_GET( (*aParams
), pFilterOptItem
, SfxStringItem
, SID_FILE_FILTEROPTIONS
, sal_False
);
2983 if ( pFilterOptItem
)
2984 pSet
->Put( *pFilterOptItem
);
2986 if ( IsDocShared() && aTempFileURL
.getLength() )
2988 // this is a shared document that has to be disconnected from the old location
2989 FreeSharedFile( aTempFileURL
);
2991 if ( pFilter
->IsOwnFormat()
2992 && pFilter
->UsesStorage()
2993 && pFilter
->GetVersion() >= SOFFICE_FILEFORMAT_60
)
2995 // the target format is the own format
2996 // the target document must be shared
2997 SwitchToShared( sal_True
, sal_False
);
3002 if ( bWasReadonly
&& !bSaveTo
)
3003 Broadcast( SfxSimpleHint(SFX_HINT_MODECHANGED
) );
3011 //-------------------------------------------------------------------------
3013 sal_Bool
SfxObjectShell::PreDoSaveAs_Impl
3015 const String
& rFileName
,
3016 const String
& aFilterName
,
3020 // copy all items stored in the itemset of the current medium
3021 SfxAllItemSet
* pMergedParams
= new SfxAllItemSet( *pMedium
->GetItemSet() );
3023 // in "SaveAs" title and password will be cleared ( maybe the new itemset contains new values, otherwise they will be empty )
3024 pMergedParams
->ClearItem( SID_PASSWORD
);
3025 pMergedParams
->ClearItem( SID_DOCINFO_TITLE
);
3027 pMergedParams
->ClearItem( SID_INPUTSTREAM
);
3028 pMergedParams
->ClearItem( SID_STREAM
);
3029 pMergedParams
->ClearItem( SID_CONTENT
);
3030 pMergedParams
->ClearItem( SID_DOC_READONLY
);
3032 pMergedParams
->ClearItem( SID_REPAIRPACKAGE
);
3034 // "SaveAs" will never store any version information - it's a complete new file !
3035 pMergedParams
->ClearItem( SID_VERSION
);
3037 // merge the new parameters into the copy
3038 // all values present in both itemsets will be overwritten by the new parameters
3040 pMergedParams
->Put( *pParams
);
3041 //DELETEZ( pParams );
3044 if ( pMergedParams
->GetItemState( SID_DOC_SALVAGE
) >= SFX_ITEM_SET
)
3045 DBG_ERROR("Salvage item present in Itemset, check the parameters!");
3048 // should be unneccessary - too hot to handle!
3049 pMergedParams
->ClearItem( SID_DOC_SALVAGE
);
3051 // take over the new merged itemset
3052 pParams
= pMergedParams
;
3054 // create a medium for the target URL
3055 SfxMedium
*pNewFile
= new SfxMedium( rFileName
, STREAM_READWRITE
| STREAM_SHARE_DENYWRITE
| STREAM_TRUNC
, sal_False
, 0, pParams
);
3057 // set filter; if no filter is given, take the default filter of the factory
3058 if ( aFilterName
.Len() )
3059 pNewFile
->SetFilter( GetFactory().GetFilterContainer()->GetFilter4FilterName( aFilterName
) );
3061 pNewFile
->SetFilter( GetFactory().GetFilterContainer()->GetAnyFilter( SFX_FILTER_IMPORT
| SFX_FILTER_EXPORT
) );
3063 //REMOVE // saving is alway done using a temporary file
3064 //REMOVE pNewFile->CreateTempFileNoCopy();
3065 if ( pNewFile
->GetErrorCode() != ERRCODE_NONE
)
3067 // creating temporary file failed ( f.e. floppy disk not inserted! )
3068 SetError( pNewFile
->GetError(), ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
) ) );
3073 // check if a "SaveTo" is wanted, no "SaveAs"
3074 SFX_ITEMSET_ARG( pParams
, pSaveToItem
, SfxBoolItem
, SID_SAVETO
, sal_False
);
3075 sal_Bool bCopyTo
= GetCreateMode() == SFX_CREATE_MODE_EMBEDDED
|| (pSaveToItem
&& pSaveToItem
->GetValue());
3077 // distinguish between "Save" and "SaveAs"
3078 pImp
->bIsSaving
= sal_False
;
3080 // copy version list from "old" medium to target medium, so it can be used on saving
3081 if ( pImp
->bPreserveVersions
)
3082 pNewFile
->TransferVersionList_Impl( *pMedium
);
3085 if ( GetMedium()->GetFilter() && ( GetMedium()->GetFilter()->GetFilterFlags() & SFX_FILTER_PACKED ) )
3087 SfxMedium *pMed = bCopyTo ? pMedium : pNewFile;
3088 pNewFile->SetError( GetMedium()->Unpack_Impl( pMed->GetPhysicalName() ) , ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
3091 // Save the document ( first as temporary file, then transfer to the target URL by committing the medium )
3092 sal_Bool bOk
= sal_False
;
3093 if ( !pNewFile
->GetErrorCode() && SaveTo_Impl( *pNewFile
, NULL
) )
3097 // transfer a possible error from the medium to the document
3098 SetError( pNewFile
->GetErrorCode(), ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
) ) );
3100 // notify the document that saving was done successfully
3101 //REMOVE if ( bCopyTo )
3103 //REMOVE if ( IsHandsOff() )
3104 //REMOVE bOk = DoSaveCompleted( pMedium );
3110 //REMOVE if ( bToOwnFormat )
3111 //REMOVE SetFileName( pNewFile->GetPhysicalName() );
3113 bOk
= DoSaveCompleted( pNewFile
);
3116 bOk
= DoSaveCompleted(0);
3121 SetModified( sal_False
);
3125 // TODO/LATER: the code below must be dead since the storage commit makes all the stuff
3126 // and the DoSaveCompleted call should not be able to fail in general
3128 DBG_ASSERT( !bCopyTo
, "Error while reconnecting to medium, can't be handled!");
3129 SetError( pNewFile
->GetErrorCode(), ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
) ) );
3133 // reconnect to the old medium
3135 bRet
= DoSaveCompleted( pMedium
);
3136 DBG_ASSERT( bRet
, "Error in DoSaveCompleted, can't be handled!");
3139 // TODO/LATER: disconnect the new file from the storage for the case when pure saving is done
3140 // if storing has corrupted the file, probably it must be restored either here or
3142 DELETEZ( pNewFile
);
3145 // TODO/LATER: there is no need in the following code in case HandsOff is not used,
3146 // hope we will not have to introduce it back
3147 //REMOVE String aPasswd;
3148 //REMOVE if ( IsOwnStorageFormat_Impl( *GetMedium() ) && GetPasswd_Impl( GetMedium()->GetItemSet(), aPasswd ) )
3152 //REMOVE // the following code must throw an exception in case of failure
3153 //REMOVE ::comphelper::OStorageHelper::SetCommonStoragePassword( GetMedium->GetStorage(), aPasswd );
3155 //REMOVE catch( uno::Exception& )
3157 //REMOVE // TODO: handle the error
3163 SetError( pNewFile
->GetErrorCode(), ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
) ) );
3165 //REMOVE // reconnect to the old storage
3166 //REMOVE if ( IsHandsOff() )
3167 //REMOVE DoSaveCompleted( pMedium );
3169 DoSaveCompleted( 0 );
3171 DELETEZ( pNewFile
);
3175 DELETEZ( pNewFile
);
3177 SetModified( sal_True
);
3182 //------------------------------------------------------------------------
3184 sal_Bool
SfxObjectShell::LoadFrom( SfxMedium
& /*rMedium*/ )
3186 DBG_ERROR( "Base implementation, must not be called in general!" );
3190 //-------------------------------------------------------------------------
3191 sal_Bool
SfxObjectShell::IsInformationLost()
3193 Sequence
< PropertyValue
> aProps
= GetModel()->getArgs();
3194 ::rtl::OUString aFilterName
;
3195 ::rtl::OUString aPreusedFilterName
;
3196 for ( sal_Int32 nInd
= 0; nInd
< aProps
.getLength(); nInd
++ )
3198 if ( aProps
[nInd
].Name
.equalsAscii( "FilterName" ) )
3199 aProps
[nInd
].Value
>>= aFilterName
;
3200 else if ( aProps
[nInd
].Name
.equalsAscii( "PreusedFilterName" ) )
3201 aProps
[nInd
].Value
>>= aPreusedFilterName
;
3204 // if current filter can lead to information loss and it was used
3205 // for the latest store then the user should be asked to store in own format
3206 if ( aFilterName
.getLength() && aFilterName
.equals( aPreusedFilterName
) )
3208 const SfxFilter
*pFilt
= GetMedium()->GetFilter();
3209 DBG_ASSERT( pFilt
&& aFilterName
.equals( pFilt
->GetName() ), "MediaDescriptor contains wrong filter!\n" );
3210 return ( pFilt
&& pFilt
->IsAlienFormat() && !(pFilt
->GetFilterFlags() & SFX_FILTER_SILENTEXPORT
) );
3216 //-------------------------------------------------------------------------
3217 sal_Bool
SfxObjectShell::CanReload_Impl()
3221 Interne Methode zum Feststellen, ob eine erneutes Laden des
3222 Dokuments (auch als RevertToSaved oder LastVersion bekannt)
3227 return pMedium
&& HasName() && !IsInModalMode() && !pImp
->bForbidReload
;
3230 //-------------------------------------------------------------------------
3232 sal_uInt16
SfxObjectShell::GetHiddenInformationState( sal_uInt16 nStates
)
3234 sal_uInt16 nState
= 0;
3235 if ( nStates
& HIDDENINFORMATION_DOCUMENTVERSIONS
)
3237 if ( GetMedium()->GetVersionList().getLength() )
3238 nState
|= HIDDENINFORMATION_DOCUMENTVERSIONS
;
3244 sal_Int16
SfxObjectShell::QueryHiddenInformation( HiddenWarningFact eFact
, Window
* pParent
)
3246 sal_Int16 nRet
= RET_YES
;
3248 SvtSecurityOptions::EOption eOption
= static_cast< SvtSecurityOptions::EOption
>( -1 );
3254 nResId
= STR_HIDDENINFO_CONTINUE_SAVING
;
3255 eOption
= SvtSecurityOptions::E_DOCWARN_SAVEORSEND
;
3260 nResId
= STR_HIDDENINFO_CONTINUE_PRINTING
;
3261 eOption
= SvtSecurityOptions::E_DOCWARN_PRINT
;
3266 nResId
= STR_HIDDENINFO_CONTINUE_SIGNING
;
3267 eOption
= SvtSecurityOptions::E_DOCWARN_SIGNING
;
3270 case WhenCreatingPDF
:
3272 nResId
= STR_HIDDENINFO_CONTINUE_CREATEPDF
;
3273 eOption
= SvtSecurityOptions::E_DOCWARN_CREATEPDF
;
3278 DBG_ERRORFILE( "SfxObjectShell::DetectHiddenInformation(): what fact?" );
3282 if ( eOption
!= -1 && SvtSecurityOptions().IsOptionSet( eOption
) )
3284 String
sMessage( SfxResId( STR_HIDDENINFO_CONTAINS
) );
3285 sal_uInt16 nWantedStates
= HIDDENINFORMATION_RECORDEDCHANGES
| HIDDENINFORMATION_NOTES
;
3286 if ( eFact
!= WhenPrinting
)
3287 nWantedStates
|= HIDDENINFORMATION_DOCUMENTVERSIONS
;
3288 sal_uInt16 nStates
= GetHiddenInformationState( nWantedStates
);
3289 bool bWarning
= false;
3291 if ( ( nStates
& HIDDENINFORMATION_RECORDEDCHANGES
) == HIDDENINFORMATION_RECORDEDCHANGES
)
3293 sMessage
+= String( SfxResId( STR_HIDDENINFO_RECORDCHANGES
) );
3297 if ( ( nStates
& HIDDENINFORMATION_NOTES
) == HIDDENINFORMATION_NOTES
)
3299 sMessage
+= String( SfxResId( STR_HIDDENINFO_NOTES
) );
3303 if ( ( nStates
& HIDDENINFORMATION_DOCUMENTVERSIONS
) == HIDDENINFORMATION_DOCUMENTVERSIONS
)
3305 sMessage
+= String( SfxResId( STR_HIDDENINFO_DOCVERSIONS
) );
3313 sMessage
+= String( SfxResId( nResId
) );
3314 WarningBox
aWBox( pParent
, WB_YES_NO
| WB_DEF_NO
, sMessage
);
3315 nRet
= aWBox
.Execute();
3322 sal_Bool
SfxObjectShell::HasSecurityOptOpenReadOnly() const
3327 sal_Bool
SfxObjectShell::IsSecurityOptOpenReadOnly() const
3329 return IsLoadReadonly();
3332 void SfxObjectShell::SetSecurityOptOpenReadOnly( sal_Bool _b
)
3334 SetLoadReadonly( _b
);
3337 sal_Bool
SfxObjectShell::LoadOwnFormat( SfxMedium
& rMedium
)
3339 RTL_LOGFILE_PRODUCT_CONTEXT( aLog
, "PERFORMANCE SfxObjectShell::LoadOwnFormat" );
3340 if( RTL_LOGFILE_HASLOGFILE() )
3342 ByteString
aString( rMedium
.GetName(), RTL_TEXTENCODING_ASCII_US
);
3343 RTL_LOGFILE_PRODUCT_CONTEXT_TRACE1( aLog
, "loading \"%s\"", aString
.GetBuffer() );
3346 uno::Reference
< embed::XStorage
> xStorage
= rMedium
.GetStorage();
3347 if ( xStorage
.is() )
3349 //REMOVE if ( rMedium.GetFileVersion() )
3350 //REMOVE xStor->SetVersion( rMedium.GetFileVersion() );
3353 SFX_ITEMSET_ARG( rMedium
.GetItemSet(), pPasswdItem
, SfxStringItem
, SID_PASSWORD
, sal_False
);
3354 if ( pPasswdItem
|| ERRCODE_IO_ABORT
!= CheckPasswd_Impl( this, SFX_APP()->GetPool(), pMedium
) )
3356 ::rtl::OUString aPasswd
;
3357 if ( GetPasswd_Impl(pMedium
->GetItemSet(), aPasswd
) )
3361 // the following code must throw an exception in case of failure
3362 ::comphelper::OStorageHelper::SetCommonStoragePassword( xStorage
, aPasswd
);
3364 catch( uno::Exception
& )
3366 // TODO/LATER: handle the error code
3371 return Load( rMedium
);
3379 sal_Bool
SfxObjectShell::SaveAsOwnFormat( SfxMedium
& rMedium
)
3381 uno::Reference
< embed::XStorage
> xStorage
= rMedium
.GetStorage();
3384 sal_Int32 nVersion
= rMedium
.GetFilter()->GetVersion();
3386 // OASIS templates have own mediatypes ( SO7 also actually, but it is to late to use them here )
3387 sal_Bool bTemplate
= ( rMedium
.GetFilter()->IsOwnTemplateFormat() && nVersion
> SOFFICE_FILEFORMAT_60
);
3389 SetupStorage( xStorage
, nVersion
, bTemplate
);
3396 // Save dialog/script container
3397 pImp
->pBasicManager
->storeLibrariesToStorage( xStorage
);
3400 return SaveAs( rMedium
);
3402 else return sal_False
;
3405 uno::Reference
< embed::XStorage
> SfxObjectShell::GetStorage()
3407 if ( !pImp
->m_xDocStorage
.is() )
3409 OSL_ENSURE( pImp
->m_bCreateTempStor
, "The storage must exist already!\n" );
3411 // no notification is required the storage is set the first time
3412 pImp
->m_xDocStorage
= ::comphelper::OStorageHelper::GetTemporaryStorage();
3413 OSL_ENSURE( pImp
->m_xDocStorage
.is(), "The method must either return storage or throw an exception!" );
3415 SetupStorage( pImp
->m_xDocStorage
, SOFFICE_FILEFORMAT_CURRENT
, sal_False
);
3416 pImp
->m_bCreateTempStor
= sal_False
;
3417 SFX_APP()->NotifyEvent( SfxEventHint( SFX_EVENT_STORAGECHANGED
, this ) );
3419 catch( uno::Exception
& )
3421 // TODO/LATER: error handling?
3425 OSL_ENSURE( pImp
->m_xDocStorage
.is(), "The document storage must be created!" );
3426 return pImp
->m_xDocStorage
;
3430 sal_Bool
SfxObjectShell::SaveChildren( BOOL bObjectsOnly
)
3432 RTL_LOGFILE_CONTEXT( aLog
, "sfx2 (mv76033) SfxObjectShell::SaveChildren" );
3434 sal_Bool bResult
= sal_True
;
3435 if ( pImp
->mpObjectContainer
)
3437 sal_Bool bOasis
= ( SotStorage::GetVersion( GetStorage() ) > SOFFICE_FILEFORMAT_60
);
3438 GetEmbeddedObjectContainer().StoreChildren(bOasis
,bObjectsOnly
);
3444 sal_Bool
SfxObjectShell::SaveAsChildren( SfxMedium
& rMedium
)
3446 RTL_LOGFILE_CONTEXT( aLog
, "sfx2 (mv76033) SfxObjectShell::SaveAsChildren" );
3448 sal_Bool bResult
= sal_True
;
3450 uno::Reference
< embed::XStorage
> xStorage
= rMedium
.GetStorage();
3451 if ( !xStorage
.is() )
3454 if ( xStorage
== GetStorage() )
3455 return SaveChildren();
3457 sal_Bool bOasis
= sal_True
;
3458 if ( pImp
->mpObjectContainer
)
3460 bOasis
= ( SotStorage::GetVersion( xStorage
) > SOFFICE_FILEFORMAT_60
);
3461 GetEmbeddedObjectContainer().StoreAsChildren(bOasis
,SFX_CREATE_MODE_EMBEDDED
== eCreateMode
,xStorage
);
3465 bResult
= CopyStoragesOfUnknownMediaType( GetStorage(), xStorage
);
3470 sal_Bool
SfxObjectShell::SaveCompletedChildren( sal_Bool bSuccess
)
3472 RTL_LOGFILE_CONTEXT( aLog
, "sfx2 (mv76033) SfxObjectShell::SaveCompletedChildren" );
3474 sal_Bool bResult
= sal_True
;
3476 if ( pImp
->mpObjectContainer
)
3478 uno::Sequence
< ::rtl::OUString
> aNames
= GetEmbeddedObjectContainer().GetObjectNames();
3479 for ( sal_Int32 n
=0; n
<aNames
.getLength(); n
++ )
3481 uno::Reference
< embed::XEmbeddedObject
> xObj
= GetEmbeddedObjectContainer().GetEmbeddedObject( aNames
[n
] );
3482 OSL_ENSURE( xObj
.is(), "An empty entry in the embedded objects list!\n" );
3485 uno::Reference
< embed::XEmbedPersist
> xPersist( xObj
, uno::UNO_QUERY
);
3486 if ( xPersist
.is() )
3490 xPersist
->saveCompleted( bSuccess
);
3492 catch( uno::Exception
& )
3494 // TODO/LATER: error handling
3495 bResult
= sal_False
;
3506 sal_Bool
SfxObjectShell::SwitchChildrenPersistance( const uno::Reference
< embed::XStorage
>& xStorage
,
3507 sal_Bool bForceNonModified
)
3509 RTL_LOGFILE_CONTEXT( aLog
, "sfx2 (mv76033) SfxObjectShell::SwitchChildrenPersistence" );
3511 if ( !xStorage
.is() )
3513 // TODO/LATER: error handling
3517 sal_Bool bResult
= sal_True
;
3519 if ( pImp
->mpObjectContainer
)
3520 pImp
->mpObjectContainer
->SetPersistentEntries(xStorage
,bForceNonModified
);
3525 // Never call this method directly, always use the DoSaveCompleted call
3526 sal_Bool
SfxObjectShell::SaveCompleted( const uno::Reference
< embed::XStorage
>& xStorage
)
3528 RTL_LOGFILE_CONTEXT( aLog
, "sfx2 (mv76033) SfxObjectShell::SaveCompleted" );
3530 sal_Bool bResult
= sal_False
;
3531 sal_Bool bSendNotification
= sal_False
;
3532 uno::Reference
< embed::XStorage
> xOldStorageHolder
;
3535 // check for wrong creation of object container
3536 BOOL bHasContainer
= ( pImp
->mpObjectContainer
!= 0 );
3539 if ( !xStorage
.is() || xStorage
== GetStorage() )
3541 // no persistence change
3542 bResult
= SaveCompletedChildren( sal_False
);
3546 if ( pImp
->mpObjectContainer
)
3547 GetEmbeddedObjectContainer().SwitchPersistence( xStorage
);
3549 bResult
= SwitchChildrenPersistance( xStorage
, sal_True
);
3554 if ( xStorage
.is() && pImp
->m_xDocStorage
!= xStorage
)
3556 // make sure that until the storage is assigned the object container is not created by accident!
3557 DBG_ASSERT( bHasContainer
== (pImp
->mpObjectContainer
!= 0), "Wrong storage in object container!" );
3558 xOldStorageHolder
= pImp
->m_xDocStorage
;
3559 pImp
->m_xDocStorage
= xStorage
;
3560 bSendNotification
= sal_True
;
3562 if ( IsEnableSetModified() )
3563 SetModified( sal_False
);
3568 if ( pImp
->mpObjectContainer
)
3569 GetEmbeddedObjectContainer().SwitchPersistence( pImp
->m_xDocStorage
);
3571 // let already successfully connected objects be switched back
3572 SwitchChildrenPersistance( pImp
->m_xDocStorage
, sal_True
);
3575 if ( bSendNotification
)
3577 SFX_APP()->NotifyEvent( SfxEventHint( SFX_EVENT_STORAGECHANGED
, this ) );
3584 sal_Bool
StoragesOfUnknownMediaTypeAreCopied_Impl( const uno::Reference
< embed::XStorage
>& xSource
,
3585 const uno::Reference
< embed::XStorage
>& xTarget
)
3587 OSL_ENSURE( xSource
.is() && xTarget
.is(), "Source and/or target storages are not available!\n" );
3588 if ( !xSource
.is() || !xTarget
.is() || xSource
== xTarget
)
3593 uno::Sequence
< ::rtl::OUString
> aSubElements
= xSource
->getElementNames();
3594 for ( sal_Int32 nInd
= 0; nInd
< aSubElements
.getLength(); nInd
++ )
3596 if ( xSource
->isStorageElement( aSubElements
[nInd
] ) )
3598 ::rtl::OUString aMediaType
;
3599 ::rtl::OUString
aMediaTypePropName( RTL_CONSTASCII_USTRINGPARAM( "MediaType" ) );
3600 sal_Bool bGotMediaType
= sal_False
;
3604 uno::Reference
< embed::XOptimizedStorage
> xOptStorage( xSource
, uno::UNO_QUERY_THROW
);
3606 ( xOptStorage
->getElementPropertyValue( aSubElements
[nInd
], aMediaTypePropName
) >>= aMediaType
);
3608 catch( uno::Exception
& )
3611 if ( !bGotMediaType
)
3613 uno::Reference
< embed::XStorage
> xSubStorage
;
3615 xSubStorage
= xSource
->openStorageElement( aSubElements
[nInd
], embed::ElementModes::READ
);
3616 } catch( uno::Exception
& )
3619 if ( !xSubStorage
.is() )
3621 xSubStorage
= ::comphelper::OStorageHelper::GetTemporaryStorage();
3622 xSource
->copyStorageElementLastCommitTo( aSubElements
[nInd
], xSubStorage
);
3625 uno::Reference
< beans::XPropertySet
> xProps( xSubStorage
, uno::UNO_QUERY_THROW
);
3626 bGotMediaType
= ( xProps
->getPropertyValue( aMediaTypePropName
) >>= aMediaType
);
3629 // TODO/LATER: there should be a way to detect whether an object with such a MediaType can exist
3630 // probably it should be placed in the MimeType-ClassID table or in standalone table
3631 if ( aMediaType
.getLength()
3632 && aMediaType
.compareToAscii( "application/vnd.sun.star.oleobject" ) != COMPARE_EQUAL
)
3634 ::com::sun::star::datatransfer::DataFlavor aDataFlavor
;
3635 aDataFlavor
.MimeType
= aMediaType
;
3636 sal_uInt32 nFormat
= SotExchange::GetFormat( aDataFlavor
);
3640 case SOT_FORMATSTR_ID_STARWRITER_60
:
3641 case SOT_FORMATSTR_ID_STARWRITERWEB_60
:
3642 case SOT_FORMATSTR_ID_STARWRITERGLOB_60
:
3643 case SOT_FORMATSTR_ID_STARDRAW_60
:
3644 case SOT_FORMATSTR_ID_STARIMPRESS_60
:
3645 case SOT_FORMATSTR_ID_STARCALC_60
:
3646 case SOT_FORMATSTR_ID_STARCHART_60
:
3647 case SOT_FORMATSTR_ID_STARMATH_60
:
3648 case SOT_FORMATSTR_ID_STARWRITER_8
:
3649 case SOT_FORMATSTR_ID_STARWRITERWEB_8
:
3650 case SOT_FORMATSTR_ID_STARWRITERGLOB_8
:
3651 case SOT_FORMATSTR_ID_STARDRAW_8
:
3652 case SOT_FORMATSTR_ID_STARIMPRESS_8
:
3653 case SOT_FORMATSTR_ID_STARCALC_8
:
3654 case SOT_FORMATSTR_ID_STARCHART_8
:
3655 case SOT_FORMATSTR_ID_STARMATH_8
:
3660 if ( !xTarget
->hasByName( aSubElements
[nInd
] ) )
3668 catch( uno::Exception
& )
3670 OSL_ENSURE( sal_False
, "Cant check storage consistency!\n" );
3677 sal_Bool
SfxObjectShell::SwitchPersistance( const uno::Reference
< embed::XStorage
>& xStorage
)
3679 RTL_LOGFILE_CONTEXT( aLog
, "sfx2 (mv76033) SfxObjectShell::SwitchPersistance" );
3681 sal_Bool bResult
= sal_False
;
3683 // check for wrong creation of object container
3684 BOOL bHasContainer
= ( pImp
->mpObjectContainer
!= 0 );
3686 if ( xStorage
.is() )
3688 if ( pImp
->mpObjectContainer
)
3689 GetEmbeddedObjectContainer().SwitchPersistence( xStorage
);
3690 bResult
= SwitchChildrenPersistance( xStorage
);
3692 // TODO/LATER: substorages that have unknown mimetypes probably should be copied to the target storage here
3693 OSL_ENSURE( StoragesOfUnknownMediaTypeAreCopied_Impl( pImp
->m_xDocStorage
, xStorage
),
3694 "Some of substorages with unknown mimetypes is lost!" );
3699 // make sure that until the storage is assigned the object container is not created by accident!
3700 DBG_ASSERT( bHasContainer
== (pImp
->mpObjectContainer
!= 0), "Wrong storage in object container!" );
3701 if ( pImp
->m_xDocStorage
!= xStorage
)
3702 DoSaveCompleted( new SfxMedium( xStorage
, GetMedium()->GetBaseURL() ) );
3704 if ( IsEnableSetModified() )
3705 SetModified( sal_True
); // ???
3711 sal_Bool
SfxObjectShell::CopyStoragesOfUnknownMediaType( const uno::Reference
< embed::XStorage
>& xSource
,
3712 const uno::Reference
< embed::XStorage
>& xTarget
)
3714 RTL_LOGFILE_CONTEXT( aLog
, "sfx2 (mv76033) SfxObjectShell::CopyStoragesOfUnknownMediaType" );
3716 // This method does not commit the target storage and should not do it
3717 sal_Bool bResult
= sal_True
;
3721 uno::Sequence
< ::rtl::OUString
> aSubElements
= xSource
->getElementNames();
3722 for ( sal_Int32 nInd
= 0; nInd
< aSubElements
.getLength(); nInd
++ )
3724 if ( aSubElements
[nInd
].equals( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Configurations" ) ) ) )
3726 // The workaround for compatibility with SO7, "Configurations" substorage must be preserved
3727 if ( xSource
->isStorageElement( aSubElements
[nInd
] ) )
3729 OSL_ENSURE( !xTarget
->hasByName( aSubElements
[nInd
] ),
3730 "The target storage is an output storage, the element should not exist in the target!\n" );
3732 xSource
->copyElementTo( aSubElements
[nInd
], xTarget
, aSubElements
[nInd
] );
3735 else if ( xSource
->isStorageElement( aSubElements
[nInd
] ) )
3737 ::rtl::OUString aMediaType
;
3738 ::rtl::OUString
aMediaTypePropName( RTL_CONSTASCII_USTRINGPARAM( "MediaType" ) );
3739 sal_Bool bGotMediaType
= sal_False
;
3743 uno::Reference
< embed::XOptimizedStorage
> xOptStorage( xSource
, uno::UNO_QUERY_THROW
);
3745 ( xOptStorage
->getElementPropertyValue( aSubElements
[nInd
], aMediaTypePropName
) >>= aMediaType
);
3747 catch( uno::Exception
& )
3750 if ( !bGotMediaType
)
3752 uno::Reference
< embed::XStorage
> xSubStorage
;
3754 xSubStorage
= xSource
->openStorageElement( aSubElements
[nInd
], embed::ElementModes::READ
);
3755 } catch( uno::Exception
& )
3758 if ( !xSubStorage
.is() )
3760 // TODO/LATER: as optimization in future a substorage of target storage could be used
3761 // instead of the temporary storage; this substorage should be removed later
3762 // if the MimeType is wrong
3763 xSubStorage
= ::comphelper::OStorageHelper::GetTemporaryStorage();
3764 xSource
->copyStorageElementLastCommitTo( aSubElements
[nInd
], xSubStorage
);
3767 uno::Reference
< beans::XPropertySet
> xProps( xSubStorage
, uno::UNO_QUERY_THROW
);
3768 bGotMediaType
= ( xProps
->getPropertyValue( aMediaTypePropName
) >>= aMediaType
);
3771 // TODO/LATER: there should be a way to detect whether an object with such a MediaType can exist
3772 // probably it should be placed in the MimeType-ClassID table or in standalone table
3773 if ( aMediaType
.getLength()
3774 && aMediaType
.compareToAscii( "application/vnd.sun.star.oleobject" ) != COMPARE_EQUAL
)
3776 ::com::sun::star::datatransfer::DataFlavor aDataFlavor
;
3777 aDataFlavor
.MimeType
= aMediaType
;
3778 sal_uInt32 nFormat
= SotExchange::GetFormat( aDataFlavor
);
3782 case SOT_FORMATSTR_ID_STARWRITER_60
:
3783 case SOT_FORMATSTR_ID_STARWRITERWEB_60
:
3784 case SOT_FORMATSTR_ID_STARWRITERGLOB_60
:
3785 case SOT_FORMATSTR_ID_STARDRAW_60
:
3786 case SOT_FORMATSTR_ID_STARIMPRESS_60
:
3787 case SOT_FORMATSTR_ID_STARCALC_60
:
3788 case SOT_FORMATSTR_ID_STARCHART_60
:
3789 case SOT_FORMATSTR_ID_STARMATH_60
:
3790 case SOT_FORMATSTR_ID_STARWRITER_8
:
3791 case SOT_FORMATSTR_ID_STARWRITERWEB_8
:
3792 case SOT_FORMATSTR_ID_STARWRITERGLOB_8
:
3793 case SOT_FORMATSTR_ID_STARDRAW_8
:
3794 case SOT_FORMATSTR_ID_STARIMPRESS_8
:
3795 case SOT_FORMATSTR_ID_STARCALC_8
:
3796 case SOT_FORMATSTR_ID_STARCHART_8
:
3797 case SOT_FORMATSTR_ID_STARMATH_8
:
3803 aSubElements
[nInd
].equalsAscii( "Configurations2" ) || !xTarget
->hasByName( aSubElements
[nInd
] ),
3804 "The target storage is an output storage, the element should not exist in the target!\n" );
3806 if ( !xTarget
->hasByName( aSubElements
[nInd
] ) )
3808 xSource
->copyElementTo( aSubElements
[nInd
], xTarget
, aSubElements
[nInd
] );
3816 catch( uno::Exception
& )
3818 bResult
= sal_False
;
3819 // TODO/LATER: a specific error could be provided
3825 sal_Bool
SfxObjectShell::GenerateAndStoreThumbnail( sal_Bool bEncrypted
,
3827 sal_Bool bIsTemplate
,
3828 const uno::Reference
< embed::XStorage
>& xStor
)
3830 RTL_LOGFILE_CONTEXT( aLog
, "sfx2 (mv76033) SfxObjectShell::GenerateAndStoreThumbnail" );
3832 sal_Bool bResult
= sal_False
;
3835 uno::Reference
< embed::XStorage
> xThumbnailStor
=
3836 xStor
->openStorageElement( ::rtl::OUString::createFromAscii( "Thumbnails" ),
3837 embed::ElementModes::READWRITE
);
3838 if ( xThumbnailStor
.is() )
3840 uno::Reference
< io::XStream
> xStream
= xThumbnailStor
->openStreamElement(
3841 ::rtl::OUString::createFromAscii( "thumbnail.png" ),
3842 embed::ElementModes::READWRITE
);
3844 if ( xStream
.is() && WriteThumbnail( bEncrypted
, bSigned
, bIsTemplate
, xStream
) )
3846 uno::Reference
< embed::XTransactedObject
> xTransact( xThumbnailStor
, uno::UNO_QUERY_THROW
);
3847 xTransact
->commit();
3852 catch( uno::Exception
& )
3859 sal_Bool
SfxObjectShell::WriteThumbnail( sal_Bool bEncrypted
,
3861 sal_Bool bIsTemplate
,
3862 const uno::Reference
< io::XStream
>& xStream
)
3864 sal_Bool bResult
= sal_False
;
3869 uno::Reference
< io::XTruncate
> xTruncate( xStream
->getOutputStream(), uno::UNO_QUERY_THROW
);
3870 xTruncate
->truncate();
3874 sal_uInt16 nResID
= GraphicHelper::getThumbnailReplacementIDByFactoryName_Impl(
3875 ::rtl::OUString::createFromAscii( GetFactory().GetShortName() ),
3881 bResult
= GraphicHelper::getThumbnailReplacement_Impl( nResID
, xStream
);
3885 // retrieve the bitmap and write a signature bitmap over it
3886 SfxResId
aResId( nResID
);
3887 BitmapEx
aThumbBitmap( aResId
);
3888 bResult
= GraphicHelper::getSignedThumbnailFormatFromBitmap_Impl( aThumbBitmap
, xStream
);
3894 ::boost::shared_ptr
<GDIMetaFile
> pMetaFile
=
3895 GetPreviewMetaFile( sal_False
);
3898 bResult
= GraphicHelper::getThumbnailFormatFromGDI_Impl(
3899 pMetaFile
.get(), bSigned
, xStream
);
3903 catch( uno::Exception
& )
3910 void SfxObjectShell::UpdateLinks()
3914 bool SfxObjectShell::GetApplicationFlag(SfxApplicationFlagType eFlagType
)
3919 sal_Bool
SfxObjectShell::QuerySaveSizeExceededModules_Impl( const uno::Reference
< task::XInteractionHandler
>& xHandler
)
3924 if ( !pImp
->pBasicManager
->isValid() )
3926 uno::Sequence
< rtl::OUString
> sModules
;
3927 if ( xHandler
.is() )
3929 if( pImp
->pBasicManager
->LegacyPsswdBinaryLimitExceeded( sModules
) )
3931 ModuleSizeExceeded
* pReq
= new ModuleSizeExceeded( sModules
);
3932 uno::Reference
< task::XInteractionRequest
> xReq( pReq
);
3933 xHandler
->handle( xReq
);
3934 return pReq
->isApprove();
3937 // No interaction handler, default is to continue to save
3940 // -----------------------------------------------------------------------------
3941 uno::Reference
< task::XInteractionHandler
> SfxObjectShell::getInteractionHandler() const
3943 uno::Reference
< task::XInteractionHandler
> xRet
;
3945 xRet
= GetMedium()->GetInteractionHandler();