xref: /trunk/main/sc/source/filter/inc/xestream.hxx (revision 86e1cf34)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // ============================================================================
25 
26 #ifndef SC_XESTREAM_HXX
27 #define SC_XESTREAM_HXX
28 
29 #include <com/sun/star/beans/NamedValue.hpp>
30 
31 #include <map>
32 #include <stack>
33 #include <string>
34 
35 #include <oox/core/xmlfilterbase.hxx>
36 #include <oox/token/tokens.hxx>
37 #include <sax/fshelper.hxx>
38 
39 #include "xlstream.hxx"
40 #include "xestring.hxx"
41 
42 #include <filter/msfilter/mscodec.hxx>
43 #include <vector>
44 
45 /* ============================================================================
46 Output stream class for Excel export
47 - CONTINUE record handling
48 - ByteString and UniString support
49 ============================================================================ */
50 
51 class XclExpRoot;
52 class XclExpBiff8Encrypter;
53 typedef ScfRef< XclExpBiff8Encrypter > XclExpEncrypterRef;
54 
55 /** This class is used to export Excel record streams.
56     @descr  An instance is constructed with an SvStream and the maximum size of Excel
57     record contents (in BIFF5: 2080 bytes, in BIFF8: 8224 bytes).
58 
59     To start writing a record call StartRecord(). Parameters are the record identifier
60     and any calculated record size. This is for optimizing the write process: if the real
61     written data has the same size as the calculated, the stream will not seek back and
62     update the record size field. But it is not mandatory to calculate a size. Each
63     record must be closed by calling EndRecord(). This will check (and update) the record
64     size field.
65 
66     If some data exceeds the record size limit, a CONTINUE record is started automatically
67     and the new data will be written to this record.
68 
69     If specific data pieces must not be splitted, use SetSliceLen(). For instance:
70     To write a sequence of 16-bit values, where 4 values form a unit and cannot be
71     split, call SetSliceLen( 8 ) first (4*2 bytes == 8).
72 
73     To write unicode character arrays, call WriteUnicodeBuffer(). It creates CONTINUE
74     records and repeats the unicode string flag byte automatically. This function is used
75     for instance from the class XclExpString which can write complete unicode strings.
76 */
77 class XclExpStream
78 {
79 public:
80     /** Constructs the Excel record export stream.
81         @param rOutStrm  The system output stream to write to.
82         @param nMaxRecSize  The maximum allowed size of record content (depending on BIFF type).
83         If 0 is passed, the record size will be set automatically, depending on the current BIFF type. */
84                         XclExpStream(
85                             SvStream& rOutStrm,
86                             const XclExpRoot& rRoot,
87                             sal_uInt16 nMaxRecSize = 0 );
88 
89                         ~XclExpStream();
90 
91     /** Returns the filter root data. */
GetRoot() const92     inline const XclExpRoot& GetRoot() const { return mrRoot; }
93 
94     /** Starts a new record: writes header data, stores calculated record size. */
95     void                StartRecord( sal_uInt16 nRecId, sal_Size nRecSize );
96     /** Checks and corrects real record length. Must be called every time a record is finished. */
97     void                EndRecord();
98 
99     /** Returns the position inside of current record (starts by 0 in every CONTINUE). */
GetRawRecPos() const100     inline sal_uInt16   GetRawRecPos() const { return mnCurrSize; }
101 
102     /** Returns the maximum size of a record. */
GetMaxRecSize() const103     inline sal_uInt16   GetMaxRecSize() const { return mnMaxRecSize; }
104     /** Sets maximum record size (valid only for current record). */
SetMaxRecSize(sal_uInt16 nMax)105     inline void         SetMaxRecSize( sal_uInt16 nMax ) { mnCurrMaxSize = nMax; }
106     /** Sets maximum size of CONTINUE records (valid only for current record). */
SetMaxContSize(sal_uInt16 nMax)107     inline void         SetMaxContSize( sal_uInt16 nMax ) { mnMaxContSize = nMax; }
108 
109     /** Sets data slice length. 0 = no slices. */
110     void                SetSliceSize( sal_uInt16 nSize );
111 
112     XclExpStream& operator<<( sal_Int8 nValue );
113     XclExpStream& operator<<( sal_uInt8 nValue );
114     XclExpStream& operator<<( sal_Int16 nValue );
115     XclExpStream& operator<<( sal_uInt16 nValue );
116     XclExpStream& operator<<( sal_Int32 nValue );
117     XclExpStream& operator<<( sal_uInt32 nValue );
118     XclExpStream& operator<<( float fValue );
119     XclExpStream& operator<<( double fValue );
120 
121     /** Writes nBytes bytes from memory. */
122     sal_Size            Write( const void* pData, sal_Size nBytes );
123     /** Writes a sequence of nBytes zero bytes (respects slice setting). */
124     void                WriteZeroBytes( sal_Size nBytes );
125 
126     void                WriteZeroBytesToRecord( sal_Size nBytes );
127 
128     /** Copies nBytes bytes from current position of the stream rInStrm.
129         @descr  Omitting the second parameter means: read to end of stream. */
130     sal_Size            CopyFromStream( SvStream& rInStrm, sal_Size nBytes = STREAM_SEEK_TO_END );
131 
132     // *** unicode string export is realized with helper class XclExpString ***
133     // (slice length setting has no effect here -> disabled automatically)
134 
135 //UNUSED2008-05  /** Writes Unicode buffer as 8/16 bit, repeats nFlags at start of a CONTINUE record. */
136 //UNUSED2008-05  void                WriteUnicodeBuffer( const sal_uInt16* pBuffer, sal_Size nChars, sal_uInt8 nFlags );
137 
138     /** Writes Unicode buffer as 8/16 bit, repeats nFlags at start of a CONTINUE record. */
139     void                WriteUnicodeBuffer( const ScfUInt16Vec& rBuffer, sal_uInt8 nFlags );
140 
141     // *** write 8-bit-strings ***
142     // (slice length setting has no effect here -> disabled automatically)
143 
144 //UNUSED2008-05  /** Writes ByteString buffer (without string length field). */
145 //UNUSED2008-05  void                WriteByteStringBuffer(
146 //UNUSED2008-05                          const ByteString& rString,
147 //UNUSED2008-05                          sal_uInt16 nMaxLen = 0x00FF );
148 
149     /** Writes string length field and ByteString buffer. */
150     void                WriteByteString(
151                             const ByteString& rString,
152                             sal_uInt16 nMaxLen = 0x00FF,
153                             bool b16BitCount = false );
154 
155     /** Writes 8-bit character buffer. */
156     void                WriteCharBuffer( const ScfUInt8Vec& rBuffer );
157 
158     // *** SvStream access ***
159 
160     /** Sets position of system stream (only allowed outside of records). */
161     sal_Size            SetSvStreamPos( sal_Size nPos );
162     /** Returns the absolute position of the system stream. */
GetSvStreamPos() const163     inline sal_Size     GetSvStreamPos() const { return mrStrm.Tell(); }
164 
165     void                SetEncrypter( XclExpEncrypterRef xEncrypter );
166 
167     bool                HasValidEncrypter() const;
168 
169     void                EnableEncryption( bool bEnable = true );
170 
171     void                DisableEncryption();
172 
173 private:
174     /** Writes header data, internal setup. */
175     void                InitRecord( sal_uInt16 nRecId );
176     /** Rewrites correct record length, if different from calculated. */
177     void                UpdateRecSize();
178     /** Recalculates mnCurrSize and mnSliceSize. */
179     void                UpdateSizeVars( sal_Size nSize );
180     /** Writes CONTINUE header, internal setup. */
181     void                StartContinue();
182     /** Refreshes counter vars, creates CONTINUE records. */
183     void                PrepareWrite( sal_uInt16 nSize );
184     /** Creates CONTINUE record at end of record.
185         @return  Maximum data block size remaining. */
186     sal_uInt16          PrepareWrite();
187 
188     /** Writes a raw sequence of zero bytes. */
189     void                WriteRawZeroBytes( sal_Size nBytes );
190 
191 private:
192     SvStream&           mrStrm;         /// Reference to the system output stream.
193     const XclExpRoot&   mrRoot;         /// Filter root data.
194 
195     bool                mbUseEncrypter;
196     XclExpEncrypterRef  mxEncrypter;
197 
198                         // length data
199     sal_uInt16          mnMaxRecSize;   /// Maximum size of record content.
200     sal_uInt16          mnMaxContSize;  /// Maximum size of CONTINUE content.
201     sal_uInt16          mnCurrMaxSize;  /// Current maximum, either mnMaxRecSize or mnMaxContSize.
202     sal_uInt16          mnMaxSliceSize; /// Maximum size of data slices (parts that cannot be split).
203     sal_uInt16          mnHeaderSize;   /// Record size written in last record header.
204     sal_uInt16          mnCurrSize;     /// Count of bytes already written in current record.
205     sal_uInt16          mnSliceSize;    /// Count of bytes already written in current slice.
206     sal_Size            mnPredictSize;   /// Predicted size received from calling function.
207 
208                         // stream position data
209     sal_Size            mnLastSizePos;  /// Stream position of size field in current header.
210     bool                mbInRec;        /// true = currently writing inside of a record.
211 };
212 
213 // ============================================================================
214 
215 class XclExpBiff8Encrypter
216 {
217 public:
218     explicit XclExpBiff8Encrypter( const XclExpRoot& rRoot );
219     ~XclExpBiff8Encrypter();
220 
221     bool IsValid() const;
222 
223     void GetSaltDigest( sal_uInt8 pnSaltDigest[16] ) const;
224     void GetSalt( sal_uInt8 pnSalt[16] ) const;
225     void GetDocId( sal_uInt8 pnDocId[16] ) const;
226 
227     void Encrypt( SvStream& rStrm, sal_uInt8  nData );
228     void Encrypt( SvStream& rStrm, sal_uInt16 nData );
229     void Encrypt( SvStream& rStrm, sal_uInt32 nData );
230 
231     void Encrypt( SvStream& rStrm, sal_Int8  nData );
232     void Encrypt( SvStream& rStrm, sal_Int16 nData );
233     void Encrypt( SvStream& rStrm, sal_Int32 nData );
234 
235     void Encrypt( SvStream& rStrm, float fValue );
236     void Encrypt( SvStream& rStrm, double fValue );
237 
238     void EncryptBytes( SvStream& rStrm, ::std::vector<sal_uInt8>& aBytes );
239 
240 private:
241     void Init( const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::NamedValue >& aEncryptionData );
242 
243     sal_uInt32 GetBlockPos( sal_Size nStrmPos ) const;
244     sal_uInt16 GetOffsetInBlock( sal_Size nStrmPos ) const;
245 
246 private:
247     ::msfilter::MSCodec_Std97 maCodec;      /// Crypto algorithm implementation.
248     sal_uInt8           mpnDocId[16];
249     sal_uInt8           mpnSalt[16];
250     sal_uInt8           mpnSaltDigest[16];
251 
252     const XclExpRoot&   mrRoot;
253     sal_Size            mnOldPos;      /// Last known stream position
254     bool                mbValid;
255 };
256 
257 // ----------------------------------------------------------------------------
258 
259 
260 // ============================================================================
261 
262 // `s.GetChar(0) != 0` needed because some strings on export only contain NULL.
263 #define XESTRING_TO_PSZ(s) \
264     (s.Len() && s.GetChar( 0 ) != 0 ? XclXmlUtils::ToOString( s ).getStr() : NULL)
265 
266 class ScAddress;
267 class ScDocument;
268 class ScRange;
269 class ScRangeList;
270 class ScTokenArray;
271 struct XclAddress;
272 struct XclFontData;
273 class XclRangeList;
274 
275 class XclXmlUtils
276 {
277     XclXmlUtils();
278     ~XclXmlUtils();
279     XclXmlUtils(const XclXmlUtils&);
280     XclXmlUtils& operator=(const XclXmlUtils&);
281 public:
282     static ::rtl::OUString          GetStreamName( const char* sStreamDir, const char* sStream, sal_Int32 nId );
283 
284     static ::rtl::OString ToOString( const Color& rColor );
285     static ::rtl::OString ToOString( const ::rtl::OUString& s );
286     static ::rtl::OString ToOString( const ScfUInt16Vec& rBuffer );
287     static ::rtl::OString ToOString( const String& s );
288     static ::rtl::OString ToOString( const ScAddress& rRange );
289     static ::rtl::OString ToOString( const ScRange& rRange );
290     static ::rtl::OString ToOString( const ScRangeList& rRangeList );
291     static ::rtl::OString ToOString( const XclAddress& rAddress );
292     static ::rtl::OString ToOString( const XclExpString& s );
293     static ::rtl::OString ToOString( const XclRangeList& rRangeList );
294 
295     static ::rtl::OUString ToOUString( const char* s );
296     static ::rtl::OUString ToOUString( const ScfUInt16Vec& rBuffer, sal_Int32 nStart = 0, sal_Int32 nLength = -1 );
297     static ::rtl::OUString ToOUString( const String& s );
298     static ::rtl::OUString ToOUString( ScDocument& rDocument, const ScAddress& rAddress, ScTokenArray* pTokenArray );
299     static ::rtl::OUString ToOUString( const XclExpString& s );
300     static const char* ToPsz( bool b );
301 };
302 
303 class XclExpXmlStream : public oox::core::XmlFilterBase
304 {
305 public:
306     XclExpXmlStream( const com::sun::star::uno::Reference< com::sun::star::uno::XComponentContext >& rxContext, SvStream& rStrm, const XclExpRoot& rRoot );
307     virtual ~XclExpXmlStream();
308 
309     /** Returns the filter root data. */
GetRoot() const310     inline const XclExpRoot& GetRoot() const { return mrRoot; }
311 
312     sax_fastparser::FSHelperPtr& GetCurrentStream();
313     void PushStream( sax_fastparser::FSHelperPtr aStream );
314     void PopStream();
315 
316     ::rtl::OUString                 GetIdForPath( const ::rtl::OUString& rPath );
317     sax_fastparser::FSHelperPtr     GetStreamForPath( const ::rtl::OUString& rPath );
318 
319     sax_fastparser::FSHelperPtr&    WriteAttributes( sal_Int32 nAttribute, ... );
320     sax_fastparser::FSHelperPtr&    WriteFontData( const XclFontData& rFontData, sal_Int32 nNameId );
321 
322     sax_fastparser::FSHelperPtr     CreateOutputStream (
323                                         const ::rtl::OUString& sFullStream,
324                                         const ::rtl::OUString& sRelativeStream,
325                                         const ::com::sun::star::uno::Reference< ::com::sun::star::io::XOutputStream >& xParentRelation,
326                                         const char* sContentType,
327                                         const char* sRelationshipType,
328                                         ::rtl::OUString* pRelationshipId = NULL );
329 
330     // ignore
331     virtual bool exportDocument() throw();
332 
333     // only needed for import; ignore
334     virtual bool importDocument() throw();
335     virtual oox::vml::Drawing* getVmlDrawing();
336     virtual const oox::drawingml::Theme* getCurrentTheme() const;
337     virtual const oox::drawingml::table::TableStyleListPtr getTableStyles();
338     virtual oox::drawingml::chart::ChartConverter& getChartConverter();
339 
340     void Trace( const char* format, ...);
341 private:
342     virtual ::oox::ole::VbaProject* implCreateVbaProject() const;
343     virtual ::rtl::OUString implGetImplementationName() const;
344 
345     typedef std::map< ::rtl::OUString,
346         std::pair< ::rtl::OUString,
347             sax_fastparser::FSHelperPtr > >     XclExpXmlPathToStateMap;
348 
349     const XclExpRoot&                           mrRoot;         /// Filter root data.
350     std::stack< sax_fastparser::FSHelperPtr >   maStreams;
351     XclExpXmlPathToStateMap                     maOpenedStreamMap;
352 };
353 
354 #endif
355 
356