diff options
Diffstat (limited to 'filter/source/msfilter/svxmsbas.cxx')
-rw-r--r-- | filter/source/msfilter/svxmsbas.cxx | 406 |
1 files changed, 406 insertions, 0 deletions
diff --git a/filter/source/msfilter/svxmsbas.cxx b/filter/source/msfilter/svxmsbas.cxx new file mode 100644 index 000000000000..02370dd75c92 --- /dev/null +++ b/filter/source/msfilter/svxmsbas.cxx @@ -0,0 +1,406 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: svxmsbas.cxx,v $ + * $Revision: 1.24 $ + * + * 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" + +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil -*- */ +#include <tools/debug.hxx> +#include <sfx2/objsh.hxx> +#include <sfx2/app.hxx> +#include <basic/basmgr.hxx> +#include <basic/sbmod.hxx> +#include <svx/svxerr.hxx> +#include <filter/msfilter/svxmsbas.hxx> +#include <msvbasic.hxx> +#include <filter/msfilter/msocximex.hxx> +#include <sot/storinfo.hxx> +#include <comphelper/processfactory.hxx> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/awt/Size.hpp> +#include <com/sun/star/awt/XControlModel.hpp> +using namespace com::sun::star::beans; +using namespace com::sun::star::io; +using namespace com::sun::star::awt; +#include <comphelper/storagehelper.hxx> + +#include <com/sun/star/container/XNameContainer.hpp> +#include <com/sun/star/script/XLibraryContainer.hpp> +using namespace com::sun::star::container; +using namespace com::sun::star::script; +using namespace com::sun::star::uno; +using namespace com::sun::star::lang; +using namespace com::sun::star; + +using rtl::OUString; + +int SvxImportMSVBasic::Import( const String& rStorageName, + const String &rSubStorageName, + BOOL bAsComment, BOOL bStripped ) +{ + int nRet = 0; + if( bImport && ImportCode_Impl( rStorageName, rSubStorageName, + bAsComment, bStripped )) + nRet |= 1; + + if (bImport) + ImportForms_Impl(rStorageName, rSubStorageName); + + if( bCopy && CopyStorage_Impl( rStorageName, rSubStorageName )) + nRet |= 2; + + return nRet; +} + +bool SvxImportMSVBasic::ImportForms_Impl(const String& rStorageName, + const String& rSubStorageName) +{ + SvStorageRef xVBAStg(xRoot->OpenSotStorage(rStorageName, + STREAM_READWRITE | STREAM_NOCREATE | STREAM_SHARE_DENYALL)); + if (!xVBAStg.Is() || xVBAStg->GetError()) + return false; + + std::vector<String> aUserForms; + SvStorageInfoList aContents; + xVBAStg->FillInfoList(&aContents); + for (USHORT nI = 0; nI < aContents.Count(); ++nI) + { + SvStorageInfo& rInfo = aContents.GetObject(nI); + if (!rInfo.IsStream() && rInfo.GetName() != rSubStorageName) + aUserForms.push_back(rInfo.GetName()); + } + + if (aUserForms.empty()) + return false; + + bool bRet = true; + SFX_APP()->EnterBasicCall(); + try + { + Reference<XMultiServiceFactory> xSF(comphelper::getProcessServiceFactory()); + + Reference<XComponentContext> xContext; + Reference<XPropertySet> xProps(xSF, UNO_QUERY); + xProps->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("DefaultContext")) ) >>= xContext; + + + Reference<XLibraryContainer> xLibContainer = rDocSh.GetDialogContainer(); + DBG_ASSERT( xLibContainer.is(), "No BasicContainer!" ); + + String aLibName( RTL_CONSTASCII_USTRINGPARAM( "Standard" ) ); + Reference<XNameContainer> xLib; + if (xLibContainer.is()) + { + if( !xLibContainer->hasByName(aLibName)) + xLibContainer->createLibrary(aLibName); + + Any aLibAny = xLibContainer->getByName( aLibName ); + aLibAny >>= xLib; + } + + if(xLib.is()) + { + typedef std::vector<String>::iterator myIter; + myIter aEnd = aUserForms.end(); + for (myIter aIter = aUserForms.begin(); aIter != aEnd; ++aIter) + { + SvStorageRef xForm (xVBAStg->OpenSotStorage(*aIter, + STREAM_READWRITE | STREAM_NOCREATE | STREAM_SHARE_DENYALL)); + + if (!xForm.Is() || xForm->GetError()) + continue; + + SvStorageStreamRef xFrame = xForm->OpenSotStream( + String( RTL_CONSTASCII_USTRINGPARAM( "\3VBFrame" ) ), + STREAM_STD_READ | STREAM_NOCREATE); + + if (!xFrame.Is() || xFrame->GetError()) + continue; + + SvStorageStreamRef xTypes = xForm->OpenSotStream( + String( 'f' ), STREAM_STD_READ | STREAM_NOCREATE); + + if (!xTypes.Is() || xTypes->GetError()) + continue; + + //<UserForm Name=""><VBFrame></VBFrame>" + String sData; + String sLine; + while(xFrame->ReadByteStringLine(sLine, RTL_TEXTENCODING_MS_1252)) + { + sData += sLine; + sData += '\n'; + } + sData.ConvertLineEnd(); + + Reference<container::XNameContainer> xDialog( + xSF->createInstance( + OUString(RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.awt.UnoControlDialogModel"))), uno::UNO_QUERY); + + OCX_UserForm aForm(xVBAStg, *aIter, *aIter, xDialog, xSF ); + aForm.pDocSh = &rDocSh; + sal_Bool bOk = aForm.Read(xTypes); + DBG_ASSERT(bOk, "Had unexpected content, not risking this module"); + if (bOk) + aForm.Import(xLib); + } + } + } + catch(...) + { + DBG_ERRORFILE( "SvxImportMSVBasic::ImportForms_Impl - any exception caught" ); + //bRet = false; + } + SFX_APP()->LeaveBasicCall(); + return bRet; +} + + +BOOL SvxImportMSVBasic::CopyStorage_Impl( const String& rStorageName, + const String& rSubStorageName) +{ + BOOL bValidStg = FALSE; + { + SvStorageRef xVBAStg( xRoot->OpenSotStorage( rStorageName, + STREAM_READWRITE | STREAM_NOCREATE | + STREAM_SHARE_DENYALL )); + if( xVBAStg.Is() && !xVBAStg->GetError() ) + { + SvStorageRef xVBASubStg( xVBAStg->OpenSotStorage( rSubStorageName, + STREAM_READWRITE | STREAM_NOCREATE | + STREAM_SHARE_DENYALL )); + if( xVBASubStg.Is() && !xVBASubStg->GetError() ) + { + // then we will copy these storages into the (temporary) storage of the document + bValidStg = TRUE; + } + } + } + + if( bValidStg ) + { + String aDstStgName( GetMSBasicStorageName() ); + SotStorageRef xDst = SotStorage::OpenOLEStorage( rDocSh.GetStorage(), aDstStgName, STREAM_READWRITE | STREAM_TRUNC ); + SotStorageRef xSrc = xRoot->OpenSotStorage( rStorageName, STREAM_STD_READ ); + + // TODO/LATER: should we commit the storage? + xSrc->CopyTo( xDst ); + xDst->Commit(); + ErrCode nError = xDst->GetError(); + if ( nError == ERRCODE_NONE ) + nError = xSrc->GetError(); + if ( nError != ERRCODE_NONE ) + xRoot->SetError( nError ); + else + bValidStg = TRUE; + } + + return bValidStg; +} + +BOOL SvxImportMSVBasic::ImportCode_Impl( const String& rStorageName, + const String &rSubStorageName, + BOOL bAsComment, BOOL bStripped ) +{ + BOOL bRet = FALSE; + VBA_Impl aVBA( *xRoot, bAsComment ); + if( aVBA.Open(rStorageName,rSubStorageName) ) + { + SFX_APP()->EnterBasicCall(); + Reference<XLibraryContainer> xLibContainer = rDocSh.GetBasicContainer(); + DBG_ASSERT( xLibContainer.is(), "No BasicContainer!" ); + + UINT16 nStreamCount = aVBA.GetNoStreams(); + Reference<XNameContainer> xLib; + if( xLibContainer.is() && nStreamCount ) + { + String aLibName( RTL_CONSTASCII_USTRINGPARAM( "Standard" ) ); + if( !xLibContainer->hasByName( aLibName ) ) + xLibContainer->createLibrary( aLibName ); + + Any aLibAny = xLibContainer->getByName( aLibName ); + aLibAny >>= xLib; + } + if( xLib.is() ) + { + for( UINT16 i=0; i<nStreamCount;i++) + { + StringArray aDecompressed = aVBA.Decompress(i); +#if 0 +/* DR 2005-08-11 #124850# Do not filter special characters from module name. + Just put the original module name and let the Basic interpreter deal with + it. Needed for roundtrip... + */ + ByteString sByteBasic(aVBA.GetStreamName(i), + RTL_TEXTENCODING_ASCII_US, + (RTL_UNICODETOTEXT_FLAGS_UNDEFINED_UNDERLINE| + RTL_UNICODETOTEXT_FLAGS_INVALID_UNDERLINE | + RTL_UNICODETOTEXT_FLAGS_PRIVATE_MAPTO0 | + RTL_UNICODETOTEXT_FLAGS_NOCOMPOSITE) + ); + + const String sBasicModule(sByteBasic, + RTL_TEXTENCODING_ASCII_US); +#else + const String &sBasicModule = aVBA.GetStreamName( i); +#endif + /* #117718# expose information regarding type of Module + * Class, Form or plain 'ould VBA module with a REM statment + * at the top of the module. Mapping of Module Name + * to type is performed in VBA_Impl::Open() method, + * ( msvbasic.cxx ) by examining the PROJECT stream. + */ + + // using name from aVBA.GetStreamName + // because the encoding of the same returned + // is the same as the encoding for the names + // that are keys in the map used by GetModuleType method + const String &sOrigVBAModName = aVBA.GetStreamName( i ); + ModuleType mType = aVBA.GetModuleType( sOrigVBAModName ); + + rtl::OUString sClassRem( RTL_CONSTASCII_USTRINGPARAM( "Rem Attribute VBA_ModuleType=" ) ); + + rtl::OUString modeTypeComment; + + switch( mType ) + { + case Class: + modeTypeComment = sClassRem + + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "VBAClassModule\n" ) ); + break; + case Form: + modeTypeComment = sClassRem + + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "VBAFormModule\n" ) ); + break; + case Document: + modeTypeComment = sClassRem + + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "VBADocumentModule\n" ) ); + break; + case Normal: + modeTypeComment = sClassRem + + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "VBAModule\n" ) ); + break; + case Unknown: + modeTypeComment = sClassRem + + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "VBAUnknown\n" ) ); + break; + default: + DBG_ERRORFILE( "SvxImportMSVBasic::ImportCode_Impl - unknown module type" ); + break; + } + static ::rtl::OUString sVBAOption( RTL_CONSTASCII_USTRINGPARAM( "Option VBASupport 1\n" ) ); + static ::rtl::OUString sClassOption( RTL_CONSTASCII_USTRINGPARAM( "Option ClassModule\n" ) ); + if ( !bAsComment ) + { + modeTypeComment = modeTypeComment + sVBAOption; + if ( mType == Class ) + modeTypeComment = modeTypeComment + sClassOption; + + } + + String sModule(sBasicModule); //#i52606# no need to split Macros in 64KB blocks any more! + String sTemp; + if (bAsComment) + { + sTemp+=String(RTL_CONSTASCII_USTRINGPARAM( "Sub " )); + String sMunge(sModule); + //Streams can have spaces in them, but modulenames + //cannot ! + sMunge.SearchAndReplaceAll(' ','_'); + + sTemp += sMunge; + sTemp.AppendAscii("\n"); + }; + ::rtl::OUString aSource(sTemp); + + for(ULONG j=0;j<aDecompressed.GetSize();j++) + { + if (bStripped) + { + String *pStr = aDecompressed.Get(j); + bool bMac = true; + xub_StrLen nBegin = pStr->Search('\x0D'); + if ((STRING_NOTFOUND != nBegin) && (pStr->Len() > 1) && (pStr->GetChar(nBegin+1) == '\x0A')) + bMac = false; + + const char cLineEnd = bMac ? '\x0D' : '\x0A'; + const String sAttribute(String::CreateFromAscii( + bAsComment ? "Rem Attribute" : "Attribute")); + nBegin = 0; + while (STRING_NOTFOUND != (nBegin = pStr->Search(sAttribute, nBegin))) + { + if ((nBegin) && pStr->GetChar(nBegin-1) != cLineEnd) + { + // npower #i63766# Need to skip instances of Attribute + // that are NOT Attribute statements + nBegin = nBegin + sAttribute.Len(); + continue; + } + xub_StrLen nEnd = pStr->Search(cLineEnd ,nBegin); + // DR #i26521# catch STRING_NOTFOUND, will loop endless otherwise + if( nEnd == STRING_NOTFOUND ) + pStr->Erase(); + else + pStr->Erase(nBegin, (nEnd-nBegin)+1); + } + } + if( aDecompressed.Get(j)->Len() ) + { + aSource+=::rtl::OUString( *aDecompressed.Get(j) ); + } + + } + if (bAsComment) + { + aSource += rtl::OUString::createFromAscii("\nEnd Sub"); + } + ::rtl::OUString aModName( sModule ); + if ( aSource.getLength() ) + { + aSource = modeTypeComment + aSource; + + Any aSourceAny; + aSourceAny <<= aSource; + if( xLib->hasByName( aModName ) ) + xLib->replaceByName( aModName, aSourceAny ); + else + xLib->insertByName( aModName, aSourceAny ); + } + + bRet = true; + } + } + SFX_APP()->LeaveBasicCall(); + } + return bRet; +} + +/* vi:set tabstop=4 shiftwidth=4 expandtab: */ |