xref: /aoo41x/main/oox/source/ole/vbainputstream.cxx (revision cdf0e10c)
1*cdf0e10cSrcweir /*************************************************************************
2*cdf0e10cSrcweir  *
3*cdf0e10cSrcweir  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4*cdf0e10cSrcweir  *
5*cdf0e10cSrcweir  * Copyright 2000, 2010 Oracle and/or its affiliates.
6*cdf0e10cSrcweir  *
7*cdf0e10cSrcweir  * OpenOffice.org - a multi-platform office productivity suite
8*cdf0e10cSrcweir  *
9*cdf0e10cSrcweir  * This file is part of OpenOffice.org.
10*cdf0e10cSrcweir  *
11*cdf0e10cSrcweir  * OpenOffice.org is free software: you can redistribute it and/or modify
12*cdf0e10cSrcweir  * it under the terms of the GNU Lesser General Public License version 3
13*cdf0e10cSrcweir  * only, as published by the Free Software Foundation.
14*cdf0e10cSrcweir  *
15*cdf0e10cSrcweir  * OpenOffice.org is distributed in the hope that it will be useful,
16*cdf0e10cSrcweir  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17*cdf0e10cSrcweir  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18*cdf0e10cSrcweir  * GNU Lesser General Public License version 3 for more details
19*cdf0e10cSrcweir  * (a copy is included in the LICENSE file that accompanied this code).
20*cdf0e10cSrcweir  *
21*cdf0e10cSrcweir  * You should have received a copy of the GNU Lesser General Public License
22*cdf0e10cSrcweir  * version 3 along with OpenOffice.org.  If not, see
23*cdf0e10cSrcweir  * <http://www.openoffice.org/license.html>
24*cdf0e10cSrcweir  * for a copy of the LGPLv3 License.
25*cdf0e10cSrcweir  *
26*cdf0e10cSrcweir  ************************************************************************/
27*cdf0e10cSrcweir 
28*cdf0e10cSrcweir #include "oox/ole/vbainputstream.hxx"
29*cdf0e10cSrcweir #include <osl/diagnose.h>
30*cdf0e10cSrcweir 
31*cdf0e10cSrcweir namespace oox {
32*cdf0e10cSrcweir namespace ole {
33*cdf0e10cSrcweir 
34*cdf0e10cSrcweir // ============================================================================
35*cdf0e10cSrcweir 
36*cdf0e10cSrcweir namespace {
37*cdf0e10cSrcweir 
38*cdf0e10cSrcweir const sal_uInt8 VBASTREAM_SIGNATURE         = 1;
39*cdf0e10cSrcweir 
40*cdf0e10cSrcweir const sal_uInt16 VBACHUNK_SIGMASK           = 0x7000;
41*cdf0e10cSrcweir const sal_uInt16 VBACHUNK_SIG               = 0x3000;
42*cdf0e10cSrcweir const sal_uInt16 VBACHUNK_COMPRESSED        = 0x8000;
43*cdf0e10cSrcweir const sal_uInt16 VBACHUNK_LENMASK           = 0x0FFF;
44*cdf0e10cSrcweir 
45*cdf0e10cSrcweir } // namespace
46*cdf0e10cSrcweir 
47*cdf0e10cSrcweir // ============================================================================
48*cdf0e10cSrcweir 
49*cdf0e10cSrcweir VbaInputStream::VbaInputStream( BinaryInputStream& rInStrm ) :
50*cdf0e10cSrcweir     BinaryStreamBase( false ),
51*cdf0e10cSrcweir     mpInStrm( &rInStrm ),
52*cdf0e10cSrcweir     mnChunkPos( 0 )
53*cdf0e10cSrcweir {
54*cdf0e10cSrcweir     maChunk.reserve( 4096 );
55*cdf0e10cSrcweir 
56*cdf0e10cSrcweir     sal_uInt8 nSig = rInStrm.readuInt8();
57*cdf0e10cSrcweir     OSL_ENSURE( nSig == VBASTREAM_SIGNATURE, "VbaInputStream::VbaInputStream - wrong signature" );
58*cdf0e10cSrcweir     mbEof = mbEof || rInStrm.isEof() || (nSig != VBASTREAM_SIGNATURE);
59*cdf0e10cSrcweir }
60*cdf0e10cSrcweir 
61*cdf0e10cSrcweir sal_Int64 VbaInputStream::size() const
62*cdf0e10cSrcweir {
63*cdf0e10cSrcweir     return -1;
64*cdf0e10cSrcweir }
65*cdf0e10cSrcweir 
66*cdf0e10cSrcweir sal_Int64 VbaInputStream::tell() const
67*cdf0e10cSrcweir {
68*cdf0e10cSrcweir     return -1;
69*cdf0e10cSrcweir }
70*cdf0e10cSrcweir 
71*cdf0e10cSrcweir void VbaInputStream::seek( sal_Int64 )
72*cdf0e10cSrcweir {
73*cdf0e10cSrcweir }
74*cdf0e10cSrcweir 
75*cdf0e10cSrcweir void VbaInputStream::close()
76*cdf0e10cSrcweir {
77*cdf0e10cSrcweir     mpInStrm = 0;
78*cdf0e10cSrcweir     mbEof = true;
79*cdf0e10cSrcweir }
80*cdf0e10cSrcweir 
81*cdf0e10cSrcweir sal_Int32 VbaInputStream::readData( StreamDataSequence& orData, sal_Int32 nBytes, size_t nAtomSize )
82*cdf0e10cSrcweir {
83*cdf0e10cSrcweir     sal_Int32 nRet = 0;
84*cdf0e10cSrcweir     if( !mbEof )
85*cdf0e10cSrcweir     {
86*cdf0e10cSrcweir         orData.realloc( ::std::max< sal_Int32 >( nBytes, 0 ) );
87*cdf0e10cSrcweir         if( nBytes > 0 )
88*cdf0e10cSrcweir         {
89*cdf0e10cSrcweir             nRet = readMemory( orData.getArray(), nBytes, nAtomSize );
90*cdf0e10cSrcweir             if( nRet < nBytes )
91*cdf0e10cSrcweir                 orData.realloc( nRet );
92*cdf0e10cSrcweir         }
93*cdf0e10cSrcweir     }
94*cdf0e10cSrcweir     return nRet;
95*cdf0e10cSrcweir }
96*cdf0e10cSrcweir 
97*cdf0e10cSrcweir sal_Int32 VbaInputStream::readMemory( void* opMem, sal_Int32 nBytes, size_t /*nAtomSize*/ )
98*cdf0e10cSrcweir {
99*cdf0e10cSrcweir     sal_Int32 nRet = 0;
100*cdf0e10cSrcweir     sal_uInt8* opnMem = reinterpret_cast< sal_uInt8* >( opMem );
101*cdf0e10cSrcweir     while( (nBytes > 0) && updateChunk() )
102*cdf0e10cSrcweir     {
103*cdf0e10cSrcweir         sal_Int32 nChunkLeft = static_cast< sal_Int32 >( maChunk.size() - mnChunkPos );
104*cdf0e10cSrcweir         sal_Int32 nReadBytes = ::std::min( nBytes, nChunkLeft );
105*cdf0e10cSrcweir         memcpy( opnMem, &*(maChunk.begin() + mnChunkPos), nReadBytes );
106*cdf0e10cSrcweir         opnMem += nReadBytes;
107*cdf0e10cSrcweir         mnChunkPos += static_cast< size_t >( nReadBytes );
108*cdf0e10cSrcweir         nBytes -= nReadBytes;
109*cdf0e10cSrcweir         nRet += nReadBytes;
110*cdf0e10cSrcweir     }
111*cdf0e10cSrcweir     return nRet;
112*cdf0e10cSrcweir }
113*cdf0e10cSrcweir 
114*cdf0e10cSrcweir void VbaInputStream::skip( sal_Int32 nBytes, size_t /*nAtomSize*/ )
115*cdf0e10cSrcweir {
116*cdf0e10cSrcweir     while( (nBytes > 0) && updateChunk() )
117*cdf0e10cSrcweir     {
118*cdf0e10cSrcweir         sal_Int32 nChunkLeft = static_cast< sal_Int32 >( maChunk.size() - mnChunkPos );
119*cdf0e10cSrcweir         sal_Int32 nSkipBytes = ::std::min( nBytes, nChunkLeft );
120*cdf0e10cSrcweir         mnChunkPos += static_cast< size_t >( nSkipBytes );
121*cdf0e10cSrcweir         nBytes -= nSkipBytes;
122*cdf0e10cSrcweir     }
123*cdf0e10cSrcweir }
124*cdf0e10cSrcweir 
125*cdf0e10cSrcweir // private --------------------------------------------------------------------
126*cdf0e10cSrcweir 
127*cdf0e10cSrcweir bool VbaInputStream::updateChunk()
128*cdf0e10cSrcweir {
129*cdf0e10cSrcweir     if( mbEof || (mnChunkPos < maChunk.size()) ) return !mbEof;
130*cdf0e10cSrcweir 
131*cdf0e10cSrcweir     // try to read next chunk header, this may trigger EOF
132*cdf0e10cSrcweir     sal_uInt16 nHeader = mpInStrm->readuInt16();
133*cdf0e10cSrcweir     mbEof = mpInStrm->isEof();
134*cdf0e10cSrcweir     if( mbEof ) return false;
135*cdf0e10cSrcweir 
136*cdf0e10cSrcweir     // check header signature
137*cdf0e10cSrcweir     OSL_ENSURE( (nHeader & VBACHUNK_SIGMASK) == VBACHUNK_SIG, "VbaInputStream::updateChunk - invalid chunk signature" );
138*cdf0e10cSrcweir     mbEof = (nHeader & VBACHUNK_SIGMASK) != VBACHUNK_SIG;
139*cdf0e10cSrcweir     if( mbEof ) return false;
140*cdf0e10cSrcweir 
141*cdf0e10cSrcweir     // decode length of chunk data and compression flag
142*cdf0e10cSrcweir     bool bCompressed = getFlag( nHeader, VBACHUNK_COMPRESSED );
143*cdf0e10cSrcweir     sal_uInt16 nChunkLen = (nHeader & VBACHUNK_LENMASK) + 1;
144*cdf0e10cSrcweir     OSL_ENSURE( bCompressed || (nChunkLen == 4096), "VbaInputStream::updateChunk - invalid uncompressed chunk size" );
145*cdf0e10cSrcweir     if( bCompressed )
146*cdf0e10cSrcweir     {
147*cdf0e10cSrcweir         maChunk.clear();
148*cdf0e10cSrcweir         sal_uInt8 nBitCount = 4;
149*cdf0e10cSrcweir         sal_uInt16 nChunkPos = 0;
150*cdf0e10cSrcweir         while( !mbEof && !mpInStrm->isEof() && (nChunkPos < nChunkLen) )
151*cdf0e10cSrcweir         {
152*cdf0e10cSrcweir             sal_uInt8 nTokenFlags = mpInStrm->readuInt8();
153*cdf0e10cSrcweir             ++nChunkPos;
154*cdf0e10cSrcweir             for( int nBit = 0; !mbEof && !mpInStrm->isEof() && (nBit < 8) && (nChunkPos < nChunkLen); ++nBit, nTokenFlags >>= 1 )
155*cdf0e10cSrcweir             {
156*cdf0e10cSrcweir                 if( nTokenFlags & 1 )
157*cdf0e10cSrcweir                 {
158*cdf0e10cSrcweir                     sal_uInt16 nCopyToken = mpInStrm->readuInt16();
159*cdf0e10cSrcweir                     nChunkPos = nChunkPos + 2;
160*cdf0e10cSrcweir                     // update bit count used for offset/length in the token
161*cdf0e10cSrcweir                     while( static_cast< size_t >( 1 << nBitCount ) < maChunk.size() ) ++nBitCount;
162*cdf0e10cSrcweir                     // extract length from lower (16-nBitCount) bits, plus 3
163*cdf0e10cSrcweir                     sal_uInt16 nLength = extractValue< sal_uInt16 >( nCopyToken, 0, 16 - nBitCount ) + 3;
164*cdf0e10cSrcweir                     // extract offset from high nBitCount bits, plus 1
165*cdf0e10cSrcweir                     sal_uInt16 nOffset = extractValue< sal_uInt16 >( nCopyToken, 16 - nBitCount, nBitCount ) + 1;
166*cdf0e10cSrcweir                     mbEof = (nOffset > maChunk.size()) || (maChunk.size() + nLength > 4096);
167*cdf0e10cSrcweir                     OSL_ENSURE( !mbEof, "VbaInputStream::updateChunk - invalid offset or size in copy token" );
168*cdf0e10cSrcweir                     if( !mbEof )
169*cdf0e10cSrcweir                     {
170*cdf0e10cSrcweir                         // append data to buffer
171*cdf0e10cSrcweir                         maChunk.resize( maChunk.size() + nLength );
172*cdf0e10cSrcweir                         sal_uInt8* pnTo = &*(maChunk.end() - nLength);
173*cdf0e10cSrcweir                         const sal_uInt8* pnEnd = pnTo + nLength;
174*cdf0e10cSrcweir                         const sal_uInt8* pnFrom = pnTo - nOffset;
175*cdf0e10cSrcweir                         // offset may be less than length, effectively duplicating source data several times
176*cdf0e10cSrcweir                         size_t nRunLen = ::std::min< size_t >( nLength, nOffset );
177*cdf0e10cSrcweir                         while( pnTo < pnEnd )
178*cdf0e10cSrcweir                         {
179*cdf0e10cSrcweir                             size_t nStepLen = ::std::min< size_t >( nRunLen, pnEnd - pnTo );
180*cdf0e10cSrcweir                             memcpy( pnTo, pnFrom, nStepLen );
181*cdf0e10cSrcweir                             pnTo += nStepLen;
182*cdf0e10cSrcweir                         }
183*cdf0e10cSrcweir                     }
184*cdf0e10cSrcweir                 }
185*cdf0e10cSrcweir                 else
186*cdf0e10cSrcweir                 {
187*cdf0e10cSrcweir                     maChunk.resize( maChunk.size() + 1 );
188*cdf0e10cSrcweir                     *mpInStrm >> maChunk.back();
189*cdf0e10cSrcweir                     ++nChunkPos;
190*cdf0e10cSrcweir                 }
191*cdf0e10cSrcweir             }
192*cdf0e10cSrcweir         }
193*cdf0e10cSrcweir     }
194*cdf0e10cSrcweir     else
195*cdf0e10cSrcweir     {
196*cdf0e10cSrcweir         maChunk.resize( nChunkLen );
197*cdf0e10cSrcweir         mpInStrm->readMemory( &maChunk.front(), nChunkLen );
198*cdf0e10cSrcweir     }
199*cdf0e10cSrcweir 
200*cdf0e10cSrcweir     mnChunkPos = 0;
201*cdf0e10cSrcweir     return !mbEof;
202*cdf0e10cSrcweir }
203*cdf0e10cSrcweir 
204*cdf0e10cSrcweir // ============================================================================
205*cdf0e10cSrcweir 
206*cdf0e10cSrcweir } // namespace ole
207*cdf0e10cSrcweir } // namespace oox
208*cdf0e10cSrcweir 
209