tdf#135799: properly load arrays in user-defined types from image
This requires to reset Fixed flag temporarily, as in SbiParser::DefType
for non-image case.
And save the dimensions of the arrays in the custom types correctly:
the dimensions are numbered from 1, not from 0.
The existing unit test (that happened to not test anything actually)
was fixed.
Change-Id: I48c6b6d5d735d9972a2c0dd40345d5db75f87f39
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/100877
Tested-by: Jenkins
Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
Signed-off-by: Xisco Fauli <xiscofauli@libreoffice.org>
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/102748
diff --git a/basic/source/classes/image.cxx b/basic/source/classes/image.cxx
index e6e2776..edee768 100644
--- a/basic/source/classes/image.cxx
+++ b/basic/source/classes/image.cxx
@@ -269,7 +269,7 @@ bool SbiImage::Load( SvStream& r, sal_uInt32& nVersion )
nCount = nMaxRecords;
}
// User defined types
// User defined types; ref.: SbiParser::DefType
for (sal_uInt16 i = 0; i < nCount; i++)
{
OUString aTypeName = r.ReadUniOrByteString(eCharSet);
@@ -324,7 +324,8 @@ bool SbiImage::Load( SvStream& r, sal_uInt32& nVersion )
else
{
// an array
SbxDimArray* pArray = new SbxDimArray();
SbxDimArray* pArray = new SbxDimArray(
static_cast<SbxDataType>(aMemberType & 0x0FFF));
sal_Int16 isFixedSize;
r.ReadInt16(isFixedSize);
@@ -341,7 +342,12 @@ bool SbiImage::Load( SvStream& r, sal_uInt32& nVersion )
pArray->unoAddDim32(lBound, uBound);
}
const SbxFlagBits nSavFlags = pTypeElem->GetFlags();
// need to reset the FIXED flag
// when calling PutObject ( because the type will not match Object )
pTypeElem->ResetFlag(SbxFlagBits::Fixed);
pTypeElem->PutObject( pArray );
pTypeElem->SetFlags(nSavFlags);
}
}
@@ -542,7 +548,7 @@ bool SbiImage::Save( SvStream& r, sal_uInt32 nVer )
sal_Int32 nDims = pArray->GetDims32();
r.WriteInt32(nDims);
for (sal_Int32 d = 0; d < nDims; d++)
for (sal_Int32 d = 1; d <= nDims; d++)
{
sal_Int32 lBound;
sal_Int32 uBound;
diff --git a/sc/qa/extras/macros-test.cxx b/sc/qa/extras/macros-test.cxx
index 3801a99..05c3fc3 100644
--- a/sc/qa/extras/macros-test.cxx
+++ b/sc/qa/extras/macros-test.cxx
@@ -37,6 +37,7 @@ public:
void testPasswordProtectedStarBasic();
void testRowColumn();
void testPasswordProtectedUnicodeString();
void testPasswordProtectedArrayInUserType();
void testTdf131296_legacy();
void testTdf131296_new();
@@ -47,6 +48,7 @@ public:
CPPUNIT_TEST(testPasswordProtectedStarBasic);
CPPUNIT_TEST(testRowColumn);
CPPUNIT_TEST(testPasswordProtectedUnicodeString);
CPPUNIT_TEST(testPasswordProtectedArrayInUserType);
CPPUNIT_TEST(testTdf131296_legacy);
CPPUNIT_TEST(testTdf131296_new);
@@ -132,7 +134,7 @@ void ScMacrosTest::testPasswordProtectedStarBasic()
SfxObjectShell::CallXScript(
xComponent,
"vnd.sun.Star.script:MyLibrary.Module1.Main?language=Basic&location=document",
"vnd.sun.Star.script:Standard.Module1.LoadAndExecuteTest?language=Basic&location=document",
aParams, aRet, aOutParamIndex, aOutParam);
OUString aValue = rDoc.GetString(0,0,0);
@@ -457,6 +459,65 @@ void ScMacrosTest::testPasswordProtectedUnicodeString()
xCloseable->close(true);
}
void ScMacrosTest::testPasswordProtectedArrayInUserType()
{
const OUString sMacroURL(
"vnd.sun.Star.script:Protected.Module1.TestMyType?language=Basic&location=document");
const OUString sLibName("Protected");
OUString aFileName;
createFileURL("ProtectedArrayInCustomType.ods", aFileName);
auto xComponent = loadFromDesktop(aFileName, "com.sun.star.sheet.SpreadsheetDocument");
CPPUNIT_ASSERT(xComponent);
// Check that loading password-protected macro image correctly loads array bounds
{
Any aRet;
Sequence<sal_Int16> aOutParamIndex;
Sequence<Any> aOutParam;
Sequence<uno::Any> aParams;
SfxObjectShell::CallXScript(xComponent, sMacroURL, aParams, aRet, aOutParamIndex,
aOutParam);
sal_Int16 nReturnValue;
aRet >>= nReturnValue;
CPPUNIT_ASSERT_EQUAL(sal_Int16(1), nReturnValue);
}
// Unlock and load the library, to regenerate the image on save
css::uno::Reference<css::document::XEmbeddedScripts> xES(xComponent, UNO_QUERY_THROW);
css::uno::Reference<css::script::XLibraryContainer> xLC(xES->getBasicLibraries(),
UNO_QUERY_THROW);
css::uno::Reference<css::script::XLibraryContainerPassword> xPasswd(xLC, UNO_QUERY_THROW);
CPPUNIT_ASSERT(xPasswd->isLibraryPasswordProtected(sLibName));
CPPUNIT_ASSERT(!xPasswd->isLibraryPasswordVerified(sLibName));
CPPUNIT_ASSERT(xPasswd->verifyLibraryPassword(sLibName, "password"));
xLC->loadLibrary(sLibName);
CPPUNIT_ASSERT(xLC->isLibraryLoaded(sLibName));
// Now check that saving stores array bounds correctly
saveAndReload(xComponent, "calc8");
CPPUNIT_ASSERT(xComponent);
{
Any aRet;
Sequence<sal_Int16> aOutParamIndex;
Sequence<Any> aOutParam;
Sequence<uno::Any> aParams;
SfxObjectShell::CallXScript(xComponent, sMacroURL, aParams, aRet, aOutParamIndex,
aOutParam);
sal_Int16 nReturnValue;
aRet >>= nReturnValue;
CPPUNIT_ASSERT_EQUAL(sal_Int16(1), nReturnValue);
}
css::uno::Reference<css::util::XCloseable> xCloseable(xComponent, css::uno::UNO_QUERY_THROW);
xCloseable->close(true);
}
void ScMacrosTest::testTdf131296_legacy()
{
// For legacy password-protected library images, we must correctly get the constants' values,
diff --git a/sc/qa/extras/testdocuments/ProtectedArrayInCustomType.ods b/sc/qa/extras/testdocuments/ProtectedArrayInCustomType.ods
new file mode 100644
index 0000000..5d7b1a4
--- /dev/null
+++ b/sc/qa/extras/testdocuments/ProtectedArrayInCustomType.ods
Binary files differ
diff --git a/sc/qa/extras/testdocuments/testTypePassword.ods b/sc/qa/extras/testdocuments/testTypePassword.ods
index 7f249bc9..d75c17a 100644
--- a/sc/qa/extras/testdocuments/testTypePassword.ods
+++ b/sc/qa/extras/testdocuments/testTypePassword.ods
Binary files differ