1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sc.hxx"
26
27
28
29 // INCLUDE ---------------------------------------------------------------
30
31 #include "xmlexternaltabi.hxx"
32 #include "xmlimprt.hxx"
33 #include "xmltabi.hxx"
34 #include "xmlstyli.hxx"
35
36 #include "token.hxx"
37 #include "document.hxx"
38
39 #include <xmloff/nmspmap.hxx>
40 #include <xmloff/xmlnmspe.hxx>
41 #include <xmloff/xmltoken.hxx>
42 #include <xmloff/xmluconv.hxx>
43 #include <com/sun/star/util/NumberFormat.hpp>
44
45 using namespace ::com::sun::star;
46
47 using ::rtl::OUString;
48 using ::com::sun::star::uno::Reference;
49 using ::com::sun::star::xml::sax::XAttributeList;
50
51 // ============================================================================
52
ScXMLExternalRefTabSourceContext(ScXMLImport & rImport,sal_uInt16 nPrefix,const OUString & rLName,const Reference<XAttributeList> & xAttrList,ScXMLExternalTabData & rRefInfo)53 ScXMLExternalRefTabSourceContext::ScXMLExternalRefTabSourceContext(
54 ScXMLImport& rImport, sal_uInt16 nPrefix, const OUString& rLName,
55 const Reference<XAttributeList>& xAttrList, ScXMLExternalTabData& rRefInfo ) :
56 SvXMLImportContext( rImport, nPrefix, rLName ),
57 mrScImport(rImport),
58 mrExternalRefInfo(rRefInfo)
59 {
60 using namespace ::xmloff::token;
61
62 sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
63 for (sal_Int16 i = 0; i < nAttrCount; ++i)
64 {
65 const rtl::OUString& sAttrName = xAttrList->getNameByIndex(i);
66 rtl::OUString aLocalName;
67 sal_uInt16 nAttrPrefix = mrScImport.GetNamespaceMap().GetKeyByAttrName(sAttrName, &aLocalName);
68 const rtl::OUString& sValue = xAttrList->getValueByIndex(i);
69 if (nAttrPrefix == XML_NAMESPACE_XLINK)
70 {
71 if (IsXMLToken(aLocalName, XML_HREF))
72 maRelativeUrl = sValue;
73 }
74 else if (nAttrPrefix == XML_NAMESPACE_TABLE)
75 {
76 if (IsXMLToken(aLocalName, XML_TABLE_NAME))
77 maTableName = sValue;
78 else if (IsXMLToken(aLocalName, XML_FILTER_NAME))
79 maFilterName = sValue;
80 else if (IsXMLToken(aLocalName, XML_FILTER_OPTIONS))
81 maFilterOptions = sValue;
82 }
83 }
84 }
85
~ScXMLExternalRefTabSourceContext()86 ScXMLExternalRefTabSourceContext::~ScXMLExternalRefTabSourceContext()
87 {
88 }
89
CreateChildContext(sal_uInt16 nPrefix,const OUString & rLocalName,const Reference<XAttributeList> &)90 SvXMLImportContext* ScXMLExternalRefTabSourceContext::CreateChildContext(
91 sal_uInt16 nPrefix, const OUString& rLocalName, const Reference<XAttributeList>& /*xAttrList*/ )
92 {
93 return new SvXMLImportContext(GetImport(), nPrefix, rLocalName);
94 }
95
96 /**
97 * Make sure the URL is a valid relative URL, mainly to avoid storing
98 * absolute URL as relative URL by accident. For now, we only check the first
99 * three characters which are assumed to be always '../', because the relative
100 * URL for an external document is always in reference to the content.xml
101 * fragment of the original document.
102 */
lcl_isValidRelativeURL(const OUString & rUrl)103 static bool lcl_isValidRelativeURL(const OUString& rUrl)
104 {
105 sal_Int32 n = ::std::min( rUrl.getLength(), static_cast<sal_Int32>(3));
106 if (n < 3)
107 return false;
108 const sal_Unicode* p = rUrl.getStr();
109 for (sal_Int32 i = 0; i < n; ++i)
110 {
111 sal_Unicode c = p[i];
112 if (i < 2 && c != '.')
113 // the path must begin with '..'
114 return false;
115 else if (i == 2 && c != '/')
116 // a '/' path separator must follow
117 return false;
118 }
119 return true;
120 }
121
EndElement()122 void ScXMLExternalRefTabSourceContext::EndElement()
123 {
124 ScDocument* pDoc = mrScImport.GetDocument();
125 if (!pDoc)
126 return;
127
128 ScExternalRefManager* pRefMgr = pDoc->GetExternalRefManager();
129 if (lcl_isValidRelativeURL(maRelativeUrl))
130 pRefMgr->setRelativeFileName(mrExternalRefInfo.mnFileId, maRelativeUrl);
131 pRefMgr->setFilterData(mrExternalRefInfo.mnFileId, maFilterName, maFilterOptions);
132 }
133
134 // ============================================================================
135
ScXMLExternalRefRowsContext(ScXMLImport & rImport,sal_uInt16 nPrefix,const OUString & rLName,const Reference<XAttributeList> &,ScXMLExternalTabData & rRefInfo)136 ScXMLExternalRefRowsContext::ScXMLExternalRefRowsContext(
137 ScXMLImport& rImport, sal_uInt16 nPrefix, const OUString& rLName,
138 const Reference<XAttributeList>& /* xAttrList */, ScXMLExternalTabData& rRefInfo ) :
139 SvXMLImportContext( rImport, nPrefix, rLName ),
140 mrScImport(rImport),
141 mrExternalRefInfo(rRefInfo)
142 {
143 }
144
~ScXMLExternalRefRowsContext()145 ScXMLExternalRefRowsContext::~ScXMLExternalRefRowsContext()
146 {
147 }
148
CreateChildContext(sal_uInt16 nPrefix,const OUString & rLocalName,const Reference<XAttributeList> & xAttrList)149 SvXMLImportContext* ScXMLExternalRefRowsContext::CreateChildContext(
150 sal_uInt16 nPrefix, const OUString& rLocalName, const Reference<XAttributeList>& xAttrList )
151 {
152 // #i101319# row elements inside group, rows or header-rows
153 // are treated like row elements directly in the table element
154
155 const SvXMLTokenMap& rTokenMap = mrScImport.GetTableRowsElemTokenMap();
156 sal_uInt16 nToken = rTokenMap.Get(nPrefix, rLocalName);
157 switch (nToken)
158 {
159 case XML_TOK_TABLE_ROWS_ROW_GROUP:
160 case XML_TOK_TABLE_ROWS_HEADER_ROWS:
161 case XML_TOK_TABLE_ROWS_ROWS:
162 return new ScXMLExternalRefRowsContext(
163 mrScImport, nPrefix, rLocalName, xAttrList, mrExternalRefInfo);
164 case XML_TOK_TABLE_ROWS_ROW:
165 return new ScXMLExternalRefRowContext(
166 mrScImport, nPrefix, rLocalName, xAttrList, mrExternalRefInfo);
167 default:
168 ;
169 }
170 return new SvXMLImportContext(GetImport(), nPrefix, rLocalName);
171 }
172
EndElement()173 void ScXMLExternalRefRowsContext::EndElement()
174 {
175 }
176
177 // ============================================================================
178
ScXMLExternalRefRowContext(ScXMLImport & rImport,sal_uInt16 nPrefix,const OUString & rLName,const Reference<XAttributeList> & xAttrList,ScXMLExternalTabData & rRefInfo)179 ScXMLExternalRefRowContext::ScXMLExternalRefRowContext(
180 ScXMLImport& rImport, sal_uInt16 nPrefix, const OUString& rLName,
181 const Reference<XAttributeList>& xAttrList, ScXMLExternalTabData& rRefInfo ) :
182 SvXMLImportContext( rImport, nPrefix, rLName ),
183 mrScImport(rImport),
184 mrExternalRefInfo(rRefInfo),
185 mnRepeatRowCount(1)
186 {
187 mrExternalRefInfo.mnCol = 0;
188
189 sal_Int16 nAttrCount(xAttrList.is() ? xAttrList->getLength() : 0);
190 const SvXMLTokenMap& rAttrTokenMap = mrScImport.GetTableRowAttrTokenMap();
191 for( sal_Int16 i=0; i < nAttrCount; ++i )
192 {
193 const rtl::OUString& sAttrName = xAttrList->getNameByIndex(i);
194 rtl::OUString aLocalName;
195 sal_uInt16 nAttrPrefix = mrScImport.GetNamespaceMap().GetKeyByAttrName(sAttrName, &aLocalName);
196 const rtl::OUString& sValue = xAttrList->getValueByIndex(i);
197
198 switch (rAttrTokenMap.Get(nAttrPrefix, aLocalName))
199 {
200 case XML_TOK_TABLE_ROW_ATTR_REPEATED:
201 {
202 mnRepeatRowCount = std::max(sValue.toInt32(), static_cast<sal_Int32>(1));
203 }
204 break;
205 }
206 }
207 }
208
~ScXMLExternalRefRowContext()209 ScXMLExternalRefRowContext::~ScXMLExternalRefRowContext()
210 {
211 }
212
CreateChildContext(sal_uInt16 nPrefix,const OUString & rLocalName,const Reference<XAttributeList> & xAttrList)213 SvXMLImportContext* ScXMLExternalRefRowContext::CreateChildContext(
214 sal_uInt16 nPrefix, const OUString& rLocalName, const Reference<XAttributeList>& xAttrList )
215 {
216 const SvXMLTokenMap& rTokenMap = mrScImport.GetTableRowElemTokenMap();
217 sal_uInt16 nToken = rTokenMap.Get(nPrefix, rLocalName);
218 if (nToken == XML_TOK_TABLE_ROW_CELL || nToken == XML_TOK_TABLE_ROW_COVERED_CELL)
219 return new ScXMLExternalRefCellContext(mrScImport, nPrefix, rLocalName, xAttrList, mrExternalRefInfo);
220
221 return new SvXMLImportContext(GetImport(), nPrefix, rLocalName);
222 }
223
EndElement()224 void ScXMLExternalRefRowContext::EndElement()
225 {
226 ScExternalRefCache::TableTypeRef pTab = mrExternalRefInfo.mpCacheTable;
227
228 for (sal_Int32 i = 1; i < mnRepeatRowCount; ++i)
229 {
230 // Performance: duplicates of a non-existent row will still not exist.
231 // Don't find that out for every cell.
232 // External references often are a sparse matrix.
233 if (i == 1 && !pTab->hasRow( mrExternalRefInfo.mnRow))
234 {
235 mrExternalRefInfo.mnRow += mnRepeatRowCount;
236 return;
237 }
238
239 for (sal_Int32 j = 0; j < mrExternalRefInfo.mnCol; ++j)
240 {
241 ScExternalRefCache::TokenRef pToken = pTab->getCell(
242 static_cast<SCCOL>(j), static_cast<SCROW>(mrExternalRefInfo.mnRow));
243
244 if (pToken.get())
245 {
246 pTab->setCell(static_cast<SCCOL>(j),
247 static_cast<SCROW>(mrExternalRefInfo.mnRow+i), pToken);
248 }
249 }
250 }
251 mrExternalRefInfo.mnRow += mnRepeatRowCount;
252 }
253
254 // ============================================================================
255
ScXMLExternalRefCellContext(ScXMLImport & rImport,sal_uInt16 nPrefix,const OUString & rLName,const Reference<XAttributeList> & xAttrList,ScXMLExternalTabData & rRefInfo)256 ScXMLExternalRefCellContext::ScXMLExternalRefCellContext(
257 ScXMLImport& rImport, sal_uInt16 nPrefix, const OUString& rLName,
258 const Reference<XAttributeList>& xAttrList, ScXMLExternalTabData& rRefInfo ) :
259 SvXMLImportContext( rImport, nPrefix, rLName ),
260 mrScImport(rImport),
261 mrExternalRefInfo(rRefInfo),
262 mfCellValue(0.0),
263 mnRepeatCount(1),
264 mnNumberFormat(-1),
265 mnCellType(::com::sun::star::util::NumberFormat::UNDEFINED),
266 mbIsNumeric(false),
267 mbIsEmpty(true)
268 {
269 using namespace ::xmloff::token;
270
271 sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
272 const SvXMLTokenMap& rTokenMap = rImport.GetTableRowCellAttrTokenMap();
273 for (sal_Int16 i = 0; i < nAttrCount; ++i)
274 {
275 OUString aLocalName;
276 sal_uInt16 nAttrPrefix = rImport.GetNamespaceMap().GetKeyByAttrName(
277 xAttrList->getNameByIndex(i), &aLocalName);
278
279 const rtl::OUString& sValue = xAttrList->getValueByIndex(i);
280 sal_uInt16 nToken = rTokenMap.Get(nAttrPrefix, aLocalName);
281
282 switch (nToken)
283 {
284 case XML_TOK_TABLE_ROW_CELL_ATTR_STYLE_NAME:
285 {
286 XMLTableStylesContext* pStyles = static_cast<XMLTableStylesContext*>(mrScImport.GetAutoStyles());
287 const XMLTableStyleContext* pStyle = static_cast<const XMLTableStyleContext*>(
288 pStyles->FindStyleChildContext(XML_STYLE_FAMILY_TABLE_CELL, sValue, true));
289 if (pStyle)
290 mnNumberFormat = const_cast<XMLTableStyleContext*>(pStyle)->GetNumberFormat();
291 }
292 break;
293 case XML_TOK_TABLE_ROW_CELL_ATTR_REPEATED:
294 {
295 mnRepeatCount = ::std::max(sValue.toInt32(), static_cast<sal_Int32>(1));
296 }
297 break;
298 case XML_TOK_TABLE_ROW_CELL_ATTR_VALUE_TYPE:
299 {
300 mnCellType = mrScImport.GetCellType(sValue);
301 }
302 break;
303 case XML_TOK_TABLE_ROW_CELL_ATTR_VALUE:
304 {
305 if (sValue.getLength())
306 {
307 mrScImport.GetMM100UnitConverter().convertDouble(mfCellValue, sValue);
308 mbIsNumeric = true;
309 mbIsEmpty = false;
310 }
311 }
312 break;
313 case XML_TOK_TABLE_ROW_CELL_ATTR_DATE_VALUE:
314 {
315 if (sValue.getLength() && mrScImport.SetNullDateOnUnitConverter())
316 {
317 mrScImport.GetMM100UnitConverter().convertDateTime(mfCellValue, sValue);
318 mbIsNumeric = true;
319 mbIsEmpty = false;
320 }
321 }
322 break;
323 case XML_TOK_TABLE_ROW_CELL_ATTR_TIME_VALUE:
324 {
325 if (sValue.getLength())
326 {
327 mrScImport.GetMM100UnitConverter().convertTime(mfCellValue, sValue);
328 mbIsNumeric = true;
329 mbIsEmpty = false;
330 }
331 }
332 break;
333 case XML_TOK_TABLE_ROW_CELL_ATTR_STRING_VALUE:
334 {
335 if (sValue.getLength())
336 {
337 maCellString = sValue;
338 mbIsNumeric = false;
339 mbIsEmpty = false;
340 }
341 }
342 break;
343 case XML_TOK_TABLE_ROW_CELL_ATTR_BOOLEAN_VALUE:
344 {
345 if (sValue.getLength())
346 {
347 mfCellValue = IsXMLToken(sValue, XML_TRUE) ? 1.0 : 0.0;
348 mbIsNumeric = true;
349 mbIsEmpty = false;
350 }
351 }
352 break;
353 default:
354 ;
355 }
356 }
357 }
358
~ScXMLExternalRefCellContext()359 ScXMLExternalRefCellContext::~ScXMLExternalRefCellContext()
360 {
361 }
362
CreateChildContext(sal_uInt16 nPrefix,const OUString & rLocalName,const Reference<XAttributeList> & xAttrList)363 SvXMLImportContext* ScXMLExternalRefCellContext::CreateChildContext(
364 sal_uInt16 nPrefix, const OUString& rLocalName, const Reference<XAttributeList>& xAttrList )
365 {
366 const SvXMLTokenMap& rTokenMap = mrScImport.GetTableRowCellElemTokenMap();
367 sal_uInt16 nToken = rTokenMap.Get(nPrefix, rLocalName);
368 if (nToken == XML_TOK_TABLE_ROW_CELL_P)
369 return new ScXMLExternalRefCellTextContext(mrScImport, nPrefix, rLocalName, xAttrList, *this);
370
371 return new SvXMLImportContext(GetImport(), nPrefix, rLocalName);
372 }
373
EndElement()374 void ScXMLExternalRefCellContext::EndElement()
375 {
376 if (maCellString.getLength())
377 mbIsEmpty = false;
378
379 for (sal_Int32 i = 0; i < mnRepeatCount; ++i, ++mrExternalRefInfo.mnCol)
380 {
381 if (mbIsEmpty)
382 continue;
383
384 ScExternalRefCache::TokenRef aToken;
385 if (mbIsNumeric)
386 aToken.reset(new formula::FormulaDoubleToken(mfCellValue));
387 else
388 aToken.reset(new formula::FormulaStringToken(maCellString));
389
390 sal_uInt32 nNumFmt = mnNumberFormat >= 0 ? static_cast<sal_uInt32>(mnNumberFormat) : 0;
391 mrExternalRefInfo.mpCacheTable->setCell(
392 static_cast<SCCOL>(mrExternalRefInfo.mnCol),
393 static_cast<SCROW>(mrExternalRefInfo.mnRow),
394 aToken, nNumFmt);
395 }
396 }
397
SetCellString(const OUString & rStr)398 void ScXMLExternalRefCellContext::SetCellString(const OUString& rStr)
399 {
400 maCellString = rStr;
401 }
402
403 // ============================================================================
404
ScXMLExternalRefCellTextContext(ScXMLImport & rImport,sal_uInt16 nPrefix,const OUString & rLName,const Reference<XAttributeList> &,ScXMLExternalRefCellContext & rParent)405 ScXMLExternalRefCellTextContext::ScXMLExternalRefCellTextContext(
406 ScXMLImport& rImport, sal_uInt16 nPrefix, const OUString& rLName,
407 const Reference<XAttributeList>& /*xAttrList*/,
408 ScXMLExternalRefCellContext& rParent ) :
409 SvXMLImportContext( rImport, nPrefix, rLName ),
410 mrScImport(rImport),
411 mrParent(rParent)
412 {
413 }
414
~ScXMLExternalRefCellTextContext()415 ScXMLExternalRefCellTextContext::~ScXMLExternalRefCellTextContext()
416 {
417 }
418
CreateChildContext(sal_uInt16 nPrefix,const OUString & rLocalName,const Reference<XAttributeList> &)419 SvXMLImportContext* ScXMLExternalRefCellTextContext::CreateChildContext(
420 sal_uInt16 nPrefix, const OUString& rLocalName, const Reference<XAttributeList>& /*xAttrList*/ )
421 {
422 return new SvXMLImportContext(GetImport(), nPrefix, rLocalName);
423 }
424
Characters(const OUString & rChar)425 void ScXMLExternalRefCellTextContext::Characters(const OUString& rChar)
426 {
427 maCellStrBuf.append(rChar);
428 }
429
EndElement()430 void ScXMLExternalRefCellTextContext::EndElement()
431 {
432 mrParent.SetCellString(maCellStrBuf.makeStringAndClear());
433 }
434