1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 "lotfilter.hxx"
21 #include <lotimpop.hxx>
22 #include <osl/mutex.hxx>
23 #include <sal/log.hxx>
25 #include <document.hxx>
26 #include <formulacell.hxx>
29 #include <lotfntbf.hxx>
30 #include <lotform.hxx>
32 #include <namebuff.hxx>
33 #include <lotattr.hxx>
34 #include <stringutil.hxx>
35 #include <config_fuzzers.h>
38 static osl::Mutex aLotImpSemaphore
;
40 ImportLotus::ImportLotus(LotusContext
&rContext
, SvStream
& aStream
, rtl_TextEncoding eQ
)
41 : ImportTyp(rContext
.rDoc
, eQ
)
43 , aConv(rContext
, *pIn
, rContext
.rDoc
.GetSharedStringPool(), eQ
, false)
47 // good point to start locking of import lotus
48 aLotImpSemaphore
.acquire();
51 ImportLotus::~ImportLotus()
53 // no need 4 pLotusRoot anymore
54 aLotImpSemaphore
.release();
57 void ImportLotus::Bof()
59 sal_uInt16 nFileCode
, nFileSub
, nSaveCnt
;
60 sal_uInt8 nMajorId
, nMinorId
, nFlags
;
64 LotusContext
&rContext
= aConv
.getContext();
65 Read( rContext
.aActRange
);
75 if( nFileSub
== 0x0004 )
77 if( nFileCode
== 0x1000 )
79 rContext
.eFirstType
= rContext
.eActType
= Lotus123Typ::WK3
;
81 else if( nFileCode
== 0x1002 )
83 rContext
.eFirstType
= rContext
.eActType
= Lotus123Typ::WK4
;
88 bool ImportLotus::BofFm3()
90 sal_uInt16
nFileCode(0), nFileSub(0);
95 return ( nFileCode
== 0x8007 && ( nFileSub
== 0x0000 || nFileSub
== 0x00001 ) );
98 void ImportLotus::Columnwidth( sal_uInt16 nRecLen
)
100 SAL_WARN_IF( nRecLen
< 4, "sc.filter", "*ImportLotus::Columnwidth(): Record too short!" );
102 sal_uInt16 nCnt
= (nRecLen
< 4) ? 0 : ( nRecLen
- 4 ) / 2;
104 sal_uInt8
nLTab(0), nWindow2(0);
108 if( !rD
.HasTable( static_cast<SCTAB
> (nLTab
) ) )
109 rD
.MakeTable( static_cast<SCTAB
> (nLTab
) );
116 while (nCnt
&& pIn
->good())
118 sal_uInt8
nCol(0), nSpaces(0);
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
) );
127 SAL_WARN_IF(!pIn
->good(), "sc.filter", "*ImportLotus::Columnwidth(): short read");
130 void ImportLotus::Hiddencolumn( sal_uInt16 nRecLen
)
132 SAL_WARN_IF( nRecLen
< 4, "sc.filter", "*ImportLotus::Hiddencolumn(): Record too short!" );
134 sal_uInt16 nCnt
= (nRecLen
< 4) ? 0 : ( nRecLen
- 4 ) / 2;
136 sal_uInt8
nLTab(0), nWindow2(0);
145 while (nCnt
&& pIn
->good())
150 rD
.SetColHidden(static_cast<SCCOL
>(nCol
), static_cast<SCCOL
>(nCol
), static_cast<SCTAB
>(nLTab
), true);
154 SAL_WARN_IF(!pIn
->good(), "sc.filter", "*ImportLotus::Hiddencolumn(): short read");
157 void ImportLotus::Userrange()
159 sal_uInt16 nRangeType
;
165 aBuffer
[pIn
->ReadBytes(aBuffer
, 16)] = 0;
166 OUString
aName(aBuffer
, strlen(aBuffer
), eQuellChar
);
172 SAL_WARN("sc.filter", "invalid range");
176 LotusContext
&rContext
= aConv
.getContext();
177 rContext
.pRngNmBffWK3
->Add( rContext
.rDoc
, aName
, aScRange
);
180 void ImportLotus::Errcell()
186 if (!pIn
->good() || !rD
.ValidAddress(aA
))
188 SAL_WARN("sc.filter", "invalid address");
192 ScSetStringParam aParam
;
193 aParam
.setTextInput();
194 rD
.EnsureTable(aA
.Tab());
195 // coverity[tainted_data : FALSE] - ValidAddress has sanitized aA
196 rD
.SetString(aA
, u
"#ERR!"_ustr
, &aParam
);
199 void ImportLotus::Nacell()
205 if (!pIn
->good() || !rD
.ValidAddress(aA
))
207 SAL_WARN("sc.filter", "invalid address");
211 ScSetStringParam aParam
;
212 aParam
.setTextInput();
213 rD
.EnsureTable(aA
.Tab());
214 // coverity[tainted_data : FALSE] - ValidAddress has sanitized aA
215 rD
.SetString(aA
, u
"#NA!"_ustr
, &aParam
);
218 void ImportLotus::Labelcell()
228 if (!pIn
->good() || !rD
.ValidAddress(aA
))
230 SAL_WARN("sc.filter", "invalid address");
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
);
241 void ImportLotus::Numbercell()
249 if (!pIn
->good() || !rD
.ValidAddress(aAddr
))
251 SAL_WARN("sc.filter", "invalid address");
255 rD
.EnsureTable(aAddr
.Tab());
256 // coverity[tainted_data : FALSE] - ValidAddress has sanitized aAddr
257 rD
.SetValue(aAddr
, fVal
);
260 void ImportLotus::Smallnumcell()
268 if (!pIn
->good() || !rD
.ValidAddress(aAddr
))
270 SAL_WARN("sc.filter", "invalid address");
274 rD
.EnsureTable(aAddr
.Tab());
275 // coverity[tainted_data : FALSE] - ValidAddress has sanitized aAddr
276 rD
.SetValue(aAddr
, SnumToDouble(nVal
));
279 void ImportLotus::Formulacell( sal_uInt16 n
)
281 SAL_WARN_IF( !pIn
, "sc.filter", "-ImportLotus::Formulacell(): Null-Stream!" );
288 n
-= std::min
<sal_uInt16
>(n
, 14);
290 std::unique_ptr
<ScTokenArray
> pErg
;
293 aConv
.Reset( aAddr
);
295 aConv
.Convert( pErg
, nRest
);
299 if (!pIn
->good() || !rD
.ValidAddress(aAddr
))
301 SAL_WARN("sc.filter", "invalid address");
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
);
312 void ImportLotus::Read( OUString
&r
)
314 ScfTools::AppendCString( *pIn
, r
, eQuellChar
);
317 void ImportLotus::RowPresentation( sal_uInt16 nRecLen
)
319 SAL_WARN_IF( nRecLen
< 5, "sc.filter", "*ImportLotus::RowPresentation(): Record too short!" );
321 sal_uInt16 nCnt
= (nRecLen
< 4) ? 0 : ( nRecLen
- 4 ) / 8;
327 while (nCnt
&& pIn
->good())
331 sal_uInt16
nHeight(0);
338 if( nFlags
& 0x02 ) // Fixed / Stretch to fit fonts
340 // Height in Lotus in 1/32 Points
341 nHeight
*= 20; // -> 32 * TWIPS
342 nHeight
/= 32; // -> TWIPS
344 rD
.SetRowFlags( static_cast<SCROW
> (nRow
), static_cast<SCTAB
> (nLTab
), rD
.GetRowFlags( static_cast<SCROW
> (nRow
), static_cast<SCTAB
> (nLTab
) ) | CRFlags::ManualSize
);
346 rD
.SetRowHeight( static_cast<SCROW
> (nRow
), static_cast<SCTAB
> (nLTab
), nHeight
);
353 void ImportLotus::NamedSheet()
355 sal_uInt16
nTmpTab(0);
360 SCTAB
nLTab(SanitizeTab(static_cast<SCTAB
>(nTmpTab
)));
362 //ofz#14167 arbitrary sheet limit to make fuzzing useful
367 if (rD
.HasTable(nLTab
))
368 rD
.RenameTab(nLTab
, aName
);
370 rD
.InsertTab(nLTab
, aName
);
373 void ImportLotus::Font_Face()
380 if( nNum
>= LotusFontBuffer::nSize
)
385 LotusContext
&rContext
= aConv
.getContext();
386 rContext
.maFontBuff
.SetName( nNum
, aName
);
389 void ImportLotus::Font_Type()
391 LotusContext
&rContext
= aConv
.getContext();
392 for( sal_uInt16 nCnt
= 0 ; nCnt
< LotusFontBuffer::nSize
; nCnt
++ )
396 rContext
.maFontBuff
.SetType( nCnt
, nType
);
400 void ImportLotus::Font_Ysize()
402 LotusContext
&rContext
= aConv
.getContext();
403 for( sal_uInt16 nCnt
= 0 ; nCnt
< LotusFontBuffer::nSize
; nCnt
++ )
407 rContext
.maFontBuff
.SetHeight( nCnt
, nSize
);
411 void ImportLotus::Row_( const sal_uInt16 nRecLen
)
413 SAL_WARN_IF( nExtTab
< 0, "sc.filter", "*ImportLotus::Row_(): not possible!" );
415 sal_uInt16 nCntDwn
= (nRecLen
< 4) ? 0 : ( nRecLen
- 4 ) / 5;
420 bool bCenter
= false;
421 SCCOL nCenterStart
= 0, nCenterEnd
= 0;
422 LotusContext
&rContext
= aConv
.getContext();
424 sal_uInt16
nTmpRow(0);
426 SCROW
nRow(rContext
.rDoc
.SanitizeRow(static_cast<SCROW
>(nTmpRow
)));
427 sal_uInt16
nHeight(0);
433 SCTAB
nDestTab(static_cast<SCTAB
>(nExtTab
));
436 rD
.SetRowHeight(nRow
, nDestTab
, nHeight
);
443 if( aAttr
.HasStyles() )
444 rContext
.maAttrTable
.SetAttr(
445 rContext
, nColCnt
, static_cast<SCCOL
> ( nColCnt
+ nRepeats
), nRow
, aAttr
);
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() )
454 if (rD
.HasData(nColCnt
, nRow
, nDestTab
))
456 // new Center after previous Center
457 rD
.DoMerge( nCenterStart
, nRow
, nCenterEnd
, nRow
, nDestTab
);
458 nCenterStart
= nColCnt
;
465 nCenterStart
= nColCnt
;
467 nCenterEnd
= nColCnt
+ static_cast<SCCOL
>(nRepeats
);
473 // possibly reset old Center
474 rD
.DoMerge( nCenterStart
, nRow
, nCenterEnd
, nRow
, nDestTab
);
479 nColCnt
= nColCnt
+ static_cast<SCCOL
>(nRepeats
);
486 // possibly reset old Center
487 rD
.DoMerge( nCenterStart
, nRow
, nCenterEnd
, nRow
, nDestTab
);
489 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */