Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
20 : #ifndef INCLUDED_SC_SOURCE_FILTER_INC_BIFFINPUTSTREAM_HXX
21 : #define INCLUDED_SC_SOURCE_FILTER_INC_BIFFINPUTSTREAM_HXX
22 :
23 : #include <vector>
24 : #include <oox/helper/binaryinputstream.hxx>
25 : #include "biffhelper.hxx"
26 : #include "biffcodec.hxx"
27 :
28 : namespace oox {
29 : namespace xls {
30 :
31 : namespace prv {
32 :
33 : /** Buffers the contents of a raw record and encapsulates stream decoding. */
34 0 : class BiffInputRecordBuffer
35 : {
36 : public:
37 : explicit BiffInputRecordBuffer( BinaryInputStream& rInStrm );
38 :
39 : /** Returns the wrapped binary base stream. */
40 : inline const BinaryInputStream& getBaseStream() const { return mrInStrm; }
41 :
42 : /** Sets a decoder object and decrypts buffered record data. */
43 : void setDecoder( const BiffDecoderRef& rxDecoder );
44 : /** Returns the current decoder object. */
45 : inline BiffDecoderRef getDecoder() const { return mxDecoder; }
46 : /** Enables/disables usage of current decoder. */
47 : void enableDecoder( bool bEnable );
48 :
49 : /** Restarts the stream at the passed position. Buffer is invalid until the
50 : next call of startRecord() or startNextRecord(). */
51 : void restartAt( sal_Int64 nPos );
52 :
53 : /** Reads the record header at the passed position. */
54 : bool startRecord( sal_Int64 nHeaderPos );
55 : /** Reads the next record header from the stream. */
56 : bool startNextRecord();
57 : /** Returns the start position of the record header in the core stream. */
58 : sal_uInt16 getNextRecId();
59 :
60 : /** Returns the start position of the record header in the core stream. */
61 0 : inline sal_Int64 getRecHeaderPos() const { return mnHeaderPos; }
62 : /** Returns the current record identifier. */
63 0 : inline sal_uInt16 getRecId() const { return mnRecId; }
64 : /** Returns the current record size. */
65 0 : inline sal_uInt16 getRecSize() const { return mnRecSize; }
66 : /** Returns the current read position in the current record body. */
67 : inline sal_uInt16 getRecPos() const { return mnRecPos; }
68 : /** Returns the number of remaining bytes in the current record body. */
69 0 : inline sal_uInt16 getRecLeft() const { return mnRecSize - mnRecPos; }
70 :
71 : /** Reads nBytes bytes to the existing buffer opData. Must NOT overread the source buffer. */
72 : void read( void* opData, sal_uInt16 nBytes );
73 : /** Ignores nBytes bytes. Must NOT overread the buffer. */
74 : void skip( sal_uInt16 nBytes );
75 :
76 : private:
77 : /** Updates data buffer from stream, if needed. */
78 : void updateBuffer();
79 : /** Updates decoded data from original data. */
80 : void updateDecoded();
81 :
82 : private:
83 : typedef ::std::vector< sal_uInt8 > DataBuffer;
84 :
85 : BinaryInputStream& mrInStrm; /// Core input stream.
86 : DataBuffer maOriginalData; /// Original data read from stream.
87 : DataBuffer maDecodedData; /// Decoded data.
88 : DataBuffer* mpCurrentData; /// Points to data buffer currently in use.
89 : BiffDecoderRef mxDecoder; /// Decoder object.
90 : sal_Int64 mnHeaderPos; /// Stream start position of current record header.
91 : sal_Int64 mnBodyPos; /// Stream start position of current record body.
92 : sal_Int64 mnBufferBodyPos; /// Stream start position of buffered data.
93 : sal_Int64 mnNextHeaderPos; /// Stream start position of next record header.
94 : sal_uInt16 mnRecId; /// Current record identifier.
95 : sal_uInt16 mnRecSize; /// Current record size.
96 : sal_uInt16 mnRecPos; /// Current position in record body.
97 : bool mbValidHeader; /// True = valid record header.
98 : };
99 :
100 : } // namespace prv
101 :
102 : /** This class is used to read BIFF record streams.
103 :
104 : An instance is constructed with a BinaryInputStream object. The passed
105 : stream is reset to its start while constructing this stream.
106 :
107 : To start reading a record call startNextRecord(). Now it is possible to
108 : read all contents of the record using operator>>() or any of the read***()
109 : functions. If some data exceeds the record size limit, the stream looks for
110 : a following CONTINUE record and jumps automatically to it. It is NOT
111 : allowed that an atomic data type is split into two records (e.g. 4 bytes of
112 : a double in one record and the other 4 bytes in a following CONTINUE).
113 :
114 : Trying to read over the record limits results in a stream error. The
115 : isValid() function indicates that by returning false. From now on the data
116 : returned by the read functions is undefined. The error state will be reset,
117 : if the next record is started.
118 :
119 : The import stream supports decrypting the stream data. The contents of a
120 : record (not the record header) will be encrypted by Excel if the file has
121 : been stored with password protection. The functions setDecoder() and
122 : enableDecoder() control the usage of the decryption algorithms.
123 : setDecoder() sets a new decryption algorithm and initially enables it.
124 : enableDecoder( false ) may be used to stop the usage of the decryption
125 : temporarily (sometimes record contents are never encrypted, e.g. all BOF
126 : records or the stream position in SHEET records). Decryption will be
127 : reenabled automatically, if a new record is started with the function
128 : startNextRecord().
129 : */
130 0 : class BiffInputStream : public BinaryInputStream
131 : {
132 : public:
133 : /** Constructs the BIFF record stream using the passed binary stream.
134 :
135 : @param rInStream
136 : The base input stream. Must be seekable. Will be sought to its
137 : start position.
138 :
139 : @param bContLookup Automatic CONTINUE lookup on/off.
140 : */
141 : explicit BiffInputStream(
142 : BinaryInputStream& rInStream,
143 : bool bContLookup = true );
144 :
145 : // record control ---------------------------------------------------------
146 :
147 : /** Sets stream pointer to the start of the next record content.
148 :
149 : Ignores all CONTINUE records of the current record, if automatic
150 : CONTINUE usage is switched on.
151 :
152 : @return False = no record found (end of stream).
153 : */
154 : bool startNextRecord();
155 :
156 : /** Sets stream pointer to the start of the content of the specified record.
157 :
158 : The handle of the current record can be received and stored using the
159 : function getRecHandle() for later usage with this function. The record
160 : handle is equivalent to the position of the underlying binary stream,
161 : thus the function can be used to perform a hard seek to a specific
162 : position, if it is sure that a record starts exactly at this position.
163 :
164 : @return False = no record found (invalid handle passed).
165 : */
166 : bool startRecordByHandle( sal_Int64 nRecHandle );
167 :
168 : /** Sets stream pointer before current record and invalidates stream.
169 :
170 : The next call to startNextRecord() will start again the current record.
171 : This can be used in situations where a loop or a function leaves on a
172 : specific record, but the parent context expects to start this record by
173 : itself. The stream is invalid as long as the first record has not been
174 : started (it is not allowed to call any other stream operation then).
175 : */
176 : void rewindRecord();
177 :
178 : // decoder ----------------------------------------------------------------
179 :
180 : /** Sets a new decoder object.
181 :
182 : Enables decryption of record contents for the rest of the stream.
183 : */
184 : void setDecoder( const BiffDecoderRef& rxDecoder );
185 :
186 : /** Enables/disables usage of current decoder.
187 :
188 : Decryption is reenabled automatically, if a new record is started using
189 : the function startNextRecord().
190 : */
191 : void enableDecoder( bool bEnable = true );
192 :
193 : // stream/record state and info -------------------------------------------
194 :
195 : /** Returns the current record identifier. */
196 0 : inline sal_uInt16 getRecId() const { return mnRecId; }
197 : /** Returns the record identifier of the following record. */
198 : sal_uInt16 getNextRecId();
199 :
200 : /** Returns a unique handle for the current record that can be used with
201 : the function startRecordByHandle(). */
202 0 : inline sal_Int64 getRecHandle() const { return mnRecHandle; }
203 :
204 : // BinaryStreamBase interface (seeking) -----------------------------------
205 :
206 : /** Returns the data size of the whole record without record headers. */
207 : virtual sal_Int64 size() const SAL_OVERRIDE;
208 : /** Returns the position inside of the whole record content. */
209 : virtual sal_Int64 tell() const SAL_OVERRIDE;
210 : /** Seeks in record content to the specified position. */
211 : virtual void seek( sal_Int64 nRecPos ) SAL_OVERRIDE;
212 : /** Closes the input stream but not the wrapped stream. */
213 : virtual void close() SAL_OVERRIDE;
214 :
215 : // BinaryInputStream interface (stream read access) -----------------------
216 :
217 : /** Reads nBytes bytes to the passed sequence.
218 : @return Number of bytes really read. */
219 : virtual sal_Int32 readData( StreamDataSequence& orData, sal_Int32 nBytes, size_t nAtomSize = 1 ) SAL_OVERRIDE;
220 : /** Reads nBytes bytes and copies them to the passed buffer opMem.
221 : @return Number of bytes really read. */
222 : virtual sal_Int32 readMemory( void* opMem, sal_Int32 nBytes, size_t nAtomSize = 1 ) SAL_OVERRIDE;
223 : /** Seeks forward inside the current record. */
224 : virtual void skip( sal_Int32 nBytes, size_t nAtomSize = 1 ) SAL_OVERRIDE;
225 :
226 : /** Stream operator for integral and floating-point types. */
227 : template< typename Type >
228 0 : inline BiffInputStream& operator>>( Type& ornValue ) { ornValue = readValue<Type>(); return *this; }
229 :
230 : // byte strings -----------------------------------------------------------
231 :
232 : /** Reads 8/16 bit string length and character array, and returns the string.
233 : @param b16BitLen
234 : True = Read 16-bit string length field before the character array.
235 : False = Read 8-bit string length field before the character array.
236 : @param bAllowNulChars
237 : True = NUL characters are inserted into the imported string.
238 : False = NUL characters are replaced by question marks (default).
239 : */
240 : OString readByteString( bool b16BitLen, bool bAllowNulChars = false );
241 :
242 : /** Reads 8/16 bit string length and character array, and returns a Unicode string.
243 : @param b16BitLen
244 : True = Read 16-bit string length field before the character array.
245 : False = Read 8-bit string length field before the character array.
246 : @param eTextEnc The text encoding used to create the Unicode string.
247 : @param bAllowNulChars
248 : True = NUL characters are inserted into the imported string.
249 : False = NUL characters are replaced by question marks (default).
250 : */
251 : OUString readByteStringUC( bool b16BitLen, rtl_TextEncoding eTextEnc, bool bAllowNulChars = false );
252 :
253 : // Unicode strings --------------------------------------------------------
254 :
255 : /** Reads nChars characters of a BIFF8 string, and returns the string.
256 : @param nChars Number of characters to read from the stream.
257 : @param b16BitChars
258 : True = The character array contains 16-bit characters.
259 : False = The character array contains truncated 8-bit characters.
260 : @param bAllowNulChars
261 : True = NUL characters are inserted into the imported string.
262 : False = NUL characters are replaced by question marks (default).
263 : */
264 : OUString readUniStringChars( sal_uInt16 nChars, bool b16BitChars, bool bAllowNulChars = false );
265 :
266 : /** Reads 8-bit flags, extended header, nChar characters, extended data of
267 : a BIFF8 string, and returns the string.
268 : @param nChars Number of characters to read from the stream.
269 : @param bAllowNulChars
270 : True = NUL characters are inserted into the imported string.
271 : False = NUL characters are replaced by question marks (default).
272 : */
273 : OUString readUniStringBody( sal_uInt16 nChars, bool bAllowNulChars = false );
274 :
275 : /** Reads 16-bit character count, 8-bit flags, extended header, character
276 : array, extended data of a BIFF8 string, and returns the string.
277 : @param bAllowNulChars
278 : True = NUL characters are inserted into the imported string.
279 : False = NUL characters are replaced by question marks (default).
280 : */
281 : OUString readUniString( bool bAllowNulChars = false );
282 :
283 : private:
284 : /** Initializes all members after base stream has been sought to new record. */
285 : void setupRecord();
286 : /** Restarts the current record from the beginning. */
287 : void restartRecord( bool bInvalidateRecSize );
288 : /** Sets stream pointer before specified record and invalidates stream. */
289 : void rewindToRecord( sal_Int64 nRecHandle );
290 : /** Returns true, if stream was able to start a valid record. */
291 0 : inline bool isInRecord() const { return mnRecHandle >= 0; }
292 :
293 : /** Returns true, if the passed ID is real or alternative continuation record ID. */
294 : bool isContinueId( sal_uInt16 nRecId ) const;
295 : /** Goes to start of the next CONTINUE record.
296 : @descr Stream must be located at the end of a raw record, and handling
297 : of CONTINUE records must be enabled.
298 : @return True if next CONTINUE record has been found and initialized. */
299 : bool jumpToNextContinue();
300 : /** Goes to start of the next CONTINUE record while reading strings.
301 : @descr Stream must be located at the end of a raw record. If reading
302 : has been started in a CONTINUE record, jumps to an existing following
303 : CONTINUE record, even if handling of CONTINUE records is disabled (this
304 : is a special handling for TXO string data). Reads additional Unicode
305 : flag byte at start of the new raw record and sets or resets rb16BitChars.
306 : @return True if next CONTINUE record has been found and initialized. */
307 : bool jumpToNextStringContinue( bool& rb16BitChars );
308 : /** Calculates the complete length of the current record including CONTINUE
309 : records, stores the length in mnComplRecSize. */
310 : void calcRecordLength();
311 :
312 : /** Returns the maximum size of raw data possible to read in one block. */
313 : sal_uInt16 getMaxRawReadSize( sal_Int32 nBytes, size_t nAtomSize ) const;
314 :
315 : /** Reads the BIFF8 Unicode string header fields. */
316 : void readUniStringHeader( bool& orb16BitChars, sal_Int32& ornAddSize );
317 :
318 : private:
319 : prv::BiffInputRecordBuffer maRecBuffer; /// Raw record data buffer.
320 :
321 : sal_Int64 mnRecHandle; /// Handle of current record.
322 : sal_uInt16 mnRecId; /// Identifier of current record (not the CONTINUE ID).
323 : sal_uInt16 mnAltContId; /// Alternative identifier for content continuation records.
324 :
325 : sal_Int64 mnCurrRecSize; /// Helper for record size and position.
326 : sal_Int64 mnComplRecSize; /// Size of complete record data (with CONTINUEs).
327 : bool mbHasComplRec; /// True = mnComplRecSize is valid.
328 :
329 : bool mbCont; /// True = automatic CONTINUE lookup enabled.
330 : };
331 :
332 : class BiffInputStreamPos
333 : {
334 : public:
335 : explicit BiffInputStreamPos( BiffInputStream& rStrm );
336 :
337 : bool restorePosition();
338 :
339 0 : inline BiffInputStream& getStream() { return mrStrm; }
340 :
341 : private:
342 : BiffInputStream& mrStrm;
343 : sal_Int64 mnRecHandle;
344 : sal_Int64 mnRecPos;
345 : };
346 :
347 : /** Stores the current position of the passed stream on construction and
348 : restores it automatically on destruction. */
349 : class BiffInputStreamPosGuard : private BiffInputStreamPos
350 : {
351 : public:
352 : explicit BiffInputStreamPosGuard( BiffInputStream& rStrm );
353 : ~BiffInputStreamPosGuard();
354 : };
355 :
356 : } // namespace xls
357 : } // namespace oox
358 :
359 : #endif
360 :
361 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|