summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLaurent Godard <lgodard.libre@laposte.net>2015-08-18 16:44:55 +0200
committerCaolán McNamara <caolanm@redhat.com>2015-08-31 10:21:41 +0000
commitcd91509191bee9faaabdae185fef58b811f3a5a4 (patch)
treeb29d3d60445f9fb247cbe3fd2503de2cc54db4ae
parentd3f5b205e4600bfa2ca062f404bb8e58b657c621 (diff)
tdf#75973 : User Defined Types in password encrypted macros
save/load basic script so that when executing password protected the user defined types can be rebuilt supports array and nested types New identifier B_USERTYPE for save/open macro with user defined types No version bump but saves binary format now to current_version a unit test in sc macros-test.cxx full round trip on password protected document (ie. use binary storage) master --(0)--> master --(1)--> libreoffice 4.4 --(2)--> master --(3)--> master (0) in master, User type supported, big module supported (1) in libreoffice 4.4, user type not supported, big module supported, no loss of code (2) in master, user type not supported, big module not found, no loss of code it is OK as libreoffice 4.4 saves to LegacyVersion (see sbxmod.cxx changes) (3) in master, User type supported, big module supported (all is restored) it is OK as module was saved with CURRENT_VERSION (see sbxmod.cxx changes) Change-Id: Idab5de85e948dc11f4aba631b1569a1cc1cb4bf6 Reviewed-on: https://gerrit.libreoffice.org/17841 Reviewed-by: Caolán McNamara <caolanm@redhat.com> Tested-by: Caolán McNamara <caolanm@redhat.com>
-rw-r--r--basic/source/classes/image.cxx171
-rw-r--r--basic/source/classes/sbxmod.cxx5
-rw-r--r--basic/source/inc/filefmt.hxx30
-rw-r--r--basic/source/uno/scriptcont.cxx5
-rw-r--r--include/basic/sbmod.hxx1
-rw-r--r--sc/qa/extras/macros-test.cxx33
-rw-r--r--sc/qa/extras/testdocuments/testTypePassword.odsbin0 -> 14623 bytes
7 files changed, 236 insertions, 9 deletions
diff --git a/basic/source/classes/image.cxx b/basic/source/classes/image.cxx
index d99259b0082c..6726da140c6a 100644
--- a/basic/source/classes/image.cxx
+++ b/basic/source/classes/image.cxx
@@ -240,6 +240,99 @@ bool SbiImage::Load( SvStream& r, sal_uInt32& nVersion )
}
break;
}
+ case B_USERTYPES:
+ {
+ //assuming an empty string with just the lead 32bit/16bit len indicator
+ const size_t nMinStringSize = (eCharSet == RTL_TEXTENCODING_UNICODE) ? 4 : 2;
+ const size_t nMinRecordSize = nMinStringSize + sizeof(sal_Int16);
+ const size_t nMaxRecords = r.remainingSize() / nMinRecordSize;
+ if (nCount > nMaxRecords)
+ {
+ SAL_WARN("basic", "Parsing error: " << nMaxRecords <<
+ " max possible entries, but " << nCount << " claimed, truncating");
+ nCount = nMaxRecords;
+ }
+
+ // User defined types
+ for (sal_uInt16 i = 0; i < nCount; i++)
+ {
+ OUString aTypeName = r.ReadUniOrByteString(eCharSet);
+
+ sal_Int16 nTypeMembers;
+ r.ReadInt16(nTypeMembers);
+
+ SbxObject *pType = new SbxObject(aTypeName);
+ SbxArray *pTypeMembers = pType->GetProperties();
+
+ for (sal_uInt16 j = 0; j < nTypeMembers; j++)
+ {
+ OUString aMemberName = r.ReadUniOrByteString(eCharSet);
+
+ sal_Int16 aIntMemberType;
+ r.ReadInt16(aIntMemberType);
+ SbxDataType aMemberType = static_cast< SbxDataType > ( aIntMemberType );
+
+ SbxProperty *pTypeElem = new SbxProperty( aMemberName, aMemberType );
+
+ sal_uInt32 aIntFlag;
+ r.ReadUInt32(aIntFlag);
+ SbxFlagBits nElemFlags = static_cast< SbxFlagBits > ( aIntFlag );
+
+ pTypeElem->SetFlags(nElemFlags);
+
+ sal_Int16 hasObject;
+ r.ReadInt16(hasObject);
+
+ if (hasObject == 1)
+ {
+ if(aMemberType == SbxOBJECT)
+ {
+ // nested user defined types
+ // declared before use, so it is ok to reference it by name on load
+ OUString aNestedTypeName = r.ReadUniOrByteString(eCharSet);
+ SbxObject* pNestedTypeObj = static_cast< SbxObject* >( rTypes->Find( aNestedTypeName, SbxCLASS_OBJECT ) );
+ if (pNestedTypeObj)
+ {
+ SbxObject* pCloneObj = cloneTypeObjectImpl( *pNestedTypeObj );
+ pTypeElem->PutObject( pCloneObj );
+ }
+ }
+ else
+ {
+ // an array
+ SbxDimArray* pArray = new SbxDimArray();
+
+ sal_Int16 isFixedSize;
+ r.ReadInt16(isFixedSize);
+ if (isFixedSize == 1)
+ pArray->setHasFixedSize( true );
+
+ sal_Int32 nDims;
+ r.ReadInt32(nDims);
+ for (sal_Int32 d = 0; d < nDims; d++)
+ {
+ sal_Int32 lBound;
+ sal_Int32 uBound;
+ r.ReadInt32(lBound).ReadInt32(uBound);
+ pArray->unoAddDim32(lBound, uBound);
+ }
+
+ pTypeElem->PutObject( pArray );
+ }
+ }
+
+ pTypeMembers->Insert( pTypeElem, pTypeMembers->Count() );
+
+ }
+
+ pType->Remove( OUString("Name"), SbxCLASS_DONTCARE );
+ pType->Remove( OUString("Parent"), SbxCLASS_DONTCARE );
+
+ AddType(pType);
+ }
+
+ break;
+ }
case B_MODEND:
goto done;
default:
@@ -360,6 +453,84 @@ bool SbiImage::Save( SvStream& r, sal_uInt32 nVer )
pByteStrings.reset();
SbiCloseRecord( r, nPos );
}
+ // User defined types
+ if (rTypes)
+ {
+ sal_uInt16 nTypes = rTypes->Count();
+ if (nTypes > 0 )
+ {
+ nPos = SbiOpenRecord( r, B_USERTYPES, nTypes );
+
+ for (sal_uInt16 i = 0; i < nTypes; i++)
+ {
+ SbxObject* pType = static_cast< SbxObject* > ( rTypes->Get(i) );
+ OUString aTypeName = pType->GetClassName();
+
+ r.WriteUniOrByteString( aTypeName, eCharSet );
+
+ SbxArray *pTypeMembers = pType->GetProperties();
+ sal_uInt16 nTypeMembers = pTypeMembers->Count();
+
+ r.WriteInt16(nTypeMembers);
+
+ for (sal_uInt16 j = 0; j < nTypeMembers; j++)
+ {
+
+ SbxProperty* pTypeElem = static_cast< SbxProperty* > ( pTypeMembers->Get(j) );
+
+ OUString aElemName = pTypeElem->GetName();
+ r.WriteUniOrByteString( aElemName, eCharSet );
+
+ SbxDataType dataType = pTypeElem->GetType();
+ r.WriteInt16(dataType);
+
+ SbxFlagBits nElemFlags = pTypeElem->GetFlags();
+ r.WriteUInt32(static_cast< sal_uInt32 > (nElemFlags) );
+
+ SbxBase* pElemObject = pTypeElem->GetObject();
+
+ if (pElemObject)
+ {
+ r.WriteInt16(1); // has elem Object
+
+ if( dataType == SbxOBJECT )
+ {
+ // nested user defined types
+ // declared before use, so it is ok to reference it by name on load
+ SbxObject* pNestedType = static_cast< SbxObject* > ( pElemObject );
+ r.WriteUniOrByteString( pNestedType->GetClassName(), eCharSet );
+ }
+ else
+ {
+ // an array
+ SbxDimArray* pArray = static_cast< SbxDimArray* > ( pElemObject );
+
+ bool bFixedSize = pArray->hasFixedSize();
+ if (bFixedSize)
+ r.WriteInt16(1);
+ else
+ r.WriteInt16(0);
+
+ sal_Int32 nDims = pArray->GetDims();
+ r.WriteInt32(nDims);
+
+ for (sal_Int32 d = 0; d < nDims; d++)
+ {
+ sal_Int32 lBound;
+ sal_Int32 uBound;
+ pArray->GetDim32(d, lBound, uBound);
+ r.WriteInt32(lBound).WriteInt32(uBound);
+ }
+ }
+ }
+ else
+ r.WriteInt16(0); // no elem Object
+
+ }
+ }
+ SbiCloseRecord( r, nPos );
+ }
+ }
// Set overall length
SbiCloseRecord( r, nStart );
if( !SbiGood( r ) )
diff --git a/basic/source/classes/sbxmod.cxx b/basic/source/classes/sbxmod.cxx
index e6375e272905..aaa9db9b6aed 100644
--- a/basic/source/classes/sbxmod.cxx
+++ b/basic/source/classes/sbxmod.cxx
@@ -1806,11 +1806,6 @@ bool SbModule::HasExeCode()
}
// Store only image, no source
-bool SbModule::StoreBinaryData( SvStream& rStrm )
-{
- return StoreBinaryData( rStrm, 0 );
-}
-
bool SbModule::StoreBinaryData( SvStream& rStrm, sal_uInt16 nVer )
{
bool bRet = Compile();
diff --git a/basic/source/inc/filefmt.hxx b/basic/source/inc/filefmt.hxx
index 9b294a8c2028..db0b1f6e919f 100644
--- a/basic/source/inc/filefmt.hxx
+++ b/basic/source/inc/filefmt.hxx
@@ -38,10 +38,13 @@ class SvStream;
// Version F: #57844 introduction of SvNumberformat::StringToDouble
// Version 10: #29955 generate for-loop-level in Statement-PCodes
// Version 11: #29955 force anew compilation because of build-inconsistences
+// Version 12: aoo#64377 increase code size that basic can handle
+// tdf#75973 support user defined types B_USERTYPES in password protected macros
+//
#define B_LEGACYVERSION 0x00000011L
-#define B_CURVERSION 0x00000012L
#define B_EXT_IMG_VERSION 0x00000012L
+#define B_CURVERSION 0x00000012L
// The file contains either a module- or a library-record.
// Those records contain further records. Every record's got
@@ -69,6 +72,9 @@ class SvStream;
#define B_SBXOBJECTS 0x5853 // SX SBX objects
#define B_EXTSOURCE 0x5345 // ES extended source
+#define B_USERTYPES 0x4369 // UT user defined types
+
+
// A library record contains only module records
// sal_uInt16 identifier BL
// sal_uInt32 the record's length
@@ -153,6 +159,28 @@ class SvStream;
// sal_uInt16 number of objects
// .... object data
+// user defined types B_USERTYPES :
+// sal_uInt16 identifier UT
+// sal_uInt32 the record's length
+// sal_uInt16 number of types
+// Data for every user defined type:
+// string instance type name
+// sal_Int16 number of type members
+// Data for every type member:
+// string name
+// sal_Int16 type
+// sal_uInt32 flags
+// sal_Int16 hasObjects (0/1)
+// If hasObjects
+// If member type is nested type
+// string nested type name
+// Else (array declaration)
+// sal_Int16 isFixedSize (0/1)
+// sal_Int32 number of dimensions
+// Data for every dimension:
+// sal_Int32 lower bound
+// sal_Int32 upper bound
+
#endif
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/basic/source/uno/scriptcont.cxx b/basic/source/uno/scriptcont.cxx
index ae1b9bf4e78e..bbf1fa6b2117 100644
--- a/basic/source/uno/scriptcont.cxx
+++ b/basic/source/uno/scriptcont.cxx
@@ -18,6 +18,7 @@
*/
#include "scriptcont.hxx"
+#include <filefmt.hxx>
#include <com/sun/star/container/XNameContainer.hpp>
#include <com/sun/star/xml/sax/Parser.hpp>
#include <com/sun/star/xml/sax/InputSource.hpp>
@@ -652,7 +653,7 @@ bool SfxScriptLibraryContainer::implStorePasswordLibrary( SfxLibrary* pLib, cons
throw uno::RuntimeException();
}
SvMemoryStream aMemStream;
- /*sal_Bool bStore = */pMod->StoreBinaryData( aMemStream );
+ /*sal_Bool bStore = */pMod->StoreBinaryData( aMemStream, B_CURVERSION );
sal_Size nSize = aMemStream.Tell();
Sequence< sal_Int8 > aBinSeq( nSize );
@@ -795,7 +796,7 @@ bool SfxScriptLibraryContainer::implStorePasswordLibrary( SfxLibrary* pLib, cons
embed::ElementModes::WRITE | embed::ElementModes::TRUNCATE );
SvMemoryStream aMemStream;
- /*sal_Bool bStore = */pMod->StoreBinaryData( aMemStream );
+ /*sal_Bool bStore = */pMod->StoreBinaryData( aMemStream, B_CURVERSION );
sal_Size nSize = aMemStream.Tell();
Sequence< sal_Int8 > aBinSeq( nSize );
diff --git a/include/basic/sbmod.hxx b/include/basic/sbmod.hxx
index c5a9e16480fb..cddfffb86b4b 100644
--- a/include/basic/sbmod.hxx
+++ b/include/basic/sbmod.hxx
@@ -119,7 +119,6 @@ public:
void ClearAllBP();
// Store only image, no source (needed for new password protection)
- bool StoreBinaryData( SvStream& );
bool StoreBinaryData( SvStream&, sal_uInt16 nVer );
bool LoadBinaryData( SvStream&, sal_uInt16 nVer );
bool LoadBinaryData( SvStream& );
diff --git a/sc/qa/extras/macros-test.cxx b/sc/qa/extras/macros-test.cxx
index 3bc3a94d4b68..745de8673d51 100644
--- a/sc/qa/extras/macros-test.cxx
+++ b/sc/qa/extras/macros-test.cxx
@@ -40,6 +40,7 @@ public:
void testStarBasic();
void testVba();
void testMSP();
+ void testPasswordProtectedStarBasic();
#endif
CPPUNIT_TEST_SUITE(ScMacrosTest);
#if !defined(MACOSX)
@@ -48,6 +49,7 @@ public:
CPPUNIT_TEST(testStarBasic);
CPPUNIT_TEST(testMSP);
CPPUNIT_TEST(testVba);
+ CPPUNIT_TEST(testPasswordProtectedStarBasic);
#endif
CPPUNIT_TEST_SUITE_END();
@@ -96,6 +98,37 @@ void ScMacrosTest::testMSP()
xDocSh->DoClose();
}
+void ScMacrosTest::testPasswordProtectedStarBasic()
+{
+ const OUString aFileNameBase("testTypePassword.ods");
+ OUString aFileName;
+ createFileURL(aFileNameBase, aFileName);
+ uno::Reference< com::sun::star::lang::XComponent > xComponent = loadFromDesktop(aFileName, "com.sun.star.sheet.SpreadsheetDocument");
+
+ CPPUNIT_ASSERT_MESSAGE("Failed to load testTypePassword.ods", xComponent.is());
+
+ Any aRet;
+ Sequence< sal_Int16 > aOutParamIndex;
+ Sequence< Any > aOutParam;
+ Sequence< uno::Any > aParams;
+
+ SfxObjectShell* pFoundShell = SfxObjectShell::GetShellFromComponent(xComponent);
+
+ CPPUNIT_ASSERT_MESSAGE("Failed to access document shell", pFoundShell);
+ ScDocShell* xDocSh = static_cast<ScDocShell*>(pFoundShell);
+ ScDocument& rDoc = xDocSh->GetDocument();
+
+ SfxObjectShell::CallXScript(
+ xComponent,
+ "vnd.sun.Star.script:MyLibrary.Module1.Main?language=Basic&location=document",
+ aParams, aRet, aOutParamIndex, aOutParam);
+
+ OUString aValue = rDoc.GetString(0,0,0);
+ CPPUNIT_ASSERT_MESSAGE("script did not change the value of Sheet1.A1", aValue == "success");
+
+ xDocSh->DoClose();
+}
+
void ScMacrosTest::testStarBasic()
{
const OUString aFileNameBase("StarBasic.ods");
diff --git a/sc/qa/extras/testdocuments/testTypePassword.ods b/sc/qa/extras/testdocuments/testTypePassword.ods
new file mode 100644
index 000000000000..80a0006d58c5
--- /dev/null
+++ b/sc/qa/extras/testdocuments/testTypePassword.ods
Binary files differ