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