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