Version 7.5.1.1, tag libreoffice-7.5.1.1
[LibreOffice.git] / sc / source / filter / inc / xestream.hxx
blob669dadaec0148c102d0f598c39737e31f477b8fa
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 #pragma once
22 #include <map>
23 #include <stack>
24 #include <string_view>
26 #include <rtl/strbuf.hxx>
28 #include <oox/core/xmlfilterbase.hxx>
29 #include <sax/fshelper.hxx>
30 #include <tools/stream.hxx>
31 #include <formula/errorcodes.hxx>
32 #include "ftools.hxx"
33 #include <types.hxx>
35 #include <filter/msfilter/mscodec.hxx>
36 #include <vector>
38 namespace com::sun::star::beans { struct NamedValue; }
40 /* ============================================================================
41 Output stream class for Excel export
42 - CONTINUE record handling
43 ============================================================================ */
45 class XclExpString;
46 class XclExpRoot;
47 class XclExpBiff8Encrypter;
48 typedef std::shared_ptr< XclExpBiff8Encrypter > XclExpEncrypterRef;
50 /** This class is used to export Excel record streams.
51 @descr An instance is constructed with an SvStream and the maximum size of Excel
52 record contents (in BIFF5: 2080 bytes, in BIFF8: 8224 bytes).
54 To start writing a record call StartRecord(). Parameters are the record identifier
55 and any calculated record size. This is for optimizing the write process: if the real
56 written data has the same size as the calculated, the stream will not seek back and
57 update the record size field. But it is not mandatory to calculate a size. Each
58 record must be closed by calling EndRecord(). This will check (and update) the record
59 size field.
61 If some data exceeds the record size limit, a CONTINUE record is started automatically
62 and the new data will be written to this record.
64 If specific data pieces must not be split, use SetSliceSize(). For instance:
65 To write a sequence of 16-bit values, where 4 values form a unit and cannot be
66 split, call SetSliceSize( 8 ) first (4*2 bytes == 8).
68 To write unicode character arrays, call WriteUnicodeBuffer(). It creates CONTINUE
69 records and repeats the unicode string flag byte automatically. This function is used
70 for instance from the class XclExpString which can write complete unicode strings.
72 class XclExpStream
74 public:
75 /** Constructs the Excel record export stream.
76 @param rOutStrm The system output stream to write to.
77 @param nMaxRecSize The maximum allowed size of record content (depending on BIFF type).
78 If 0 is passed, the record size will be set automatically, depending on the current BIFF type. */
79 XclExpStream(
80 SvStream& rOutStrm,
81 const XclExpRoot& rRoot,
82 sal_uInt16 nMaxRecSize = 0 );
84 ~XclExpStream();
86 /** Returns the filter root data. */
87 const XclExpRoot& GetRoot() const { return mrRoot; }
89 /** Starts a new record: writes header data, stores calculated record size. */
90 void StartRecord( sal_uInt16 nRecId, std::size_t nRecSize );
91 /** Checks and corrects real record length. Must be called every time a record is finished. */
92 void EndRecord();
94 /** Returns the position inside of current record (starts by 0 in every CONTINUE). */
95 sal_uInt16 GetRawRecPos() const { return mnCurrSize; }
97 /** Sets data slice length. 0 = no slices. */
98 void SetSliceSize( sal_uInt16 nSize );
100 XclExpStream& operator<<( sal_Int8 nValue );
101 XclExpStream& operator<<( sal_uInt8 nValue );
102 XclExpStream& operator<<( sal_Int16 nValue );
103 XclExpStream& operator<<( sal_uInt16 nValue );
104 XclExpStream& operator<<( sal_Int32 nValue );
105 XclExpStream& operator<<( sal_uInt32 nValue );
106 XclExpStream& operator<<( float fValue );
107 XclExpStream& operator<<( double fValue );
109 /** Writes nBytes bytes from memory. */
110 std::size_t Write( const void* pData, std::size_t nBytes );
111 /** Writes a sequence of nBytes zero bytes (respects slice setting). */
112 void WriteZeroBytes( std::size_t nBytes );
114 void WriteZeroBytesToRecord( std::size_t nBytes );
116 /** Copies nBytes bytes from current position of the stream rInStrm.
117 @descr Omitting the second parameter means: read to end of stream. */
118 void CopyFromStream( SvStream& rInStrm, sal_uInt64 nBytes = STREAM_SEEK_TO_END );
120 // *** unicode string export is realized with helper class XclExpString ***
121 // (slice length setting has no effect here -> disabled automatically)
123 /** Writes Unicode buffer as 8/16 bit, repeats nFlags at start of a CONTINUE record. */
124 void WriteUnicodeBuffer( const ScfUInt16Vec& rBuffer, sal_uInt8 nFlags );
126 // *** write 8-bit-strings ***
127 // (slice length setting has no effect here -> disabled automatically)
129 /** Writes string length field and OString buffer. */
130 void WriteByteString( const OString& rString );
132 /** Writes 8-bit character buffer. */
133 void WriteCharBuffer( const ScfUInt8Vec& rBuffer );
135 // *** SvStream access ***
137 /** Sets position of system stream (only allowed outside of records). */
138 void SetSvStreamPos(sal_uInt64 nPos);
139 /** Returns the absolute position of the system stream. */
140 sal_uInt64 GetSvStreamPos() const { return mrStrm.Tell(); }
142 void SetEncrypter( XclExpEncrypterRef const & xEncrypter );
144 bool HasValidEncrypter() const;
146 void EnableEncryption( bool bEnable = true );
148 void DisableEncryption();
150 private:
151 /** Writes header data, internal setup. */
152 void InitRecord( sal_uInt16 nRecId );
153 /** Rewrites correct record length, if different from calculated. */
154 void UpdateRecSize();
155 /** Recalculates mnCurrSize and mnSliceSize. */
156 void UpdateSizeVars( std::size_t nSize );
157 /** Writes CONTINUE header, internal setup. */
158 void StartContinue();
159 /** Refreshes counter vars, creates CONTINUE records. */
160 void PrepareWrite( sal_uInt16 nSize );
161 /** Creates CONTINUE record at end of record.
162 @return Maximum data block size remaining. */
163 sal_uInt16 PrepareWrite();
165 /** Writes a raw sequence of zero bytes. */
166 void WriteRawZeroBytes( std::size_t nBytes );
168 private:
169 SvStream& mrStrm; /// Reference to the system output stream.
170 const XclExpRoot& mrRoot; /// Filter root data.
172 bool mbUseEncrypter;
173 XclExpEncrypterRef mxEncrypter;
175 // length data
176 sal_uInt16 mnMaxRecSize; /// Maximum size of record content.
177 sal_uInt16 mnMaxContSize; /// Maximum size of CONTINUE content.
178 sal_uInt16 mnCurrMaxSize; /// Current maximum, either mnMaxRecSize or mnMaxContSize.
179 sal_uInt16 mnMaxSliceSize; /// Maximum size of data slices (parts that cannot be split).
180 sal_uInt16 mnHeaderSize; /// Record size written in last record header.
181 sal_uInt16 mnCurrSize; /// Count of bytes already written in current record.
182 sal_uInt16 mnSliceSize; /// Count of bytes already written in current slice.
183 std::size_t mnPredictSize; /// Predicted size received from calling function.
185 // stream position data
186 std::size_t mnLastSizePos; /// Stream position of size field in current header.
187 bool mbInRec; /// true = currently writing inside of a record.
190 class XclExpBiff8Encrypter
192 public:
193 explicit XclExpBiff8Encrypter( const XclExpRoot& rRoot );
194 ~XclExpBiff8Encrypter();
196 bool IsValid() const { return mbValid; }
198 void GetSaltDigest( sal_uInt8 pnSaltDigest[16] ) const;
199 void GetSalt( sal_uInt8 pnSalt[16] ) const;
200 void GetDocId( sal_uInt8 pnDocId[16] ) const;
202 void Encrypt( SvStream& rStrm, sal_uInt8 nData );
203 void Encrypt( SvStream& rStrm, sal_uInt16 nData );
204 void Encrypt( SvStream& rStrm, sal_uInt32 nData );
206 void Encrypt( SvStream& rStrm, sal_Int8 nData );
207 void Encrypt( SvStream& rStrm, sal_Int16 nData );
208 void Encrypt( SvStream& rStrm, sal_Int32 nData );
210 void Encrypt( SvStream& rStrm, float fValue );
211 void Encrypt( SvStream& rStrm, double fValue );
213 void EncryptBytes( SvStream& rStrm, ::std::vector<sal_uInt8>& aBytes );
215 private:
216 void Init( const css::uno::Sequence< css::beans::NamedValue >& aEncryptionData );
218 static sal_uInt32 GetBlockPos( std::size_t nStrmPos );
219 static sal_uInt16 GetOffsetInBlock( std::size_t nStrmPos );
221 private:
222 ::msfilter::MSCodec_Std97 maCodec; /// Crypto algorithm implementation.
223 sal_uInt8 mpnDocId[16];
224 sal_uInt8 mpnSalt[16];
225 sal_uInt8 mpnSaltDigest[16];
227 sal_uInt64 mnOldPos; /// Last known stream position
228 bool mbValid;
231 // `s.GetChar(0) != 0` needed because some strings on export only contain NULL.
232 #define XESTRING_TO_PSZ(s) \
233 (s.Len() && s.GetChar( 0 ) != 0 ? XclXmlUtils::ToOString( s ).getStr() : nullptr)
235 class ScAddress;
236 class ScDocShell;
237 class ScFormulaCell;
238 class ScRange;
239 class ScRangeList;
240 class ScTokenArray;
241 struct XclAddress;
242 struct XclFontData;
243 class XclRangeList;
244 namespace sc { class CompileFormulaContext; }
246 class XclXmlUtils
248 public:
249 XclXmlUtils() = delete;
250 ~XclXmlUtils() = delete;
251 XclXmlUtils(const XclXmlUtils&) = delete;
252 XclXmlUtils& operator=(const XclXmlUtils&) = delete;
254 static void GetFormulaTypeAndValue( ScFormulaCell& rCell, const char*& sType, OUString& rValue);
255 static OUString GetStreamName( const char* sStreamDir, const char* sStream, sal_Int32 nId );
257 static OString ToOString( const Color& rColor );
258 static OString ToOString( const ScfUInt16Vec& rBuffer );
259 static OStringBuffer& ToOString( OStringBuffer& s, const ScAddress& rRange );
260 static OString ToOString( const ScDocument& rDoc, const ScRange& rRange, bool bFullAddressNotation = false );
261 static OString ToOString( const ScDocument& rDoc, const ScRangeList& rRangeList );
262 static OStringBuffer& ToOString( OStringBuffer& s, const XclAddress& rAddress );
263 static OString ToOString( const XclExpString& s );
264 static OString ToOString( const ScDocument& rDoc, const XclRangeList& rRangeList );
266 static OUString ToOUString( const char* s );
267 static OUString ToOUString( const ScfUInt16Vec& rBuffer, sal_Int32 nStart = 0, sal_Int32 nLength = -1 );
268 static OUString ToOUString( sc::CompileFormulaContext& rCtx, const ScAddress& rAddress,
269 const ScTokenArray* pTokenArray, FormulaError nErrCode = FormulaError::NONE );
270 static OUString ToOUString( const XclExpString& s );
272 template <class T>
273 static sax_fastparser::FSHelperPtr WriteElement(sax_fastparser::FSHelperPtr pStream, sal_Int32 nElement, const T& value)
275 pStream->startElement(nElement);
276 pStream->write(value);
277 pStream->endElement(nElement);
279 return pStream;
281 static sax_fastparser::FSHelperPtr WriteFontData( sax_fastparser::FSHelperPtr pStream, const XclFontData& rFontData, sal_Int32 nNameId );
284 class XclExpXmlStream : public oox::core::XmlFilterBase
286 public:
287 XclExpXmlStream( const css::uno::Reference< css::uno::XComponentContext >& rCC, bool bExportVBA, bool bExportTemplate );
288 virtual ~XclExpXmlStream() override;
290 /** Returns the filter root data. */
291 const XclExpRoot& GetRoot() const { return *mpRoot; }
293 sax_fastparser::FSHelperPtr& GetCurrentStream();
294 void PushStream( sax_fastparser::FSHelperPtr const & aStream );
295 void PopStream();
297 sax_fastparser::FSHelperPtr GetStreamForPath( const OUString& rPath );
299 template <typename Str, typename... Args>
300 void WriteAttributes(sal_Int32 nAttribute, Str&& value, Args&&... rest)
302 WriteAttribute(nAttribute, std::forward<Str>(value));
303 if constexpr(sizeof...(rest) > 0)
305 // coverity[stray_semicolon : FALSE] - coverity parse error
306 WriteAttributes(std::forward<Args>(rest)...);
310 sax_fastparser::FSHelperPtr CreateOutputStream (
311 const OUString& sFullStream,
312 std::u16string_view sRelativeStream,
313 const css::uno::Reference< css::io::XOutputStream >& xParentRelation,
314 const char* sContentType,
315 std::u16string_view sRelationshipType,
316 OUString* pRelationshipId = nullptr );
318 // ignore
319 virtual bool exportDocument() override;
321 // only needed for import; ignore
322 virtual bool importDocument() noexcept override;
323 virtual oox::vml::Drawing* getVmlDrawing() override;
324 virtual const oox::drawingml::Theme* getCurrentTheme() const override;
325 virtual oox::drawingml::table::TableStyleListPtr getTableStyles() override;
326 virtual oox::drawingml::chart::ChartConverter* getChartConverter() override;
328 private:
329 virtual ::oox::ole::VbaProject* implCreateVbaProject() const override;
330 virtual OUString SAL_CALL getImplementationName() override;
331 ScDocShell *getDocShell();
332 void WriteAttribute(sal_Int32 nAttr, std::u16string_view sVal);
333 void WriteAttribute(sal_Int32 nAttr, std::string_view sVal)
335 WriteAttribute(nAttr, OStringToOUString(sVal, RTL_TEXTENCODING_UTF8));
337 void WriteAttribute(sal_Int32 nAttr, const char* sVal)
339 if (sVal)
340 WriteAttribute(nAttr, OUString(sVal, strlen(sVal), RTL_TEXTENCODING_UTF8));
343 void validateTabNames(std::vector<OUString>& aOriginalTabNames);
344 void restoreTabNames(const std::vector<OUString>& aOriginalTabNames);
345 void renameTab(SCTAB aTab, OUString aNewName);
347 typedef std::map< OUString,
348 std::pair< OUString,
349 sax_fastparser::FSHelperPtr > > XclExpXmlPathToStateMap;
351 const XclExpRoot* mpRoot;
352 std::stack< sax_fastparser::FSHelperPtr > maStreams;
353 XclExpXmlPathToStateMap maOpenedStreamMap;
355 bool mbExportVBA;
356 bool mbExportTemplate;
359 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */