LibreOffice Module sc (master)  1
lotimpop.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 "lotfilter.hxx"
21 #include <lotimpop.hxx>
22 #include <osl/mutex.hxx>
23 #include <sal/log.hxx>
24 
25 #include <document.hxx>
26 #include <formulacell.hxx>
27 #include <global.hxx>
28 
29 #include <lotfntbf.hxx>
30 #include <lotform.hxx>
31 #include <tool.h>
32 #include <namebuff.hxx>
33 #include <lotattr.hxx>
34 #include <stringutil.hxx>
35 #include <config_fuzzers.h>
36 
37 
38 static osl::Mutex aLotImpSemaphore;
39 
40 ImportLotus::ImportLotus(LotusContext &rContext, SvStream& aStream, rtl_TextEncoding eQ)
41  : ImportTyp(rContext.rDoc, eQ)
42  , pIn(&aStream)
43  , aConv(rContext, *pIn, rContext.rDoc.GetSharedStringPool(), eQ, false)
44  , nTab(0)
45  , nExtTab(0)
46 {
47  // good point to start locking of import lotus
48  aLotImpSemaphore.acquire();
49 }
50 
52 {
53  // no need 4 pLotusRoot anymore
54  aLotImpSemaphore.release();
55 }
56 
58 {
59  sal_uInt16 nFileCode, nFileSub, nSaveCnt;
60  sal_uInt8 nMajorId, nMinorId, nFlags;
61 
62  Read( nFileCode );
63  Read( nFileSub );
64  LotusContext &rContext = aConv.getContext();
65  Read( rContext.aActRange );
66  Read( nSaveCnt );
67  Read( nMajorId );
68  Read( nMinorId );
69  Skip( 1 );
70  Read( nFlags );
71 
72  if (!pIn->good())
73  return;
74 
75  if( nFileSub == 0x0004 )
76  {
77  if( nFileCode == 0x1000 )
78  {// <= WK3
79  rContext.eFirstType = rContext.eActType = Lotus123Typ::WK3;
80  }
81  else if( nFileCode == 0x1002 )
82  {// WK4
83  rContext.eFirstType = rContext.eActType = Lotus123Typ::WK4;
84  }
85  }
86 }
87 
89 {
90  sal_uInt16 nFileCode(0), nFileSub(0);
91 
92  Read( nFileCode );
93  Read( nFileSub );
94 
95  return ( nFileCode == 0x8007 && ( nFileSub == 0x0000 || nFileSub == 0x00001 ) );
96 }
97 
98 void ImportLotus::Columnwidth( sal_uInt16 nRecLen )
99 {
100  SAL_WARN_IF( nRecLen < 4, "sc.filter", "*ImportLotus::Columnwidth(): Record too short!" );
101 
102  sal_uInt16 nCnt = (nRecLen < 4) ? 0 : ( nRecLen - 4 ) / 2;
103 
104  sal_uInt8 nLTab(0), nWindow2(0);
105  Read( nLTab );
106  Read( nWindow2 );
107 
108  if( !rD.HasTable( static_cast<SCTAB> (nLTab) ) )
109  rD.MakeTable( static_cast<SCTAB> (nLTab) );
110 
111  if( nWindow2 )
112  return;
113 
114  Skip( 2 );
115 
116  while (nCnt && pIn->good())
117  {
118  sal_uInt8 nCol(0), nSpaces(0);
119  Read( nCol );
120  Read( nSpaces );
121  // Attention: ambiguous Correction factor!
122  rD.SetColWidth( static_cast<SCCOL> (nCol), static_cast<SCTAB> (nLTab), static_cast<sal_uInt16>( TWIPS_PER_CHAR * 1.28 * nSpaces ) );
123 
124  nCnt--;
125  }
126 
127  SAL_WARN_IF(!pIn->good(), "sc.filter", "*ImportLotus::Columnwidth(): short read");
128 }
129 
130 void ImportLotus::Hiddencolumn( sal_uInt16 nRecLen )
131 {
132  SAL_WARN_IF( nRecLen < 4, "sc.filter", "*ImportLotus::Hiddencolumn(): Record too short!" );
133 
134  sal_uInt16 nCnt = (nRecLen < 4) ? 0 : ( nRecLen - 4 ) / 2;
135 
136  sal_uInt8 nLTab(0), nWindow2(0);
137  Read( nLTab );
138  Read( nWindow2 );
139 
140  if( nWindow2 )
141  return;
142 
143  Skip( 2 );
144 
145  while (nCnt && pIn->good())
146  {
147  sal_uInt8 nCol(0);
148  Read( nCol );
149 
150  rD.SetColHidden(static_cast<SCCOL>(nCol), static_cast<SCCOL>(nCol), static_cast<SCTAB>(nLTab), true);
151  nCnt--;
152  }
153 
154  SAL_WARN_IF(!pIn->good(), "sc.filter", "*ImportLotus::Hiddencolumn(): short read");
155 }
156 
158 {
159  sal_uInt16 nRangeType;
160  ScRange aScRange;
161 
162  Read( nRangeType );
163 
164  char aBuffer[ 17 ];
165  aBuffer[pIn->ReadBytes(aBuffer, 16)] = 0;
166  OUString aName(aBuffer, strlen(aBuffer), eQuellChar);
167 
168  Read(aScRange);
169 
170  if (!pIn->good())
171  {
172  SAL_WARN("sc.filter", "invalid range");
173  return;
174  }
175 
176  LotusContext &rContext = aConv.getContext();
177  rContext.pRngNmBffWK3->Add( rContext.rDoc, aName, aScRange );
178 }
179 
181 {
182  ScAddress aA;
183 
184  Read( aA );
185 
186  if (!pIn->good() || !rD.ValidAddress(aA))
187  {
188  SAL_WARN("sc.filter", "invalid address");
189  return;
190  }
191 
192  ScSetStringParam aParam;
193  aParam.setTextInput();
194  rD.EnsureTable(aA.Tab());
195  // coverity[tainted_data : FALSE] - ValidAddress has sanitized aA
196  rD.SetString(aA, "#ERR!", &aParam);
197 }
198 
200 {
201  ScAddress aA;
202 
203  Read( aA );
204 
205  if (!pIn->good() || !rD.ValidAddress(aA))
206  {
207  SAL_WARN("sc.filter", "invalid address");
208  return;
209  }
210 
211  ScSetStringParam aParam;
212  aParam.setTextInput();
213  rD.EnsureTable(aA.Tab());
214  // coverity[tainted_data : FALSE] - ValidAddress has sanitized aA
215  rD.SetString(aA, "#NA!", &aParam);
216 }
217 
219 {
220  ScAddress aA;
221  OUString aLabel;
222  char cAlign;
223 
224  Read( aA );
225  Read( cAlign );
226  Read( aLabel );
227 
228  if (!pIn->good() || !rD.ValidAddress(aA))
229  {
230  SAL_WARN("sc.filter", "invalid address");
231  return;
232  }
233 
234  ScSetStringParam aParam;
235  aParam.setTextInput();
236  rD.EnsureTable(aA.Tab());
237  // coverity[tainted_data : FALSE] - ValidAddress has sanitized aA
238  rD.SetString(aA, aLabel, &aParam);
239 }
240 
242 {
243  ScAddress aAddr;
244  double fVal;
245 
246  Read( aAddr );
247  Read( fVal );
248 
249  if (!pIn->good() || !rD.ValidAddress(aAddr))
250  {
251  SAL_WARN("sc.filter", "invalid address");
252  return;
253  }
254 
255  rD.EnsureTable(aAddr.Tab());
256  // coverity[tainted_data : FALSE] - ValidAddress has sanitized aAddr
257  rD.SetValue(aAddr, fVal);
258 }
259 
261 {
262  ScAddress aAddr;
263  sal_Int16 nVal;
264 
265  Read( aAddr );
266  Read( nVal );
267 
268  if (!pIn->good() || !rD.ValidAddress(aAddr))
269  {
270  SAL_WARN("sc.filter", "invalid address");
271  return;
272  }
273 
274  rD.EnsureTable(aAddr.Tab());
275  // coverity[tainted_data : FALSE] - ValidAddress has sanitized aAddr
276  rD.SetValue(aAddr, SnumToDouble(nVal));
277 }
278 
279 void ImportLotus::Formulacell( sal_uInt16 n )
280 {
281  SAL_WARN_IF( !pIn, "sc.filter", "-ImportLotus::Formulacell(): Null-Stream!" );
282 
283  ScAddress aAddr;
284 
285  Read( aAddr );
286  Skip( 10 );
287 
288  n -= std::min<sal_uInt16>(n, 14);
289 
290  std::unique_ptr<ScTokenArray> pErg;
291  sal_Int32 nRest = n;
292 
293  aConv.Reset( aAddr );
294  aConv.SetWK3();
295  aConv.Convert( pErg, nRest );
296  if (!aConv.good())
297  return;
298 
299  if (!pIn->good() || !rD.ValidAddress(aAddr))
300  {
301  SAL_WARN("sc.filter", "invalid address");
302  return;
303  }
304 
305  ScFormulaCell* pCell = pErg ? new ScFormulaCell(rD, aAddr, std::move(pErg)) : new ScFormulaCell(rD, aAddr);
306  pCell->AddRecalcMode( ScRecalcMode::ONLOAD_ONCE );
307  rD.EnsureTable(aAddr.Tab());
308  // coverity[tainted_data : FALSE] - ValidAddress has sanitized aAddr
309  rD.SetFormulaCell(aAddr, pCell);
310 }
311 
312 void ImportLotus::Read( OUString &r )
313 {
315 }
316 
317 void ImportLotus::RowPresentation( sal_uInt16 nRecLen )
318 {
319  SAL_WARN_IF( nRecLen < 5, "sc.filter", "*ImportLotus::RowPresentation(): Record too short!" );
320 
321  sal_uInt16 nCnt = (nRecLen < 4) ? 0 : ( nRecLen - 4 ) / 8;
322 
323  sal_uInt8 nLTab(0);
324  Read( nLTab );
325  Skip( 1 );
326 
327  while (nCnt && pIn->good())
328  {
329  sal_uInt16 nRow(0);
330  Read( nRow );
331  sal_uInt16 nHeight(0);
332  Read( nHeight );
333  Skip( 2 );
334  sal_uInt8 nFlags(0);
335  Read( nFlags );
336  Skip( 1 );
337 
338  if( nFlags & 0x02 ) // Fixed / Stretch to fit fonts
339  { // fixed
340  // Height in Lotus in 1/32 Points
341  nHeight *= 20; // -> 32 * TWIPS
342  nHeight /= 32; // -> TWIPS
343 
344  rD.SetRowFlags( static_cast<SCROW> (nRow), static_cast<SCTAB> (nLTab), rD.GetRowFlags( static_cast<SCROW> (nRow), static_cast<SCTAB> (nLTab) ) | CRFlags::ManualSize );
345 
346  rD.SetRowHeight( static_cast<SCROW> (nRow), static_cast<SCTAB> (nLTab), nHeight );
347  }
348 
349  nCnt--;
350  }
351 }
352 
354 {
355  sal_uInt16 nTmpTab(0);
356  Read(nTmpTab);
357  OUString aName;
358  Read(aName);
359 
360  SCTAB nLTab(SanitizeTab(static_cast<SCTAB>(nTmpTab)));
361 #if ENABLE_FUZZERS
362  //ofz#14167 arbitrary sheet limit to make fuzzing useful
363  if (nLTab > 5)
364  nLTab = 5;
365 #endif
366 
367  if (rD.HasTable(nLTab))
368  rD.RenameTab(nLTab, aName);
369  else
370  rD.InsertTab(nLTab, aName);
371 }
372 
374 {
375  sal_uInt8 nNum;
376  OUString aName;
377 
378  Read( nNum );
379 
380  if( nNum >= LotusFontBuffer::nSize )
381  return; // nonsense
382 
383  Read( aName );
384 
385  LotusContext &rContext = aConv.getContext();
386  rContext.maFontBuff.SetName( nNum, aName );
387 }
388 
390 {
391  LotusContext &rContext = aConv.getContext();
392  for( sal_uInt16 nCnt = 0 ; nCnt < LotusFontBuffer::nSize ; nCnt++ )
393  {
394  sal_uInt16 nType;
395  Read( nType );
396  rContext.maFontBuff.SetType( nCnt, nType );
397  }
398 }
399 
401 {
402  LotusContext &rContext = aConv.getContext();
403  for( sal_uInt16 nCnt = 0 ; nCnt < LotusFontBuffer::nSize ; nCnt++ )
404  {
405  sal_uInt16 nSize;
406  Read( nSize );
407  rContext.maFontBuff.SetHeight( nCnt, nSize );
408  }
409 }
410 
411 void ImportLotus::Row_( const sal_uInt16 nRecLen )
412 {
413  SAL_WARN_IF( nExtTab < 0, "sc.filter", "*ImportLotus::Row_(): not possible!" );
414 
415  sal_uInt16 nCntDwn = (nRecLen < 4) ? 0 : ( nRecLen - 4 ) / 5;
416  SCCOL nColCnt = 0;
417  sal_uInt8 nRepeats;
418  LotAttrWK3 aAttr;
419 
420  bool bCenter = false;
421  SCCOL nCenterStart = 0, nCenterEnd = 0;
422  LotusContext &rContext = aConv.getContext();
423 
424  sal_uInt16 nTmpRow(0);
425  Read(nTmpRow);
426  SCROW nRow(rContext.rDoc.SanitizeRow(static_cast<SCROW>(nTmpRow)));
427  sal_uInt16 nHeight(0);
428  Read(nHeight);
429 
430  nHeight &= 0x0FFF;
431  nHeight *= 22;
432 
433  SCTAB nDestTab(static_cast<SCTAB>(nExtTab));
434 
435  if( nHeight )
436  rD.SetRowHeight(nRow, nDestTab, nHeight);
437 
438  while( nCntDwn )
439  {
440  Read( aAttr );
441  Read( nRepeats );
442 
443  if( aAttr.HasStyles() )
444  rContext.maAttrTable.SetAttr(
445  rContext, nColCnt, static_cast<SCCOL> ( nColCnt + nRepeats ), nRow, aAttr );
446 
447  // Do this here and NOT in class LotAttrTable, as we only add attributes if the other
448  // attributes are set
449  // -> for Center-Attribute default is centered
450  if( aAttr.IsCentered() )
451  {
452  if( bCenter )
453  {
454  if (rD.HasData(nColCnt, nRow, nDestTab))
455  {
456  // new Center after previous Center
457  rD.DoMerge(nDestTab, nCenterStart, nRow, nCenterEnd, nRow);
458  nCenterStart = nColCnt;
459  }
460  }
461  else
462  {
463  // fully new Center
464  bCenter = true;
465  nCenterStart = nColCnt;
466  }
467  nCenterEnd = nColCnt + static_cast<SCCOL>(nRepeats);
468  }
469  else
470  {
471  if( bCenter )
472  {
473  // possibly reset old Center
474  rD.DoMerge(nDestTab, nCenterStart, nRow, nCenterEnd, nRow);
475  bCenter = false;
476  }
477  }
478 
479  nColCnt = nColCnt + static_cast<SCCOL>(nRepeats);
480  nColCnt++;
481 
482  nCntDwn--;
483  }
484 
485  if( bCenter )
486  // possibly reset old Center
487  rD.DoMerge(nDestTab, nCenterStart, nRow, nCenterEnd, nRow);
488 }
489 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
static void AppendCString(SvStream &rStrm, OUString &rString, rtl_TextEncoding eTextEnc)
Appends a zero terminated byte string.
Definition: ftools.cxx:277
void NamedSheet()
Definition: lotimpop.cxx:353
void Font_Ysize()
Definition: lotimpop.cxx:400
Store parameters used in the ScDocument::SetString() method.
Definition: stringutil.hxx:34
ScRange aActRange
Definition: lotfilter.hxx:54
void setTextInput()
Call this whenever you need to unconditionally set input as text, no matter what the input is...
Definition: stringutil.cxx:38
virtual ~ImportLotus() override
Definition: lotimpop.cxx:51
SC_DLLPUBLIC void SetColHidden(SCCOL nStartCol, SCCOL nEndCol, SCTAB nTab, bool bHidden)
Definition: document.cxx:4499
void Row_(const sal_uInt16 nRecLen)
Definition: lotimpop.cxx:411
double SnumToDouble(sal_Int16 nVal)
Definition: tool.cxx:104
void Skip(const sal_uInt16 nNumBytes)
Definition: lotimpop.hxx:131
void RowPresentation(sal_uInt16 nRecLen)
Definition: lotimpop.cxx:317
SC_DLLPUBLIC void SetValue(SCCOL nCol, SCROW nRow, SCTAB nTab, const double &rVal)
Definition: document.cxx:3490
LotAttrTable maAttrTable
Definition: lotfilter.hxx:57
#define TWIPS_PER_CHAR
Definition: global.hxx:90
ScDocument & rDoc
Definition: lotfilter.hxx:44
void Reset(const ScAddress &rEingPos)
Definition: lotform.cxx:363
void Nacell()
Definition: lotimpop.cxx:199
void Userrange()
Definition: lotimpop.cxx:157
std::unique_ptr< RangeNameBufferWK3 > pRngNmBffWK3
Definition: lotfilter.hxx:55
ScDocument & rD
Definition: imp_op.hxx:46
void Formulacell(sal_uInt16 nRecLen)
Definition: lotimpop.cxx:279
SC_DLLPUBLIC bool RenameTab(SCTAB nTab, const OUString &rName, bool bExternalDocument=false)
Definition: document.cxx:853
SC_DLLPUBLIC void SetColWidth(SCCOL nCol, SCTAB nTab, sal_uInt16 nNewWidth)
Definition: document.cxx:4115
void SetName(const sal_uInt16 nIndex, const OUString &rName)
Definition: fontbuff.cxx:70
rtl_TextEncoding eQuellChar
Definition: imp_op.hxx:45
void Numbercell()
Definition: lotimpop.cxx:241
SC_DLLPUBLIC bool HasTable(SCTAB nTab) const
Definition: document.cxx:191
SCTAB Tab() const
Definition: address.hxx:270
SC_DLLPUBLIC bool SetString(SCCOL nCol, SCROW nRow, SCTAB nTab, const OUString &rString, const ScSetStringParam *pParam=nullptr)
Definition: document.cxx:3395
static const sal_uInt16 nSize
Definition: lotfntbf.hxx:50
ImportLotus(LotusContext &rContext, SvStream &, rtl_TextEncoding eSrc)
Definition: lotimpop.cxx:40
void Font_Type()
Definition: lotimpop.cxx:389
void Labelcell()
Definition: lotimpop.cxx:218
bool HasStyles() const
Definition: lotattr.hxx:42
sal_Int16 SCCOL
Definition: types.hxx:21
void Bof()
Definition: lotimpop.cxx:57
SvStream * pIn
Definition: lotimpop.hxx:34
SC_DLLPUBLIC void SetRowHeight(SCROW nRow, SCTAB nTab, sal_uInt16 nNewHeight)
Definition: document.cxx:4127
SC_DLLPUBLIC bool InsertTab(SCTAB nPos, const OUString &rName, bool bExternalDocument=false, bool bUndoDeleteTab=false)
Definition: document.cxx:504
bool BofFm3()
Definition: lotimpop.cxx:88
void Hiddencolumn(sal_uInt16 nRecLen)
Definition: lotimpop.cxx:130
void Smallnumcell()
Definition: lotimpop.cxx:260
SC_DLLPUBLIC void DoMerge(SCTAB nTab, SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, bool bDeleteCaptions=true)
Definition: documen3.cxx:2076
bool IsCentered() const
Definition: lotattr.hxx:48
bool ValidAddress(const ScAddress &rAddress) const
Definition: document.hxx:878
void Font_Face()
Definition: lotimpop.cxx:373
SC_DLLPUBLIC void EnsureTable(SCTAB nTab)
Definition: documen2.cxx:540
std::size_t ReadBytes(void *pData, std::size_t nSize)
LotusFontBuffer maFontBuff
Definition: lotfilter.hxx:56
SCROW SanitizeRow(SCROW nRow) const
Definition: document.hxx:880
virtual void Convert(std::unique_ptr< ScTokenArray > &rpErg, sal_Int32 &nRest) override
Definition: lotform.cxx:391
SCTAB SanitizeTab(SCTAB nTab)
Definition: address.hxx:138
sal_Int32 SCROW
Definition: types.hxx:17
void SetType(const sal_uInt16 nIndex, const sal_uInt16 nType)
Definition: fontbuff.cxx:90
std::unique_ptr< char[]> aBuffer
SC_DLLPUBLIC ScFormulaCell * SetFormulaCell(const ScAddress &rPos, ScFormulaCell *pCell)
Set formula cell, and transfer its ownership to the document.
Definition: documen2.cxx:1086
ErrCode Read()
Definition: lotread.cxx:226
Lotus123Typ eActType
Definition: lotfilter.hxx:53
#define SAL_WARN_IF(condition, area, stream)
unsigned char sal_uInt8
OUString aName
sal_Int32 nExtTab
Definition: lotimpop.hxx:37
void SetWK3()
Definition: lotform.hxx:109
SC_DLLPUBLIC bool HasData(SCCOL nCol, SCROW nRow, SCTAB nTab)
Definition: documen5.cxx:526
OUString aLabel
QPRO_FUNC_TYPE nType
Definition: qproform.cxx:398
bool good() const
Definition: formel.hxx:125
Lotus123Typ eFirstType
Definition: lotfilter.hxx:52
static osl::Mutex aLotImpSemaphore
Definition: lotimpop.cxx:38
LotusContext & getContext()
Definition: lotform.hxx:94
bool good() const
#define SAL_WARN(area, stream)
SC_DLLPUBLIC void MakeTable(SCTAB nTab, bool _bNeedsNameCheck=true)
Definition: document.cxx:168
SC_DLLPUBLIC void SetRowFlags(SCROW nRow, SCTAB nTab, CRFlags nNewFlags)
Definition: document.cxx:4348
void SetAttr(LotusContext &rContext, const SCCOL nColFirst, const SCCOL nColLast, const SCROW nRow, const LotAttrWK3 &)
Definition: lotattr.cxx:230
void AddRecalcMode(ScRecalcMode)
void SetHeight(const sal_uInt16 nIndex, const sal_uInt16 nHeight)
Definition: fontbuff.cxx:83
LotusToSc aConv
Definition: lotimpop.hxx:35
void Errcell()
Definition: lotimpop.cxx:180
sal_Int16 SCTAB
Definition: types.hxx:22
SC_DLLPUBLIC CRFlags GetRowFlags(SCROW nRow, SCTAB nTab) const
Definition: document.cxx:4368
void Columnwidth(sal_uInt16 nRecLen)
Definition: lotimpop.cxx:98