diff options
Diffstat (limited to 'filter/source/msfilter/msoleexp.cxx')
-rw-r--r-- | filter/source/msfilter/msoleexp.cxx | 364 |
1 files changed, 364 insertions, 0 deletions
diff --git a/filter/source/msfilter/msoleexp.cxx b/filter/source/msfilter/msoleexp.cxx new file mode 100644 index 000000000000..ebafd06688b0 --- /dev/null +++ b/filter/source/msfilter/msoleexp.cxx @@ -0,0 +1,364 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_filter.hxx" +#include <com/sun/star/uno/Reference.hxx> +#include <com/sun/star/uno/Sequence.hxx> +#include <com/sun/star/uno/Any.hxx> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/container/XNameAccess.hpp> +#include <com/sun/star/embed/XEmbedPersist.hpp> +#include <com/sun/star/embed/NoVisualAreaSizeException.hpp> +#include <com/sun/star/embed/EmbedStates.hpp> +#include <com/sun/star/frame/XStorable.hpp> +#include <com/sun/star/awt/Size.hpp> +#include <com/sun/star/embed/Aspects.hpp> +#include <sot/clsids.hxx> +#include <sfx2/objsh.hxx> +#include <sfx2/docfac.hxx> +#include <sfx2/docfilt.hxx> +#include <sfx2/docfile.hxx> +#include <sfx2/fcontnr.hxx> +#include <sot/formats.hxx> +#include <comphelper/processfactory.hxx> +#include <unotools/streamwrap.hxx> +#include <comphelper/storagehelper.hxx> +#include <svtools/embedhlp.hxx> +#include <filter/msfilter/msdffimp.hxx> // extern sichtbare Header-Datei + +#include "filter/msfilter/msoleexp.hxx" + +#define CREATE_CONST_ASC(s) String::CreateFromAscii( \ + RTL_CONSTASCII_STRINGPARAM(s)) + +using namespace ::com::sun::star; + +SvGlobalName GetEmbeddedVersion( const SvGlobalName& aAppName ) +{ + if ( aAppName == SvGlobalName( SO3_SM_CLASSID_60 ) ) + return SvGlobalName( SO3_SM_OLE_EMBED_CLASSID_8 ); + else if ( aAppName == SvGlobalName( SO3_SW_CLASSID_60 ) ) + return SvGlobalName( SO3_SW_OLE_EMBED_CLASSID_8 ); + else if ( aAppName == SvGlobalName( SO3_SC_CLASSID_60 ) ) + return SvGlobalName( SO3_SC_OLE_EMBED_CLASSID_8 ); + else if ( aAppName == SvGlobalName( SO3_SDRAW_CLASSID_60 ) ) + return SvGlobalName( SO3_SDRAW_OLE_EMBED_CLASSID_8 ); + else if ( aAppName == SvGlobalName( SO3_SIMPRESS_CLASSID_60 ) ) + return SvGlobalName( SO3_SIMPRESS_OLE_EMBED_CLASSID_8 ); + else if ( aAppName == SvGlobalName( SO3_SCH_CLASSID_60 ) ) + return SvGlobalName( SO3_SCH_OLE_EMBED_CLASSID_8 ); + + return SvGlobalName(); +} + +String GetStorageType( const SvGlobalName& aEmbName ) +{ + if ( aEmbName == SvGlobalName( SO3_SM_OLE_EMBED_CLASSID_8 ) ) + return String::CreateFromAscii( "opendocument.MathDocument.1" ); + else if ( aEmbName == SvGlobalName( SO3_SW_OLE_EMBED_CLASSID_8 ) ) + return String::CreateFromAscii( "opendocument.WriterDocument.1" ); + else if ( aEmbName == SvGlobalName( SO3_SC_OLE_EMBED_CLASSID_8 ) ) + return String::CreateFromAscii( "opendocument.CalcDocument.1" ); + else if ( aEmbName == SvGlobalName( SO3_SDRAW_OLE_EMBED_CLASSID_8 ) ) + return String::CreateFromAscii( "opendocument.DrawDocument.1" ); + else if ( aEmbName == SvGlobalName( SO3_SIMPRESS_OLE_EMBED_CLASSID_8 ) ) + return String::CreateFromAscii( "opendocument.ImpressDocument.1" ); + else if ( aEmbName == SvGlobalName( SO3_SCH_OLE_EMBED_CLASSID_8 ) ) + return String::CreateFromAscii( "opendocument.ChartDocument.1" ); + + return String(); +} + +sal_Bool UseOldMSExport() +{ + uno::Reference< lang::XMultiServiceFactory > xFactory = ::comphelper::getProcessServiceFactory(); + + if ( xFactory.is() ) + { + uno::Reference< lang::XMultiServiceFactory > xProvider( xFactory->createInstance( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.configuration.ConfigurationProvider"))), + uno::UNO_QUERY); + if ( xProvider.is() ) + { + try { + uno::Sequence< uno::Any > aArg( 1 ); + aArg[0] <<= rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/org.openoffice.Office.Common/InternalMSExport") ); + uno::Reference< container::XNameAccess > xNameAccess( + xProvider->createInstanceWithArguments( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.configuration.ConfigurationUpdateAccess" ) ), + aArg ), + uno::UNO_QUERY ); + if ( xNameAccess.is() ) + { + uno::Any aResult = xNameAccess->getByName( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "UseOldExport" ) ) ); + + sal_Bool bResult = sal_Bool(); + if ( aResult >>= bResult ) + return bResult; + } + } + catch( uno::Exception& ) + { + } + } + } + + OSL_ENSURE( sal_False, "Could not get access to configuration entry!\n" ); + return sal_False; +} + +void SvxMSExportOLEObjects::ExportOLEObject( const com::sun::star::uno::Reference < com::sun::star::embed::XEmbeddedObject>& rObj, SotStorage& rDestStg ) +{ + svt::EmbeddedObjectRef aObj( rObj, embed::Aspects::MSOLE_CONTENT ); + ExportOLEObject( aObj, rDestStg ); +} + +void SvxMSExportOLEObjects::ExportOLEObject( svt::EmbeddedObjectRef& rObj, SvStorage& rDestStg ) +{ + SvGlobalName aOwnGlobalName; + SvGlobalName aObjName( rObj->getClassID() ); + const SfxFilter* pExpFilter = NULL; + { + static struct _ObjExpType { + UINT32 nFlag; + const char* pFilterNm; + // GlobalNameId + struct _GlobalNameIds { + UINT32 n1; + USHORT n2, n3; + BYTE b8, b9, b10, b11, b12, b13, b14, b15; + } + aGlNmIds[4]; + } aArr[] = { + { OLE_STARMATH_2_MATHTYPE, "MathType 3.x", + {{SO3_SM_CLASSID_60}, {SO3_SM_CLASSID_50}, + {SO3_SM_CLASSID_40}, {SO3_SM_CLASSID_30 }}}, + { OLE_STARWRITER_2_WINWORD, "MS Word 97", + {{SO3_SW_CLASSID_60}, {SO3_SW_CLASSID_50}, + {SO3_SW_CLASSID_40}, {SO3_SW_CLASSID_30 }}}, + { OLE_STARCALC_2_EXCEL, "MS Excel 97", + {{SO3_SC_CLASSID_60}, {SO3_SC_CLASSID_50}, + {SO3_SC_CLASSID_40}, {SO3_SC_CLASSID_30 }}}, + { OLE_STARIMPRESS_2_POWERPOINT, "MS PowerPoint 97", + {{SO3_SIMPRESS_CLASSID_60}, {SO3_SIMPRESS_CLASSID_50}, + {SO3_SIMPRESS_CLASSID_40}, {SO3_SIMPRESS_CLASSID_30 }}}, + { 0, "", + {{SO3_SCH_CLASSID_60}, {SO3_SCH_CLASSID_50}, + {SO3_SCH_CLASSID_40}, {SO3_SCH_CLASSID_30 }}}, + { 0, "", + {{SO3_SDRAW_CLASSID_60}, {SO3_SDRAW_CLASSID_50}, // SJ: !!!! SO3_SDRAW_CLASSID is only available up from + {SO3_SDRAW_CLASSID_60}, {SO3_SDRAW_CLASSID_50 }}}, // ver 5.0, it is purpose to have double entrys here. + + { 0xffff,0, + {{SO3_SDRAW_CLASSID_60}, {SO3_SDRAW_CLASSID_50}, + {SO3_SDRAW_CLASSID_60}, {SO3_SDRAW_CLASSID_50}}} + }; + + for( const _ObjExpType* pArr = aArr; !pExpFilter && ( pArr->nFlag != 0xffff ); ++pArr ) + { + for ( int n = 0; n < 4; ++n ) + { + const _ObjExpType::_GlobalNameIds& rId = pArr->aGlNmIds[ n ]; + SvGlobalName aGlbNm( rId.n1, rId.n2, rId.n3, + rId.b8, rId.b9, rId.b10, rId.b11, + rId.b12, rId.b13, rId.b14, rId.b15 ); + if( aObjName == aGlbNm ) + { + aOwnGlobalName = aGlbNm; + + // flags for checking if conversion is wanted at all (SaveOptions?!) + if( GetFlags() & pArr->nFlag ) + { + pExpFilter = SfxFilterMatcher().GetFilter4FilterName(String::CreateFromAscii(pArr->pFilterNm)); + break; + } + } + } + } + } + + if( pExpFilter ) // use this filter for the export + { + try + { + if ( rObj->getCurrentState() == embed::EmbedStates::LOADED ) + rObj->changeState( embed::EmbedStates::RUNNING ); + //TODO/LATER: is stream instead of outputstream a better choice?! + //TODO/LATER: a "StoreTo" method at embedded object would be nice + uno::Sequence < beans::PropertyValue > aSeq(2); + SvStream* pStream = new SvMemoryStream; + aSeq[0].Name = ::rtl::OUString::createFromAscii( "OutputStream" ); + ::uno::Reference < io::XOutputStream > xOut = new ::utl::OOutputStreamWrapper( *pStream ); + aSeq[0].Value <<= xOut; + aSeq[1].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "FilterName" ) ); + aSeq[1].Value <<= ::rtl::OUString( pExpFilter->GetName() ); + uno::Reference < frame::XStorable > xStor( rObj->getComponent(), uno::UNO_QUERY ); + xStor->storeToURL( ::rtl::OUString::createFromAscii( "private:stream" ), aSeq ); + SotStorageRef xOLEStor = new SotStorage( pStream, TRUE ); + xOLEStor->CopyTo( &rDestStg ); + rDestStg.Commit(); + } + catch( uno::Exception& ) + { + // TODO/LATER: Error handling + DBG_ERROR( "The object could not be exported!" ); + } + } + else if( aOwnGlobalName != SvGlobalName() ) + { + // own format, maybe SO6 format or lower + SvGlobalName aEmbName = GetEmbeddedVersion( aOwnGlobalName ); + if ( aEmbName != SvGlobalName() && !UseOldMSExport() ) + { + // this is a SO6 embedded object, save in old binary format + rDestStg.SetVersion( SOFFICE_FILEFORMAT_31 ); + rDestStg.SetClass( aEmbName, + SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE, + GetStorageType( aEmbName ) ); + SotStorageStreamRef xExtStm = rDestStg.OpenSotStream( + String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM( "properties_stream" ) ), + STREAM_STD_READWRITE ); + + sal_Bool bExtentSuccess = sal_False; + if( !xExtStm->GetError() ) + { + // write extent + //TODO/MBA: check if writing a size is enough + if( rObj.GetObject().is() ) + { + // MSOLE objects don't need to be in running state for VisualArea access + awt::Size aSize; + try + { + // this is an own object, the content size must be stored in the + // extension stream + aSize = rObj->getVisualAreaSize( embed::Aspects::MSOLE_CONTENT ); + } + catch( embed::NoVisualAreaSizeException& ) + { + OSL_ENSURE( sal_False, "Could not get visual area size!\n" ); + aSize.Width = 5000; + aSize.Height = 5000; + } + catch( uno::Exception& ) + { + OSL_ENSURE( sal_False, "Unexpected exception while getting visual area size!\n" ); + aSize.Width = 5000; + aSize.Height = 5000; + } + + //Rectangle aVisArea = xSfxIPObj->GetVisArea( ASPECT_CONTENT ); + sal_Int32 pRect[4]; + //pRect[0] = aVisArea.Left(); + //pRect[1] = aVisArea.Right(); + //pRect[2] = aVisArea.Top(); + //pRect[3] = aVisArea.Bottom(); + pRect[0] = 0; + pRect[1] = aSize.Width; + pRect[2] = 0; + pRect[3] = aSize.Height; + + sal_Int8 aWriteSet[16]; + for ( int ind = 0; ind < 4; ind++ ) + { + sal_Int32 nVal = pRect[ind]; + for ( int nByte = 0; nByte < 4; nByte++ ) + { + aWriteSet[ind*4+nByte] = (sal_Int8) nVal % 0x100; + nVal /= 0x100; + } + } + + bExtentSuccess = ( xExtStm->Write( aWriteSet, 16 ) == 16 ); + } + } + + if ( bExtentSuccess ) + { + SotStorageStreamRef xEmbStm = rDestStg.OpenSotStream( + String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM( "package_stream" ) ), + STREAM_STD_READWRITE ); + if( !xEmbStm->GetError() ) + { + try + { + if ( rObj->getCurrentState() == embed::EmbedStates::LOADED ) + rObj->changeState( embed::EmbedStates::RUNNING ); + //TODO/LATER: is stream instead of outputstream a better choice?! + //TODO/LATER: a "StoreTo" method at embedded object would be nice + uno::Sequence < beans::PropertyValue > aSeq(1); + aSeq[0].Name = ::rtl::OUString::createFromAscii( "OutputStream" ); + ::uno::Reference < io::XOutputStream > xOut = new ::utl::OOutputStreamWrapper( *xEmbStm ); + aSeq[0].Value <<= xOut; + uno::Reference < frame::XStorable > xStor( rObj->getComponent(), uno::UNO_QUERY ); + xStor->storeToURL( ::rtl::OUString::createFromAscii( "private:stream" ), aSeq ); + } + catch( uno::Exception& ) + { + // TODO/LATER: Error handling + DBG_ERROR( "The object could not be exported!" ); + } + } + } + } + else + { + DBG_ERROR("Own binary format inside own container document!"); + } + } + else + { + // alien objects + //TODO/LATER: a "StoreTo" method at embedded object would be nice + rDestStg.SetVersion( SOFFICE_FILEFORMAT_31 ); + uno::Reference < embed::XStorage > xStor = ::comphelper::OStorageHelper::GetTemporaryStorage(); + uno::Reference < embed::XEmbedPersist > xPers( rObj.GetObject(), uno::UNO_QUERY ); + if ( xPers.is() ) + { + uno::Sequence < beans::PropertyValue > aEmptySeq; + ::rtl::OUString aTempName(::rtl::OUString::createFromAscii("bla")); + try + { + xPers->storeToEntry( xStor, aTempName, aEmptySeq, aEmptySeq ); + } + catch ( uno::Exception& ) + {} + + SotStorageRef xOLEStor = SotStorage::OpenOLEStorage( xStor, aTempName, STREAM_STD_READ ); + xOLEStor->CopyTo( &rDestStg ); + rDestStg.Commit(); + } + } + + //We never need this stream: See #99809# and #i2179# + rDestStg.Remove(CREATE_CONST_ASC(SVEXT_PERSIST_STREAM)); +} + + + |