LibreOffice Module sc (master)  1
xmltabi.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
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 .
18  */
19 
20 #include "xmltabi.hxx"
21 #include "xmlimprt.hxx"
22 #include "xmlrowi.hxx"
23 #include "xmlcoli.hxx"
24 #include "xmlsceni.hxx"
25 #include "xmlexternaltabi.hxx"
26 #include "xmlnexpi.hxx"
27 #include <document.hxx>
28 #include <docuno.hxx>
29 #include <olinetab.hxx>
33 #include <rangeutl.hxx>
34 #include <externalrefmgr.hxx>
35 #include <sheetdata.hxx>
36 #include "xmlcondformat.hxx"
38 
39 #include <xmloff/xmltoken.hxx>
40 #include <xmloff/xmlnamespace.hxx>
42 
43 #include <tools/urlobj.hxx>
44 #include <sax/fastattribs.hxx>
45 #include <com/sun/star/sheet/XSpreadsheet.hpp>
47 
48 using namespace com::sun::star;
49 using namespace xmloff::token;
50 using ::com::sun::star::uno::Reference;
51 using ::com::sun::star::uno::UNO_QUERY;
52 using ::com::sun::star::xml::sax::XAttributeList;
53 
66 static bool lcl_isExternalRefCache(const OUString& rName, OUString& rUrl, OUString& rExtTabName)
67 {
68  // 'file:///path/to/file.ods'#MySheet
69  // 'file:///path/to/file.ods'#MySheet with space
70  // 'file:///path/to/file's.ods'#Sheet (Notice the quote in the file name.
71  // That's allowed.)
72 
73  if ( rName.toChar() != '\'' ) // initial quote
74  return false;
75 
76  // #i114504# Other schemes besides "file:" are also allowed.
77  // CompareProtocolScheme is quick, only looks at the start of the string.
78  INetProtocol eProt = INetURLObject::CompareProtocolScheme( rName.subView(1) );
79  if ( eProt == INetProtocol::NotValid )
80  return false;
81 
82  OUString aPrefix = INetURLObject::GetScheme( eProt );
83  sal_Int32 nPrefLen = aPrefix.getLength();
84 
85  OUStringBuffer aUrlBuf, aTabNameBuf;
86  aUrlBuf.append( aPrefix );
87  sal_Int32 n = rName.getLength();
88  const sal_Unicode* p = rName.getStr();
89 
90  bool bInUrl = true;
91  sal_Unicode cPrev = 0;
92  for (sal_Int32 i = nPrefLen+1; i < n; ++i) // start the loop after quote and prefix
93  {
94  const sal_Unicode c = p[i];
95  if (bInUrl)
96  {
97  // parsing file URL
98  if (c == '#')
99  {
100  if (cPrev != '\'')
101  return false;
102 
103  rUrl = aUrlBuf.makeStringAndClear();
104  rUrl = rUrl.copy(0, rUrl.getLength()-1); // remove the trailing single-quote.
105  bInUrl = false;
106  }
107  else
108  aUrlBuf.append(c);
109  }
110  else
111  // parsing sheet name.
112  aTabNameBuf.append(c);
113 
114  cPrev = c;
115  }
116 
117  if (bInUrl)
118  return false;
119 
120  if (aTabNameBuf.isEmpty())
121  return false;
122 
123  rExtTabName = aTabNameBuf.makeStringAndClear();
124 
125  return true;
126 }
127 
129  mnRow(0), mnCol(0), mnFileId(0)
130 {
131 }
132 
135  ScXMLImportContext( rImport ),
136  nStartOffset(-1),
137  bStartFormPage(false),
138  bPrintEntireSheet(true)
139 {
140  // get start offset in file (if available)
142 
143  ScXMLTabProtectionData aProtectData;
144  OUString sName;
145  OUString sStyleName;
146 
147  if ( rAttrList.is() )
148  {
149  for (auto &it : *rAttrList)
150  {
151  switch (it.getToken())
152  {
153  case XML_ELEMENT( TABLE, XML_NAME ):
154  sName = it.toString();
155  break;
157  sStyleName = it.toString();
158  break;
160  aProtectData.mbProtected = IsXMLToken( it, XML_TRUE );
161  break;
163  sPrintRanges = it.toString();
164  break;
166  aProtectData.maPassword = it.toString();
167  break;
169  aProtectData.meHash1 = ScPassHashHelper::getHashTypeFromURI( it.toString() );
170  break;
173  aProtectData.meHash2 = ScPassHashHelper::getHashTypeFromURI( it.toString() );
174  break;
175  case XML_ELEMENT( TABLE, XML_PRINT ):
176  {
177  if ( IsXMLToken( it, XML_FALSE) )
178  bPrintEntireSheet = false;
179  }
180  break;
181  }
182 
183  }
184  }
185 
186  OUString aExtUrl, aExtTabName;
187  if (lcl_isExternalRefCache(sName, aExtUrl, aExtTabName))
188  {
189  // This is an external ref cache table.
191  ScDocument* pDoc = GetScImport().GetDocument();
192  if (pDoc)
193  {
194  ScExternalRefManager* pRefMgr = pDoc->GetExternalRefManager();
195  pExternalRefInfo->mnFileId = pRefMgr->getExternalFileId(aExtUrl);
196  pExternalRefInfo->mpCacheTable = pRefMgr->getCacheTable(pExternalRefInfo->mnFileId, aExtTabName, true,
197  nullptr, &aExtUrl);
198  pExternalRefInfo->mpCacheTable->setWholeTableCached();
199  }
200  }
201  else
202  {
203  // This is a regular table.
204  GetScImport().GetTables().NewSheet(sName, sStyleName, aProtectData);
205  }
206 }
207 
209 {
210 }
211 
212 uno::Reference< xml::sax::XFastContextHandler > SAL_CALL
214  const uno::Reference< xml::sax::XFastAttributeList > & xAttrList )
215 {
216  sax_fastparser::FastAttributeList *pAttribList =
218 
219  if (pExternalRefInfo)
220  {
221  // We only care about the table-row and table-source elements for
222  // external cache data.
223  switch ( nElement )
224  {
228  // #i101319# don't discard rows in groups or header (repeat range)
229  return new ScXMLExternalRefRowsContext(
232  return new ScXMLExternalRefRowContext(
233  GetScImport(), pAttribList, *pExternalRefInfo);
236  GetScImport(), pAttribList, *pExternalRefInfo);
237  default:
238  ;
239  }
240  return nullptr;
241  }
242 
243  SvXMLImportContext *pContext(nullptr);
244 
245  switch ( nElement )
246  {
248  {
250  pContext = new ScXMLNamedExpressionsContext(
251  GetScImport(),
252  std::make_shared<ScXMLNamedExpressionsContext::SheetLocalInserter>(GetScImport(), nTab));
253  }
254  break;
256  pContext = new ScXMLTableColsContext( GetScImport(), pAttribList,
257  false, true );
258  break;
260  pContext = new ScXMLTableColsContext( GetScImport(), pAttribList,
261  true, false );
262  break;
264  pContext = new ScXMLTableColsContext( GetScImport(), pAttribList,
265  false, false );
266  break;
268  pContext = new ScXMLTableColContext( GetScImport(), pAttribList );
269  break;
271  case XML_ELEMENT( LO_EXT, XML_TABLE_PROTECTION ):
272  case XML_ELEMENT( OFFICE_EXT, XML_TABLE_PROTECTION ):
273  pContext = new ScXMLTableProtectionContext( GetScImport(), pAttribList );
274  break;
276  pContext = new ScXMLTableRowsContext( GetScImport(), pAttribList,
277  false, true );
278  break;
280  pContext = new ScXMLTableRowsContext( GetScImport(), pAttribList,
281  true, false );
282  break;
284  pContext = new ScXMLTableRowsContext( GetScImport(), pAttribList,
285  false, false );
286  break;
288  pContext = new ScXMLTableRowContext( GetScImport(), pAttribList );
289  break;
291  pContext = new ScXMLTableSourceContext( GetScImport(), pAttribList);
292  break;
293  case XML_ELEMENT( TABLE, XML_SCENARIO ):
294  pContext = new ScXMLTableScenarioContext( GetScImport(), pAttribList);
295  break;
296  case XML_ELEMENT( TABLE, XML_SHAPES ):
297  pContext = new ScXMLTableShapesContext( GetScImport() );
298  break;
299  case XML_ELEMENT( CALC_EXT, XML_CONDITIONAL_FORMATS ):
300  pContext = new ScXMLConditionalFormatsContext( GetScImport() );
301  break;
302  case XML_ELEMENT(CALC_EXT, XML_SPARKLINE_GROUPS):
304  break;
306  case XML_ELEMENT(OFFICE_EXT, XML_EVENT_LISTENERS):
307  {
308  // use XEventsSupplier interface of the sheet
309  uno::Reference<document::XEventsSupplier> xSupplier( GetScImport().GetTables().GetCurrentXSheet(), uno::UNO_QUERY );
310  pContext = new XMLEventsImportContext( GetImport(), xSupplier );
311  }
312  break;
314  {
315  GetScImport().GetFormImport()->startPage(GetScImport().GetTables().GetCurrentXDrawPage());
316  bStartFormPage = true;
318  }
319  break;
320  default:
321  XMLOFF_WARN_UNKNOWN_ELEMENT("sc", nElement);
322  break;
323  }
324 
325  return pContext;
326 }
327 
328 void SAL_CALL ScXMLTableContext::endFastElement(sal_Int32 /*nElement*/)
329 {
330  ScXMLImport::MutexGuard aMutexGuard(GetScImport());
331  ScXMLImport& rImport = GetScImport();
332  rImport.GetStylesImportHelper()->EndTable();
333  ScDocument* pDoc(rImport.GetDocument());
334  if (!pDoc)
335  return;
336 
337  ScMyTables& rTables = rImport.GetTables();
338  SCTAB nCurTab = rTables.GetCurrentSheet();
339  // tdf#51022 process only print ranges of internal sheets
340  if (!pExternalRefInfo)
341  {
342  if (!sPrintRanges.isEmpty())
343  {
344  ScRangeList aRangeList;
346  size_t nCount = aRangeList.size();
347  for (size_t i = 0; i < nCount; i++)
348  {
349  pDoc->AddPrintRange(nCurTab, aRangeList[i]);
350  }
351  }
352  else if (!bPrintEntireSheet)
353  // Sheet has "print entire sheet" option by default. Remove it.
354  pDoc->ClearPrintRanges(nCurTab);
355  }
356 
357  ScOutlineTable* pOutlineTable(pDoc->GetOutlineTable(nCurTab));
358  if (pOutlineTable)
359  {
360  ScOutlineArray& rColArray(pOutlineTable->GetColArray());
361  size_t nDepth = rColArray.GetDepth();
362  for (size_t i = 0; i < nDepth; ++i)
363  {
364  size_t nCount = rColArray.GetCount(i);
365  for (size_t j = 0; j < nCount; ++j)
366  {
367  const ScOutlineEntry* pEntry = rColArray.GetEntry(i, j);
368  if (pEntry->IsHidden())
369  rColArray.SetVisibleBelow(i, j, false);
370  }
371  }
372  ScOutlineArray& rRowArray(pOutlineTable->GetRowArray());
373  nDepth = rRowArray.GetDepth();
374  for (size_t i = 0; i < nDepth; ++i)
375  {
376  size_t nCount = rRowArray.GetCount(i);
377  for (size_t j = 0; j < nCount; ++j)
378  {
379  const ScOutlineEntry* pEntry = rRowArray.GetEntry(i, j);
380  if (pEntry->IsHidden())
381  rRowArray.SetVisibleBelow(i, j, false);
382  }
383  }
384  }
385  if (rTables.HasDrawPage())
386  {
387  if (rTables.HasXShapes())
388  {
389  rImport.GetShapeImport()->popGroupAndPostProcess();
390  uno::Reference < drawing::XShapes > xTempShapes(rTables.GetCurrentXShapes());
391  rImport.GetShapeImport()->endPage(xTempShapes);
392  }
393  if (bStartFormPage)
394  rImport.GetFormImport()->endPage();
395  }
396 
397  rTables.DeleteTable();
398  rImport.ProgressBarIncrement();
399 
400  // store stream positions
401  if (!pExternalRefInfo && nStartOffset >= 0 /* && nEndOffset >= 0 */)
402  {
403  ScSheetSaveData* pSheetData = comphelper::getFromUnoTunnel<ScModelObj>(rImport.GetModel())->GetSheetSaveData();
404  SCTAB nTab = rTables.GetCurrentSheet();
405  // pSheetData->AddStreamPos( nTab, nStartOffset, nEndOffset );
406  pSheetData->StartStreamPos( nTab, nStartOffset );
407  }
408 }
409 
411  ScXMLImport& rImport,
413  ScXMLImportContext( rImport )
414 {
415  bool bSelectProtectedCells = false;
416  bool bSelectUnprotectedCells = false;
417  bool bInsertColumns = false;
418  bool bInsertRows = false;
419  bool bDeleteColumns = false;
420  bool bDeleteRows = false;
421 
422  if ( rAttrList.is() )
423  {
424  for (auto &aIter : *rAttrList)
425  {
426  sal_Int32 nToken = aIter.getToken();
427  switch (nToken)
428  {
430  case XML_ELEMENT( OFFICE_EXT, XML_SELECT_PROTECTED_CELLS ):
431  case XML_ELEMENT( LO_EXT, XML_SELECT_PROTECTED_CELLS ):
432  bSelectProtectedCells = IsXMLToken(aIter, XML_TRUE);
433  break;
435  case XML_ELEMENT( OFFICE_EXT, XML_SELECT_UNPROTECTED_CELLS ):
437  bSelectUnprotectedCells = IsXMLToken(aIter, XML_TRUE);
438  break;
439  case XML_ELEMENT( LO_EXT, XML_INSERT_COLUMNS ):
440  bInsertColumns = IsXMLToken(aIter, XML_TRUE);
441  break;
442  case XML_ELEMENT( LO_EXT, XML_INSERT_ROWS ):
443  bInsertRows = IsXMLToken(aIter, XML_TRUE);
444  break;
445  case XML_ELEMENT( LO_EXT, XML_DELETE_COLUMNS ):
446  bDeleteColumns = IsXMLToken(aIter, XML_TRUE);
447  break;
448  case XML_ELEMENT( LO_EXT, XML_DELETE_ROWS ):
449  bDeleteRows = IsXMLToken(aIter, XML_TRUE);
450  break;
451  default:
452  XMLOFF_WARN_UNKNOWN("sc", aIter);
453  }
454  }
455  }
456 
458  rProtectData.mbSelectProtectedCells = bSelectProtectedCells;
459  rProtectData.mbSelectUnprotectedCells = bSelectUnprotectedCells;
460  rProtectData.mbInsertColumns = bInsertColumns;
461  rProtectData.mbInsertRows = bInsertRows;
462  rProtectData.mbDeleteColumns = bDeleteColumns;
463  rProtectData.mbDeleteRows = bDeleteRows;
464 }
465 
467 {
468 }
469 
470 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
void NewSheet(const OUString &sTableName, const OUString &sStyleName, const ScXMLTabProtectionData &rProtectData)
Definition: xmlsubti.cxx:93
XML_EVENT_LISTENERS
::std::unique_ptr< ScXMLExternalTabData > pExternalRefInfo
Definition: xmltabi.hxx:42
rtl::Reference< ::xmloff::OFormLayerXMLImport > const & GetFormImport()
bool bPrintEntireSheet
Definition: xmltabi.hxx:45
SC_DLLPUBLIC bool IsHidden() const
Definition: olinetab.hxx:49
XML_PROTECTION_KEY_DIGEST_ALGORITHM
sal_Int32 nStartOffset
Definition: xmltabi.hxx:43
SCTAB GetCurrentSheet() const
Definition: xmlsubti.hxx:84
ScDocument * GetDocument()
Definition: xmlimprt.hxx:205
XML_TABLE_HEADER_COLUMNS
void StartStreamPos(SCTAB nTab, sal_Int32 nStartOffset)
Definition: sheetdata.cxx:116
ScMyTables & GetTables()
Definition: xmlimprt.hxx:208
SvXMLImport & GetImport()
bool HasDrawPage() const
Definition: xmlsubti.cxx:242
sal_Int64 n
sal_Int32 mnCol
bool IsXMLToken(std::u16string_view rString, enum XMLTokenEnum eToken)
FastAttributeList & castToFastAttributeList(const css::uno::Reference< css::xml::sax::XFastAttributeList > &xAttrList)
sal_uInt16 getExternalFileId(const OUString &rFile)
static INetProtocol CompareProtocolScheme(std::u16string_view aTheAbsURIRef)
ScMyStylesImportHelper * GetStylesImportHelper()
Definition: xmlimprt.hxx:250
ScPasswordHash meHash1
Definition: xmlsubti.hxx:36
XML_SPARKLINE_GROUPS
sal_uInt16 sal_Unicode
XML_DELETE_ROWS
XML_PROTECTION_KEY_DIGEST_ALGORITHM_2
virtual void SAL_CALL endFastElement(sal_Int32 nElement) override
Definition: xmltabi.cxx:328
size_t GetDepth() const
Definition: olinetab.hxx:110
int nCount
XML_TABLE_ROWS
#define XMLOFF_WARN_UNKNOWN(area, rIter)
XML_PRINT_RANGES
SC_DLLPUBLIC ScExternalRefManager * GetExternalRefManager() const
Definition: documen3.cxx:627
XML_CONDITIONAL_FORMATS
INetProtocol
XML_PRINT
ScXMLTableContext(ScXMLImport &rImport, const rtl::Reference< sax_fastparser::FastAttributeList > &rAttrList)
Definition: xmltabi.cxx:133
bool HasXShapes() const
Definition: xmlsubti.cxx:247
const char * sName
XML_FORMS
virtual ~ScXMLTableProtectionContext() override
Definition: xmltabi.cxx:466
XML_TABLE_COLUMNS
static SvXMLImportContext * createOfficeFormsContext(SvXMLImport &_rImport)
This class exists only to provide GetScImport() to its derived classes.
XML_PROTECTED
XML_TABLE_ROW
XML_SHAPES
int i
XML_PROTECTION_KEY
XML_TABLE_SOURCE
XML_TABLE_ROW_GROUP
size_t size() const
Definition: rangelst.hxx:89
static OUString GetScheme(INetProtocol eTheScheme)
Use this class to manage solar mutex locking instead of calling LockSolarMutex() and UnlockSolarMutex...
Definition: xmlimprt.hxx:288
ScExternalRefCache::TableTypeRef getCacheTable(sal_uInt16 nFileId, size_t nTabIndex) const
Get a cache table instance for specified table and table index.
ScXMLImport & GetScImport()
virtual ~ScXMLTableContext() override
Definition: xmltabi.cxx:208
ScXMLTableProtectionContext(ScXMLImport &rImport, const rtl::Reference< sax_fastparser::FastAttributeList > &rAttrList)
Definition: xmltabi.cxx:410
void DeleteTable()
Definition: xmlsubti.cxx:182
XML_TRUE
ScPasswordHash getHashTypeFromURI(std::u16string_view rURI)
TABLE
XML_INSERT_COLUMNS
XML_SCENARIO
DefTokenId nToken
Definition: qproform.cxx:397
XML_TABLE_HEADER_ROWS
XML_TABLE_COLUMN
XML_FALSE
virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList > &xAttrList) override
Definition: xmltabi.cxx:213
XML_DELETE_COLUMNS
css::uno::Reference< css::drawing::XShapes > const & GetCurrentXShapes()
Definition: xmlsubti.cxx:230
XML_INSERT_ROWS
#define XML_ELEMENT(prefix, name)
OUString sPrintRanges
Definition: xmltabi.hxx:41
const css::uno::Reference< css::frame::XModel > & GetModel() const
void * p
XML_SELECT_PROTECTED_CELLS
XML_STYLE_NAME
ScXMLTabProtectionData & GetCurrentProtectionData()
Definition: xmlsubti.hxx:82
XML_SELECT_UNPROTECTED_CELLS
static bool GetRangeListFromString(ScRangeList &rRangeList, const OUString &rRangeListStr, const ScDocument &rDocument, formula::FormulaGrammar::AddressConvention eConv, sal_Unicode cSeparator= ' ', sal_Unicode cQuote= '\'')
Definition: rangeutl.cxx:552
#define XMLOFF_WARN_UNKNOWN_ELEMENT(area, token)
XML_TABLE_PROTECTION
sal_Int32 mnRow
sal_Int32 GetByteOffset() const
Definition: xmlimprt.cxx:1538
XML_NAMED_EXPRESSIONS
void ProgressBarIncrement()
Definition: xmlimprt.cxx:1558
ScPasswordHash meHash2
Definition: xmlsubti.hxx:37
sal_Int16 SCTAB
Definition: types.hxx:22
rtl::Reference< XMLShapeImportHelper > const & GetShapeImport()
XML_NAME
bool m_bDetectedRangeSegmentation false
XML_TABLE_COLUMN_GROUP
static bool lcl_isExternalRefCache(const OUString &rName, OUString &rUrl, OUString &rExtTabName)
Determine whether this table is an external reference cache from its name.
Definition: xmltabi.cxx:66