summaryrefslogtreecommitdiff
path: root/oox/source
diff options
context:
space:
mode:
authorHenning Brinkmann <hbrinkm@openoffice.org>2011-01-05 13:59:51 +0100
committerHenning Brinkmann <hbrinkm@openoffice.org>2011-01-05 13:59:51 +0100
commit0ab620d32e49a7822c66dc3c466488fd21554b7d (patch)
treefd0fd5acbeff0c7ff568597fb1501de6f7aea870 /oox/source
parent7efe40c915619ac4f1ca5d5a26641a10aeafe418 (diff)
parent220821e1f4c3cb86a891e5864b665cadcfaed0c6 (diff)
merged DEV300_m96
Diffstat (limited to 'oox/source')
-rw-r--r--oox/source/core/binarycodec.cxx111
-rw-r--r--oox/source/core/filterbase.cxx4
-rw-r--r--oox/source/core/filterdetect.cxx109
-rw-r--r--oox/source/drawingml/textcharacterproperties.cxx2
-rw-r--r--oox/source/drawingml/textrun.cxx50
-rw-r--r--oox/source/dump/biffdumper.cxx2
-rw-r--r--oox/source/dump/dumperbase.cxx16
-rw-r--r--oox/source/ole/vbamodule.cxx79
-rw-r--r--oox/source/ole/vbaproject.cxx107
-rw-r--r--oox/source/xls/biffcodec.cxx92
-rwxr-xr-xoox/source/xls/excelvbaproject.cxx161
-rw-r--r--oox/source/xls/makefile.mk1
-rw-r--r--oox/source/xls/workbookhelper.cxx4
-rw-r--r--oox/source/xls/worksheethelper.cxx134
14 files changed, 702 insertions, 170 deletions
diff --git a/oox/source/core/binarycodec.cxx b/oox/source/core/binarycodec.cxx
index 6127524c2aae..954f623f1f91 100644
--- a/oox/source/core/binarycodec.cxx
+++ b/oox/source/core/binarycodec.cxx
@@ -30,6 +30,11 @@
#include <string.h>
#include "oox/helper/attributelist.hxx"
+#include <comphelper/sequenceashashmap.hxx>
+#include <comphelper/docpasswordhelper.hxx>
+
+using namespace ::com::sun::star;
+
namespace oox {
namespace core {
@@ -176,6 +181,37 @@ void BinaryCodec_XOR::initKey( const sal_uInt8 pnPassData[ 16 ] )
}
}
+bool BinaryCodec_XOR::initCodec( const uno::Sequence< beans::NamedValue >& aData )
+{
+ bool bResult = sal_False;
+
+ ::comphelper::SequenceAsHashMap aHashData( aData );
+ uno::Sequence< sal_Int8 > aKey = aHashData.getUnpackedValueOrDefault( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "XOR95EncryptionKey" ) ), uno::Sequence< sal_Int8 >() );
+
+ if ( aKey.getLength() == 16 )
+ {
+ (void)memcpy( mpnKey, aKey.getConstArray(), 16 );
+ bResult = sal_True;
+
+ mnBaseKey = (sal_uInt16)aHashData.getUnpackedValueOrDefault( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "XOR95BaseKey" ) ), (sal_Int16)0 );
+ mnHash = (sal_uInt16)aHashData.getUnpackedValueOrDefault( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "XOR95PasswordHash" ) ), (sal_Int16)0 );
+ }
+ else
+ OSL_ENSURE( sal_False, "Unexpected key size!\n" );
+
+ return bResult;
+}
+
+uno::Sequence< beans::NamedValue > BinaryCodec_XOR::getEncryptionData()
+{
+ ::comphelper::SequenceAsHashMap aHashData;
+ aHashData[ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "XOR95EncryptionKey" ) ) ] <<= uno::Sequence<sal_Int8>( (sal_Int8*)mpnKey, 16 );
+ aHashData[ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "XOR95BaseKey" ) ) ] <<= (sal_Int16)mnBaseKey;
+ aHashData[ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "XOR95PasswordHash" ) ) ] <<= (sal_Int16)mnHash;
+
+ return aHashData.getAsConstNamedValueList();
+}
+
bool BinaryCodec_XOR::verifyKey( sal_uInt16 nKey, sal_uInt16 nHash ) const
{
return (nKey == mnBaseKey) && (nHash == mnHash);
@@ -230,11 +266,6 @@ bool BinaryCodec_XOR::skip( sal_Int32 nBytes )
return true;
}
-sal_uInt16 BinaryCodec_XOR::getHash( const sal_uInt8* pnPassData, sal_Int32 nSize )
-{
- return lclGetHash( pnPassData, nSize );
-}
-
// ============================================================================
BinaryCodec_RCF::BinaryCodec_RCF()
@@ -246,56 +277,62 @@ BinaryCodec_RCF::BinaryCodec_RCF()
OSL_ENSURE( mhDigest != 0, "BinaryCodec_RCF::BinaryCodec_RCF - cannot create digest" );
(void)memset( mpnDigestValue, 0, sizeof( mpnDigestValue ) );
+ (void)memset (mpnUnique, 0, sizeof(mpnUnique));
}
BinaryCodec_RCF::~BinaryCodec_RCF()
{
(void)memset( mpnDigestValue, 0, sizeof( mpnDigestValue ) );
+ (void)memset (mpnUnique, 0, sizeof(mpnUnique));
rtl_digest_destroy( mhDigest );
rtl_cipher_destroy( mhCipher );
}
-void BinaryCodec_RCF::initKey( const sal_uInt16 pnPassData[ 16 ], const sal_uInt8 pnSalt[ 16 ] )
+bool BinaryCodec_RCF::initCodec( const uno::Sequence< beans::NamedValue >& aData )
{
- // create little-endian key data array from password data
- sal_uInt8 pnKeyData[ 64 ];
- (void)memset( pnKeyData, 0, sizeof( pnKeyData ) );
+ bool bResult = sal_False;
- const sal_uInt16* pnCurrPass = pnPassData;
- const sal_uInt16* pnPassEnd = pnPassData + 16;
- sal_uInt8* pnCurrKey = pnKeyData;
- size_t nPassSize = 0;
- for( ; (pnCurrPass < pnPassEnd) && (*pnCurrPass != 0); ++pnCurrPass, ++nPassSize )
+ ::comphelper::SequenceAsHashMap aHashData( aData );
+ uno::Sequence< sal_Int8 > aKey = aHashData.getUnpackedValueOrDefault( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "STD97EncryptionKey" ) ), uno::Sequence< sal_Int8 >() );
+
+ if ( aKey.getLength() == RTL_DIGEST_LENGTH_MD5 )
{
- *pnCurrKey++ = static_cast< sal_uInt8 >( *pnCurrPass );
- *pnCurrKey++ = static_cast< sal_uInt8 >( *pnCurrPass >> 8 );
+ (void)memcpy( mpnDigestValue, aKey.getConstArray(), RTL_DIGEST_LENGTH_MD5 );
+ uno::Sequence< sal_Int8 > aUniqueID = aHashData.getUnpackedValueOrDefault( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "STD97UniqueID" ) ), uno::Sequence< sal_Int8 >() );
+ if ( aUniqueID.getLength() == 16 )
+ {
+ (void)memcpy( mpnUnique, aUniqueID.getConstArray(), 16 );
+ bResult = sal_False;
+ }
+ else
+ OSL_ENSURE( sal_False, "Unexpected document ID!\n" );
}
- pnKeyData[ 2 * nPassSize ] = 0x80;
- pnKeyData[ 56 ] = static_cast< sal_uInt8 >( nPassSize << 4 );
+ else
+ OSL_ENSURE( sal_False, "Unexpected key size!\n" );
- // fill raw digest of key data into key data
- (void)rtl_digest_updateMD5( mhDigest, pnKeyData, sizeof( pnKeyData ) );
- (void)rtl_digest_rawMD5( mhDigest, pnKeyData, RTL_DIGEST_LENGTH_MD5 );
+ return bResult;
+}
- // update digest with key data and passed salt data
- for( size_t nIndex = 0; nIndex < 16; ++nIndex )
- {
- rtl_digest_updateMD5( mhDigest, pnKeyData, 5 );
- rtl_digest_updateMD5( mhDigest, pnSalt, 16 );
- }
+uno::Sequence< beans::NamedValue > BinaryCodec_RCF::getEncryptionData()
+{
+ ::comphelper::SequenceAsHashMap aHashData;
+ aHashData[ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "STD97EncryptionKey" ) ) ] <<= uno::Sequence< sal_Int8 >( (sal_Int8*)mpnDigestValue, RTL_DIGEST_LENGTH_MD5 );
+ aHashData[ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "STD97UniqueID" ) ) ] <<= uno::Sequence< sal_Int8 >( (sal_Int8*)mpnUnique, 16 );
- // update digest with padding
- pnKeyData[ 16 ] = 0x80;
- (void)memset( pnKeyData + 17, 0, sizeof( pnKeyData ) - 17 );
- pnKeyData[ 56 ] = 0x80;
- pnKeyData[ 57 ] = 0x0A;
- rtl_digest_updateMD5( mhDigest, pnKeyData + 16, sizeof( pnKeyData ) - 16 );
+ return aHashData.getAsConstNamedValueList();
+}
- // fill raw digest of above updates into digest value
- rtl_digest_rawMD5( mhDigest, mpnDigestValue, sizeof( mpnDigestValue ) );
+void BinaryCodec_RCF::initKey( const sal_uInt16 pnPassData[ 16 ], const sal_uInt8 pnSalt[ 16 ] )
+{
+ uno::Sequence< sal_Int8 > aKey = ::comphelper::DocPasswordHelper::GenerateStd97Key( pnPassData, uno::Sequence< sal_Int8 >( (sal_Int8*)pnSalt, 16 ) );
+ // Fill raw digest of above updates into DigestValue.
- // erase key data array and leave
- (void)memset( pnKeyData, 0, sizeof( pnKeyData ) );
+ if ( aKey.getLength() == sizeof(mpnDigestValue) )
+ (void)memcpy ( mpnDigestValue, (const sal_uInt8*)aKey.getConstArray(), sizeof(mpnDigestValue) );
+ else
+ memset( mpnDigestValue, 0, sizeof(mpnDigestValue) );
+
+ (void)memcpy( mpnUnique, pnSalt, 16 );
}
bool BinaryCodec_RCF::verifyKey( const sal_uInt8 pnVerifier[ 16 ], const sal_uInt8 pnVerifierHash[ 16 ] )
diff --git a/oox/source/core/filterbase.cxx b/oox/source/core/filterbase.cxx
index 9b7b00988dd0..6d2b98454444 100644
--- a/oox/source/core/filterbase.cxx
+++ b/oox/source/core/filterbase.cxx
@@ -67,6 +67,8 @@ using ::comphelper::MediaDescriptor;
using ::comphelper::SequenceAsHashMap;
using ::oox::ole::OleObjectHelper;
+using namespace ::com::sun::star;
+
namespace oox {
namespace core {
@@ -399,7 +401,7 @@ OleObjectHelper& FilterBase::getOleObjectHelper() const
return *mxImpl->mxOleObjHelper;
}
-OUString FilterBase::requestPassword( ::comphelper::IDocPasswordVerifier& rVerifier ) const
+uno::Sequence< beans::NamedValue > FilterBase::requestEncryptionData( ::comphelper::IDocPasswordVerifier& rVerifier ) const
{
::std::vector< OUString > aDefaultPasswords;
aDefaultPasswords.push_back( CREATE_OUSTRING( "VelvetSweatshop" ) );
diff --git a/oox/source/core/filterdetect.cxx b/oox/source/core/filterdetect.cxx
index 00244c224778..53d8809330d9 100644
--- a/oox/source/core/filterdetect.cxx
+++ b/oox/source/core/filterdetect.cxx
@@ -65,6 +65,8 @@ using ::com::sun::star::xml::sax::XLocator;
using ::comphelper::MediaDescriptor;
using ::comphelper::SequenceAsHashMap;
+using namespace ::com::sun::star;
+
namespace oox {
namespace core {
@@ -366,7 +368,49 @@ void lclDeriveKey( const sal_uInt8* pnHash, sal_uInt32 nHashLen, sal_uInt8* pnKe
// ----------------------------------------------------------------------------
-bool lclGenerateEncryptionKey( const PackageEncryptionInfo& rEncrInfo, const OUString& rPassword, sal_uInt8* pnKey, sal_uInt32 nRequiredKeyLen )
+bool lclCheckEncryptionData( const sal_uInt8* pnKey, sal_uInt32 nKeySize, const sal_uInt8* pnVerifier, sal_uInt32 nVerifierSize, const sal_uInt8* pnVerifierHash, sal_uInt32 nVerifierHashSize )
+{
+ bool bResult = false;
+
+ // the only currently supported algorithm needs key size 128
+ if ( nKeySize == 16 && nVerifierSize == 16 && nVerifierHashSize == 32 )
+ {
+ // check password
+ EVP_CIPHER_CTX aes_ctx;
+ EVP_CIPHER_CTX_init( &aes_ctx );
+ EVP_DecryptInit_ex( &aes_ctx, EVP_aes_128_ecb(), 0, pnKey, 0 );
+ EVP_CIPHER_CTX_set_padding( &aes_ctx, 0 );
+ int nOutLen = 0;
+ sal_uInt8 pnTmpVerifier[ 16 ];
+ (void) memset( pnTmpVerifier, 0, sizeof(pnTmpVerifier) );
+
+ /*int*/ EVP_DecryptUpdate( &aes_ctx, pnTmpVerifier, &nOutLen, pnVerifier, nVerifierSize );
+ EVP_CIPHER_CTX_cleanup( &aes_ctx );
+
+ EVP_CIPHER_CTX_init( &aes_ctx );
+ EVP_DecryptInit_ex( &aes_ctx, EVP_aes_128_ecb(), 0, pnKey, 0 );
+ EVP_CIPHER_CTX_set_padding( &aes_ctx, 0 );
+ sal_uInt8 pnTmpVerifierHash[ 32 ];
+ (void) memset( pnTmpVerifierHash, 0, sizeof(pnTmpVerifierHash) );
+
+ /*int*/ EVP_DecryptUpdate( &aes_ctx, pnTmpVerifierHash, &nOutLen, pnVerifierHash, nVerifierHashSize );
+ EVP_CIPHER_CTX_cleanup( &aes_ctx );
+
+ rtlDigest aDigest = rtl_digest_create( rtl_Digest_AlgorithmSHA1 );
+ rtlDigestError aError = rtl_digest_update( aDigest, pnTmpVerifier, sizeof( pnTmpVerifier ) );
+ sal_uInt8 pnSha1Hash[ RTL_DIGEST_LENGTH_SHA1 ];
+ aError = rtl_digest_get( aDigest, pnSha1Hash, RTL_DIGEST_LENGTH_SHA1 );
+ rtl_digest_destroy( aDigest );
+
+ bResult = ( memcmp( pnSha1Hash, pnTmpVerifierHash, RTL_DIGEST_LENGTH_SHA1 ) == 0 );
+ }
+
+ return bResult;
+}
+
+// ----------------------------------------------------------------------------
+
+uno::Sequence< beans::NamedValue > lclGenerateEncryptionKey( const PackageEncryptionInfo& rEncrInfo, const OUString& rPassword, sal_uInt8* pnKey, sal_uInt32 nRequiredKeyLen )
{
size_t nBufferSize = rEncrInfo.mnSaltSize + 2 * rPassword.getLength();
sal_uInt8* pnBuffer = new sal_uInt8[ nBufferSize ];
@@ -405,30 +449,19 @@ bool lclGenerateEncryptionKey( const PackageEncryptionInfo& rEncrInfo, const OUS
lclDeriveKey( pnHash, RTL_DIGEST_LENGTH_SHA1, pnKey, nRequiredKeyLen );
delete[] pnHash;
- // check password
- EVP_CIPHER_CTX aes_ctx;
- EVP_CIPHER_CTX_init( &aes_ctx );
- EVP_DecryptInit_ex( &aes_ctx, EVP_aes_128_ecb(), 0, pnKey, 0 );
- EVP_CIPHER_CTX_set_padding( &aes_ctx, 0 );
- int nOutLen = 0;
- sal_uInt8 pnVerifier[ 16 ] = { 0 };
- /*int*/ EVP_DecryptUpdate( &aes_ctx, pnVerifier, &nOutLen, rEncrInfo.mpnEncrVerifier, sizeof( rEncrInfo.mpnEncrVerifier ) );
- EVP_CIPHER_CTX_cleanup( &aes_ctx );
-
- EVP_CIPHER_CTX_init( &aes_ctx );
- EVP_DecryptInit_ex( &aes_ctx, EVP_aes_128_ecb(), 0, pnKey, 0 );
- EVP_CIPHER_CTX_set_padding( &aes_ctx, 0 );
- sal_uInt8 pnVerifierHash[ 32 ] = { 0 };
- /*int*/ EVP_DecryptUpdate( &aes_ctx, pnVerifierHash, &nOutLen, rEncrInfo.mpnEncrVerifierHash, sizeof( rEncrInfo.mpnEncrVerifierHash ) );
- EVP_CIPHER_CTX_cleanup( &aes_ctx );
+ uno::Sequence< beans::NamedValue > aResult;
+ if ( lclCheckEncryptionData( pnKey, nRequiredKeyLen, rEncrInfo.mpnEncrVerifier, sizeof( rEncrInfo.mpnEncrVerifier ), rEncrInfo.mpnEncrVerifierHash, sizeof( rEncrInfo.mpnEncrVerifierHash ) ) )
+ {
+ ::comphelper::SequenceAsHashMap aEncryptionData;
+ aEncryptionData[ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "AES128EncryptionKey" ) ) ] <<= uno::Sequence< sal_Int8 >( reinterpret_cast< const sal_Int8* >( pnKey ), nRequiredKeyLen );
+ aEncryptionData[ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "AES128EncryptionSalt" ) ) ] <<= uno::Sequence< sal_Int8 >( reinterpret_cast< const sal_Int8* >( rEncrInfo.mpnSalt ), rEncrInfo.mnSaltSize );
+ aEncryptionData[ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "AES128EncryptionVerifier" ) ) ] <<= uno::Sequence< sal_Int8 >( reinterpret_cast< const sal_Int8* >( rEncrInfo.mpnEncrVerifier ), sizeof( rEncrInfo.mpnEncrVerifier ) );
+ aEncryptionData[ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "AES128EncryptionVerifierHash" ) ) ] <<= uno::Sequence< sal_Int8 >( reinterpret_cast< const sal_Int8* >( rEncrInfo.mpnEncrVerifierHash ), sizeof( rEncrInfo.mpnEncrVerifierHash ) );
- aDigest = rtl_digest_create( rtl_Digest_AlgorithmSHA1 );
- aError = rtl_digest_update( aDigest, pnVerifier, sizeof( pnVerifier ) );
- sal_uInt8 pnSha1Hash[ RTL_DIGEST_LENGTH_SHA1 ];
- aError = rtl_digest_get( aDigest, pnSha1Hash, RTL_DIGEST_LENGTH_SHA1 );
- rtl_digest_destroy( aDigest );
+ aResult = aEncryptionData.getAsConstNamedValueList();
+ }
- return memcmp( pnSha1Hash, pnVerifierHash, RTL_DIGEST_LENGTH_SHA1 ) == 0;
+ return aResult;
}
// the password verifier ------------------------------------------------------
@@ -438,8 +471,8 @@ class PasswordVerifier : public ::comphelper::IDocPasswordVerifier
public:
explicit PasswordVerifier( const PackageEncryptionInfo& rEncryptInfo );
- virtual ::comphelper::DocPasswordVerifierResult
- verifyPassword( const OUString& rPassword );
+ virtual ::comphelper::DocPasswordVerifierResult verifyPassword( const ::rtl::OUString& rPassword, ::com::sun::star::uno::Sequence< ::com::sun::star::beans::NamedValue >& o_rEncryptionData );
+ virtual ::comphelper::DocPasswordVerifierResult verifyEncryptionData( const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::NamedValue >& rEncryptionData );
inline const sal_uInt8* getKey() const { return &maKey.front(); }
@@ -454,13 +487,31 @@ PasswordVerifier::PasswordVerifier( const PackageEncryptionInfo& rEncryptInfo )
{
}
-::comphelper::DocPasswordVerifierResult PasswordVerifier::verifyPassword( const OUString& rPassword )
+::comphelper::DocPasswordVerifierResult PasswordVerifier::verifyPassword( const ::rtl::OUString& rPassword, ::com::sun::star::uno::Sequence< ::com::sun::star::beans::NamedValue >& o_rEncryptionData )
{
// verifies the password and writes the related decryption key into maKey
- return lclGenerateEncryptionKey( mrEncryptInfo, rPassword, &maKey.front(), maKey.size() ) ?
+ o_rEncryptionData = lclGenerateEncryptionKey( mrEncryptInfo, rPassword, &maKey.front(), maKey.size() );
+ return ( o_rEncryptionData.getLength() > 0 ) ?
::comphelper::DocPasswordVerifierResult_OK : ::comphelper::DocPasswordVerifierResult_WRONG_PASSWORD;
}
+::comphelper::DocPasswordVerifierResult PasswordVerifier::verifyEncryptionData( const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::NamedValue >& rEncryptionData )
+{
+ ::comphelper::SequenceAsHashMap aHashData( rEncryptionData );
+ uno::Sequence< sal_Int8 > aKey = aHashData.getUnpackedValueOrDefault( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "AES128EncryptionKey" ) ), uno::Sequence< sal_Int8 >() );
+ uno::Sequence< sal_Int8 > aVerifier = aHashData.getUnpackedValueOrDefault( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "AES128EncryptionVerifier" ) ), uno::Sequence< sal_Int8 >() );
+ uno::Sequence< sal_Int8 > aVerifierHash = aHashData.getUnpackedValueOrDefault( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "AES128EncryptionVerifierHash" ) ), uno::Sequence< sal_Int8 >() );
+
+ return lclCheckEncryptionData(
+ reinterpret_cast< const sal_uInt8* >( aKey.getConstArray() ),
+ aKey.getLength(),
+ reinterpret_cast< const sal_uInt8* >( aVerifier.getConstArray() ),
+ aVerifier.getLength(),
+ reinterpret_cast< const sal_uInt8* >( aVerifierHash.getConstArray() ),
+ aVerifierHash.getLength() )
+ ? ::comphelper::DocPasswordVerifierResult_OK : ::comphelper::DocPasswordVerifierResult_WRONG_PASSWORD;
+}
+
} // namespace
// ----------------------------------------------------------------------------
@@ -520,10 +571,10 @@ Reference< XInputStream > FilterDetect::extractUnencryptedPackage( MediaDescript
(according to the verifier), or with an empty string if
user has cancelled the password input dialog. */
PasswordVerifier aVerifier( aEncryptInfo );
- OUString aPassword = ::comphelper::DocPasswordHelper::requestAndVerifyDocPassword(
+ uno::Sequence< beans::NamedValue > aEncryptionData = ::comphelper::DocPasswordHelper::requestAndVerifyDocPassword(
aVerifier, rMediaDesc, ::comphelper::DocPasswordRequestType_MS, &aDefaultPasswords );
- if( aPassword.getLength() == 0 )
+ if( aEncryptionData.getLength() == 0 )
{
rMediaDesc[ MediaDescriptor::PROP_ABORTED() ] <<= true;
}
diff --git a/oox/source/drawingml/textcharacterproperties.cxx b/oox/source/drawingml/textcharacterproperties.cxx
index 3ac5018c1dad..9750375f97dd 100644
--- a/oox/source/drawingml/textcharacterproperties.cxx
+++ b/oox/source/drawingml/textcharacterproperties.cxx
@@ -96,7 +96,7 @@ void TextCharacterProperties::pushToPropMap( PropertyMap& rPropMap, const XmlFil
rPropMap[ PROP_CharFontFamilyComplex ] <<= nFontFamily;
}
- // symbol font not supported
+ // symbolfont, will now be ... textrun.cxx ... ausgewertet !!!i#113673
if( maCharColor.isUsed() )
rPropMap[ PROP_CharColor ] <<= maCharColor.getColor( rFilter.getGraphicHelper() );
diff --git a/oox/source/drawingml/textrun.cxx b/oox/source/drawingml/textrun.cxx
index aa74d767a7ad..cb8304b76d04 100644
--- a/oox/source/drawingml/textrun.cxx
+++ b/oox/source/drawingml/textrun.cxx
@@ -78,7 +78,55 @@ void TextRun::insertAt(
}
else
{
- xText->insertString( xStart, getText(), sal_False );
+ OUString aLatinFontName, aSymbolFontName;
+ sal_Int16 nLatinFontPitch = 0, nSymbolFontPitch = 0;
+ sal_Int16 nLatinFontFamily = 0, nSymbolFontFamily = 0;
+
+ if ( !aTextCharacterProps.maSymbolFont.getFontData( aSymbolFontName, nSymbolFontPitch, nSymbolFontFamily, rFilterBase ) )
+ xText->insertString( xStart, getText(), sal_False );
+ else if ( getText().getLength() )
+ { // !!#i113673<<<
+ aTextCharacterProps.maLatinFont.getFontData( aLatinFontName, nLatinFontPitch, nLatinFontFamily, rFilterBase );
+
+ sal_Int32 nIndex = 0;
+ while ( sal_True )
+ {
+ sal_Int32 nCount = 0;
+ sal_Bool bSymbol = ( getText()[ nIndex ] & 0xff00 ) == 0xf000;
+ if ( bSymbol )
+ {
+ do
+ {
+ nCount++;
+ }
+ while( ( ( nCount + nIndex ) < getText().getLength() ) && ( ( getText()[ nCount + nIndex ] & 0xff00 ) == 0xf000 ) );
+ aPropSet.setAnyProperty( PROP_CharFontName, Any( aSymbolFontName ) );
+ aPropSet.setAnyProperty( PROP_CharFontPitch, Any( nSymbolFontPitch ) );
+ aPropSet.setAnyProperty( PROP_CharFontFamily, Any( nSymbolFontFamily ) );
+ }
+ else
+ {
+ do
+ {
+ nCount++;
+ }
+ while( ( ( nCount + nIndex ) < getText().getLength() ) && ( ( getText()[ nCount + nIndex ] & 0xff00 ) != 0xf000 ) );
+ aPropSet.setAnyProperty( PROP_CharFontName, Any( aLatinFontName ) );
+ aPropSet.setAnyProperty( PROP_CharFontPitch, Any( nLatinFontPitch ) );
+ aPropSet.setAnyProperty( PROP_CharFontFamily, Any( nLatinFontFamily ) );
+ }
+ rtl::OUString aSubString( getText().copy( nIndex, nCount ) );
+ xText->insertString( xStart, aSubString, sal_False );
+ nIndex += nCount;
+
+ if ( nIndex >= getText().getLength() )
+ break;
+
+ xStart = Reference< XTextRange >( xAt, UNO_QUERY );
+ aPropSet = PropertySet( xStart );
+ aTextCharacterProps.pushToPropSet( aPropSet, rFilterBase );
+ }
+ }
}
}
else
diff --git a/oox/source/dump/biffdumper.cxx b/oox/source/dump/biffdumper.cxx
index 30938f9ebbe6..b78c993a0968 100644
--- a/oox/source/dump/biffdumper.cxx
+++ b/oox/source/dump/biffdumper.cxx
@@ -2324,7 +2324,7 @@ void WorkbookStreamObject::implDumpRecordBody()
rStrm.seekToStart();
BiffDecoderRef xDecoder = BiffCodecHelper::implReadFilePass( rStrm, eBiff );
if( xDecoder.get() )
- cfg().requestPassword( *xDecoder );
+ cfg().requestEncryptionData( *xDecoder );
setBinaryOnlyMode( !xDecoder || !xDecoder->isValid() );
}
break;
diff --git a/oox/source/dump/dumperbase.cxx b/oox/source/dump/dumperbase.cxx
index 807a5ec74715..53452765288a 100644
--- a/oox/source/dump/dumperbase.cxx
+++ b/oox/source/dump/dumperbase.cxx
@@ -65,6 +65,8 @@ using ::com::sun::star::io::XTextOutputStream;
using ::comphelper::MediaDescriptor;
using ::oox::core::FilterBase;
+using namespace ::com::sun::star;
+
namespace oox {
namespace dump {
@@ -1581,18 +1583,18 @@ NameListRef SharedConfigData::getNameList( const OUString& rListName ) const
return xList;
}
-OUString SharedConfigData::requestPassword( ::comphelper::IDocPasswordVerifier& rVerifier )
+uno::Sequence< beans::NamedValue > SharedConfigData::requestEncryptionData( ::comphelper::IDocPasswordVerifier& rVerifier )
{
- OUString aPassword;
+ uno::Sequence< beans::NamedValue > aEncryptionData;
if( !mbPwCancelled )
{
::std::vector< OUString > aDefaultPasswords;
aDefaultPasswords.push_back( CREATE_OUSTRING( "VelvetSweatshop" ) );
- aPassword = ::comphelper::DocPasswordHelper::requestAndVerifyDocPassword(
+ aEncryptionData = ::comphelper::DocPasswordHelper::requestAndVerifyDocPassword(
rVerifier, mrMediaDesc, ::comphelper::DocPasswordRequestType_MS, &aDefaultPasswords );
- mbPwCancelled = aPassword.getLength() == 0;
+ mbPwCancelled = aEncryptionData.getLength() == 0;
}
- return aPassword;
+ return aEncryptionData;
}
bool SharedConfigData::implIsValid() const
@@ -1764,9 +1766,9 @@ NameListRef Config::getNameList( const String& rListName ) const
return implGetNameList( rListName );
}
-OUString Config::requestPassword( ::comphelper::IDocPasswordVerifier& rVerifier )
+uno::Sequence< beans::NamedValue > Config::requestEncryptionData( ::comphelper::IDocPasswordVerifier& rVerifier )
{
- return mxCfgData->requestPassword( rVerifier );
+ return mxCfgData->requestEncryptionData( rVerifier );
}
bool Config::isPasswordCancelled() const
diff --git a/oox/source/ole/vbamodule.cxx b/oox/source/ole/vbamodule.cxx
index 9886f2cc5968..dbd5c9c02ced 100644
--- a/oox/source/ole/vbamodule.cxx
+++ b/oox/source/ole/vbamodule.cxx
@@ -128,18 +128,56 @@ void VbaModule::importDirRecords( BinaryInputStream& rDirStrm )
OSL_ENSURE( mnOffset < SAL_MAX_UINT32, "VbaModule::importDirRecords - missing module stream offset" );
}
-void VbaModule::importSourceCode( StorageBase& rVbaStrg,
- const Reference< XNameContainer >& rxBasicLib, const Reference< XNameAccess >& rxDocObjectNA ) const
+void VbaModule::createAndImportModule( StorageBase& rVbaStrg, const Reference< XNameContainer >& rxBasicLib,
+ const Reference< XNameAccess >& rxDocObjectNA ) const
{
- if( (maName.getLength() == 0) || (maStreamName.getLength() == 0) || (mnOffset == SAL_MAX_UINT32) )
- return;
+ OUString aVBASourceCode = readSourceCode( rVbaStrg );
+ createModule( aVBASourceCode, rxBasicLib, rxDocObjectNA );
+}
+
+void VbaModule::createEmptyModule( const Reference< XNameContainer >& rxBasicLib, const Reference< XNameAccess >& rxDocObjectNA ) const
+{
+ createModule( OUString(), rxBasicLib, rxDocObjectNA );
+}
- BinaryXInputStream aInStrm( rVbaStrg.openInputStream( maStreamName ), true );
- OSL_ENSURE( !aInStrm.isEof(), "VbaModule::importSourceCode - cannot open module stream" );
- // skip the 'performance cache' stored before the actual source code
- aInStrm.seek( mnOffset );
- // if stream is still valid, load the source code
- if( aInStrm.isEof() )
+// private --------------------------------------------------------------------
+
+OUString VbaModule::readSourceCode( StorageBase& rVbaStrg ) const
+{
+ OUStringBuffer aSourceCode;
+ if( (maStreamName.getLength() > 0) && (mnOffset != SAL_MAX_UINT32) )
+ {
+ BinaryXInputStream aInStrm( rVbaStrg.openInputStream( maStreamName ), true );
+ OSL_ENSURE( !aInStrm.isEof(), "VbaModule::readSourceCode - cannot open module stream" );
+ // skip the 'performance cache' stored before the actual source code
+ aInStrm.seek( mnOffset );
+ // if stream is still valid, load the source code
+ if( !aInStrm.isEof() )
+ {
+ // decompression starts at current stream position of aInStrm
+ VbaInputStream aVbaStrm( aInStrm );
+ // load the source code line-by-line, with some more processing
+ TextInputStream aVbaTextStrm( aVbaStrm, meTextEnc );
+ while( !aVbaTextStrm.isEof() )
+ {
+ OUString aCodeLine = aVbaTextStrm.readLine();
+ if( !aCodeLine.matchAsciiL( RTL_CONSTASCII_STRINGPARAM( "Attribute " ) ) )
+ {
+ // normal source code line
+ if( !mbExecutable )
+ aSourceCode.appendAscii( RTL_CONSTASCII_STRINGPARAM( "Rem " ) );
+ aSourceCode.append( aCodeLine ).append( sal_Unicode( '\n' ) );
+ }
+ }
+ }
+ }
+ return aSourceCode.makeStringAndClear();
+}
+
+void VbaModule::createModule( const OUString& rVBASourceCode,
+ const Reference< XNameContainer >& rxBasicLib, const Reference< XNameAccess >& rxDocObjectNA ) const
+{
+ if( maName.getLength() == 0 )
return;
// prepare the Basic module
@@ -162,7 +200,7 @@ void VbaModule::importSourceCode( StorageBase& rVbaStrg,
break;
case ModuleType::DOCUMENT:
aSourceCode.appendAscii( RTL_CONSTASCII_STRINGPARAM( "VBADocumentModule" ) );
- // get the VBA object associated to the document module
+ // get the VBA implementation object associated to the document module
if( rxDocObjectNA.is() ) try
{
aModuleInfo.ModuleObject.set( rxDocObjectNA->getByName( maName ), UNO_QUERY );
@@ -188,21 +226,8 @@ void VbaModule::importSourceCode( StorageBase& rVbaStrg,
append( maName.replace( ' ', '_' ) ).append( sal_Unicode( '\n' ) );
}
- // decompression starts at current stream position of aInStrm
- VbaInputStream aVbaStrm( aInStrm );
- // load the source code line-by-line, with some more processing
- TextInputStream aVbaTextStrm( aVbaStrm, meTextEnc );
- while( !aVbaTextStrm.isEof() )
- {
- OUString aCodeLine = aVbaTextStrm.readLine();
- // skip all 'Attribute' statements
- if( !aCodeLine.matchAsciiL( RTL_CONSTASCII_STRINGPARAM( "Attribute " ) ) )
- {
- if( !mbExecutable )
- aSourceCode.appendAscii( RTL_CONSTASCII_STRINGPARAM( "Rem " ) );
- aSourceCode.append( aCodeLine ).append( sal_Unicode( '\n' ) );
- }
- }
+ // append passed VBA source code
+ aSourceCode.append( rVBASourceCode );
// close the subroutine named after the module
if( !mbExecutable )
@@ -225,7 +250,7 @@ void VbaModule::importSourceCode( StorageBase& rVbaStrg,
}
catch( Exception& )
{
- OSL_ENSURE( false, "VbaModule::importSourceCode - cannot insert module into library" );
+ OSL_ENSURE( false, "VbaModule::createModule - cannot insert module into library" );
}
}
diff --git a/oox/source/ole/vbaproject.cxx b/oox/source/ole/vbaproject.cxx
index deff066a5ed5..0f7e3cb8612a 100644
--- a/oox/source/ole/vbaproject.cxx
+++ b/oox/source/ole/vbaproject.cxx
@@ -173,6 +173,67 @@ bool VbaProject::hasDialog( const OUString& rDialogName ) const
return mxDialogLib.is() && mxDialogLib->hasByName( rDialogName );
}
+// protected ------------------------------------------------------------------
+
+void VbaProject::addDummyModule( const OUString& rName, sal_Int32 nType )
+{
+ OSL_ENSURE( rName.getLength() > 0, "VbaProject::addDummyModule - missing module name" );
+ maDummyModules[ rName ] = nType;
+}
+
+void VbaProject::createDummyModules()
+{
+ /* !! HACK !! This function is called from old XLS filter only, must be
+ removed when this filter uses the OOX VBA import instead of the old SVX
+ VBA import.
+ */
+
+ // create empty dummy modules
+ typedef RefMap< OUString, VbaModule > VbaModuleMap;
+ VbaModuleMap aDummyModules;
+ for( DummyModuleMap::iterator aIt = maDummyModules.begin(), aEnd = maDummyModules.end(); aIt != aEnd; ++aIt )
+ {
+ OSL_ENSURE( !aDummyModules.has( aIt->first ), "VbaProject::createDummyModules - multiple modules with the same name" );
+ VbaModuleMap::mapped_type& rxModule = aDummyModules[ aIt->first ];
+ rxModule.reset( new VbaModule( mxDocModel, aIt->first, RTL_TEXTENCODING_MS_1252, isImportVbaExecutable() ) );
+ rxModule->setType( aIt->second );
+ }
+
+ if( !aDummyModules.empty() ) try
+ {
+ // get the model factory and the basic library
+ Reference< XMultiServiceFactory > xModelFactory( mxDocModel, UNO_QUERY_THROW );
+ Reference< XNameContainer > xBasicLib( createBasicLibrary(), UNO_SET_THROW );
+
+ // try to get access to document objects related to code modules
+ Reference< XNameAccess > xDocObjectNA;
+ try
+ {
+ xDocObjectNA.set( xModelFactory->createInstance( CREATE_OUSTRING( "ooo.vba.VBAObjectModuleObjectProvider" ) ), UNO_QUERY );
+ }
+ catch( Exception& )
+ {
+ // not all documents support this
+ }
+
+ // create empty dummy modules
+ if( xBasicLib.is() )
+ aDummyModules.forEachMem( &VbaModule::createEmptyModule,
+ ::boost::cref( xBasicLib ), ::boost::cref( xDocObjectNA ) );
+ }
+ catch( Exception& )
+ {
+ }
+}
+
+void VbaProject::prepareImport()
+{
+}
+
+void VbaProject::finalizeImport()
+{
+}
+
// private --------------------------------------------------------------------
Reference< XLibraryContainer > VbaProject::getLibraryContainer( sal_Int32 nPropId )
@@ -231,6 +292,9 @@ void VbaProject::importVba( StorageBase& rVbaPrjStrg, const GraphicHelper& rGrap
if( aDirStrm.isEof() )
return;
+ // virtual call, derived classes may do some preparations
+ prepareImport();
+
// read all records of the directory
rtl_TextEncoding eTextEnc = RTL_TEXTENCODING_MS_1252;
sal_uInt16 nModuleCount = 0;
@@ -345,17 +409,29 @@ void VbaProject::importVba( StorageBase& rVbaPrjStrg, const GraphicHelper& rGrap
}
}
+ // create empty dummy modules
+ VbaModuleMap aDummyModules;
+ for( DummyModuleMap::iterator aIt = maDummyModules.begin(), aEnd = maDummyModules.end(); aIt != aEnd; ++aIt )
+ {
+ OSL_ENSURE( !aModules.has( aIt->first ) && !aDummyModules.has( aIt->first ), "VbaProject::importVba - multiple modules with the same name" );
+ VbaModuleMap::mapped_type& rxModule = aDummyModules[ aIt->first ];
+ rxModule.reset( new VbaModule( mxDocModel, aIt->first, eTextEnc, bExecutable ) );
+ rxModule->setType( aIt->second );
+ }
+
/* Now it is time to load the source code. All modules will be inserted
into the Basic library of the document specified by the 'maLibName'
member. Do not create the Basic library, if there are no modules
specified. */
- if( !aModules.empty() ) try
+ if( !aModules.empty() || !aDummyModules.empty() ) try
{
// get the model factory and the basic library
Reference< XMultiServiceFactory > xModelFactory( mxDocModel, UNO_QUERY_THROW );
Reference< XNameContainer > xBasicLib( createBasicLibrary(), UNO_SET_THROW );
- // set library container to VBA compatibility mode
+ /* Set library container to VBA compatibility mode. This will create
+ the VBA Globals object and store it in the Basic manager of the
+ document. */
try
{
Reference< XVBACompatibility >( getLibraryContainer( PROP_BasicLibraries ), UNO_QUERY_THROW )->setVBACompatibilityMode( sal_True );
@@ -364,15 +440,6 @@ void VbaProject::importVba( StorageBase& rVbaPrjStrg, const GraphicHelper& rGrap
{
}
- // create the VBAGlobals object, the model will store it in the Basic manager
- try
- {
- xModelFactory->createInstance( CREATE_OUSTRING( "ooo.vba.VBAGlobals" ) );
- }
- catch( Exception& )
- {
- }
-
// try to get access to document objects related to code modules
Reference< XNameAccess > xDocObjectNA;
try
@@ -384,10 +451,17 @@ void VbaProject::importVba( StorageBase& rVbaPrjStrg, const GraphicHelper& rGrap
// not all documents support this
}
- // call Basic source code import for each module, boost::[c]ref enforces pass-by-ref
if( xBasicLib.is() )
- aModules.forEachMem( &VbaModule::importSourceCode,
- ::boost::ref( *xVbaStrg ), ::boost::cref( xBasicLib ), ::boost::cref( xDocObjectNA ) );
+ {
+ // call Basic source code import for each module, boost::[c]ref enforces pass-by-ref
+ aModules.forEachMem( &VbaModule::createAndImportModule,
+ ::boost::ref( *xVbaStrg ), ::boost::cref( xBasicLib ),
+ ::boost::cref( xDocObjectNA ) );
+
+ // create empty dummy modules
+ aDummyModules.forEachMem( &VbaModule::createEmptyModule,
+ ::boost::cref( xBasicLib ), ::boost::cref( xDocObjectNA ) );
+ }
}
catch( Exception& )
{
@@ -402,7 +476,7 @@ void VbaProject::importVba( StorageBase& rVbaPrjStrg, const GraphicHelper& rGrap
for( ::std::vector< OUString >::iterator aIt = aElements.begin(), aEnd = aElements.end(); aIt != aEnd; ++aIt )
{
// try to open the element as storage
- if( !aIt->equals( CREATE_OUSTRING( "VBA" ) ) )
+ if( !aIt->equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "VBA" ) ) )
{
StorageRef xSubStrg = rVbaPrjStrg.openSubStorage( *aIt, false );
if( xSubStrg.get() ) try
@@ -425,6 +499,9 @@ void VbaProject::importVba( StorageBase& rVbaPrjStrg, const GraphicHelper& rGrap
}
}
}
+
+ // virtual call, derived classes may do some more processing
+ finalizeImport();
}
void VbaProject::copyStorage( StorageBase& rVbaPrjStrg )
diff --git a/oox/source/xls/biffcodec.cxx b/oox/source/xls/biffcodec.cxx
index 2021c21cb08c..0872dcc654df 100644
--- a/oox/source/xls/biffcodec.cxx
+++ b/oox/source/xls/biffcodec.cxx
@@ -36,6 +36,8 @@ using ::rtl::OUString;
using ::rtl::OStringToOUString;
using ::oox::core::FilterBase;
+using namespace ::com::sun::star;
+
namespace oox {
namespace xls {
@@ -50,9 +52,16 @@ BiffDecoderBase::~BiffDecoderBase()
{
}
-::comphelper::DocPasswordVerifierResult BiffDecoderBase::verifyPassword( const OUString& rPassword )
+::comphelper::DocPasswordVerifierResult BiffDecoderBase::verifyPassword( const ::rtl::OUString& rPassword, uno::Sequence< beans::NamedValue >& o_rEncryptionData )
+{
+ o_rEncryptionData = implVerifyPassword( rPassword );
+ mbValid = ( o_rEncryptionData.getLength() > 0 );
+ return mbValid ? ::comphelper::DocPasswordVerifierResult_OK : ::comphelper::DocPasswordVerifierResult_WRONG_PASSWORD;
+}
+
+::comphelper::DocPasswordVerifierResult BiffDecoderBase::verifyEncryptionData( const uno::Sequence< beans::NamedValue >& rEncryptionData )
{
- mbValid = implVerify( rPassword );
+ mbValid = implVerifyEncryptionData( rEncryptionData );
return mbValid ? ::comphelper::DocPasswordVerifierResult_OK : ::comphelper::DocPasswordVerifierResult_WRONG_PASSWORD;
}
@@ -71,7 +80,6 @@ void BiffDecoderBase::decode( sal_uInt8* pnDestData, const sal_uInt8* pnSrcData,
BiffDecoder_XOR::BiffDecoder_XOR( sal_uInt16 nKey, sal_uInt16 nHash ) :
maCodec( ::oox::core::BinaryCodec_XOR::CODEC_EXCEL ),
- maPassword( 16 ),
mnKey( nKey ),
mnHash( nHash )
{
@@ -80,12 +88,12 @@ BiffDecoder_XOR::BiffDecoder_XOR( sal_uInt16 nKey, sal_uInt16 nHash ) :
BiffDecoder_XOR::BiffDecoder_XOR( const BiffDecoder_XOR& rDecoder ) :
BiffDecoderBase(), // must be called to prevent compiler warning
maCodec( ::oox::core::BinaryCodec_XOR::CODEC_EXCEL ),
- maPassword( rDecoder.maPassword ),
+ maEncryptionData( rDecoder.maEncryptionData ),
mnKey( rDecoder.mnKey ),
mnHash( rDecoder.mnHash )
{
if( isValid() )
- maCodec.initKey( &maPassword.front() );
+ maCodec.initCodec( maEncryptionData );
}
BiffDecoder_XOR* BiffDecoder_XOR::implClone()
@@ -93,24 +101,40 @@ BiffDecoder_XOR* BiffDecoder_XOR::implClone()
return new BiffDecoder_XOR( *this );
}
-bool BiffDecoder_XOR::implVerify( const OUString& rPassword )
+uno::Sequence< beans::NamedValue > BiffDecoder_XOR::implVerifyPassword( const ::rtl::OUString& rPassword )
{
+ maEncryptionData.realloc( 0 );
+
/* Convert password to a byte string. TODO: this needs some finetuning
according to the spec... */
OString aBytePassword = OUStringToOString( rPassword, osl_getThreadTextEncoding() );
sal_Int32 nLen = aBytePassword.getLength();
if( (0 < nLen) && (nLen < 16) )
{
- // copy byte string to sal_uInt8 array
- maPassword.clear();
- maPassword.resize( 16, 0 );
- memcpy( &maPassword.front(), aBytePassword.getStr(), static_cast< size_t >( nLen ) );
+ // init codec
+ maCodec.initKey( (sal_uInt8*)aBytePassword.getStr() );
+ if ( maCodec.verifyKey( mnKey, mnHash ) )
+ maEncryptionData = maCodec.getEncryptionData();
+ }
+
+ return maEncryptionData;
+}
+
+bool BiffDecoder_XOR::implVerifyEncryptionData( const uno::Sequence< beans::NamedValue >& rEncryptionData )
+{
+ maEncryptionData.realloc( 0 );
+
+ if( rEncryptionData.getLength() )
+ {
// init codec
- maCodec.initKey( &maPassword.front() );
- return maCodec.verifyKey( mnKey, mnHash );
+ maCodec.initCodec( rEncryptionData );
+
+ if ( maCodec.verifyKey( mnKey, mnHash ) )
+ maEncryptionData = rEncryptionData;
}
- return false;
+
+ return maEncryptionData.getLength();
}
void BiffDecoder_XOR::implDecode( sal_uInt8* pnDestData, const sal_uInt8* pnSrcData, sal_Int64 nStreamPos, sal_uInt16 nBytes )
@@ -141,7 +165,6 @@ sal_Int32 lclGetRcfOffset( sal_Int64 nStreamPos )
// ----------------------------------------------------------------------------
BiffDecoder_RCF::BiffDecoder_RCF( sal_uInt8 pnSalt[ 16 ], sal_uInt8 pnVerifier[ 16 ], sal_uInt8 pnVerifierHash[ 16 ] ) :
- maPassword( 16, 0 ),
maSalt( pnSalt, pnSalt + 16 ),
maVerifier( pnVerifier, pnVerifier + 16 ),
maVerifierHash( pnVerifierHash, pnVerifierHash + 16 )
@@ -150,13 +173,13 @@ BiffDecoder_RCF::BiffDecoder_RCF( sal_uInt8 pnSalt[ 16 ], sal_uInt8 pnVerifier[
BiffDecoder_RCF::BiffDecoder_RCF( const BiffDecoder_RCF& rDecoder ) :
BiffDecoderBase(), // must be called to prevent compiler warning
- maPassword( rDecoder.maPassword ),
+ maEncryptionData( rDecoder.maEncryptionData ),
maSalt( rDecoder.maSalt ),
maVerifier( rDecoder.maVerifier ),
maVerifierHash( rDecoder.maVerifierHash )
{
if( isValid() )
- maCodec.initKey( &maPassword.front(), &maSalt.front() );
+ maCodec.initCodec( maEncryptionData );
}
BiffDecoder_RCF* BiffDecoder_RCF::implClone()
@@ -164,27 +187,48 @@ BiffDecoder_RCF* BiffDecoder_RCF::implClone()
return new BiffDecoder_RCF( *this );
}
-bool BiffDecoder_RCF::implVerify( const OUString& rPassword )
+uno::Sequence< beans::NamedValue > BiffDecoder_RCF::implVerifyPassword( const ::rtl::OUString& rPassword )
{
+ maEncryptionData.realloc( 0 );
+
sal_Int32 nLen = rPassword.getLength();
if( (0 < nLen) && (nLen < 16) )
{
// copy string to sal_uInt16 array
- maPassword.clear();
- maPassword.resize( 16, 0 );
+ ::std::vector< sal_uInt16 > aPassVect( 16 );
const sal_Unicode* pcChar = rPassword.getStr();
const sal_Unicode* pcCharEnd = pcChar + nLen;
- ::std::vector< sal_uInt16 >::iterator aIt = maPassword.begin();
+ ::std::vector< sal_uInt16 >::iterator aIt = aPassVect.begin();
for( ; pcChar < pcCharEnd; ++pcChar, ++aIt )
*aIt = static_cast< sal_uInt16 >( *pcChar );
// init codec
- maCodec.initKey( &maPassword.front(), &maSalt.front() );
- return maCodec.verifyKey( &maVerifier.front(), &maVerifierHash.front() );
+ maCodec.initKey( &aPassVect.front(), &maSalt.front() );
+ if ( maCodec.verifyKey( &maVerifier.front(), &maVerifierHash.front() ) )
+ maEncryptionData = maCodec.getEncryptionData();
+ }
+
+ return maEncryptionData;
+}
+
+bool BiffDecoder_RCF::implVerifyEncryptionData( const uno::Sequence< beans::NamedValue >& rEncryptionData )
+{
+ maEncryptionData.realloc( 0 );
+
+ if( rEncryptionData.getLength() )
+ {
+ // init codec
+ maCodec.initCodec( rEncryptionData );
+
+ if ( maCodec.verifyKey( &maVerifier.front(), &maVerifierHash.front() ) )
+ maEncryptionData = rEncryptionData;
}
- return false;
+
+ return maEncryptionData.getLength();
}
+
+
void BiffDecoder_RCF::implDecode( sal_uInt8* pnDestData, const sal_uInt8* pnSrcData, sal_Int64 nStreamPos, sal_uInt16 nBytes )
{
sal_uInt8* pnCurrDest = pnDestData;
@@ -316,7 +360,7 @@ bool BiffCodecHelper::importFilePass( BiffInputStream& rStrm )
mxDecoder = implReadFilePass( rStrm, getBiff() );
// request and verify a password (decoder implements IDocPasswordVerifier)
if( mxDecoder.get() )
- getBaseFilter().requestPassword( *mxDecoder );
+ getBaseFilter().requestEncryptionData( *mxDecoder );
// correct password is indicated by isValid() function of decoder
return mxDecoder.get() && mxDecoder->isValid();
}
diff --git a/oox/source/xls/excelvbaproject.cxx b/oox/source/xls/excelvbaproject.cxx
new file mode 100755
index 000000000000..ee22dc8398ba
--- /dev/null
+++ b/oox/source/xls/excelvbaproject.cxx
@@ -0,0 +1,161 @@
+/*************************************************************************
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+#include "oox/xls/excelvbaproject.hxx"
+
+#include <list>
+#include <set>
+#include <com/sun/star/container/XEnumeration.hpp>
+#include <com/sun/star/container/XEnumerationAccess.hpp>
+#include <com/sun/star/document/XEventsSupplier.hpp>
+#include <com/sun/star/frame/XModel.hpp>
+#include <com/sun/star/script/ModuleType.hpp>
+#include <com/sun/star/sheet/XSpreadsheetDocument.hpp>
+#include <rtl/ustrbuf.hxx>
+#include "oox/helper/helper.hxx"
+#include "oox/helper/propertyset.hxx"
+#include "properties.hxx"
+
+namespace oox {
+namespace xls {
+
+// ============================================================================
+
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::document;
+using namespace ::com::sun::star::frame;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::script;
+using namespace ::com::sun::star::sheet;
+using namespace ::com::sun::star::uno;
+
+using ::rtl::OUString;
+using ::rtl::OUStringBuffer;
+
+// ============================================================================
+
+ExcelVbaProject::ExcelVbaProject( const Reference< XMultiServiceFactory >& rxGlobalFactory, const Reference< XSpreadsheetDocument >& rxDocument ) :
+ ::oox::ole::VbaProject( rxGlobalFactory, Reference< XModel >( rxDocument, UNO_QUERY ), CREATE_OUSTRING( "Calc" ) ),
+ mxDocument( rxDocument )
+{
+}
+
+void ExcelVbaProject::createMissingModules()
+{
+ /* !! HACK !! This function is called from old XLS filter only, must be
+ removed when this filter uses the OOX VBA import instead of the old SVX
+ VBA import.
+ */
+
+ // collect and register all sheets without codenames
+ prepareImport();
+ // manually create the registered dummy modules
+ createDummyModules();
+}
+
+// protected ------------------------------------------------------------------
+
+namespace {
+
+struct SheetCodeNameInfo
+{
+ PropertySet maSheetProps; /// Property set of the sheet without codename.
+ OUString maPrefix; /// Prefix for the codename to be generated.
+
+ inline explicit SheetCodeNameInfo( PropertySet& rSheetProps, const OUString& rPrefix ) :
+ maSheetProps( rSheetProps ), maPrefix( rPrefix ) {}
+};
+
+typedef ::std::set< OUString > CodeNameSet;
+typedef ::std::list< SheetCodeNameInfo > SheetCodeNameInfoList;
+
+} // namespace
+
+void ExcelVbaProject::prepareImport()
+{
+ /* Check if the sheets have imported codenames. Generate new unused
+ codenames if not. */
+ if( mxDocument.is() ) try
+ {
+ // collect existing codenames (do not use them when creating new codenames)
+ CodeNameSet aUsedCodeNames;
+
+ // collect sheets without codenames
+ SheetCodeNameInfoList aCodeNameInfos;
+
+ // iterate over all imported sheets
+ Reference< XEnumerationAccess > xSheetsEA( mxDocument->getSheets(), UNO_QUERY_THROW );
+ Reference< XEnumeration > xSheetsEnum( xSheetsEA->createEnumeration(), UNO_SET_THROW );
+ // own try/catch for every sheet
+ while( xSheetsEnum->hasMoreElements() ) try
+ {
+ PropertySet aSheetProp( xSheetsEnum->nextElement() );
+ OUString aCodeName;
+ aSheetProp.getProperty( aCodeName, PROP_CodeName );
+ if( aCodeName.getLength() > 0 )
+ {
+ aUsedCodeNames.insert( aCodeName );
+ }
+ else
+ {
+ // TODO: once we have chart sheets we need a switch/case on sheet type ('SheetNNN' vs. 'ChartNNN')
+ aCodeNameInfos.push_back( SheetCodeNameInfo( aSheetProp, CREATE_OUSTRING( "Sheet" ) ) );
+ }
+ }
+ catch( Exception& )
+ {
+ }
+
+ // create new codenames if sheets do not have one
+ for( SheetCodeNameInfoList::iterator aIt = aCodeNameInfos.begin(), aEnd = aCodeNameInfos.end(); aIt != aEnd; ++aIt )
+ {
+ // search for an unused codename
+ sal_Int32 nCounter = 1;
+ OUString aCodeName;
+ do
+ {
+ aCodeName = OUStringBuffer( aIt->maPrefix ).append( nCounter++ ).makeStringAndClear();
+ }
+ while( aUsedCodeNames.count( aCodeName ) > 0 );
+ aUsedCodeNames.insert( aCodeName );
+
+ // set codename at sheet
+ aIt->maSheetProps.setProperty( PROP_CodeName, aCodeName );
+
+ // tell base class to create a dummy module
+ addDummyModule( aCodeName, ModuleType::DOCUMENT );
+ }
+ }
+ catch( Exception& )
+ {
+ }
+}
+
+// ============================================================================
+
+} // namespace xls
+} // namespace oox
diff --git a/oox/source/xls/makefile.mk b/oox/source/xls/makefile.mk
index cdb2e18c262d..b5ede953bbfe 100644
--- a/oox/source/xls/makefile.mk
+++ b/oox/source/xls/makefile.mk
@@ -59,6 +59,7 @@ SLOFILES = \
$(SLO)$/excelchartconverter.obj \
$(SLO)$/excelfilter.obj \
$(SLO)$/excelhandlers.obj \
+ $(SLO)$/excelvbaproject.obj \
$(SLO)$/externallinkbuffer.obj \
$(SLO)$/externallinkfragment.obj \
$(SLO)$/formulabase.obj \
diff --git a/oox/source/xls/workbookhelper.cxx b/oox/source/xls/workbookhelper.cxx
index 5684fbd8ae75..ceba5690004c 100644
--- a/oox/source/xls/workbookhelper.cxx
+++ b/oox/source/xls/workbookhelper.cxx
@@ -43,7 +43,6 @@
#include "properties.hxx"
#include "oox/helper/progressbar.hxx"
#include "oox/helper/propertyset.hxx"
-#include "oox/ole/vbaproject.hxx"
#include "oox/drawingml/theme.hxx"
#include "oox/xls/addressconverter.hxx"
#include "oox/xls/biffinputstream.hxx"
@@ -51,6 +50,7 @@
#include "oox/xls/defnamesbuffer.hxx"
#include "oox/xls/excelchartconverter.hxx"
#include "oox/xls/excelfilter.hxx"
+#include "oox/xls/excelvbaproject.hxx"
#include "oox/xls/externallinkbuffer.hxx"
#include "oox/xls/formulaparser.hxx"
#include "oox/xls/pagesettings.hxx"
@@ -691,7 +691,7 @@ void WorkbookHelper::finalizeWorkbookImport()
StorageRef xVbaPrjStrg = mrBookData.getVbaProjectStorage();
if( xVbaPrjStrg.get() && xVbaPrjStrg->isStorage() )
{
- ::oox::ole::VbaProject aVbaProject( getGlobalFactory(), getBaseFilter().getModel(), CREATE_OUSTRING( "Calc" ) );
+ ExcelVbaProject aVbaProject( getGlobalFactory(), getDocument() );
aVbaProject.importVbaProject( *xVbaPrjStrg, getBaseFilter().getGraphicHelper() );
}
}
diff --git a/oox/source/xls/worksheethelper.cxx b/oox/source/xls/worksheethelper.cxx
index 99c2d844f4b5..d2d42f2be369 100644
--- a/oox/source/xls/worksheethelper.cxx
+++ b/oox/source/xls/worksheethelper.cxx
@@ -404,7 +404,7 @@ public:
Size getCellSize( sal_Int32 nCol, sal_Int32 nRow ) const;
/** Returns the address of the cell that contains the passed point in 1/100 mm. */
- CellAddress getCellAddressFromPosition( const Point& rPosition, const CellAddress* pStartAddr = 0 ) const;
+ CellAddress getCellAddressFromPosition( const Point& rPosition, const Size& rDrawPageSize ) const;
/** Returns the cell range address that contains the passed rectangle in 1/100 mm. */
CellRangeAddress getCellRangeFromRectangle( const Rectangle& rRect ) const;
@@ -795,41 +795,117 @@ Size WorksheetData::getCellSize( sal_Int32 nCol, sal_Int32 nRow ) const
return aSize;
}
-CellAddress WorksheetData::getCellAddressFromPosition( const Point& rPosition, const CellAddress* pStartAddr ) const
+namespace {
+
+inline sal_Int32 lclGetMidAddr( sal_Int32 nBegAddr, sal_Int32 nEndAddr, sal_Int32 nBegPos, sal_Int32 nEndPos, sal_Int32 nSearchPos )
+{
+ // use sal_Int64 to prevent integer overflow
+ return nBegAddr + 1 + static_cast< sal_Int32 >( static_cast< sal_Int64 >( nEndAddr - nBegAddr - 2 ) * (nSearchPos - nBegPos) / (nEndPos - nBegPos) );
+}
+
+bool lclPrepareInterval( sal_Int32 nBegAddr, sal_Int32& rnMidAddr, sal_Int32 nEndAddr,
+ sal_Int32 nBegPos, sal_Int32 nEndPos, sal_Int32 nSearchPos )
{
- // prepare start address for search loop
- sal_Int32 nCol = pStartAddr ? ::std::min< sal_Int32 >( pStartAddr->Column + 1, mrMaxApiPos.Column ) : 1;
- sal_Int32 nRow = pStartAddr ? ::std::min< sal_Int32 >( pStartAddr->Row + 1, mrMaxApiPos.Row ) : 1;
+ // searched position before nBegPos -> use nBegAddr
+ if( nSearchPos <= nBegPos )
+ {
+ rnMidAddr = nBegAddr;
+ return false;
+ }
+
+ // searched position after nEndPos, or begin next to end -> use nEndAddr
+ if( (nSearchPos >= nEndPos) || (nBegAddr + 1 >= nEndAddr) )
+ {
+ rnMidAddr = nEndAddr;
+ return false;
+ }
+
+ /* Otherwise find mid address according to position. lclGetMidAddr() will
+ return an address between nBegAddr and nEndAddr. */
+ rnMidAddr = lclGetMidAddr( nBegAddr, nEndAddr, nBegPos, nEndPos, nSearchPos );
+ return true;
+}
+
+bool lclUpdateInterval( sal_Int32& rnBegAddr, sal_Int32& rnMidAddr, sal_Int32& rnEndAddr,
+ sal_Int32& rnBegPos, sal_Int32 nMidPos, sal_Int32& rnEndPos, sal_Int32 nSearchPos )
+{
+ // nSearchPos < nMidPos: use the interval [begin,mid] in the next iteration
+ if( nSearchPos < nMidPos )
+ {
+ // if rnBegAddr is next to rnMidAddr, the latter is the column/row in question
+ if( rnBegAddr + 1 >= rnMidAddr )
+ return false;
+ // otherwise, set interval end to mid
+ rnEndPos = nMidPos;
+ rnEndAddr = rnMidAddr;
+ rnMidAddr = lclGetMidAddr( rnBegAddr, rnEndAddr, rnBegPos, rnEndPos, nSearchPos );
+ return true;
+ }
+
+ // nSearchPos > nMidPos: use the interval [mid,end] in the next iteration
+ if( nSearchPos > nMidPos )
+ {
+ // if rnMidAddr is next to rnEndAddr, the latter is the column/row in question
+ if( rnMidAddr + 1 >= rnEndAddr )
+ {
+ rnMidAddr = rnEndAddr;
+ return false;
+ }
+ // otherwise, set interval start to mid
+ rnBegPos = nMidPos;
+ rnBegAddr = rnMidAddr;
+ rnMidAddr = lclGetMidAddr( rnBegAddr, rnEndAddr, rnBegPos, rnEndPos, nSearchPos );
+ return true;
+ }
+
+ // nSearchPos == nMidPos: rnMidAddr is the column/row in question, do not loop anymore
+ return false;
+}
+
+} // namespace
+
+CellAddress WorksheetData::getCellAddressFromPosition( const Point& rPosition, const Size& rDrawPageSize ) const
+{
+ // starting cell address and its position in drawing layer (top-left edge)
+ sal_Int32 nBegCol = 0;
+ sal_Int32 nBegRow = 0;
+ Point aBegPos( 0, 0 );
+
+ // end cell address and its position in drawing layer (bottom-right edge)
+ sal_Int32 nEndCol = mrMaxApiPos.Column + 1;
+ sal_Int32 nEndRow = mrMaxApiPos.Row + 1;
+ Point aEndPos( rDrawPageSize.Width, rDrawPageSize.Height );
+
+ // starting point for interval search
+ sal_Int32 nMidCol, nMidRow;
+ bool bLoopCols = lclPrepareInterval( nBegCol, nMidCol, nEndCol, aBegPos.X, aEndPos.X, rPosition.X );
+ bool bLoopRows = lclPrepareInterval( nBegRow, nMidRow, nEndRow, aBegPos.Y, aEndPos.Y, rPosition.Y );
+ Point aMidPos = getCellPosition( nMidCol, nMidRow );
/* The loop will find the column/row index of the cell right of/below
the cell containing the passed point, unless the point is located at
the top or left border of the containing cell. */
- bool bNextCol = true;
- bool bNextRow = true;
- Point aCellPos;
- do
+ while( bLoopCols || bLoopRows )
{
- aCellPos = getCellPosition( nCol, nRow );
- if( bNextCol && ((bNextCol = (aCellPos.X < rPosition.X) && (nCol < mrMaxApiPos.Column)) == true) )
- ++nCol;
- if( bNextRow && ((bNextRow = (aCellPos.Y < rPosition.Y) && (nRow < mrMaxApiPos.Row)) == true) )
- ++nRow;
+ bLoopCols = bLoopCols && lclUpdateInterval( nBegCol, nMidCol, nEndCol, aBegPos.X, aMidPos.X, aEndPos.X, rPosition.X );
+ bLoopRows = bLoopRows && lclUpdateInterval( nBegRow, nMidRow, nEndRow, aBegPos.Y, aMidPos.Y, aEndPos.Y, rPosition.Y );
+ aMidPos = getCellPosition( nMidCol, nMidRow );
}
- while( bNextCol || bNextRow );
/* The cell left of/above the current search position contains the passed
point, unless the point is located on the top/left border of the cell,
or the last column/row of the sheet has been reached. */
- if( aCellPos.X > rPosition.X ) --nCol;
- if( aCellPos.Y > rPosition.Y ) --nRow;
- return CellAddress( getSheetIndex(), nCol, nRow );
+ if( aMidPos.X > rPosition.X ) --nMidCol;
+ if( aMidPos.Y > rPosition.Y ) --nMidRow;
+ return CellAddress( getSheetIndex(), nMidCol, nMidRow );
}
CellRangeAddress WorksheetData::getCellRangeFromRectangle( const Rectangle& rRect ) const
{
- CellAddress aStartAddr = getCellAddressFromPosition( Point( rRect.X, rRect.Y ) );
+ Size aPageSize = getDrawPageSize();
+ CellAddress aStartAddr = getCellAddressFromPosition( Point( rRect.X, rRect.Y ), aPageSize );
Point aBotRight( rRect.X + rRect.Width, rRect.Y + rRect.Height );
- CellAddress aEndAddr = getCellAddressFromPosition( aBotRight );
+ CellAddress aEndAddr = getCellAddressFromPosition( aBotRight, aPageSize );
bool bMultiCols = aStartAddr.Column < aEndAddr.Column;
bool bMultiRows = aStartAddr.Row < aEndAddr.Row;
if( bMultiCols || bMultiRows )
@@ -945,17 +1021,25 @@ void WorksheetData::extendUsedArea( const CellRangeAddress& rRange )
void WorksheetData::extendShapeBoundingBox( const Rectangle& rShapeRect )
{
+ // scale EMUs to 1/100 mm
+ const UnitConverter& rUnitConv = getUnitConverter();
+ Rectangle aShapeRectHmm(
+ rUnitConv.scaleToMm100( rShapeRect.X, UNIT_EMU ),
+ rUnitConv.scaleToMm100( rShapeRect.Y, UNIT_EMU ),
+ rUnitConv.scaleToMm100( rShapeRect.Width, UNIT_EMU ),
+ rUnitConv.scaleToMm100( rShapeRect.Height, UNIT_EMU ) );
+
if( (maShapeBoundingBox.Width == 0) && (maShapeBoundingBox.Height == 0) )
{
// width and height of maShapeBoundingBox are assumed to be zero on first cell
- maShapeBoundingBox = rShapeRect;
+ maShapeBoundingBox = aShapeRectHmm;
}
else
{
- sal_Int32 nEndX = ::std::max( maShapeBoundingBox.X + maShapeBoundingBox.Width, rShapeRect.X + rShapeRect.Width );
- sal_Int32 nEndY = ::std::max( maShapeBoundingBox.Y + maShapeBoundingBox.Height, rShapeRect.Y + rShapeRect.Height );
- maShapeBoundingBox.X = ::std::min( maShapeBoundingBox.X, rShapeRect.X );
- maShapeBoundingBox.Y = ::std::min( maShapeBoundingBox.Y, rShapeRect.Y );
+ sal_Int32 nEndX = ::std::max( maShapeBoundingBox.X + maShapeBoundingBox.Width, aShapeRectHmm.X + aShapeRectHmm.Width );
+ sal_Int32 nEndY = ::std::max( maShapeBoundingBox.Y + maShapeBoundingBox.Height, aShapeRectHmm.Y + aShapeRectHmm.Height );
+ maShapeBoundingBox.X = ::std::min( maShapeBoundingBox.X, aShapeRectHmm.X );
+ maShapeBoundingBox.Y = ::std::min( maShapeBoundingBox.Y, aShapeRectHmm.Y );
maShapeBoundingBox.Width = nEndX - maShapeBoundingBox.X;
maShapeBoundingBox.Height = nEndY - maShapeBoundingBox.Y;
}