diff options
-rw-r--r-- | include/xmloff/unointerfacetouniqueidentifiermapper.hxx | 21 | ||||
-rw-r--r-- | sd/qa/unit/data/odg/rhbz1870501.odg | bin | 0 -> 403275 bytes | |||
-rw-r--r-- | sd/qa/unit/export-tests.cxx | 9 | ||||
-rw-r--r-- | xmloff/source/core/unointerfacetouniqueidentifiermapper.cxx | 97 | ||||
-rw-r--r-- | xmloff/source/draw/ximpshap.cxx | 9 |
5 files changed, 88 insertions, 48 deletions
diff --git a/include/xmloff/unointerfacetouniqueidentifiermapper.hxx b/include/xmloff/unointerfacetouniqueidentifiermapper.hxx index a78713f85d13..332005e720ac 100644 --- a/include/xmloff/unointerfacetouniqueidentifiermapper.hxx +++ b/include/xmloff/unointerfacetouniqueidentifiermapper.hxx @@ -24,6 +24,7 @@ #include <xmloff/dllapi.h> #include <sal/types.h> +#include <deque> #include <map> #include <rtl/ustring.hxx> #include <com/sun/star/uno/XInterface.hpp> @@ -35,6 +36,8 @@ typedef ::std::map< OUString, css::uno::Reference< css::uno::XInterface > > IdMa class XMLOFF_DLLPUBLIC UnoInterfaceToUniqueIdentifierMapper { + typedef std::deque< OUString > Reserved_t; + public: UnoInterfaceToUniqueIdentifierMapper(); @@ -50,12 +53,16 @@ public: */ bool registerReference( const OUString& rIdentifier, const css::uno::Reference< css::uno::XInterface >& rInterface ); - /** always registers the given uno object with the given identifier. + /** reserves an identifier for later registration. - In contrast to registerReference(), this here overwrites any - earlier registration of the same identifier - */ - void registerReferenceAlways( const OUString& rIdentifier, const css::uno::Reference< css::uno::XInterface >& rInterface ); + @returns + false, if the identifier already exists + */ + bool reserveIdentifier( const OUString& rIdentifier ); + + /** registers the given uno object with reserved identifier. + */ + bool registerReservedReference( const OUString& rIdentifier, const css::uno::Reference< css::uno::XInterface >& rInterface ); /** @returns the identifier for the given uno object. If this uno object is not already @@ -72,10 +79,12 @@ public: private: bool findReference( const css::uno::Reference< css::uno::XInterface >& rInterface, IdMap_t::const_iterator& rIter ) const; bool findIdentifier( const OUString& rIdentifier, IdMap_t::const_iterator& rIter ) const; - void insertReference( const OUString& rIdentifier, const css::uno::Reference< css::uno::XInterface >& rInterface ); + bool findReserved( const OUString& rIdentifier ) const; + bool findReserved( const OUString& rIdentifier, Reserved_t::const_iterator& rIter ) const; IdMap_t maEntries; sal_uInt32 mnNextId; + Reserved_t maReserved; }; } diff --git a/sd/qa/unit/data/odg/rhbz1870501.odg b/sd/qa/unit/data/odg/rhbz1870501.odg Binary files differnew file mode 100644 index 000000000000..cc4bcef193c2 --- /dev/null +++ b/sd/qa/unit/data/odg/rhbz1870501.odg diff --git a/sd/qa/unit/export-tests.cxx b/sd/qa/unit/export-tests.cxx index eb97da60fd1f..1acda7b2712f 100644 --- a/sd/qa/unit/export-tests.cxx +++ b/sd/qa/unit/export-tests.cxx @@ -81,6 +81,7 @@ public: void testSoftEdges(); void testShadowBlur(); void testTdf115753(); + void testRhbz1870501(); CPPUNIT_TEST_SUITE(SdExportTest); @@ -119,6 +120,7 @@ public: CPPUNIT_TEST(testSoftEdges); CPPUNIT_TEST(testShadowBlur); CPPUNIT_TEST(testTdf115753); + CPPUNIT_TEST(testRhbz1870501); CPPUNIT_TEST_SUITE_END(); @@ -1377,6 +1379,13 @@ void SdExportTest::testShadowBlur() xDocShRef->DoClose(); } +void SdExportTest::testRhbz1870501() +{ + //Without the fix in place, it would crash at export time + ::sd::DrawDocShellRef xDocShRef = loadURL( m_directories.getURLFromSrc("/sd/qa/unit/data/odg/rhbz1870501.odg"), ODG); + xDocShRef = saveAndReload( xDocShRef.get(), ODG ); +} + CPPUNIT_TEST_SUITE_REGISTRATION(SdExportTest); CPPUNIT_PLUGIN_IMPLEMENT(); diff --git a/xmloff/source/core/unointerfacetouniqueidentifiermapper.cxx b/xmloff/source/core/unointerfacetouniqueidentifiermapper.cxx index d2e29422ae1c..ce54fe971d44 100644 --- a/xmloff/source/core/unointerfacetouniqueidentifiermapper.cxx +++ b/xmloff/source/core/unointerfacetouniqueidentifiermapper.cxx @@ -21,6 +21,7 @@ #include <o3tl/safeint.hxx> #include <xmloff/unointerfacetouniqueidentifiermapper.hxx> +#include <algorithm> using namespace ::com::sun::star; using css::uno::Reference; @@ -64,25 +65,41 @@ bool UnoInterfaceToUniqueIdentifierMapper::registerReference( const OUString& rI { return rIdentifier != (*aIter).first; } - else if( findIdentifier( rIdentifier, aIter ) ) + else if( findIdentifier( rIdentifier, aIter ) || findReserved( rIdentifier ) ) { return false; } else { - insertReference( rIdentifier, xRef ); + maEntries.insert( IdMap_t::value_type( rIdentifier, xRef ) ); + + // see if this is a reference like something we would generate in the future + const sal_Unicode *p = rIdentifier.getStr(); + sal_Int32 nLength = rIdentifier.getLength(); + + // see if the identifier is 'id' followed by a pure integer value + if( nLength < 2 || p[0] != 'i' || p[1] != 'd' ) + return true; + + nLength -= 2; + p += 2; + + while(nLength--) + { + if( (*p < '0') || (*p > '9') ) + return true; // a custom id, that will never conflict with genereated id's + p++; + } + + // the identifier is a pure integer value + // so we make sure we will never generate + // an integer value like this one + sal_Int32 nId = rIdentifier.copy(2).toInt32(); + if (nId > 0 && mnNextId <= o3tl::make_unsigned(nId)) + mnNextId = nId + 1; + + return true; } - - return true; -} - -void UnoInterfaceToUniqueIdentifierMapper::registerReferenceAlways( const OUString& rIdentifier, const Reference< XInterface >& rInterface ) -{ - // Be certain that the references we store in our table are to the - // leading / primary XInterface - cf. findReference - uno::Reference< uno::XInterface > xRef( rInterface, uno::UNO_QUERY ); - - insertReference( rIdentifier, xRef ); } const OUString& UnoInterfaceToUniqueIdentifierMapper::getIdentifier( const Reference< XInterface >& rInterface ) const @@ -135,38 +152,42 @@ bool UnoInterfaceToUniqueIdentifierMapper::findIdentifier( const OUString& rIden return rIter != maEntries.end(); } -void UnoInterfaceToUniqueIdentifierMapper::insertReference( const OUString& rIdentifier, const Reference< XInterface >& rInterface ) +bool UnoInterfaceToUniqueIdentifierMapper::reserveIdentifier( const OUString& rIdentifier ) { - maEntries[rIdentifier] = rInterface; + if ( findReserved( rIdentifier ) ) + return false; - // see if this is a reference like something we would generate in the future - const sal_Unicode *p = rIdentifier.getStr(); - sal_Int32 nLength = rIdentifier.getLength(); + maReserved.push_back( rIdentifier ); + return true; +} - // see if the identifier is 'id' followed by a pure integer value - if( nLength < 2 || p[0] != 'i' || p[1] != 'd' ) - return; +bool UnoInterfaceToUniqueIdentifierMapper::registerReservedReference( + const OUString& rIdentifier, + const css::uno::Reference< css::uno::XInterface >& rInterface ) +{ + Reserved_t::const_iterator aIt; + if ( !findReserved( rIdentifier, aIt ) ) + return false; - nLength -= 2; - p += 2; + Reserved_t::iterator aRemoveIt( maReserved.begin() + ( aIt - maReserved.begin() ) ); + maReserved.erase( aRemoveIt ); + registerReference( rIdentifier, rInterface ); - while(nLength--) - { - if( (*p < '0') || (*p > '9') ) - return; // a custom id, that will never conflict with generated id's + return true; +} - p++; - } +bool UnoInterfaceToUniqueIdentifierMapper::findReserved( const OUString& rIdentifier ) const +{ + Reserved_t::const_iterator aDummy; + return findReserved( rIdentifier, aDummy ); +} - // the identifier is a pure integer value - // so we make sure we will never generate - // an integer value like this one - sal_Int32 nId = rIdentifier.copy(2).toInt32(); - if (nId > 0 && mnNextId <= o3tl::make_unsigned(nId)) - { - mnNextId = nId; - ++mnNextId; - } +bool UnoInterfaceToUniqueIdentifierMapper::findReserved( + const OUString& rIdentifier, + Reserved_t::const_iterator& rIter ) const +{ + rIter = std::find( maReserved.begin(), maReserved.end(), rIdentifier ); + return rIter != maReserved.end(); } } diff --git a/xmloff/source/draw/ximpshap.cxx b/xmloff/source/draw/ximpshap.cxx index c7cf5b4c08e2..e0e467b31501 100644 --- a/xmloff/source/draw/ximpshap.cxx +++ b/xmloff/source/draw/ximpshap.cxx @@ -3459,6 +3459,9 @@ SvXMLImportContextRef SdXMLFrameShapeContext::CreateChildContext( sal_uInt16 nPr if(getSupportsMultipleContents() && dynamic_cast< SdXMLGraphicObjectShapeContext* >(xContext.get())) { + if ( !maShapeId.isEmpty() ) + GetImport().getInterfaceToIdentifierMapper().reserveIdentifier( maShapeId ); + addContent(*mxImplContext); } } @@ -3568,13 +3571,11 @@ void SdXMLFrameShapeContext::EndElement() SvXMLImportContextRef const pSelectedContext(solveMultipleImages()); const SdXMLGraphicObjectShapeContext* pShapeContext( dynamic_cast<const SdXMLGraphicObjectShapeContext*>(pSelectedContext.get())); - if ( pShapeContext && !maShapeId.isEmpty() ) + if ( pShapeContext ) { - // fdo#64512 and fdo#60075 - make sure *this* shape is - // registered for given ID assert( mxImplContext.is() ); const uno::Reference< uno::XInterface > xShape( pShapeContext->getShape() ); - GetImport().getInterfaceToIdentifierMapper().registerReferenceAlways( maShapeId, xShape ); + GetImport().getInterfaceToIdentifierMapper().registerReservedReference( maShapeId, xShape ); } if( !mxImplContext.is() ) |