Avoid potential negative array index access to cached text.
[LibreOffice.git] / xmloff / source / text / XMLTextListBlockContext.cxx
blobffacadf6cf700d14946c6f59327cf28b1ac3f4d3
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <com/sun/star/container/XIndexReplace.hpp>
21 #include <com/sun/star/style/XStyle.hpp>
22 #include <com/sun/star/beans/XPropertySet.hpp>
23 #include <xmloff/xmlimp.hxx>
24 #include <xmloff/namespacemap.hxx>
25 #include <xmloff/xmlnamespace.hxx>
26 #include <xmloff/xmltoken.hxx>
27 #include "XMLTextListItemContext.hxx"
28 #include "XMLTextListBlockContext.hxx"
29 #include <txtlists.hxx>
30 #include <sal/log.hxx>
33 using namespace ::com::sun::star;
34 using namespace ::com::sun::star::uno;
35 using namespace ::com::sun::star::container;
36 using namespace ::com::sun::star::style;
37 using namespace ::com::sun::star::beans;
38 using namespace ::xmloff::token;
41 // OD 2008-05-07 #refactorlists#
42 // add optional parameter <bRestartNumberingAtSubList> and its handling
43 XMLTextListBlockContext::XMLTextListBlockContext(
44 SvXMLImport& rImport,
45 XMLTextImportHelper& rTxtImp,
46 const Reference< xml::sax::XFastAttributeList > & xAttrList,
47 const bool bRestartNumberingAtSubList )
48 : SvXMLImportContext( rImport )
49 , mrTxtImport( rTxtImp )
50 , mnLevel( 0 )
51 , mbRestartNumbering( false )
52 , mbSetDefaults( false )
54 static constexpr OUString s_PropNameDefaultListId = u"DefaultListId"_ustr;
56 // get the parent list block context (if any); this is a bit ugly...
57 XMLTextListBlockContext * pLB(nullptr);
58 XMLTextListItemContext * pLI(nullptr);
59 XMLNumberedParaContext * pNP(nullptr);
60 rTxtImp.GetTextListHelper().ListContextTop(pLB, pLI, pNP);
61 mxParentListBlock = pLB;
63 // Inherit style name from parent list, as well as the flags whether
64 // numbering must be restarted and formats have to be created.
65 OUString sParentListStyleName;
66 if( mxParentListBlock.is() )
68 XMLTextListBlockContext *pParent = mxParentListBlock.get();
69 msListStyleName = pParent->msListStyleName;
70 sParentListStyleName = msListStyleName;
71 mxNumRules = pParent->GetNumRules();
72 mnLevel = pParent->GetLevel() + 1;
73 mbRestartNumbering = pParent->IsRestartNumbering() ||
74 bRestartNumberingAtSubList;
75 mbSetDefaults = pParent->mbSetDefaults;
76 msListId = pParent->GetListId();
77 msContinueListId = pParent->GetContinueListId();
80 bool bIsContinueNumberingAttributePresent( false );
81 for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
83 switch( aIter.getToken() )
85 case XML_ELEMENT(XML, XML_ID):
86 //FIXME: there is no UNO API for lists
87 // xml:id is also the list ID (#i92221#)
88 if ( mnLevel == 0 ) // root <list> element
90 msListId = aIter.toString();
92 break;
93 case XML_ELEMENT(TEXT, XML_CONTINUE_NUMBERING):
94 mbRestartNumbering = !IsXMLToken(aIter, XML_TRUE);
95 bIsContinueNumberingAttributePresent = true;
96 break;
97 case XML_ELEMENT(TEXT, XML_STYLE_NAME):
98 msListStyleName = aIter.toString();
99 break;
100 case XML_ELEMENT(TEXT, XML_CONTINUE_LIST):
101 if ( mnLevel == 0 ) // root <list> element
103 msContinueListId = aIter.toString();
105 break;
106 default:
107 XMLOFF_WARN_UNKNOWN("xmloff", aIter);
111 // Remember this list block.
112 mrTxtImport.GetTextListHelper().PushListContext( this );
115 mxNumRules = XMLTextListsHelper::MakeNumRule(GetImport(), mxNumRules,
116 sParentListStyleName, msListStyleName,
117 mnLevel, &mbRestartNumbering, &mbSetDefaults );
118 if( !mxNumRules.is() )
119 return;
121 if ( mnLevel != 0 ) // root <list> element
122 return;
124 XMLTextListsHelper& rTextListsHelper( mrTxtImport.GetTextListHelper() );
125 // Inconsistent behavior regarding lists (#i92811#)
126 OUString sListStyleDefaultListId;
128 uno::Reference< beans::XPropertySet > xNumRuleProps( mxNumRules, UNO_QUERY );
129 if ( xNumRuleProps.is() )
131 uno::Reference< beans::XPropertySetInfo > xNumRulePropSetInfo(
132 xNumRuleProps->getPropertySetInfo());
133 if (xNumRulePropSetInfo.is() &&
134 xNumRulePropSetInfo->hasPropertyByName(
135 s_PropNameDefaultListId))
137 xNumRuleProps->getPropertyValue(s_PropNameDefaultListId)
138 >>= sListStyleDefaultListId;
139 SAL_WARN_IF( sListStyleDefaultListId.isEmpty(), "xmloff",
140 "no default list id found at numbering rules instance. Serious defect." );
144 if ( msListId.isEmpty() ) // no text:id property found
146 sal_Int32 nUPD( 0 );
147 sal_Int32 nBuild( 0 );
148 const bool bBuildIdFound = GetImport().getBuildIds( nUPD, nBuild );
149 if ( rImport.IsTextDocInOOoFileFormat() ||
150 ( bBuildIdFound && nUPD == 680 ) )
152 /* handling former documents written by OpenOffice.org:
153 use default list id of numbering rules instance, if existing
154 (#i92811#)
156 if ( !sListStyleDefaultListId.isEmpty() )
158 msListId = sListStyleDefaultListId;
159 if ( !bIsContinueNumberingAttributePresent &&
160 !mbRestartNumbering &&
161 rTextListsHelper.IsListProcessed( msListId ) )
163 mbRestartNumbering = true;
167 if ( msListId.isEmpty() )
169 // generate a new list id for the list
170 msListId = rTextListsHelper.GenerateNewListId();
174 if ( bIsContinueNumberingAttributePresent && !mbRestartNumbering &&
175 msContinueListId.isEmpty() )
177 const OUString& Last( rTextListsHelper.GetLastProcessedListId() );
178 if ( rTextListsHelper.GetListStyleOfLastProcessedList() == msListStyleName
179 && Last != msListId )
181 msContinueListId = Last;
185 bool bContinueNumbering = bIsContinueNumberingAttributePresent && !mbRestartNumbering;
186 if (msContinueListId.isEmpty() && bContinueNumbering && GetImport().IsMSO())
188 // No "continue list" id, but continue numbering was requested. Connect to the last list of
189 // the same list style in the Word case, even if there was a different list in the meantime.
190 msContinueListId = rTextListsHelper.GetLastIdOfStyleName(msListStyleName);
193 if ( !msContinueListId.isEmpty() )
195 if ( !rTextListsHelper.IsListProcessed( msContinueListId ) )
197 msContinueListId.clear();
199 else
201 // search continue list chain for master list and
202 // continue the master list.
203 OUString sTmpStr =
204 rTextListsHelper.GetContinueListIdOfProcessedList( msContinueListId );
205 while ( !sTmpStr.isEmpty() )
207 msContinueListId = sTmpStr;
209 sTmpStr =
210 rTextListsHelper.GetContinueListIdOfProcessedList( msContinueListId );
215 if ( !rTextListsHelper.IsListProcessed( msListId ) )
217 // Inconsistent behavior regarding lists (#i92811#)
218 rTextListsHelper.KeepListAsProcessed(
219 msListId, msListStyleName, msContinueListId,
220 sListStyleDefaultListId );
223 catch (uno::Exception&)
225 // pop ourselves if anything goes wrong to avoid use-after-free
226 rTxtImp.GetTextListHelper().PopListContext();
227 throw;
231 XMLTextListBlockContext::~XMLTextListBlockContext()
235 void XMLTextListBlockContext::endFastElement(sal_Int32 )
237 // Numbering has not to be restarted if it has been restarted within
238 // a child list.
239 XMLTextListBlockContext *pParent = mxParentListBlock.get();
240 if( pParent )
242 pParent->mbRestartNumbering = mbRestartNumbering;
245 // Restore current list block.
246 mrTxtImport.GetTextListHelper().PopListContext();
248 // Any paragraph following the list within the same list item must not
249 // be numbered.
250 mrTxtImport.GetTextListHelper().SetListItem( nullptr );
253 css::uno::Reference< css::xml::sax::XFastContextHandler > XMLTextListBlockContext::createFastChildContext(
254 sal_Int32 nElement,
255 const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
257 SvXMLImportContext *pContext = nullptr;
259 bool bHeader = false;
260 switch( nElement )
262 case XML_ELEMENT(TEXT, XML_LIST_HEADER):
263 bHeader = true;
264 [[fallthrough]];
265 case XML_ELEMENT(TEXT, XML_LIST_ITEM):
266 pContext = new XMLTextListItemContext( GetImport(), mrTxtImport,
267 xAttrList, bHeader );
268 break;
269 default:
270 XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement);
273 return pContext;
277 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */