summaryrefslogtreecommitdiffstats
path: root/sc/source/filter/inc/xestream.hxx
diff options
context:
space:
mode:
Diffstat (limited to 'sc/source/filter/inc/xestream.hxx')
-rw-r--r--sc/source/filter/inc/xestream.hxx359
1 files changed, 359 insertions, 0 deletions
diff --git a/sc/source/filter/inc/xestream.hxx b/sc/source/filter/inc/xestream.hxx
new file mode 100644
index 000000000..669dadaec
--- /dev/null
+++ b/sc/source/filter/inc/xestream.hxx
@@ -0,0 +1,359 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <map>
+#include <stack>
+#include <string_view>
+
+#include <rtl/strbuf.hxx>
+
+#include <oox/core/xmlfilterbase.hxx>
+#include <sax/fshelper.hxx>
+#include <tools/stream.hxx>
+#include <formula/errorcodes.hxx>
+#include "ftools.hxx"
+#include <types.hxx>
+
+#include <filter/msfilter/mscodec.hxx>
+#include <vector>
+
+namespace com::sun::star::beans { struct NamedValue; }
+
+/* ============================================================================
+Output stream class for Excel export
+- CONTINUE record handling
+============================================================================ */
+
+class XclExpString;
+class XclExpRoot;
+class XclExpBiff8Encrypter;
+typedef std::shared_ptr< XclExpBiff8Encrypter > XclExpEncrypterRef;
+
+/** This class is used to export Excel record streams.
+ @descr An instance is constructed with an SvStream and the maximum size of Excel
+ record contents (in BIFF5: 2080 bytes, in BIFF8: 8224 bytes).
+
+ To start writing a record call StartRecord(). Parameters are the record identifier
+ and any calculated record size. This is for optimizing the write process: if the real
+ written data has the same size as the calculated, the stream will not seek back and
+ update the record size field. But it is not mandatory to calculate a size. Each
+ record must be closed by calling EndRecord(). This will check (and update) the record
+ size field.
+
+ If some data exceeds the record size limit, a CONTINUE record is started automatically
+ and the new data will be written to this record.
+
+ If specific data pieces must not be split, use SetSliceSize(). For instance:
+ To write a sequence of 16-bit values, where 4 values form a unit and cannot be
+ split, call SetSliceSize( 8 ) first (4*2 bytes == 8).
+
+ To write unicode character arrays, call WriteUnicodeBuffer(). It creates CONTINUE
+ records and repeats the unicode string flag byte automatically. This function is used
+ for instance from the class XclExpString which can write complete unicode strings.
+*/
+class XclExpStream
+{
+public:
+ /** Constructs the Excel record export stream.
+ @param rOutStrm The system output stream to write to.
+ @param nMaxRecSize The maximum allowed size of record content (depending on BIFF type).
+ If 0 is passed, the record size will be set automatically, depending on the current BIFF type. */
+ XclExpStream(
+ SvStream& rOutStrm,
+ const XclExpRoot& rRoot,
+ sal_uInt16 nMaxRecSize = 0 );
+
+ ~XclExpStream();
+
+ /** Returns the filter root data. */
+ const XclExpRoot& GetRoot() const { return mrRoot; }
+
+ /** Starts a new record: writes header data, stores calculated record size. */
+ void StartRecord( sal_uInt16 nRecId, std::size_t nRecSize );
+ /** Checks and corrects real record length. Must be called every time a record is finished. */
+ void EndRecord();
+
+ /** Returns the position inside of current record (starts by 0 in every CONTINUE). */
+ sal_uInt16 GetRawRecPos() const { return mnCurrSize; }
+
+ /** Sets data slice length. 0 = no slices. */
+ void SetSliceSize( sal_uInt16 nSize );
+
+ XclExpStream& operator<<( sal_Int8 nValue );
+ XclExpStream& operator<<( sal_uInt8 nValue );
+ XclExpStream& operator<<( sal_Int16 nValue );
+ XclExpStream& operator<<( sal_uInt16 nValue );
+ XclExpStream& operator<<( sal_Int32 nValue );
+ XclExpStream& operator<<( sal_uInt32 nValue );
+ XclExpStream& operator<<( float fValue );
+ XclExpStream& operator<<( double fValue );
+
+ /** Writes nBytes bytes from memory. */
+ std::size_t Write( const void* pData, std::size_t nBytes );
+ /** Writes a sequence of nBytes zero bytes (respects slice setting). */
+ void WriteZeroBytes( std::size_t nBytes );
+
+ void WriteZeroBytesToRecord( std::size_t nBytes );
+
+ /** Copies nBytes bytes from current position of the stream rInStrm.
+ @descr Omitting the second parameter means: read to end of stream. */
+ void CopyFromStream( SvStream& rInStrm, sal_uInt64 nBytes = STREAM_SEEK_TO_END );
+
+ // *** unicode string export is realized with helper class XclExpString ***
+ // (slice length setting has no effect here -> disabled automatically)
+
+ /** Writes Unicode buffer as 8/16 bit, repeats nFlags at start of a CONTINUE record. */
+ void WriteUnicodeBuffer( const ScfUInt16Vec& rBuffer, sal_uInt8 nFlags );
+
+ // *** write 8-bit-strings ***
+ // (slice length setting has no effect here -> disabled automatically)
+
+ /** Writes string length field and OString buffer. */
+ void WriteByteString( const OString& rString );
+
+ /** Writes 8-bit character buffer. */
+ void WriteCharBuffer( const ScfUInt8Vec& rBuffer );
+
+ // *** SvStream access ***
+
+ /** Sets position of system stream (only allowed outside of records). */
+ void SetSvStreamPos(sal_uInt64 nPos);
+ /** Returns the absolute position of the system stream. */
+ sal_uInt64 GetSvStreamPos() const { return mrStrm.Tell(); }
+
+ void SetEncrypter( XclExpEncrypterRef const & xEncrypter );
+
+ bool HasValidEncrypter() const;
+
+ void EnableEncryption( bool bEnable = true );
+
+ void DisableEncryption();
+
+private:
+ /** Writes header data, internal setup. */
+ void InitRecord( sal_uInt16 nRecId );
+ /** Rewrites correct record length, if different from calculated. */
+ void UpdateRecSize();
+ /** Recalculates mnCurrSize and mnSliceSize. */
+ void UpdateSizeVars( std::size_t nSize );
+ /** Writes CONTINUE header, internal setup. */
+ void StartContinue();
+ /** Refreshes counter vars, creates CONTINUE records. */
+ void PrepareWrite( sal_uInt16 nSize );
+ /** Creates CONTINUE record at end of record.
+ @return Maximum data block size remaining. */
+ sal_uInt16 PrepareWrite();
+
+ /** Writes a raw sequence of zero bytes. */
+ void WriteRawZeroBytes( std::size_t nBytes );
+
+private:
+ SvStream& mrStrm; /// Reference to the system output stream.
+ const XclExpRoot& mrRoot; /// Filter root data.
+
+ bool mbUseEncrypter;
+ XclExpEncrypterRef mxEncrypter;
+
+ // length data
+ sal_uInt16 mnMaxRecSize; /// Maximum size of record content.
+ sal_uInt16 mnMaxContSize; /// Maximum size of CONTINUE content.
+ sal_uInt16 mnCurrMaxSize; /// Current maximum, either mnMaxRecSize or mnMaxContSize.
+ sal_uInt16 mnMaxSliceSize; /// Maximum size of data slices (parts that cannot be split).
+ sal_uInt16 mnHeaderSize; /// Record size written in last record header.
+ sal_uInt16 mnCurrSize; /// Count of bytes already written in current record.
+ sal_uInt16 mnSliceSize; /// Count of bytes already written in current slice.
+ std::size_t mnPredictSize; /// Predicted size received from calling function.
+
+ // stream position data
+ std::size_t mnLastSizePos; /// Stream position of size field in current header.
+ bool mbInRec; /// true = currently writing inside of a record.
+};
+
+class XclExpBiff8Encrypter
+{
+public:
+ explicit XclExpBiff8Encrypter( const XclExpRoot& rRoot );
+ ~XclExpBiff8Encrypter();
+
+ bool IsValid() const { return mbValid; }
+
+ void GetSaltDigest( sal_uInt8 pnSaltDigest[16] ) const;
+ void GetSalt( sal_uInt8 pnSalt[16] ) const;
+ void GetDocId( sal_uInt8 pnDocId[16] ) const;
+
+ void Encrypt( SvStream& rStrm, sal_uInt8 nData );
+ void Encrypt( SvStream& rStrm, sal_uInt16 nData );
+ void Encrypt( SvStream& rStrm, sal_uInt32 nData );
+
+ void Encrypt( SvStream& rStrm, sal_Int8 nData );
+ void Encrypt( SvStream& rStrm, sal_Int16 nData );
+ void Encrypt( SvStream& rStrm, sal_Int32 nData );
+
+ void Encrypt( SvStream& rStrm, float fValue );
+ void Encrypt( SvStream& rStrm, double fValue );
+
+ void EncryptBytes( SvStream& rStrm, ::std::vector<sal_uInt8>& aBytes );
+
+private:
+ void Init( const css::uno::Sequence< css::beans::NamedValue >& aEncryptionData );
+
+ static sal_uInt32 GetBlockPos( std::size_t nStrmPos );
+ static sal_uInt16 GetOffsetInBlock( std::size_t nStrmPos );
+
+private:
+ ::msfilter::MSCodec_Std97 maCodec; /// Crypto algorithm implementation.
+ sal_uInt8 mpnDocId[16];
+ sal_uInt8 mpnSalt[16];
+ sal_uInt8 mpnSaltDigest[16];
+
+ sal_uInt64 mnOldPos; /// Last known stream position
+ bool mbValid;
+};
+
+// `s.GetChar(0) != 0` needed because some strings on export only contain NULL.
+#define XESTRING_TO_PSZ(s) \
+ (s.Len() && s.GetChar( 0 ) != 0 ? XclXmlUtils::ToOString( s ).getStr() : nullptr)
+
+class ScAddress;
+class ScDocShell;
+class ScFormulaCell;
+class ScRange;
+class ScRangeList;
+class ScTokenArray;
+struct XclAddress;
+struct XclFontData;
+class XclRangeList;
+namespace sc { class CompileFormulaContext; }
+
+class XclXmlUtils
+{
+public:
+ XclXmlUtils() = delete;
+ ~XclXmlUtils() = delete;
+ XclXmlUtils(const XclXmlUtils&) = delete;
+ XclXmlUtils& operator=(const XclXmlUtils&) = delete;
+
+ static void GetFormulaTypeAndValue( ScFormulaCell& rCell, const char*& sType, OUString& rValue);
+ static OUString GetStreamName( const char* sStreamDir, const char* sStream, sal_Int32 nId );
+
+ static OString ToOString( const Color& rColor );
+ static OString ToOString( const ScfUInt16Vec& rBuffer );
+ static OStringBuffer& ToOString( OStringBuffer& s, const ScAddress& rRange );
+ static OString ToOString( const ScDocument& rDoc, const ScRange& rRange, bool bFullAddressNotation = false );
+ static OString ToOString( const ScDocument& rDoc, const ScRangeList& rRangeList );
+ static OStringBuffer& ToOString( OStringBuffer& s, const XclAddress& rAddress );
+ static OString ToOString( const XclExpString& s );
+ static OString ToOString( const ScDocument& rDoc, const XclRangeList& rRangeList );
+
+ static OUString ToOUString( const char* s );
+ static OUString ToOUString( const ScfUInt16Vec& rBuffer, sal_Int32 nStart = 0, sal_Int32 nLength = -1 );
+ static OUString ToOUString( sc::CompileFormulaContext& rCtx, const ScAddress& rAddress,
+ const ScTokenArray* pTokenArray, FormulaError nErrCode = FormulaError::NONE );
+ static OUString ToOUString( const XclExpString& s );
+
+ template <class T>
+ static sax_fastparser::FSHelperPtr WriteElement(sax_fastparser::FSHelperPtr pStream, sal_Int32 nElement, const T& value)
+ {
+ pStream->startElement(nElement);
+ pStream->write(value);
+ pStream->endElement(nElement);
+
+ return pStream;
+ }
+ static sax_fastparser::FSHelperPtr WriteFontData( sax_fastparser::FSHelperPtr pStream, const XclFontData& rFontData, sal_Int32 nNameId );
+};
+
+class XclExpXmlStream : public oox::core::XmlFilterBase
+{
+public:
+ XclExpXmlStream( const css::uno::Reference< css::uno::XComponentContext >& rCC, bool bExportVBA, bool bExportTemplate );
+ virtual ~XclExpXmlStream() override;
+
+ /** Returns the filter root data. */
+ const XclExpRoot& GetRoot() const { return *mpRoot; }
+
+ sax_fastparser::FSHelperPtr& GetCurrentStream();
+ void PushStream( sax_fastparser::FSHelperPtr const & aStream );
+ void PopStream();
+
+ sax_fastparser::FSHelperPtr GetStreamForPath( const OUString& rPath );
+
+ template <typename Str, typename... Args>
+ void WriteAttributes(sal_Int32 nAttribute, Str&& value, Args&&... rest)
+ {
+ WriteAttribute(nAttribute, std::forward<Str>(value));
+ if constexpr(sizeof...(rest) > 0)
+ {
+ // coverity[stray_semicolon : FALSE] - coverity parse error
+ WriteAttributes(std::forward<Args>(rest)...);
+ }
+ }
+
+ sax_fastparser::FSHelperPtr CreateOutputStream (
+ const OUString& sFullStream,
+ std::u16string_view sRelativeStream,
+ const css::uno::Reference< css::io::XOutputStream >& xParentRelation,
+ const char* sContentType,
+ std::u16string_view sRelationshipType,
+ OUString* pRelationshipId = nullptr );
+
+ // ignore
+ virtual bool exportDocument() override;
+
+ // only needed for import; ignore
+ virtual bool importDocument() noexcept override;
+ virtual oox::vml::Drawing* getVmlDrawing() override;
+ virtual const oox::drawingml::Theme* getCurrentTheme() const override;
+ virtual oox::drawingml::table::TableStyleListPtr getTableStyles() override;
+ virtual oox::drawingml::chart::ChartConverter* getChartConverter() override;
+
+private:
+ virtual ::oox::ole::VbaProject* implCreateVbaProject() const override;
+ virtual OUString SAL_CALL getImplementationName() override;
+ ScDocShell *getDocShell();
+ void WriteAttribute(sal_Int32 nAttr, std::u16string_view sVal);
+ void WriteAttribute(sal_Int32 nAttr, std::string_view sVal)
+ {
+ WriteAttribute(nAttr, OStringToOUString(sVal, RTL_TEXTENCODING_UTF8));
+ }
+ void WriteAttribute(sal_Int32 nAttr, const char* sVal)
+ {
+ if (sVal)
+ WriteAttribute(nAttr, OUString(sVal, strlen(sVal), RTL_TEXTENCODING_UTF8));
+ }
+
+ void validateTabNames(std::vector<OUString>& aOriginalTabNames);
+ void restoreTabNames(const std::vector<OUString>& aOriginalTabNames);
+ void renameTab(SCTAB aTab, OUString aNewName);
+
+ typedef std::map< OUString,
+ std::pair< OUString,
+ sax_fastparser::FSHelperPtr > > XclExpXmlPathToStateMap;
+
+ const XclExpRoot* mpRoot;
+ std::stack< sax_fastparser::FSHelperPtr > maStreams;
+ XclExpXmlPathToStateMap maOpenedStreamMap;
+
+ bool mbExportVBA;
+ bool mbExportTemplate;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */