xref: /aoo4110/main/sc/source/filter/inc/xistream.hxx (revision b1cdbd2c)
1*b1cdbd2cSJim Jagielski /**************************************************************
2*b1cdbd2cSJim Jagielski  *
3*b1cdbd2cSJim Jagielski  * Licensed to the Apache Software Foundation (ASF) under one
4*b1cdbd2cSJim Jagielski  * or more contributor license agreements.  See the NOTICE file
5*b1cdbd2cSJim Jagielski  * distributed with this work for additional information
6*b1cdbd2cSJim Jagielski  * regarding copyright ownership.  The ASF licenses this file
7*b1cdbd2cSJim Jagielski  * to you under the Apache License, Version 2.0 (the
8*b1cdbd2cSJim Jagielski  * "License"); you may not use this file except in compliance
9*b1cdbd2cSJim Jagielski  * with the License.  You may obtain a copy of the License at
10*b1cdbd2cSJim Jagielski  *
11*b1cdbd2cSJim Jagielski  *   http://www.apache.org/licenses/LICENSE-2.0
12*b1cdbd2cSJim Jagielski  *
13*b1cdbd2cSJim Jagielski  * Unless required by applicable law or agreed to in writing,
14*b1cdbd2cSJim Jagielski  * software distributed under the License is distributed on an
15*b1cdbd2cSJim Jagielski  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*b1cdbd2cSJim Jagielski  * KIND, either express or implied.  See the License for the
17*b1cdbd2cSJim Jagielski  * specific language governing permissions and limitations
18*b1cdbd2cSJim Jagielski  * under the License.
19*b1cdbd2cSJim Jagielski  *
20*b1cdbd2cSJim Jagielski  *************************************************************/
21*b1cdbd2cSJim Jagielski 
22*b1cdbd2cSJim Jagielski 
23*b1cdbd2cSJim Jagielski 
24*b1cdbd2cSJim Jagielski #ifndef SC_XISTREAM_HXX
25*b1cdbd2cSJim Jagielski #define SC_XISTREAM_HXX
26*b1cdbd2cSJim Jagielski 
27*b1cdbd2cSJim Jagielski #include <comphelper/docpasswordhelper.hxx>
28*b1cdbd2cSJim Jagielski #include <filter/msfilter/mscodec.hxx>
29*b1cdbd2cSJim Jagielski #include "xlstream.hxx"
30*b1cdbd2cSJim Jagielski #include "xlconst.hxx"
31*b1cdbd2cSJim Jagielski 
32*b1cdbd2cSJim Jagielski class XclImpRoot;
33*b1cdbd2cSJim Jagielski 
34*b1cdbd2cSJim Jagielski /* ============================================================================
35*b1cdbd2cSJim Jagielski Input stream class for Excel import
36*b1cdbd2cSJim Jagielski - CONTINUE record handling
37*b1cdbd2cSJim Jagielski - ByteString and UniString support
38*b1cdbd2cSJim Jagielski - Decryption
39*b1cdbd2cSJim Jagielski ============================================================================ */
40*b1cdbd2cSJim Jagielski 
41*b1cdbd2cSJim Jagielski // ============================================================================
42*b1cdbd2cSJim Jagielski // Decryption
43*b1cdbd2cSJim Jagielski // ============================================================================
44*b1cdbd2cSJim Jagielski 
45*b1cdbd2cSJim Jagielski class XclImpDecrypter;
46*b1cdbd2cSJim Jagielski typedef ScfRef< XclImpDecrypter > XclImpDecrypterRef;
47*b1cdbd2cSJim Jagielski 
48*b1cdbd2cSJim Jagielski /** Base class for BIFF stream decryption. */
49*b1cdbd2cSJim Jagielski class XclImpDecrypter : public ::comphelper::IDocPasswordVerifier
50*b1cdbd2cSJim Jagielski {
51*b1cdbd2cSJim Jagielski public:
52*b1cdbd2cSJim Jagielski     explicit            XclImpDecrypter();
53*b1cdbd2cSJim Jagielski     virtual             ~XclImpDecrypter();
54*b1cdbd2cSJim Jagielski 
55*b1cdbd2cSJim Jagielski     /** Returns the current error code of the decrypter. */
GetError() const56*b1cdbd2cSJim Jagielski     inline ErrCode      GetError() const { return mnError; }
57*b1cdbd2cSJim Jagielski     /** Returns true, if the decoder has been initialized correctly. */
IsValid() const58*b1cdbd2cSJim Jagielski     inline bool         IsValid() const { return mnError == ERRCODE_NONE; }
59*b1cdbd2cSJim Jagielski 
60*b1cdbd2cSJim Jagielski     /** Creates a (ref-counted) copy of this decrypter object. */
61*b1cdbd2cSJim Jagielski     XclImpDecrypterRef  Clone() const;
62*b1cdbd2cSJim Jagielski 
63*b1cdbd2cSJim Jagielski     /** Implementation of the ::comphelper::IDocPasswordVerifier interface */
64*b1cdbd2cSJim Jagielski     virtual ::comphelper::DocPasswordVerifierResult verifyPassword( const ::rtl::OUString& rPassword, ::com::sun::star::uno::Sequence< ::com::sun::star::beans::NamedValue >& o_rEncryptionData );
65*b1cdbd2cSJim Jagielski     virtual ::comphelper::DocPasswordVerifierResult verifyEncryptionData( const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::NamedValue >& rEncryptionData );
66*b1cdbd2cSJim Jagielski 
67*b1cdbd2cSJim Jagielski     /** Updates the decrypter on start of a new record or after seeking stream. */
68*b1cdbd2cSJim Jagielski     void                Update( SvStream& rStrm, sal_uInt16 nRecSize );
69*b1cdbd2cSJim Jagielski     /** Reads and decrypts nBytes bytes and stores data into the existing(!) buffer pData.
70*b1cdbd2cSJim Jagielski         @return  Count of bytes really read. */
71*b1cdbd2cSJim Jagielski     sal_uInt16          Read( SvStream& rStrm, void* pData, sal_uInt16 nBytes );
72*b1cdbd2cSJim Jagielski 
73*b1cdbd2cSJim Jagielski protected:
74*b1cdbd2cSJim Jagielski     /** Protected copy c'tor for OnClone(). */
75*b1cdbd2cSJim Jagielski     explicit            XclImpDecrypter( const XclImpDecrypter& rSrc );
76*b1cdbd2cSJim Jagielski 
77*b1cdbd2cSJim Jagielski private:
78*b1cdbd2cSJim Jagielski     /** Implementation of cloning this object. */
79*b1cdbd2cSJim Jagielski     virtual XclImpDecrypter* OnClone() const = 0;
80*b1cdbd2cSJim Jagielski     /** Derived classes implement password verification and initialization of
81*b1cdbd2cSJim Jagielski         the decoder. */
82*b1cdbd2cSJim Jagielski     virtual ::com::sun::star::uno::Sequence< ::com::sun::star::beans::NamedValue >
83*b1cdbd2cSJim Jagielski         OnVerifyPassword( const ::rtl::OUString& rPassword ) = 0;
84*b1cdbd2cSJim Jagielski     virtual bool OnVerifyEncryptionData( const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::NamedValue >& rEncryptionData ) = 0;
85*b1cdbd2cSJim Jagielski 
86*b1cdbd2cSJim Jagielski     /** Implementation of updating the decrypter. */
87*b1cdbd2cSJim Jagielski     virtual void        OnUpdate( sal_Size nOldStrmPos, sal_Size nNewStrmPos, sal_uInt16 nRecSize ) = 0;
88*b1cdbd2cSJim Jagielski     /** Implementation of the decryption. */
89*b1cdbd2cSJim Jagielski     virtual sal_uInt16  OnRead( SvStream& rStrm, sal_uInt8* pnData, sal_uInt16 nBytes ) = 0;
90*b1cdbd2cSJim Jagielski 
91*b1cdbd2cSJim Jagielski private:
92*b1cdbd2cSJim Jagielski     ErrCode             mnError;        /// Decrypter error code.
93*b1cdbd2cSJim Jagielski     sal_Size            mnOldPos;       /// Last known stream position.
94*b1cdbd2cSJim Jagielski     sal_uInt16          mnRecSize;      /// Current record size.
95*b1cdbd2cSJim Jagielski };
96*b1cdbd2cSJim Jagielski 
97*b1cdbd2cSJim Jagielski // ----------------------------------------------------------------------------
98*b1cdbd2cSJim Jagielski 
99*b1cdbd2cSJim Jagielski /** Decrypts BIFF5 stream contents. */
100*b1cdbd2cSJim Jagielski class XclImpBiff5Decrypter : public XclImpDecrypter
101*b1cdbd2cSJim Jagielski {
102*b1cdbd2cSJim Jagielski public:
103*b1cdbd2cSJim Jagielski     explicit            XclImpBiff5Decrypter( sal_uInt16 nKey, sal_uInt16 nHash );
104*b1cdbd2cSJim Jagielski 
105*b1cdbd2cSJim Jagielski private:
106*b1cdbd2cSJim Jagielski     /** Private copy c'tor for OnClone(). */
107*b1cdbd2cSJim Jagielski     explicit            XclImpBiff5Decrypter( const XclImpBiff5Decrypter& rSrc );
108*b1cdbd2cSJim Jagielski 
109*b1cdbd2cSJim Jagielski     /** Implementation of cloning this object. */
110*b1cdbd2cSJim Jagielski     virtual XclImpBiff5Decrypter* OnClone() const;
111*b1cdbd2cSJim Jagielski     /** Implements password verification and initialization of the decoder. */
112*b1cdbd2cSJim Jagielski     virtual ::com::sun::star::uno::Sequence< ::com::sun::star::beans::NamedValue >
113*b1cdbd2cSJim Jagielski         OnVerifyPassword( const ::rtl::OUString& rPassword );
114*b1cdbd2cSJim Jagielski     virtual bool OnVerifyEncryptionData( const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::NamedValue >& rEncryptionData );
115*b1cdbd2cSJim Jagielski     /** Implementation of updating the decrypter. */
116*b1cdbd2cSJim Jagielski     virtual void        OnUpdate( sal_Size nOldStrmPos, sal_Size nNewStrmPos, sal_uInt16 nRecSize );
117*b1cdbd2cSJim Jagielski     /** Implementation of the decryption. */
118*b1cdbd2cSJim Jagielski     virtual sal_uInt16  OnRead( SvStream& rStrm, sal_uInt8* pnData, sal_uInt16 nBytes );
119*b1cdbd2cSJim Jagielski 
120*b1cdbd2cSJim Jagielski private:
121*b1cdbd2cSJim Jagielski     ::msfilter::MSCodec_XorXLS95 maCodec;       /// Crypto algorithm implementation.
122*b1cdbd2cSJim Jagielski     ::com::sun::star::uno::Sequence< ::com::sun::star::beans::NamedValue > maEncryptionData;
123*b1cdbd2cSJim Jagielski     sal_uInt16          mnKey;
124*b1cdbd2cSJim Jagielski     sal_uInt16          mnHash;
125*b1cdbd2cSJim Jagielski };
126*b1cdbd2cSJim Jagielski 
127*b1cdbd2cSJim Jagielski // ----------------------------------------------------------------------------
128*b1cdbd2cSJim Jagielski 
129*b1cdbd2cSJim Jagielski /** Decrypts BIFF8 stream contents using the given document identifier. */
130*b1cdbd2cSJim Jagielski class XclImpBiff8Decrypter : public XclImpDecrypter
131*b1cdbd2cSJim Jagielski {
132*b1cdbd2cSJim Jagielski public:
133*b1cdbd2cSJim Jagielski     explicit            XclImpBiff8Decrypter( sal_uInt8 pnSalt[ 16 ],
134*b1cdbd2cSJim Jagielski                             sal_uInt8 pnVerifier[ 16 ], sal_uInt8 pnVerifierHash[ 16 ] );
135*b1cdbd2cSJim Jagielski 
136*b1cdbd2cSJim Jagielski private:
137*b1cdbd2cSJim Jagielski     /** Private copy c'tor for OnClone(). */
138*b1cdbd2cSJim Jagielski     explicit            XclImpBiff8Decrypter( const XclImpBiff8Decrypter& rSrc );
139*b1cdbd2cSJim Jagielski 
140*b1cdbd2cSJim Jagielski     /** Implementation of cloning this object. */
141*b1cdbd2cSJim Jagielski     virtual XclImpBiff8Decrypter* OnClone() const;
142*b1cdbd2cSJim Jagielski     /** Implements password verification and initialization of the decoder. */
143*b1cdbd2cSJim Jagielski     virtual ::com::sun::star::uno::Sequence< ::com::sun::star::beans::NamedValue >
144*b1cdbd2cSJim Jagielski         OnVerifyPassword( const ::rtl::OUString& rPassword );
145*b1cdbd2cSJim Jagielski     virtual bool OnVerifyEncryptionData( const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::NamedValue >& rEncryptionData );
146*b1cdbd2cSJim Jagielski     /** Implementation of updating the decrypter. */
147*b1cdbd2cSJim Jagielski     virtual void        OnUpdate( sal_Size nOldStrmPos, sal_Size nNewStrmPos, sal_uInt16 nRecSize );
148*b1cdbd2cSJim Jagielski     /** Implementation of the decryption. */
149*b1cdbd2cSJim Jagielski     virtual sal_uInt16  OnRead( SvStream& rStrm, sal_uInt8* pnData, sal_uInt16 nBytes );
150*b1cdbd2cSJim Jagielski 
151*b1cdbd2cSJim Jagielski     /** Returns the block number corresponding to the passed stream position. */
152*b1cdbd2cSJim Jagielski     sal_uInt32          GetBlock( sal_Size nStrmPos ) const;
153*b1cdbd2cSJim Jagielski     /** Returns the block offset corresponding to the passed stream position. */
154*b1cdbd2cSJim Jagielski     sal_uInt16          GetOffset( sal_Size nStrmPos ) const;
155*b1cdbd2cSJim Jagielski 
156*b1cdbd2cSJim Jagielski private:
157*b1cdbd2cSJim Jagielski     ::msfilter::MSCodec_Std97 maCodec;       /// Crypto algorithm implementation.
158*b1cdbd2cSJim Jagielski     ::com::sun::star::uno::Sequence< ::com::sun::star::beans::NamedValue > maEncryptionData;
159*b1cdbd2cSJim Jagielski     ::std::vector< sal_uInt8 > maSalt;
160*b1cdbd2cSJim Jagielski     ::std::vector< sal_uInt8 > maVerifier;
161*b1cdbd2cSJim Jagielski     ::std::vector< sal_uInt8 > maVerifierHash;
162*b1cdbd2cSJim Jagielski };
163*b1cdbd2cSJim Jagielski 
164*b1cdbd2cSJim Jagielski // ============================================================================
165*b1cdbd2cSJim Jagielski // Stream
166*b1cdbd2cSJim Jagielski // ============================================================================
167*b1cdbd2cSJim Jagielski 
168*b1cdbd2cSJim Jagielski /** This class represents an Excel stream position.
169*b1cdbd2cSJim Jagielski     @descr  It contains the relevant data for a stream position inside of a record
170*b1cdbd2cSJim Jagielski     (including CONTINUE records). */
171*b1cdbd2cSJim Jagielski class XclImpStreamPos
172*b1cdbd2cSJim Jagielski {
173*b1cdbd2cSJim Jagielski public:
174*b1cdbd2cSJim Jagielski     /** Constructs an invalid stream position data object. */
175*b1cdbd2cSJim Jagielski     explicit            XclImpStreamPos();
176*b1cdbd2cSJim Jagielski 
177*b1cdbd2cSJim Jagielski     /** Sets the stream position data to the passed values. */
178*b1cdbd2cSJim Jagielski     void                Set( const SvStream& rStrm, sal_Size nNextPos, sal_Size nCurrSize,
179*b1cdbd2cSJim Jagielski                             sal_uInt16 nRawRecId, sal_uInt16 nRawRecSize, sal_uInt16 nRawRecLeft,
180*b1cdbd2cSJim Jagielski                             bool bValid );
181*b1cdbd2cSJim Jagielski 
182*b1cdbd2cSJim Jagielski     /** Writes the contained stream position data to the given variables. */
183*b1cdbd2cSJim Jagielski     void                Get( SvStream& rStrm, sal_Size& rnNextPos, sal_Size& rnCurrSize,
184*b1cdbd2cSJim Jagielski                             sal_uInt16& rnRawRecId, sal_uInt16& rnRawRecSize, sal_uInt16& rnRawRecLeft,
185*b1cdbd2cSJim Jagielski                             bool& rbValid ) const;
186*b1cdbd2cSJim Jagielski 
187*b1cdbd2cSJim Jagielski     /** Returns the stored stream position. */
GetPos() const188*b1cdbd2cSJim Jagielski     inline sal_Size     GetPos() const { return mnPos; }
189*b1cdbd2cSJim Jagielski 
190*b1cdbd2cSJim Jagielski private:
191*b1cdbd2cSJim Jagielski     sal_Size            mnPos;          /// Absolute position of the stream.
192*b1cdbd2cSJim Jagielski     sal_Size            mnNextPos;      /// Absolute position of next record.
193*b1cdbd2cSJim Jagielski     sal_Size            mnCurrSize;     /// Current calculated size of the record.
194*b1cdbd2cSJim Jagielski     sal_uInt16          mnRawRecId;     /// Current raw record ID (including CONTINUEs).
195*b1cdbd2cSJim Jagielski     sal_uInt16          mnRawRecSize;   /// Current raw record size (without following CONTINUEs).
196*b1cdbd2cSJim Jagielski     sal_uInt16          mnRawRecLeft;   /// Bytes left in current raw record (without following CONTINUEs).
197*b1cdbd2cSJim Jagielski     bool                mbValid;        /// Read state: false = record overread.
198*b1cdbd2cSJim Jagielski };
199*b1cdbd2cSJim Jagielski 
200*b1cdbd2cSJim Jagielski // ============================================================================
201*b1cdbd2cSJim Jagielski 
202*b1cdbd2cSJim Jagielski /** This class is used to import record oriented streams.
203*b1cdbd2cSJim Jagielski     @descr  An instance is constructed with an SvStream. The SvStream stream is
204*b1cdbd2cSJim Jagielski     reset to its start while constructing this stream.
205*b1cdbd2cSJim Jagielski 
206*b1cdbd2cSJim Jagielski     To start reading a record call StartNextRecord(). Now it is possible to
207*b1cdbd2cSJim Jagielski     read all contents of the record using operator>>() or any of the Read***()
208*b1cdbd2cSJim Jagielski     functions. If some data exceeds the record size limit, the stream looks for
209*b1cdbd2cSJim Jagielski     a following CONTINUE record and jumps automatically to it. It is NOT
210*b1cdbd2cSJim Jagielski     allowed that an atomic data type is split into two records (i.e. 4 bytes of
211*b1cdbd2cSJim Jagielski     a double in one record and the other 4 bytes in a following CONTINUE).
212*b1cdbd2cSJim Jagielski 
213*b1cdbd2cSJim Jagielski     Trying to read over the record limits results in a stream error. The
214*b1cdbd2cSJim Jagielski     IsValid() function indicates that with returning false. From now on it is
215*b1cdbd2cSJim Jagielski     undefined what data the read functions will return. The error state will be
216*b1cdbd2cSJim Jagielski     reset, if the record is reset (with the method ResetRecord()) or if the
217*b1cdbd2cSJim Jagielski     next record is started.
218*b1cdbd2cSJim Jagielski 
219*b1cdbd2cSJim Jagielski     To switch off the automatic lookup of CONTINUE records, use ResetRecord()
220*b1cdbd2cSJim Jagielski     with false parameter. This is useful i.e. on import of Escher objects,
221*b1cdbd2cSJim Jagielski     where sometimes solely CONTINUE records will occur. The automatic lookup
222*b1cdbd2cSJim Jagielski     keeps switched off until the method ResetRecord() is called with parameter
223*b1cdbd2cSJim Jagielski     true. All other settings done on the stream (i.e. alternative CONTINUE
224*b1cdbd2cSJim Jagielski     record identifier, enabled decryption, NUL substitution character) will be
225*b1cdbd2cSJim Jagielski     reset to default values, if a new record is started.
226*b1cdbd2cSJim Jagielski 
227*b1cdbd2cSJim Jagielski     The import stream supports decrypting the stream data. The contents of a
228*b1cdbd2cSJim Jagielski     record (not the record header) will be encrypted by Excel if the file has
229*b1cdbd2cSJim Jagielski     been stored with password protection. The functions SetDecrypter(),
230*b1cdbd2cSJim Jagielski     EnableDecryption(), and DisableDecryption() control the usage of the
231*b1cdbd2cSJim Jagielski     decryption algorithms. SetDecrypter() sets a new decryption algorithm and
232*b1cdbd2cSJim Jagielski     initially enables it. DisableDecryption() may be used to stop the usage of
233*b1cdbd2cSJim Jagielski     the decryption temporarily (sometimes record contents are never encrypted,
234*b1cdbd2cSJim Jagielski     i.e. all BOF records or the stream position in BOUNDSHEET). Decryption will
235*b1cdbd2cSJim Jagielski     be reenabled automatically, if a new record is started with the function
236*b1cdbd2cSJim Jagielski     StartNextRecord().
237*b1cdbd2cSJim Jagielski 
238*b1cdbd2cSJim Jagielski     It is possible to store several stream positions inside a record (including
239*b1cdbd2cSJim Jagielski     its CONTINUE records). The positions are stored on a stack, which can be
240*b1cdbd2cSJim Jagielski     controlled with the functions PushPosition(), PopPosition() and
241*b1cdbd2cSJim Jagielski     RejectPosition(). The stack will be cleared whenever a new record is
242*b1cdbd2cSJim Jagielski     started with the function StartNextRecord().
243*b1cdbd2cSJim Jagielski 
244*b1cdbd2cSJim Jagielski     Additionally a single global stream position can be stored which keeps
245*b1cdbd2cSJim Jagielski     valid during the whole import process (methods StoreGlobalPosition(),
246*b1cdbd2cSJim Jagielski     SeekGlobalPosition() and DeleteGlobalPosition()). This is the only way to
247*b1cdbd2cSJim Jagielski     jump back to a previous record (that is a real jump without return).
248*b1cdbd2cSJim Jagielski */
249*b1cdbd2cSJim Jagielski class XclImpStream
250*b1cdbd2cSJim Jagielski {
251*b1cdbd2cSJim Jagielski public:
252*b1cdbd2cSJim Jagielski     /** Detects the BIFF version of the passed workbook stream. */
253*b1cdbd2cSJim Jagielski     static XclBiff      DetectBiffVersion( SvStream& rStrm );
254*b1cdbd2cSJim Jagielski 
255*b1cdbd2cSJim Jagielski     /** Constructs the Excel record import stream using a TOOLS stream object.
256*b1cdbd2cSJim Jagielski         @param rInStrm  The system input stream. Will be set to its start position.
257*b1cdbd2cSJim Jagielski         Must exist as long as this object exists.
258*b1cdbd2cSJim Jagielski         @param bContLookup  Automatic CONTINUE lookup on/off. */
259*b1cdbd2cSJim Jagielski     explicit            XclImpStream(
260*b1cdbd2cSJim Jagielski                             SvStream& rInStrm,
261*b1cdbd2cSJim Jagielski                             const XclImpRoot& rRoot,
262*b1cdbd2cSJim Jagielski                             bool bContLookup = true );
263*b1cdbd2cSJim Jagielski 
264*b1cdbd2cSJim Jagielski                         ~XclImpStream();
265*b1cdbd2cSJim Jagielski 
266*b1cdbd2cSJim Jagielski     /** Returns the filter root data. */
GetRoot() const267*b1cdbd2cSJim Jagielski     inline const XclImpRoot& GetRoot() const { return mrRoot; }
268*b1cdbd2cSJim Jagielski 
269*b1cdbd2cSJim Jagielski     /** Sets stream pointer to the start of the next record content.
270*b1cdbd2cSJim Jagielski         @descr  Ignores all CONTINUE records of the current record, if automatic
271*b1cdbd2cSJim Jagielski         CONTINUE usage is switched on.
272*b1cdbd2cSJim Jagielski         @return  false = no record found (end of stream). */
273*b1cdbd2cSJim Jagielski     bool                StartNextRecord();
274*b1cdbd2cSJim Jagielski     /** Sets stream pointer to the start of the record content for the record
275*b1cdbd2cSJim Jagielski         at the passed absolute stream position.
276*b1cdbd2cSJim Jagielski         @return  false = no record found (end of stream). */
277*b1cdbd2cSJim Jagielski     bool                StartNextRecord( sal_Size nNextRecPos );
278*b1cdbd2cSJim Jagielski     /** Sets stream pointer to begin of record content.
279*b1cdbd2cSJim Jagielski         @param bContLookup  Automatic CONTINUE lookup on/off. In difference
280*b1cdbd2cSJim Jagielski         to other stream settings, this setting is persistent until next call of
281*b1cdbd2cSJim Jagielski         this function (because it is wanted to receive the next CONTINUE
282*b1cdbd2cSJim Jagielski         records separately).
283*b1cdbd2cSJim Jagielski         @param nAltContId  Sets an alternative record ID for content
284*b1cdbd2cSJim Jagielski         continuation. This value is reset automatically when a new record is
285*b1cdbd2cSJim Jagielski         started with StartNextRecord(). */
286*b1cdbd2cSJim Jagielski     void                ResetRecord( bool bContLookup,
287*b1cdbd2cSJim Jagielski                             sal_uInt16 nAltContId = EXC_ID_UNKNOWN );
288*b1cdbd2cSJim Jagielski     /** Sets stream pointer before current record and invalidates stream.
289*b1cdbd2cSJim Jagielski         @descr  The next call to StartNextRecord() will start again the current
290*b1cdbd2cSJim Jagielski         record. This can be used in situations where a loop or a function
291*b1cdbd2cSJim Jagielski         leaves on a specific record, but the parent context expects to start
292*b1cdbd2cSJim Jagielski         this record by itself. The stream is invalid as long as the first
293*b1cdbd2cSJim Jagielski         record has not been started (it is not allowed to call any other stream
294*b1cdbd2cSJim Jagielski         operation then). */
295*b1cdbd2cSJim Jagielski     void                RewindRecord();
296*b1cdbd2cSJim Jagielski 
297*b1cdbd2cSJim Jagielski     /** Enables decryption of record contents for the rest of the stream. */
298*b1cdbd2cSJim Jagielski     void                SetDecrypter( XclImpDecrypterRef xDecrypter );
299*b1cdbd2cSJim Jagielski     /** Sets decrypter from another stream. */
300*b1cdbd2cSJim Jagielski     void                CopyDecrypterFrom( const XclImpStream& rStrm );
301*b1cdbd2cSJim Jagielski     /** Returns true, if a valid decrypter is set at the stream. */
302*b1cdbd2cSJim Jagielski     bool                HasValidDecrypter() const;
303*b1cdbd2cSJim Jagielski     /** Switches usage of current decryption algorithm on/off.
304*b1cdbd2cSJim Jagielski         @descr  Encryption is re-enabled automatically, if a new record is
305*b1cdbd2cSJim Jagielski         started using the function StartNextRecord(). */
306*b1cdbd2cSJim Jagielski     void                EnableDecryption( bool bEnable = true );
307*b1cdbd2cSJim Jagielski     /** Switches usage of current decryption algorithm off.
308*b1cdbd2cSJim Jagielski         @descr  This is a record-local setting. The function StartNextRecord()
309*b1cdbd2cSJim Jagielski         always enables decryption. */
DisableDecryption()310*b1cdbd2cSJim Jagielski     inline void         DisableDecryption() { EnableDecryption( false ); }
311*b1cdbd2cSJim Jagielski 
312*b1cdbd2cSJim Jagielski     /** Pushes current position on user position stack.
313*b1cdbd2cSJim Jagielski         @descr  This stack is emptied when starting a new record with
314*b1cdbd2cSJim Jagielski         StartNextRecord(). The decryption state (enabled/disabled) is not
315*b1cdbd2cSJim Jagielski         pushed onto the stack. */
316*b1cdbd2cSJim Jagielski     void                PushPosition();
317*b1cdbd2cSJim Jagielski     /** Seeks to last position from user position stack.
318*b1cdbd2cSJim Jagielski         @descr  This position will be removed from the stack. */
319*b1cdbd2cSJim Jagielski     void                PopPosition();
320*b1cdbd2cSJim Jagielski //UNUSED2008-05  /** Removes last position from user position stack, but does not seek to it. */
321*b1cdbd2cSJim Jagielski //UNUSED2008-05  void                RejectPosition();
322*b1cdbd2cSJim Jagielski 
323*b1cdbd2cSJim Jagielski     /** Stores current position. This position keeps valid in all records. */
324*b1cdbd2cSJim Jagielski     void                StoreGlobalPosition();
325*b1cdbd2cSJim Jagielski     /** Seeks to the stored global user position. */
326*b1cdbd2cSJim Jagielski     void                SeekGlobalPosition();
327*b1cdbd2cSJim Jagielski     /** Invalidates global user position. */
DeleteGlobalPosition()328*b1cdbd2cSJim Jagielski     inline void         DeleteGlobalPosition() { mbHasGlobPos = false; }
329*b1cdbd2cSJim Jagielski 
330*b1cdbd2cSJim Jagielski     /** Returns record reading state: false = record overread. */
IsValid() const331*b1cdbd2cSJim Jagielski     inline bool         IsValid() const { return mbValid; }
332*b1cdbd2cSJim Jagielski     /** Returns the current record ID. */
GetRecId() const333*b1cdbd2cSJim Jagielski     inline sal_uInt16   GetRecId() const { return mnRecId; }
334*b1cdbd2cSJim Jagielski     /** Returns the position inside of the whole record content. */
335*b1cdbd2cSJim Jagielski     sal_Size            GetRecPos() const;
336*b1cdbd2cSJim Jagielski     /** Returns the data size of the whole record without record headers. */
337*b1cdbd2cSJim Jagielski     sal_Size            GetRecSize();
338*b1cdbd2cSJim Jagielski     /** Returns remaining data size of the whole record without record headers. */
339*b1cdbd2cSJim Jagielski     sal_Size            GetRecLeft();
340*b1cdbd2cSJim Jagielski     /** Returns the record ID of the following record. */
341*b1cdbd2cSJim Jagielski     sal_uInt16          GetNextRecId();
342*b1cdbd2cSJim Jagielski 
343*b1cdbd2cSJim Jagielski     XclImpStream&       operator>>( sal_Int8& rnValue );
344*b1cdbd2cSJim Jagielski     XclImpStream&       operator>>( sal_uInt8& rnValue );
345*b1cdbd2cSJim Jagielski     XclImpStream&       operator>>( sal_Int16& rnValue );
346*b1cdbd2cSJim Jagielski     XclImpStream&       operator>>( sal_uInt16& rnValue );
347*b1cdbd2cSJim Jagielski     XclImpStream&       operator>>( sal_Int32& rnValue );
348*b1cdbd2cSJim Jagielski     XclImpStream&       operator>>( sal_uInt32& rnValue );
349*b1cdbd2cSJim Jagielski     XclImpStream&       operator>>( float& rfValue );
350*b1cdbd2cSJim Jagielski     XclImpStream&       operator>>( double& rfValue );
351*b1cdbd2cSJim Jagielski 
352*b1cdbd2cSJim Jagielski     sal_Int8            ReadInt8();
353*b1cdbd2cSJim Jagielski     sal_uInt8           ReaduInt8();
354*b1cdbd2cSJim Jagielski     sal_Int16           ReadInt16();
355*b1cdbd2cSJim Jagielski     sal_uInt16          ReaduInt16();
356*b1cdbd2cSJim Jagielski     sal_Int32           ReadInt32();
357*b1cdbd2cSJim Jagielski     sal_uInt32          ReaduInt32();
358*b1cdbd2cSJim Jagielski     float               ReadFloat();
359*b1cdbd2cSJim Jagielski     double              ReadDouble();
360*b1cdbd2cSJim Jagielski 
361*b1cdbd2cSJim Jagielski     /** Reads nBytes bytes to the existing(!) buffer pData.
362*b1cdbd2cSJim Jagielski         @return  Count of bytes really read. */
363*b1cdbd2cSJim Jagielski     sal_Size            Read( void* pData, sal_Size nBytes );
364*b1cdbd2cSJim Jagielski     /** Copies nBytes bytes to rOutStrm.
365*b1cdbd2cSJim Jagielski         @return  Count of bytes really written. */
366*b1cdbd2cSJim Jagielski     sal_Size            CopyToStream( SvStream& rOutStrm, sal_Size nBytes );
367*b1cdbd2cSJim Jagielski 
368*b1cdbd2cSJim Jagielski     /** Copies the entire record to rOutStrm. The current record position keeps unchanged.
369*b1cdbd2cSJim Jagielski         @return  Count of bytes really written. */
370*b1cdbd2cSJim Jagielski     sal_Size            CopyRecordToStream( SvStream& rOutStrm );
371*b1cdbd2cSJim Jagielski 
372*b1cdbd2cSJim Jagielski     /** Seeks absolute in record content to the specified position.
373*b1cdbd2cSJim Jagielski         @descr  The value 0 means start of record, independent from physical stream position. */
374*b1cdbd2cSJim Jagielski     void                Seek( sal_Size nPos );
375*b1cdbd2cSJim Jagielski     /** Seeks forward inside the current record. */
376*b1cdbd2cSJim Jagielski     void                Ignore( sal_Size nBytes );
377*b1cdbd2cSJim Jagielski 
378*b1cdbd2cSJim Jagielski     // *** special string functions *** ---------------------------------------
379*b1cdbd2cSJim Jagielski 
380*b1cdbd2cSJim Jagielski     // *** read/ignore unicode strings *** ------------------------------------
381*b1cdbd2cSJim Jagielski     /*  - look for CONTINUE records even if CONTINUE handling disabled
382*b1cdbd2cSJim Jagielski           (only if inside of a CONTINUE record - for TXO import)
383*b1cdbd2cSJim Jagielski         - no overread assertions (for Applix wrong string length export bug)
384*b1cdbd2cSJim Jagielski 
385*b1cdbd2cSJim Jagielski         structure of an Excel unicode string:
386*b1cdbd2cSJim Jagielski         (1) 2 byte character count
387*b1cdbd2cSJim Jagielski         (2) 1 byte flags (16-bit-characters, rich string, far east string)
388*b1cdbd2cSJim Jagielski         (3) [2 byte rich string format run count]
389*b1cdbd2cSJim Jagielski         (4) [4 byte far east data size]
390*b1cdbd2cSJim Jagielski         (5) character array
391*b1cdbd2cSJim Jagielski         (6) [4 * (rich string format run count) byte]
392*b1cdbd2cSJim Jagielski         (7) [(far east data size) byte]
393*b1cdbd2cSJim Jagielski         header = (1), (2)
394*b1cdbd2cSJim Jagielski         ext. header = (3), (4)
395*b1cdbd2cSJim Jagielski         ext. data = (6), (7)
396*b1cdbd2cSJim Jagielski      */
397*b1cdbd2cSJim Jagielski 
398*b1cdbd2cSJim Jagielski     /** Reads ext. header, detects 8/16 bit mode, sets all ext. info.
399*b1cdbd2cSJim Jagielski         @return  Total size of ext. data. */
400*b1cdbd2cSJim Jagielski     sal_Size            ReadUniStringExtHeader(
401*b1cdbd2cSJim Jagielski                             bool& rb16Bit, bool& rbRich, bool& rbFareast,
402*b1cdbd2cSJim Jagielski                             sal_uInt16& rnFormatRuns, sal_uInt32& rnExtInf, sal_uInt8 nFlags );
403*b1cdbd2cSJim Jagielski     /** Seeks to begin of character array, detects 8/16 bit mode.
404*b1cdbd2cSJim Jagielski         @return  Total size of ext. data. */
405*b1cdbd2cSJim Jagielski     sal_Size            ReadUniStringExtHeader( bool& rb16Bit, sal_uInt8 nFlags );
406*b1cdbd2cSJim Jagielski 
407*b1cdbd2cSJim Jagielski     /** Sets a replacement character for NUL characters.
408*b1cdbd2cSJim Jagielski         @descr  NUL characters must be replaced, because Tools strings cannot
409*b1cdbd2cSJim Jagielski         handle them. The substitution character is reset to '?' automatically,
410*b1cdbd2cSJim Jagielski         if a new record is started using the function StartNextRecord().
411*b1cdbd2cSJim Jagielski         @param cNulSubst  The character to use for NUL replacement. It is
412*b1cdbd2cSJim Jagielski         possible to specify NUL here. in this case strings are terminated when
413*b1cdbd2cSJim Jagielski         the first NUL occurs during string import. */
SetNulSubstChar(sal_Unicode cNulSubst='?')414*b1cdbd2cSJim Jagielski     inline void         SetNulSubstChar( sal_Unicode cNulSubst = '?' ) { mcNulSubst = cNulSubst; }
415*b1cdbd2cSJim Jagielski 
416*b1cdbd2cSJim Jagielski     /** Reads nChars characters and returns the string. */
417*b1cdbd2cSJim Jagielski     String              ReadRawUniString( sal_uInt16 nChars, bool b16Bit );
418*b1cdbd2cSJim Jagielski     /** Reads ext. header, nChar characters, ext. data and returns the string. */
419*b1cdbd2cSJim Jagielski     String              ReadUniString( sal_uInt16 nChars, sal_uInt8 nFlags );
420*b1cdbd2cSJim Jagielski     /** Reads 8 bit flags, ext. header, nChar characters, ext. data and returns the string. */
421*b1cdbd2cSJim Jagielski     String              ReadUniString( sal_uInt16 nChars );
422*b1cdbd2cSJim Jagielski     /** Reads 16 bit character count, 8 bit flags, ext. header, character array,
423*b1cdbd2cSJim Jagielski         ext. data and returns the string. */
424*b1cdbd2cSJim Jagielski     String              ReadUniString();
425*b1cdbd2cSJim Jagielski 
426*b1cdbd2cSJim Jagielski     /** Ignores nChars characters. */
427*b1cdbd2cSJim Jagielski     void                IgnoreRawUniString( sal_uInt16 nChars, bool b16Bit );
428*b1cdbd2cSJim Jagielski     /** Ignores ext. header, nChar characters, ext. data. */
429*b1cdbd2cSJim Jagielski     void                IgnoreUniString( sal_uInt16 nChars, sal_uInt8 nFlags );
430*b1cdbd2cSJim Jagielski     /** Ignores 8 bit flags, ext. header, nChar characters, ext. data. */
431*b1cdbd2cSJim Jagielski     void                IgnoreUniString( sal_uInt16 nChars );
432*b1cdbd2cSJim Jagielski     /** Ignores 16 bit character count, 8 bit flags, ext. header, character array, ext. data. */
433*b1cdbd2cSJim Jagielski     void                IgnoreUniString();
434*b1cdbd2cSJim Jagielski 
435*b1cdbd2cSJim Jagielski     // *** read/ignore 8-bit-strings, store in String *** ---------------------
436*b1cdbd2cSJim Jagielski 
437*b1cdbd2cSJim Jagielski     /** Reads nChar byte characters and returns the string. */
438*b1cdbd2cSJim Jagielski     String              ReadRawByteString( sal_uInt16 nChars );
439*b1cdbd2cSJim Jagielski     /** Reads 8/16 bit string length, character array and returns the string. */
440*b1cdbd2cSJim Jagielski     String              ReadByteString( bool b16BitLen );
441*b1cdbd2cSJim Jagielski 
442*b1cdbd2cSJim Jagielski     // *** SvStream functions *** ---------------------------------------------
443*b1cdbd2cSJim Jagielski 
444*b1cdbd2cSJim Jagielski     /** Returns the absolute stream position. */
GetSvStreamPos() const445*b1cdbd2cSJim Jagielski     inline sal_Size     GetSvStreamPos() const { return mrStrm.Tell(); }
446*b1cdbd2cSJim Jagielski     /** Returns the stream size. */
GetSvStreamSize() const447*b1cdbd2cSJim Jagielski     inline sal_Size     GetSvStreamSize() const { return mnStreamSize; }
448*b1cdbd2cSJim Jagielski 
449*b1cdbd2cSJim Jagielski private:
450*b1cdbd2cSJim Jagielski     /** Stores current stream position into rPos. */
451*b1cdbd2cSJim Jagielski     void                StorePosition( XclImpStreamPos& rPos );
452*b1cdbd2cSJim Jagielski     /** Restores stream position contained in rPos. */
453*b1cdbd2cSJim Jagielski     void                RestorePosition( const XclImpStreamPos& rPos );
454*b1cdbd2cSJim Jagielski 
455*b1cdbd2cSJim Jagielski     /** Seeks to next raw record header and reads record ID and size.
456*b1cdbd2cSJim Jagielski         @descr  This is a "raw" function, means that stream members are
457*b1cdbd2cSJim Jagielski         inconsistent after return. Does only change mnRawRecId, mnRawRecSize,
458*b1cdbd2cSJim Jagielski         and the base stream position, but no other members.
459*b1cdbd2cSJim Jagielski         @return  false = No record header found (end of stream). */
460*b1cdbd2cSJim Jagielski     bool                ReadNextRawRecHeader();
461*b1cdbd2cSJim Jagielski 
462*b1cdbd2cSJim Jagielski     /** Initializes the decrypter to read a new record. */
463*b1cdbd2cSJim Jagielski     void                SetupDecrypter();
464*b1cdbd2cSJim Jagielski     /** Initializes all members after base stream has been seeked to new raw record. */
465*b1cdbd2cSJim Jagielski     void                SetupRawRecord();
466*b1cdbd2cSJim Jagielski     /** Initializes all members after base stream has been seeked to new record. */
467*b1cdbd2cSJim Jagielski     void                SetupRecord();
468*b1cdbd2cSJim Jagielski 
469*b1cdbd2cSJim Jagielski     /** Returns true, if the passed ID is real or alternative continuation record ID. */
470*b1cdbd2cSJim Jagielski     bool                IsContinueId( sal_uInt16 nRecId ) const;
471*b1cdbd2cSJim Jagielski 
472*b1cdbd2cSJim Jagielski     /** Goes to start of the next CONTINUE record.
473*b1cdbd2cSJim Jagielski         @descr  Stream must be located at the end of a raw record, and handling
474*b1cdbd2cSJim Jagielski         of CONTINUE records must be enabled.
475*b1cdbd2cSJim Jagielski         @return  Copy of mbValid. */
476*b1cdbd2cSJim Jagielski     bool                JumpToNextContinue();
477*b1cdbd2cSJim Jagielski     /** Goes to start of the next CONTINUE record while reading strings.
478*b1cdbd2cSJim Jagielski         @descr  Stream must be located at the end of a raw record. If reading
479*b1cdbd2cSJim Jagielski         has been started in a CONTINUE record, jumps to an existing following
480*b1cdbd2cSJim Jagielski         CONTINUE record, even if handling of CONTINUE records is disabled (This
481*b1cdbd2cSJim Jagielski         is a special handling for TXO string data). Reads additional Unicode
482*b1cdbd2cSJim Jagielski         flag byte at start of the new raw record and sets or resets rb16Bit.
483*b1cdbd2cSJim Jagielski         @return  Copy of mbValid. */
484*b1cdbd2cSJim Jagielski     bool                JumpToNextStringContinue( bool& rb16Bit );
485*b1cdbd2cSJim Jagielski 
486*b1cdbd2cSJim Jagielski     /** Ensures that reading nBytes bytes is possible with next stream access.
487*b1cdbd2cSJim Jagielski         @descr  Stream must be located at the end of a raw record, and handling
488*b1cdbd2cSJim Jagielski         of CONTINUE records must be enabled.
489*b1cdbd2cSJim Jagielski         @return  Copy of mbValid. */
490*b1cdbd2cSJim Jagielski     bool                EnsureRawReadSize( sal_uInt16 nBytes );
491*b1cdbd2cSJim Jagielski     /** Returns the maximum size of raw data possible to read in one block. */
492*b1cdbd2cSJim Jagielski     sal_uInt16          GetMaxRawReadSize( sal_Size nBytes ) const;
493*b1cdbd2cSJim Jagielski 
494*b1cdbd2cSJim Jagielski     /** Reads and decrypts nBytes bytes to the existing(!) buffer pData.
495*b1cdbd2cSJim Jagielski         @return  Count of bytes really read. */
496*b1cdbd2cSJim Jagielski     sal_uInt16          ReadRawData( void* pData, sal_uInt16 nBytes );
497*b1cdbd2cSJim Jagielski 
498*b1cdbd2cSJim Jagielski     /** Reads 8 bit/16 bit string length. */
ReadByteStrLen(bool b16BitLen)499*b1cdbd2cSJim Jagielski     inline sal_uInt16   ReadByteStrLen( bool b16BitLen )
500*b1cdbd2cSJim Jagielski                             { return b16BitLen ? ReaduInt16() : ReaduInt8(); }
501*b1cdbd2cSJim Jagielski 
502*b1cdbd2cSJim Jagielski private:
503*b1cdbd2cSJim Jagielski     typedef ::std::vector< XclImpStreamPos > XclImpStreamPosStack;
504*b1cdbd2cSJim Jagielski 
505*b1cdbd2cSJim Jagielski     SvStream&           mrStrm;         /// Reference to the system input stream.
506*b1cdbd2cSJim Jagielski     const XclImpRoot&   mrRoot;         /// Filter root data.
507*b1cdbd2cSJim Jagielski 
508*b1cdbd2cSJim Jagielski     XclImpDecrypterRef  mxDecrypter;    /// Provides methods to decrypt data.
509*b1cdbd2cSJim Jagielski 
510*b1cdbd2cSJim Jagielski     XclImpStreamPos     maFirstRec;     /// Start position of current record.
511*b1cdbd2cSJim Jagielski     XclImpStreamPosStack maPosStack;    /// Stack for record positions.
512*b1cdbd2cSJim Jagielski 
513*b1cdbd2cSJim Jagielski     XclImpStreamPos     maGlobPos;      /// User defined position elsewhere in stream.
514*b1cdbd2cSJim Jagielski     sal_uInt16          mnGlobRecId;    /// Record ID for user defined position.
515*b1cdbd2cSJim Jagielski     bool                mbGlobValidRec; /// Was user position a valid record?
516*b1cdbd2cSJim Jagielski     bool                mbHasGlobPos;   /// Is user position defined?
517*b1cdbd2cSJim Jagielski 
518*b1cdbd2cSJim Jagielski     sal_Size            mnStreamSize;   /// Size of system stream.
519*b1cdbd2cSJim Jagielski     sal_Size            mnNextRecPos;   /// Start of next record header.
520*b1cdbd2cSJim Jagielski     sal_Size            mnCurrRecSize;  /// Helper for record position.
521*b1cdbd2cSJim Jagielski     sal_Size            mnComplRecSize; /// Size of complete record data (with CONTINUEs).
522*b1cdbd2cSJim Jagielski     bool                mbHasComplRec;  /// true = mnComplRecSize is valid.
523*b1cdbd2cSJim Jagielski 
524*b1cdbd2cSJim Jagielski     sal_uInt16          mnRecId;        /// Current record ID (not the CONTINUE ID).
525*b1cdbd2cSJim Jagielski     sal_uInt16          mnAltContId;    /// Alternative record ID for content continuation.
526*b1cdbd2cSJim Jagielski 
527*b1cdbd2cSJim Jagielski     sal_uInt16          mnRawRecId;     /// Current raw record ID (including CONTINUEs).
528*b1cdbd2cSJim Jagielski     sal_uInt16          mnRawRecSize;   /// Current raw record size (without following CONTINUEs).
529*b1cdbd2cSJim Jagielski     sal_uInt16          mnRawRecLeft;   /// Bytes left in current raw record (without following CONTINUEs).
530*b1cdbd2cSJim Jagielski 
531*b1cdbd2cSJim Jagielski     sal_Unicode         mcNulSubst;     /// Replacement for NUL characters.
532*b1cdbd2cSJim Jagielski 
533*b1cdbd2cSJim Jagielski     bool                mbCont;         /// Automatic CONTINUE lookup on/off.
534*b1cdbd2cSJim Jagielski     bool                mbUseDecr;      /// Usage of decryption.
535*b1cdbd2cSJim Jagielski     bool                mbValidRec;     /// false = No more records to read.
536*b1cdbd2cSJim Jagielski     bool                mbValid;        /// false = Record overread.
537*b1cdbd2cSJim Jagielski };
538*b1cdbd2cSJim Jagielski 
539*b1cdbd2cSJim Jagielski // ============================================================================
540*b1cdbd2cSJim Jagielski 
541*b1cdbd2cSJim Jagielski #endif
542*b1cdbd2cSJim Jagielski 
543