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 #ifndef INCLUDED_SC_SOURCE_FILTER_INC_XESTREAM_HXX
21 #define INCLUDED_SC_SOURCE_FILTER_INC_XESTREAM_HXX
25 #include <rtl/strbuf.hxx>
27 #include <oox/core/xmlfilterbase.hxx>
28 #include <sax/fshelper.hxx>
29 #include <tools/stream.hxx>
32 #include <filter/msfilter/mscodec.hxx>
35 namespace com
{ namespace sun
{ namespace star
{ namespace beans
{ struct NamedValue
; } } } }
37 /* ============================================================================
38 Output stream class for Excel export
39 - CONTINUE record handling
40 ============================================================================ */
44 class XclExpBiff8Encrypter
;
45 typedef std::shared_ptr
< XclExpBiff8Encrypter
> XclExpEncrypterRef
;
47 /** This class is used to export Excel record streams.
48 @descr An instance is constructed with an SvStream and the maximum size of Excel
49 record contents (in BIFF5: 2080 bytes, in BIFF8: 8224 bytes).
51 To start writing a record call StartRecord(). Parameters are the record identifier
52 and any calculated record size. This is for optimizing the write process: if the real
53 written data has the same size as the calculated, the stream will not seek back and
54 update the record size field. But it is not mandatory to calculate a size. Each
55 record must be closed by calling EndRecord(). This will check (and update) the record
58 If some data exceeds the record size limit, a CONTINUE record is started automatically
59 and the new data will be written to this record.
61 If specific data pieces must not be split, use SetSliceSize(). For instance:
62 To write a sequence of 16-bit values, where 4 values form a unit and cannot be
63 split, call SetSliceSize( 8 ) first (4*2 bytes == 8).
65 To write unicode character arrays, call WriteUnicodeBuffer(). It creates CONTINUE
66 records and repeats the unicode string flag byte automatically. This function is used
67 for instance from the class XclExpString which can write complete unicode strings.
72 /** Constructs the Excel record export stream.
73 @param rOutStrm The system output stream to write to.
74 @param nMaxRecSize The maximum allowed size of record content (depending on BIFF type).
75 If 0 is passed, the record size will be set automatically, depending on the current BIFF type. */
78 const XclExpRoot
& rRoot
,
79 sal_uInt16 nMaxRecSize
= 0 );
83 /** Returns the filter root data. */
84 const XclExpRoot
& GetRoot() const { return mrRoot
; }
86 /** Starts a new record: writes header data, stores calculated record size. */
87 void StartRecord( sal_uInt16 nRecId
, std::size_t nRecSize
);
88 /** Checks and corrects real record length. Must be called every time a record is finished. */
91 /** Returns the position inside of current record (starts by 0 in every CONTINUE). */
92 sal_uInt16
GetRawRecPos() const { return mnCurrSize
; }
94 /** Sets data slice length. 0 = no slices. */
95 void SetSliceSize( sal_uInt16 nSize
);
97 XclExpStream
& operator<<( sal_Int8 nValue
);
98 XclExpStream
& operator<<( sal_uInt8 nValue
);
99 XclExpStream
& operator<<( sal_Int16 nValue
);
100 XclExpStream
& operator<<( sal_uInt16 nValue
);
101 XclExpStream
& operator<<( sal_Int32 nValue
);
102 XclExpStream
& operator<<( sal_uInt32 nValue
);
103 XclExpStream
& operator<<( float fValue
);
104 XclExpStream
& operator<<( double fValue
);
106 /** Writes nBytes bytes from memory. */
107 std::size_t Write( const void* pData
, std::size_t nBytes
);
108 /** Writes a sequence of nBytes zero bytes (respects slice setting). */
109 void WriteZeroBytes( std::size_t nBytes
);
111 void WriteZeroBytesToRecord( std::size_t nBytes
);
113 /** Copies nBytes bytes from current position of the stream rInStrm.
114 @descr Omitting the second parameter means: read to end of stream. */
115 void CopyFromStream( SvStream
& rInStrm
, sal_uInt64 nBytes
= STREAM_SEEK_TO_END
);
117 // *** unicode string export is realized with helper class XclExpString ***
118 // (slice length setting has no effect here -> disabled automatically)
120 /** Writes Unicode buffer as 8/16 bit, repeats nFlags at start of a CONTINUE record. */
121 void WriteUnicodeBuffer( const ScfUInt16Vec
& rBuffer
, sal_uInt8 nFlags
);
123 // *** write 8-bit-strings ***
124 // (slice length setting has no effect here -> disabled automatically)
126 /** Writes string length field and OString buffer. */
127 void WriteByteString( const OString
& rString
);
129 /** Writes 8-bit character buffer. */
130 void WriteCharBuffer( const ScfUInt8Vec
& rBuffer
);
132 // *** SvStream access ***
134 /** Sets position of system stream (only allowed outside of records). */
135 void SetSvStreamPos(sal_uInt64 nPos
);
136 /** Returns the absolute position of the system stream. */
137 sal_uInt64
GetSvStreamPos() const { return mrStrm
.Tell(); }
139 void SetEncrypter( XclExpEncrypterRef
const & xEncrypter
);
141 bool HasValidEncrypter() const;
143 void EnableEncryption( bool bEnable
= true );
145 void DisableEncryption();
148 /** Writes header data, internal setup. */
149 void InitRecord( sal_uInt16 nRecId
);
150 /** Rewrites correct record length, if different from calculated. */
151 void UpdateRecSize();
152 /** Recalculates mnCurrSize and mnSliceSize. */
153 void UpdateSizeVars( std::size_t nSize
);
154 /** Writes CONTINUE header, internal setup. */
155 void StartContinue();
156 /** Refreshes counter vars, creates CONTINUE records. */
157 void PrepareWrite( sal_uInt16 nSize
);
158 /** Creates CONTINUE record at end of record.
159 @return Maximum data block size remaining. */
160 sal_uInt16
PrepareWrite();
162 /** Writes a raw sequence of zero bytes. */
163 void WriteRawZeroBytes( std::size_t nBytes
);
166 SvStream
& mrStrm
; /// Reference to the system output stream.
167 const XclExpRoot
& mrRoot
; /// Filter root data.
170 XclExpEncrypterRef mxEncrypter
;
173 sal_uInt16 mnMaxRecSize
; /// Maximum size of record content.
174 sal_uInt16 mnMaxContSize
; /// Maximum size of CONTINUE content.
175 sal_uInt16 mnCurrMaxSize
; /// Current maximum, either mnMaxRecSize or mnMaxContSize.
176 sal_uInt16 mnMaxSliceSize
; /// Maximum size of data slices (parts that cannot be split).
177 sal_uInt16 mnHeaderSize
; /// Record size written in last record header.
178 sal_uInt16 mnCurrSize
; /// Count of bytes already written in current record.
179 sal_uInt16 mnSliceSize
; /// Count of bytes already written in current slice.
180 std::size_t mnPredictSize
; /// Predicted size received from calling function.
182 // stream position data
183 std::size_t mnLastSizePos
; /// Stream position of size field in current header.
184 bool mbInRec
; /// true = currently writing inside of a record.
187 class XclExpBiff8Encrypter
190 explicit XclExpBiff8Encrypter( const XclExpRoot
& rRoot
);
191 ~XclExpBiff8Encrypter();
193 bool IsValid() const { return mbValid
; }
195 void GetSaltDigest( sal_uInt8 pnSaltDigest
[16] ) const;
196 void GetSalt( sal_uInt8 pnSalt
[16] ) const;
197 void GetDocId( sal_uInt8 pnDocId
[16] ) const;
199 void Encrypt( SvStream
& rStrm
, sal_uInt8 nData
);
200 void Encrypt( SvStream
& rStrm
, sal_uInt16 nData
);
201 void Encrypt( SvStream
& rStrm
, sal_uInt32 nData
);
203 void Encrypt( SvStream
& rStrm
, sal_Int8 nData
);
204 void Encrypt( SvStream
& rStrm
, sal_Int16 nData
);
205 void Encrypt( SvStream
& rStrm
, sal_Int32 nData
);
207 void Encrypt( SvStream
& rStrm
, float fValue
);
208 void Encrypt( SvStream
& rStrm
, double fValue
);
210 void EncryptBytes( SvStream
& rStrm
, ::std::vector
<sal_uInt8
>& aBytes
);
213 void Init( const css::uno::Sequence
< css::beans::NamedValue
>& aEncryptionData
);
215 static sal_uInt32
GetBlockPos( std::size_t nStrmPos
);
216 static sal_uInt16
GetOffsetInBlock( std::size_t nStrmPos
);
219 ::msfilter::MSCodec_Std97 maCodec
; /// Crypto algorithm implementation.
220 sal_uInt8 mpnDocId
[16];
221 sal_uInt8 mpnSalt
[16];
222 sal_uInt8 mpnSaltDigest
[16];
224 sal_uInt64 mnOldPos
; /// Last known stream position
228 // `s.GetChar(0) != 0` needed because some strings on export only contain NULL.
229 #define XESTRING_TO_PSZ(s) \
230 (s.Len() && s.GetChar( 0 ) != 0 ? XclXmlUtils::ToOString( s ).getStr() : nullptr)
241 namespace sc
{ class CompileFormulaContext
; }
246 XclXmlUtils() = delete;
247 ~XclXmlUtils() = delete;
248 XclXmlUtils(const XclXmlUtils
&) = delete;
249 XclXmlUtils
& operator=(const XclXmlUtils
&) = delete;
251 static void GetFormulaTypeAndValue( ScFormulaCell
& rCell
, const char*& sType
, OUString
& rValue
);
252 static OUString
GetStreamName( const char* sStreamDir
, const char* sStream
, sal_Int32 nId
);
254 static OString
ToOString( const Color
& rColor
);
255 static OString
ToOString( const ScfUInt16Vec
& rBuffer
);
256 static OStringBuffer
& ToOString( OStringBuffer
& s
, const ScAddress
& rRange
);
257 static OString
ToOString( const ScDocument
* pDoc
, const ScRange
& rRange
, bool bFullAddressNotation
= false );
258 static OString
ToOString( const ScDocument
* pDoc
, const ScRangeList
& rRangeList
);
259 static OStringBuffer
& ToOString( OStringBuffer
& s
, const XclAddress
& rAddress
);
260 static OString
ToOString( const XclExpString
& s
);
261 static OString
ToOString( const ScDocument
* pDoc
, const XclRangeList
& rRangeList
);
263 static OUString
ToOUString( const char* s
);
264 static OUString
ToOUString( const ScfUInt16Vec
& rBuffer
, sal_Int32 nStart
= 0, sal_Int32 nLength
= -1 );
265 static OUString
ToOUString( sc::CompileFormulaContext
& rCtx
, const ScAddress
& rAddress
, const ScTokenArray
* pTokenArray
);
266 static OUString
ToOUString( const XclExpString
& s
);
269 static sax_fastparser::FSHelperPtr
WriteElement(sax_fastparser::FSHelperPtr pStream
, sal_Int32 nElement
, const T
& value
)
271 pStream
->startElement(nElement
);
272 pStream
->write(value
);
273 pStream
->endElement(nElement
);
277 static sax_fastparser::FSHelperPtr
WriteFontData( sax_fastparser::FSHelperPtr pStream
, const XclFontData
& rFontData
, sal_Int32 nNameId
);
280 class XclExpXmlStream
: public oox::core::XmlFilterBase
283 XclExpXmlStream( const css::uno::Reference
< css::uno::XComponentContext
>& rCC
, bool bExportVBA
, bool bExportTemplate
);
284 virtual ~XclExpXmlStream() override
;
286 /** Returns the filter root data. */
287 const XclExpRoot
& GetRoot() const { return *mpRoot
; }
289 sax_fastparser::FSHelperPtr
& GetCurrentStream();
290 void PushStream( sax_fastparser::FSHelperPtr
const & aStream
);
293 sax_fastparser::FSHelperPtr
GetStreamForPath( const OUString
& rPath
);
295 template <typename Str
, typename
... Args
>
296 void WriteAttributes(sal_Int32 nAttribute
, Str
&& value
, Args
&&... rest
)
298 WriteAttribute(nAttribute
, std::forward
<Str
>(value
));
299 if constexpr(sizeof...(rest
) > 0)
301 // coverity[stray_semicolon : FALSE] - coverity parse error
302 WriteAttributes(std::forward
<Args
>(rest
)...);
306 sax_fastparser::FSHelperPtr
CreateOutputStream (
307 const OUString
& sFullStream
,
308 const OUString
& sRelativeStream
,
309 const css::uno::Reference
< css::io::XOutputStream
>& xParentRelation
,
310 const char* sContentType
,
311 const char* sRelationshipType
,
312 OUString
* pRelationshipId
= nullptr );
315 virtual bool exportDocument() override
;
317 // only needed for import; ignore
318 virtual bool importDocument() throw() override
;
319 virtual oox::vml::Drawing
* getVmlDrawing() override
;
320 virtual const oox::drawingml::Theme
* getCurrentTheme() const override
;
321 virtual oox::drawingml::table::TableStyleListPtr
getTableStyles() override
;
322 virtual oox::drawingml::chart::ChartConverter
* getChartConverter() override
;
325 virtual ::oox::ole::VbaProject
* implCreateVbaProject() const override
;
326 virtual OUString SAL_CALL
getImplementationName() override
;
327 ScDocShell
*getDocShell();
328 void WriteAttribute(sal_Int32 nAttr
, const OUString
& sVal
);
329 void WriteAttribute(sal_Int32 nAttr
, const OString
& sVal
)
331 WriteAttribute(nAttr
, OStringToOUString(sVal
, RTL_TEXTENCODING_UTF8
));
333 void WriteAttribute(sal_Int32 nAttr
, const char* sVal
)
336 WriteAttribute(nAttr
, OUString(sVal
, strlen(sVal
), RTL_TEXTENCODING_UTF8
));
339 typedef std::map
< OUString
,
341 sax_fastparser::FSHelperPtr
> > XclExpXmlPathToStateMap
;
343 const XclExpRoot
* mpRoot
;
344 std::stack
< sax_fastparser::FSHelperPtr
> maStreams
;
345 XclExpXmlPathToStateMap maOpenedStreamMap
;
347 bool const mbExportVBA
;
348 bool const mbExportTemplate
;
353 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */