diff options
author | Rohit Deshmukh <rohit.deshmukh@synerzip.com> | 2013-11-21 11:17:40 +0530 |
---|---|---|
committer | Miklos Vajna <vmiklos@collabora.co.uk> | 2013-12-13 13:49:14 +0100 |
commit | 29c079f0480f63dd3f046f30c2b81023c2a5aebf (patch) | |
tree | 7b5d48da27c7db6d2abac7d122be8c214b4be21d /sw | |
parent | 0b9644e2443879e825fc72d5faf55080888a91b8 (diff) |
fdo#71594: Fix for LO crash while saving of file.
1] Libreoffice gets crashed while saving.
2] This caused:
"testCrashWhileSave.docx" file crashes on save
Tested on Libreoffice 4.2
Implementation:
1] It crashes when we are trying to access cell number 2 from
cells vector which contains only single cell. So put check
for cell number which we are accessing and Number of cells
in single row.
2] As we are exporting Header and footer in between when we are
exporting document.xml. In this case we are facing issue in
table export for header and footer. Because flags for table
is getting shared in both export.
So we are switching between flags in between exporting
"document.xml" and Header & footer
export.
After fix:
1] No crash on save for "testCrashWhileSave.docx" and
opens successfully on MS Office 2010
Added Unit test case in export.
Conflicts:
sw/qa/extras/ooxmlexport/ooxmlexport.cxx
Reviewed on:
https://gerrit.libreoffice.org/6676
Change-Id: Iefbf565f7b512d76ac68e9353e225edca425ef06
Diffstat (limited to 'sw')
-rw-r--r-- | sw/qa/extras/ooxmlexport/data/testCrashWhileSave.docx | bin | 0 -> 40873 bytes | |||
-rw-r--r-- | sw/qa/extras/ooxmlexport/ooxmlexport.cxx | 8 | ||||
-rw-r--r-- | sw/source/filter/ww8/docxattributeoutput.cxx | 82 | ||||
-rw-r--r-- | sw/source/filter/ww8/docxattributeoutput.hxx | 30 | ||||
-rw-r--r-- | sw/source/filter/ww8/docxexport.cxx | 6 | ||||
-rw-r--r-- | sw/source/filter/ww8/docxexport.hxx | 3 |
6 files changed, 98 insertions, 31 deletions
diff --git a/sw/qa/extras/ooxmlexport/data/testCrashWhileSave.docx b/sw/qa/extras/ooxmlexport/data/testCrashWhileSave.docx Binary files differnew file mode 100644 index 000000000000..205995171119 --- /dev/null +++ b/sw/qa/extras/ooxmlexport/data/testCrashWhileSave.docx diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport.cxx index d5946273dd8f..7428200b14f7 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport.cxx @@ -2128,6 +2128,14 @@ DECLARE_OOXMLEXPORT_TEST(testFdo71785, "fdo71785.docx") // crashtest } +DECLARE_OOXMLEXPORT_TEST(testCrashWhileSave, "testCrashWhileSave.docx") +{ + xmlDocPtr pXmlDoc = parseExport("word/footer1.xml"); + if (!pXmlDoc) + return; + CPPUNIT_ASSERT(getXPath(pXmlDoc, "/w:ftr/w:tbl/w:tr/w:tc[1]/w:p[1]/w:pPr/w:pStyle", "val").match("Normal")); +} + #endif CPPUNIT_PLUGIN_IMPLEMENT(); diff --git a/sw/source/filter/ww8/docxattributeoutput.cxx b/sw/source/filter/ww8/docxattributeoutput.cxx index 68967175dc85..2d938b57c45d 100644 --- a/sw/source/filter/ww8/docxattributeoutput.cxx +++ b/sw/source/filter/ww8/docxattributeoutput.cxx @@ -237,9 +237,9 @@ void DocxAttributeOutput::StartParagraph( ww8::WW8TableNodeInfo::Pointer_t pText sal_uInt32 nCell = pTextNodeInfo->getCell(); // New cell/row? - if ( m_nTableDepth > 0 && !m_bTableCellOpen ) + if ( m_tableReference->m_nTableDepth > 0 && !m_tableReference->m_bTableCellOpen ) { - ww8::WW8TableNodeInfoInner::Pointer_t pDeepInner( pTextNodeInfo->getInnerForDepth( m_nTableDepth ) ); + ww8::WW8TableNodeInfoInner::Pointer_t pDeepInner( pTextNodeInfo->getInnerForDepth( m_tableReference->m_nTableDepth ) ); if ( pDeepInner->getCell() == 0 ) StartTableRow( pDeepInner ); @@ -253,10 +253,10 @@ void DocxAttributeOutput::StartParagraph( ww8::WW8TableNodeInfo::Pointer_t pText // continue the table cell] sal_uInt32 nCurrentDepth = pTextNodeInfo->getDepth(); - if ( nCurrentDepth > m_nTableDepth ) + if ( nCurrentDepth > m_tableReference->m_nTableDepth ) { // Start all the tables that begin here - for ( sal_uInt32 nDepth = m_nTableDepth + 1; nDepth <= pTextNodeInfo->getDepth(); ++nDepth ) + for ( sal_uInt32 nDepth = m_tableReference->m_nTableDepth + 1; nDepth <= pTextNodeInfo->getDepth(); ++nDepth ) { ww8::WW8TableNodeInfoInner::Pointer_t pInner( pTextNodeInfo->getInnerForDepth( nDepth ) ); @@ -265,7 +265,7 @@ void DocxAttributeOutput::StartParagraph( ww8::WW8TableNodeInfo::Pointer_t pText StartTableCell( pInner ); } - m_nTableDepth = nCurrentDepth; + m_tableReference->m_nTableDepth = nCurrentDepth; } } } @@ -2014,13 +2014,18 @@ void DocxAttributeOutput::TableCellProperties( ww8::WW8TableNodeInfoInner::Point // Horizontal spans const SwWriteTableRows& aRows = m_pTableWrt->GetRows( ); SwWriteTableRow *pRow = aRows[ pTableTextNodeInfoInner->getRow( ) ]; - const SwWriteTableCell *pCell = &pRow->GetCells( )[ pTableTextNodeInfoInner->getCell( ) ]; + sal_uInt32 nCell = pTableTextNodeInfoInner->getCell(); + const SwWriteTableCells *tableCells = &pRow->GetCells(); + if (nCell < tableCells->size() ) + { + const SwWriteTableCell *pCell = &pRow->GetCells( )[ pTableTextNodeInfoInner->getCell( ) ]; - sal_uInt16 nColSpan = pCell->GetColSpan(); - if ( nColSpan > 1 ) - m_pSerializer->singleElementNS( XML_w, XML_gridSpan, - FSNS( XML_w, XML_val ), OString::number( nColSpan ).getStr(), - FSEND ); + sal_uInt16 nColSpan = pCell->GetColSpan(); + if ( nColSpan > 1 ) + m_pSerializer->singleElementNS( XML_w, XML_gridSpan, + FSNS( XML_w, XML_val ), OString::number( nColSpan ).getStr(), + FSEND ); + } // Vertical merges long vSpan = pTblBox->getRowSpan( ); @@ -2076,6 +2081,32 @@ void DocxAttributeOutput::InitTableHelper( ww8::WW8TableNodeInfoInner::Pointer_t (sal_uInt16)nTblSz, false); } +/** + * As we are exporting Header and footer in between when we are exporting document.xml. + * In this case we are facing issue in table export for header and footer. Because + * flags for table is getting shared in both export. + * So we are switching between flags in between exporting "document.xml" and Header & footer + * export. + */ +void DocxAttributeOutput::switchHeaderFooter(bool isHeaderFooter, sal_Int32 index) +{ + if( isHeaderFooter && index == 1) + { + m_oldTableReference->m_bTableCellOpen = m_tableReference->m_bTableCellOpen; + m_oldTableReference->m_nTableDepth = m_tableReference->m_nTableDepth; + m_tableReference->m_bTableCellOpen = false; + m_tableReference->m_nTableDepth = 0; + } + else if( index == -1) + { + m_tableReference = m_oldTableReference; + } + else + { + m_tableReference->m_bTableCellOpen = false; + m_tableReference->m_nTableDepth = 0; + } +} void DocxAttributeOutput::StartTable( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner ) { m_pSerializer->startElementNS( XML_w, XML_tbl, FSEND ); @@ -2090,14 +2121,14 @@ void DocxAttributeOutput::EndTable() { m_pSerializer->endElementNS( XML_w, XML_tbl ); - if ( m_nTableDepth > 0 ) - --m_nTableDepth; + if ( m_tableReference->m_nTableDepth > 0 ) + --m_tableReference->m_nTableDepth; tableFirstCells.pop_back(); // We closed the table; if it is a nested table, the cell that contains it // still continues - m_bTableCellOpen = true; + m_tableReference->m_bTableCellOpen = true; // Cleans the table helper delete m_pTableWrt, m_pTableWrt = NULL; @@ -2138,7 +2169,7 @@ void DocxAttributeOutput::StartTableCell( ww8::WW8TableNodeInfoInner::Pointer_t // Write the cell properties here TableCellProperties( pTableTextNodeInfoInner ); - m_bTableCellOpen = true; + m_tableReference->m_bTableCellOpen = true; } void DocxAttributeOutput::EndTableCell( ) @@ -2146,7 +2177,7 @@ void DocxAttributeOutput::EndTableCell( ) m_pSerializer->endElementNS( XML_w, XML_tc ); m_bBtLr = false; - m_bTableCellOpen = false; + m_tableReference->m_bTableCellOpen = false; } void DocxAttributeOutput::TableInfoCell( ww8::WW8TableNodeInfoInner::Pointer_t /*pTableTextNodeInfoInner*/ ) @@ -2235,7 +2266,7 @@ void DocxAttributeOutput::TableDefinition( ww8::WW8TableNodeInfoInner::Pointer_t // If nested, tblInd is added to parent table's left spacing and defines left edge position // If not nested, text position of left-most cell must be at absolute X = tblInd // so, table_spacing + table_spacing_to_content = tblInd - if (m_nTableDepth == 0) + if (m_tableReference->m_nTableDepth == 0) { const SwTableBox * pTabBox = pTableTextNodeInfoInner->getTableBox(); const SwFrmFmt * pFrmFmt = pTabBox->GetFrmFmt(); @@ -2410,19 +2441,24 @@ void DocxAttributeOutput::TableVerticalCell( ww8::WW8TableNodeInfoInner::Pointer const SwWriteTableRows& aRows = m_pTableWrt->GetRows( ); SwWriteTableRow *pRow = aRows[ pTableTextNodeInfoInner->getRow( ) ]; - const SwWriteTableCell *pCell = &pRow->GetCells( )[ pTableTextNodeInfoInner->getCell( ) ]; - switch( pCell->GetVertOri()) + sal_uInt32 nCell = pTableTextNodeInfoInner->getCell(); + const SwWriteTableCells *tableCells = &pRow->GetCells(); + if (nCell < tableCells->size() ) { + const SwWriteTableCell *pCell = &pRow->GetCells( )[ pTableTextNodeInfoInner->getCell( ) ]; + switch( pCell->GetVertOri()) + { case text::VertOrientation::TOP: break; case text::VertOrientation::CENTER: m_pSerializer->singleElementNS( XML_w, XML_vAlign, - FSNS( XML_w, XML_val ), "center", FSEND ); + FSNS( XML_w, XML_val ), "center", FSEND ); break; case text::VertOrientation::BOTTOM: m_pSerializer->singleElementNS( XML_w, XML_vAlign, - FSNS( XML_w, XML_val ), "bottom", FSEND ); + FSNS( XML_w, XML_val ), "bottom", FSEND ); break; + } } } @@ -6570,8 +6606,6 @@ DocxAttributeOutput::DocxAttributeOutput( DocxExport &rExport, FSHelperPtr pSeri m_bPostitStart(false), m_bPostitEnd(false), m_pTableWrt( NULL ), - m_bTableCellOpen( false ), - m_nTableDepth( 0 ), m_bParagraphOpened( false ), m_nColBreakStatus( COLBRK_NONE ), m_bTextFrameSyntax( false ), @@ -6589,6 +6623,8 @@ DocxAttributeOutput::DocxAttributeOutput( DocxExport &rExport, FSHelperPtr pSeri m_postitFieldsMaxId( 0 ), m_anchorId( 1 ), m_nextFontId( 1 ), + m_tableReference(new TableReference()), + m_oldTableReference(new TableReference()), m_bBtLr(false), m_bFrameBtLr(false), m_pTableStyleExport(new DocxTableStyleExport(rExport.pDoc, pSerializer)), diff --git a/sw/source/filter/ww8/docxattributeoutput.hxx b/sw/source/filter/ww8/docxattributeoutput.hxx index 958300dec491..3ef815abbfa6 100644 --- a/sw/source/filter/ww8/docxattributeoutput.hxx +++ b/sw/source/filter/ww8/docxattributeoutput.hxx @@ -100,6 +100,24 @@ struct PageMargins PageMargins() : nPageMarginLeft(0), nPageMarginRight(0), nPageMarginTop(0), nPageMarginBottom(0) {} }; +/** + * A structure that holds flags for the table export. + */ +struct TableReference +{ + /// Remember if we are in an open cell, or not. + bool m_bTableCellOpen; + + /// Remember the current table depth. + sal_uInt32 m_nTableDepth; + + TableReference() + : m_bTableCellOpen(false), + m_nTableDepth(0) + { + } +}; + /// The class that has handlers for various resource types when exporting as DOCX. class DocxAttributeOutput : public AttributeOutputBase, public oox::vml::VMLTextExport, public oox::drawingml::DMLTextExport { @@ -721,12 +739,6 @@ private: /// The current table helper SwWriteTable *m_pTableWrt; - /// Remember if we are in an open cell, or not. - bool m_bTableCellOpen; - - /// Remember the current table depth. - sal_uInt32 m_nTableDepth; - bool m_bParagraphOpened; // Remember that a column break has to be opened at the @@ -781,6 +793,11 @@ private: OString relId; OString fontKey; }; + + + TableReference *m_tableReference; + TableReference *m_oldTableReference; + std::map< OUString, EmbeddedFontRef > fontFilesMap; // font file url to data // Remember first cell (used for for default borders/margins) of each table @@ -836,6 +853,7 @@ public: /// VMLTextExport virtual void WriteOutliner(const OutlinerParaObject& rParaObj); virtual oox::drawingml::DrawingML& GetDrawingML(); + virtual void switchHeaderFooter(bool isHeaderFooter, sal_Int32 index); void BulletDefinition(int nId, const Graphic& rGraphic, Size aSize) SAL_OVERRIDE; diff --git a/sw/source/filter/ww8/docxexport.cxx b/sw/source/filter/ww8/docxexport.cxx index 2edcf5654db8..2409e425ad94 100644 --- a/sw/source/filter/ww8/docxexport.cxx +++ b/sw/source/filter/ww8/docxexport.cxx @@ -201,6 +201,7 @@ bool DocxExport::DisallowInheritingOutlineNumbering( const SwFmt& rFmt ) void DocxExport::WriteHeadersFooters( sal_uInt8 nHeadFootFlags, const SwFrmFmt& rFmt, const SwFrmFmt& rLeftFmt, const SwFrmFmt& rFirstPageFmt, sal_uInt8 /*nBreakCode*/ ) { + m_nHeadersFootersInSection = 1; // Turn ON flag for 'Writing Headers \ Footers' m_pAttrOutput->SetWritingHeaderFooter( true ); @@ -229,7 +230,7 @@ void DocxExport::WriteHeadersFooters( sal_uInt8 nHeadFootFlags, // Turn OFF flag for 'Writing Headers \ Footers' m_pAttrOutput->SetWritingHeaderFooter( false ); - + m_pAttrOutput->switchHeaderFooter(false, -1); #if OSL_DEBUG_LEVEL > 1 fprintf( stderr, "DocxExport::WriteHeadersFooters() - nBreakCode introduced, but ignored\n" ); #endif @@ -628,7 +629,7 @@ void DocxExport::WriteHeaderFooter( const SwFmt& rFmt, bool bHeader, const char* // switch the serializer to redirect the output to word/styles.xml m_pAttrOutput->SetSerializer( pFS ); m_pVMLExport->SetFS( pFS ); - + m_pAttrOutput->switchHeaderFooter(true, m_nHeadersFootersInSection++); // do the work WriteHeaderFooterText( rFmt, bHeader ); @@ -1199,6 +1200,7 @@ DocxExport::DocxExport( DocxExportFilter *pFilter, SwDoc *pDocument, SwPaM *pCur m_pSections( NULL ), m_nHeaders( 0 ), m_nFooters( 0 ), + m_nHeadersFootersInSection(0), m_pVMLExport( NULL ) { // Write the document properies diff --git a/sw/source/filter/ww8/docxexport.hxx b/sw/source/filter/ww8/docxexport.hxx index cac754e0539c..5dd9e04b9f1b 100644 --- a/sw/source/filter/ww8/docxexport.hxx +++ b/sw/source/filter/ww8/docxexport.hxx @@ -83,6 +83,9 @@ class DocxExport : public MSWordExportBase /// Footer counter. sal_Int32 m_nFooters; + ///Footer and Header counter in Section properties + sal_Int32 m_nHeadersFootersInSection; + /// Exporter of the VML shapes. oox::vml::VMLExport *m_pVMLExport; |