Avoid potential negative array index access to cached text.
[LibreOffice.git] / xmloff / source / text / XMLIndexTemplateContext.cxx
blob411e4c6b94b0601229318b5e6b814a5817c3f651
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 "XMLIndexTemplateContext.hxx"
21 #include "XMLIndexSimpleEntryContext.hxx"
22 #include "XMLIndexSpanEntryContext.hxx"
23 #include "XMLIndexTabStopEntryContext.hxx"
24 #include "XMLIndexBibliographyEntryContext.hxx"
25 #include "XMLIndexChapterInfoEntryContext.hxx"
26 #include <xmloff/xmlictxt.hxx>
27 #include <xmloff/xmlimp.hxx>
28 #include <xmloff/txtimp.hxx>
29 #include <xmloff/namespacemap.hxx>
30 #include <xmloff/xmlnamespace.hxx>
31 #include <xmloff/xmltoken.hxx>
32 #include <xmloff/xmluconv.hxx>
33 #include <xmloff/xmlement.hxx>
34 #include <tools/debug.hxx>
35 #include <rtl/ustring.hxx>
36 #include <sal/log.hxx>
37 #include <com/sun/star/container/XIndexReplace.hpp>
38 #include <com/sun/star/container/XNameContainer.hpp>
39 #include <com/sun/star/beans/XPropertySet.hpp>
41 #include <algorithm>
43 using namespace ::xmloff::token;
45 using ::com::sun::star::beans::XPropertySet;
46 using ::com::sun::star::beans::PropertyValues;
47 using ::com::sun::star::uno::Reference;
48 using ::com::sun::star::uno::Sequence;
49 using ::com::sun::star::uno::Any;
50 using ::com::sun::star::container::XIndexReplace;
52 XMLIndexTemplateContext::XMLIndexTemplateContext(
53 SvXMLImport& rImport,
54 Reference<XPropertySet> & rPropSet,
55 const SvXMLEnumMapEntry<sal_uInt16>* pLevelNameMap,
56 enum XMLTokenEnum eLevelAttrName,
57 const char** pLevelStylePropMap,
58 const bool* pAllowedTokenTypes,
59 bool bT )
60 : SvXMLImportContext(rImport)
61 , pOutlineLevelNameMap(pLevelNameMap)
62 , eOutlineLevelAttrName(eLevelAttrName)
63 , pOutlineLevelStylePropMap(pLevelStylePropMap)
64 , pAllowedTokenTypesMap(pAllowedTokenTypes)
65 , nOutlineLevel(1) // all indices have level 1 (0 is for header)
66 , bStyleNameOK(false)
67 , bOutlineLevelOK(false)
68 , bTOC( bT )
69 , rPropertySet(rPropSet)
71 DBG_ASSERT( ((XML_TOKEN_INVALID != eLevelAttrName) && (nullptr != pLevelNameMap))
72 || ((XML_TOKEN_INVALID == eLevelAttrName) && (nullptr == pLevelNameMap)),
73 "need both, attribute name and value map, or neither" );
74 SAL_WARN_IF( nullptr == pOutlineLevelStylePropMap, "xmloff", "need property name map" );
75 SAL_WARN_IF( nullptr == pAllowedTokenTypes, "xmloff", "need allowed tokens map" );
77 // no map for outline-level? then use 1
78 if (nullptr == pLevelNameMap)
80 nOutlineLevel = 1;
81 bOutlineLevelOK = true;
85 XMLIndexTemplateContext::~XMLIndexTemplateContext()
90 void XMLIndexTemplateContext::addTemplateEntry(
91 const PropertyValues& aValues)
93 aValueVector.push_back(aValues);
97 void XMLIndexTemplateContext::startFastElement(
98 sal_Int32 /*nElement*/,
99 const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
101 // process two attributes: style-name, outline-level
102 for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
104 if(aIter.getToken() == XML_ELEMENT(TEXT, XML_STYLE_NAME))
106 // style name
107 sStyleName = aIter.toString();
108 bStyleNameOK = true;
110 else if (aIter.getToken() == XML_ELEMENT(TEXT, eOutlineLevelAttrName))
112 // we have an attr name! Then see if we have the attr, too.
113 // outline level
114 sal_uInt16 nTmp;
115 if (SvXMLUnitConverter::convertEnum(nTmp, aIter.toView(), pOutlineLevelNameMap))
117 nOutlineLevel = nTmp;
118 bOutlineLevelOK = true;
120 // else: illegal value -> ignore
122 // else: attribute not in text namespace -> ignore
126 void XMLIndexTemplateContext::endFastElement(sal_Int32 )
128 if (!bOutlineLevelOK)
129 return;
131 const sal_Int32 nCount = aValueVector.size();
132 Sequence<PropertyValues> aValueSequence(nCount);
133 std::copy(aValueVector.begin(), aValueVector.end(), aValueSequence.getArray());
135 // get LevelFormat IndexReplace ...
136 Any aAny = rPropertySet->getPropertyValue("LevelFormat");
137 Reference<XIndexReplace> xIndexReplace;
138 aAny >>= xIndexReplace;
140 // ... and insert
141 xIndexReplace->replaceByIndex(nOutlineLevel, Any(aValueSequence));
143 if (!bStyleNameOK)
144 return;
146 const char* pStyleProperty =
147 pOutlineLevelStylePropMap[nOutlineLevel];
149 DBG_ASSERT(nullptr != pStyleProperty, "need property name");
150 if (nullptr == pStyleProperty)
151 return;
153 OUString sDisplayStyleName =
154 GetImport().GetStyleDisplayName(
155 XmlStyleFamily::TEXT_PARAGRAPH,
156 sStyleName );
157 // #i50288#: Check if style exists
158 const Reference < css::container::XNameContainer > & rStyles =
159 GetImport().GetTextImport()->GetParaStyles();
160 if( rStyles.is() &&
161 rStyles->hasByName( sDisplayStyleName ) )
163 rPropertySet->setPropertyValue(
164 OUString::createFromAscii(pStyleProperty), css::uno::Any(sDisplayStyleName));
168 namespace {
169 /// template token types; used for aTokenTypeMap parameter
170 enum TemplateTokenType
172 XML_TOK_INDEX_TYPE_ENTRY_TEXT = 0,
173 XML_TOK_INDEX_TYPE_TAB_STOP,
174 XML_TOK_INDEX_TYPE_TEXT,
175 XML_TOK_INDEX_TYPE_PAGE_NUMBER,
176 XML_TOK_INDEX_TYPE_CHAPTER,
177 XML_TOK_INDEX_TYPE_LINK_START,
178 XML_TOK_INDEX_TYPE_LINK_END,
179 XML_TOK_INDEX_TYPE_BIBLIOGRAPHY
184 SvXMLEnumMapEntry<TemplateTokenType> const aTemplateTokenTypeMap[] =
186 { XML_INDEX_ENTRY_TEXT, XML_TOK_INDEX_TYPE_ENTRY_TEXT },
187 { XML_INDEX_ENTRY_TAB_STOP, XML_TOK_INDEX_TYPE_TAB_STOP },
188 { XML_INDEX_ENTRY_SPAN, XML_TOK_INDEX_TYPE_TEXT },
189 { XML_INDEX_ENTRY_PAGE_NUMBER, XML_TOK_INDEX_TYPE_PAGE_NUMBER },
190 { XML_INDEX_ENTRY_CHAPTER, XML_TOK_INDEX_TYPE_CHAPTER },
191 { XML_INDEX_ENTRY_LINK_START, XML_TOK_INDEX_TYPE_LINK_START },
192 { XML_INDEX_ENTRY_LINK_END, XML_TOK_INDEX_TYPE_LINK_END },
193 { XML_INDEX_ENTRY_BIBLIOGRAPHY, XML_TOK_INDEX_TYPE_BIBLIOGRAPHY },
194 { XML_TOKEN_INVALID, TemplateTokenType(0) }
197 css::uno::Reference< css::xml::sax::XFastContextHandler > XMLIndexTemplateContext::createFastChildContext(
198 sal_Int32 nElement,
199 const css::uno::Reference< css::xml::sax::XFastAttributeList >& )
201 SvXMLImportContext* pContext = nullptr;
203 if (IsTokenInNamespace(nElement, XML_NAMESPACE_TEXT) || IsTokenInNamespace(nElement, XML_NAMESPACE_LO_EXT))
205 TemplateTokenType nToken;
206 if (SvXMLUnitConverter::convertEnum(nToken, SvXMLImport::getNameFromToken(nElement),
207 aTemplateTokenTypeMap))
209 // can this index accept this kind of token?
210 if (pAllowedTokenTypesMap[nToken])
212 switch (nToken)
214 case XML_TOK_INDEX_TYPE_ENTRY_TEXT:
215 pContext = new XMLIndexSimpleEntryContext(
216 GetImport(), "TokenEntryText", *this);
217 break;
219 case XML_TOK_INDEX_TYPE_PAGE_NUMBER:
220 pContext = new XMLIndexSimpleEntryContext(
221 GetImport(), "TokenPageNumber", *this);
222 break;
224 case XML_TOK_INDEX_TYPE_LINK_START:
225 pContext = new XMLIndexSimpleEntryContext(
226 GetImport(), "TokenHyperlinkStart", *this);
227 break;
229 case XML_TOK_INDEX_TYPE_LINK_END:
230 pContext = new XMLIndexSimpleEntryContext(
231 GetImport(), "TokenHyperlinkEnd", *this);
232 break;
234 case XML_TOK_INDEX_TYPE_TEXT:
235 pContext = new XMLIndexSpanEntryContext(
236 GetImport(), *this);
237 break;
239 case XML_TOK_INDEX_TYPE_TAB_STOP:
240 pContext = new XMLIndexTabStopEntryContext(
241 GetImport(), *this);
242 break;
244 case XML_TOK_INDEX_TYPE_BIBLIOGRAPHY:
245 pContext = new XMLIndexBibliographyEntryContext(
246 GetImport(), *this);
247 break;
249 case XML_TOK_INDEX_TYPE_CHAPTER:
250 pContext = new XMLIndexChapterInfoEntryContext(
251 GetImport(), *this, bTOC );
252 break;
254 default:
255 // ignore!
256 break;
262 // ignore unknown
263 return pContext;
267 // maps for the XMLIndexTemplateContext constructor
270 // table of content and user defined index:
272 const SvXMLEnumMapEntry<sal_uInt16> aSvLevelNameTOCMap[] =
274 { XML_1, 1 },
275 { XML_2, 2 },
276 { XML_3, 3 },
277 { XML_4, 4 },
278 { XML_5, 5 },
279 { XML_6, 6 },
280 { XML_7, 7 },
281 { XML_8, 8 },
282 { XML_9, 9 },
283 { XML_10, 10 },
284 { XML_TOKEN_INVALID, 0 }
287 const char* aLevelStylePropNameTOCMap[] =
288 { nullptr, "ParaStyleLevel1", "ParaStyleLevel2", "ParaStyleLevel3",
289 "ParaStyleLevel4", "ParaStyleLevel5", "ParaStyleLevel6",
290 "ParaStyleLevel7", "ParaStyleLevel8", "ParaStyleLevel9",
291 "ParaStyleLevel10", nullptr };
293 const bool aAllowedTokenTypesTOC[] =
295 true, // XML_TOK_INDEX_TYPE_ENTRY_TEXT =
296 true, // XML_TOK_INDEX_TYPE_TAB_STOP,
297 true, // XML_TOK_INDEX_TYPE_TEXT,
298 true, // XML_TOK_INDEX_TYPE_PAGE_NUMBER,
299 true, // XML_TOK_INDEX_TYPE_CHAPTER,
300 true, // XML_TOK_INDEX_TYPE_LINK_START,
301 true, // XML_TOK_INDEX_TYPE_LINK_END,
302 false // XML_TOK_INDEX_TYPE_BIBLIOGRAPHY
305 const bool aAllowedTokenTypesUser[] =
307 true, // XML_TOK_INDEX_TYPE_ENTRY_TEXT =
308 true, // XML_TOK_INDEX_TYPE_TAB_STOP,
309 true, // XML_TOK_INDEX_TYPE_TEXT,
310 true, // XML_TOK_INDEX_TYPE_PAGE_NUMBER,
311 true, // XML_TOK_INDEX_TYPE_CHAPTER,
312 true, // XML_TOK_INDEX_TYPE_LINK_START,
313 true, // XML_TOK_INDEX_TYPE_LINK_END,
314 false // XML_TOK_INDEX_TYPE_BIBLIOGRAPHY
318 // alphabetical index
320 const SvXMLEnumMapEntry<sal_uInt16> aLevelNameAlphaMap[] =
322 { XML_SEPARATOR, 1 },
323 { XML_1, 2 },
324 { XML_2, 3 },
325 { XML_3, 4 },
326 { XML_TOKEN_INVALID, 0 }
329 const char* aLevelStylePropNameAlphaMap[] =
330 { nullptr, "ParaStyleSeparator", "ParaStyleLevel1", "ParaStyleLevel2",
331 "ParaStyleLevel3", nullptr };
333 const bool aAllowedTokenTypesAlpha[] =
335 true, // XML_TOK_INDEX_TYPE_ENTRY_TEXT =
336 true, // XML_TOK_INDEX_TYPE_TAB_STOP,
337 true, // XML_TOK_INDEX_TYPE_TEXT,
338 true, // XML_TOK_INDEX_TYPE_PAGE_NUMBER,
339 true, // XML_TOK_INDEX_TYPE_CHAPTER,
340 false, // XML_TOK_INDEX_TYPE_LINK_START,
341 false, // XML_TOK_INDEX_TYPE_LINK_END,
342 false // XML_TOK_INDEX_TYPE_BIBLIOGRAPHY
346 // bibliography index:
348 const SvXMLEnumMapEntry<sal_uInt16> aLevelNameBibliographyMap[] =
350 { XML_ARTICLE, 1 },
351 { XML_BOOK, 2 },
352 { XML_BOOKLET, 3 },
353 { XML_CONFERENCE, 4 },
354 { XML_CUSTOM1, 5 },
355 { XML_CUSTOM2, 6 },
356 { XML_CUSTOM3, 7 },
357 { XML_CUSTOM4, 8 },
358 { XML_CUSTOM5, 9 },
359 { XML_EMAIL, 10 },
360 { XML_INBOOK, 11 },
361 { XML_INCOLLECTION, 12 },
362 { XML_INPROCEEDINGS, 13 },
363 { XML_JOURNAL, 14 },
364 { XML_MANUAL, 15 },
365 { XML_MASTERSTHESIS, 16 },
366 { XML_MISC, 17 },
367 { XML_PHDTHESIS, 18 },
368 { XML_PROCEEDINGS, 19 },
369 { XML_TECHREPORT, 20 },
370 { XML_UNPUBLISHED, 21 },
371 { XML_WWW, 22 },
372 { XML_TOKEN_INVALID, 0 }
375 // TODO: replace with real property names, when available
376 const char* aLevelStylePropNameBibliographyMap[] =
378 nullptr, "ParaStyleLevel1", "ParaStyleLevel1", "ParaStyleLevel1",
379 "ParaStyleLevel1", "ParaStyleLevel1", "ParaStyleLevel1",
380 "ParaStyleLevel1", "ParaStyleLevel1", "ParaStyleLevel1",
381 "ParaStyleLevel1", "ParaStyleLevel1", "ParaStyleLevel1",
382 "ParaStyleLevel1", "ParaStyleLevel1", "ParaStyleLevel1",
383 "ParaStyleLevel1", "ParaStyleLevel1", "ParaStyleLevel1",
384 "ParaStyleLevel1", "ParaStyleLevel1", "ParaStyleLevel1",
385 "ParaStyleLevel1", nullptr };
387 const bool aAllowedTokenTypesBibliography[] =
389 true, // XML_TOK_INDEX_TYPE_ENTRY_TEXT =
390 true, // XML_TOK_INDEX_TYPE_TAB_STOP,
391 true, // XML_TOK_INDEX_TYPE_TEXT,
392 true, // XML_TOK_INDEX_TYPE_PAGE_NUMBER,
393 false, // XML_TOK_INDEX_TYPE_CHAPTER,
394 false, // XML_TOK_INDEX_TYPE_LINK_START,
395 false, // XML_TOK_INDEX_TYPE_LINK_END,
396 true // XML_TOK_INDEX_TYPE_BIBLIOGRAPHY
400 // table, illustration and object index
402 // no name map
403 const SvXMLEnumMapEntry<sal_uInt16>* aLevelNameTableMap = nullptr;
405 const char* aLevelStylePropNameTableMap[] =
406 { nullptr, "ParaStyleLevel1", nullptr };
408 const bool aAllowedTokenTypesTable[] =
410 true, // XML_TOK_INDEX_TYPE_ENTRY_TEXT =
411 true, // XML_TOK_INDEX_TYPE_TAB_STOP,
412 true, // XML_TOK_INDEX_TYPE_TEXT,
413 true, // XML_TOK_INDEX_TYPE_PAGE_NUMBER,
414 true, // XML_TOK_INDEX_TYPE_CHAPTER,
415 true, // XML_TOK_INDEX_TYPE_LINK_START,
416 true, // XML_TOK_INDEX_TYPE_LINK_END,
417 false // XML_TOK_INDEX_TYPE_BIBLIOGRAPHY
420 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */