Branch data 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 : : #include "oox/ole/axbinaryreader.hxx"
21 : :
22 : : #include "oox/ole/olehelper.hxx"
23 : :
24 : : namespace oox {
25 : : namespace ole {
26 : :
27 : : // ============================================================================
28 : :
29 : : using ::rtl::OUString;
30 : :
31 : : // ============================================================================
32 : :
33 : : namespace {
34 : :
35 : : const sal_uInt32 AX_STRING_SIZEMASK = 0x7FFFFFFF;
36 : : const sal_uInt32 AX_STRING_COMPRESSED = 0x80000000;
37 : :
38 : : } // namespace
39 : :
40 : : // ============================================================================
41 : :
42 : 28 : AxAlignedInputStream::AxAlignedInputStream( BinaryInputStream& rInStrm ) :
43 : : BinaryStreamBase( false ),
44 : : mpInStrm( &rInStrm ),
45 : : mnStrmPos( 0 ),
46 [ + - ][ + - ]: 28 : mnStrmSize( rInStrm.getRemaining() )
[ # # ][ # # ]
47 : : {
48 [ + - ][ - + ]: 28 : mbEof = mbEof || rInStrm.isEof();
[ # # ][ # # ]
49 : 28 : }
50 : :
51 : 0 : sal_Int64 AxAlignedInputStream::size() const
52 : : {
53 [ # # ]: 0 : return mpInStrm ? mnStrmSize : -1;
54 : : }
55 : :
56 : 53 : sal_Int64 AxAlignedInputStream::tell() const
57 : : {
58 [ + - ]: 53 : return mpInStrm ? mnStrmPos : -1;
59 : : }
60 : :
61 : 53 : void AxAlignedInputStream::seek( sal_Int64 nPos )
62 : : {
63 [ + - ][ - + ]: 53 : mbEof = mbEof || (nPos < mnStrmPos);
64 [ + - ]: 53 : if( !mbEof )
65 : 53 : skip( static_cast< sal_Int32 >( nPos - mnStrmPos ) );
66 : 53 : }
67 : :
68 : 0 : void AxAlignedInputStream::close()
69 : : {
70 : 0 : mpInStrm = 0;
71 : 0 : mbEof = true;
72 : 0 : }
73 : :
74 : 0 : sal_Int32 AxAlignedInputStream::readData( StreamDataSequence& orData, sal_Int32 nBytes, size_t nAtomSize )
75 : : {
76 : 0 : sal_Int32 nReadSize = 0;
77 [ # # ]: 0 : if( !mbEof )
78 : : {
79 : 0 : nReadSize = mpInStrm->readData( orData, nBytes, nAtomSize );
80 : 0 : mnStrmPos += nReadSize;
81 : 0 : mbEof = mpInStrm->isEof();
82 : : }
83 : 0 : return nReadSize;
84 : : }
85 : :
86 : 206 : sal_Int32 AxAlignedInputStream::readMemory( void* opMem, sal_Int32 nBytes, size_t nAtomSize )
87 : : {
88 : 206 : sal_Int32 nReadSize = 0;
89 [ + - ]: 206 : if( !mbEof )
90 : : {
91 : 206 : nReadSize = mpInStrm->readMemory( opMem, nBytes, nAtomSize );
92 : 206 : mnStrmPos += nReadSize;
93 : 206 : mbEof = mpInStrm->isEof();
94 : : }
95 : 206 : return nReadSize;
96 : : }
97 : :
98 : 291 : void AxAlignedInputStream::skip( sal_Int32 nBytes, size_t nAtomSize )
99 : : {
100 [ + - ]: 291 : if( !mbEof )
101 : : {
102 : 291 : mpInStrm->skip( nBytes, nAtomSize );
103 : 291 : mnStrmPos += nBytes;
104 : 291 : mbEof = mpInStrm->isEof();
105 : : }
106 : 291 : }
107 : :
108 : 190 : void AxAlignedInputStream::align( size_t nSize )
109 : : {
110 : 190 : skip( static_cast< sal_Int32 >( (nSize - (mnStrmPos % nSize)) % nSize ) );
111 : 190 : }
112 : :
113 : : // ============================================================================
114 : :
115 : : namespace {
116 : :
117 : 25 : bool lclReadString( AxAlignedInputStream& rInStrm, OUString& rValue, sal_uInt32 nSize, bool bArrayString )
118 : : {
119 : 25 : bool bCompressed = getFlag( nSize, AX_STRING_COMPRESSED );
120 : 25 : sal_uInt32 nBufSize = nSize & AX_STRING_SIZEMASK;
121 : : // Unicode: simple strings store byte count, array strings store char count
122 [ # # ][ - + ]: 25 : sal_Int32 nChars = static_cast< sal_Int32 >( nBufSize / ((bCompressed || bArrayString) ? 1 : 2) );
123 : 25 : bool bValidChars = nChars <= 65536;
124 : : OSL_ENSURE( bValidChars, "lclReadString - string too long" );
125 [ + - ][ + - ]: 25 : sal_Int64 nEndPos = rInStrm.tell() + nChars * (bCompressed ? 1 : 2);
126 [ + - ]: 25 : nChars = ::std::min< sal_Int32 >( nChars, 65536 );
127 [ + - ]: 25 : rValue = rInStrm.readCompressedUnicodeArray( nChars, bCompressed );
128 [ + - ]: 25 : rInStrm.seek( nEndPos );
129 : 25 : return bValidChars;
130 : : }
131 : :
132 : : } // namespace
133 : :
134 : : // ----------------------------------------------------------------------------
135 : :
136 : 39 : AxBinaryPropertyReader::ComplexProperty::~ComplexProperty()
137 : : {
138 [ - + ]: 39 : }
139 : :
140 : 14 : bool AxBinaryPropertyReader::PairProperty::readProperty( AxAlignedInputStream& rInStrm )
141 : : {
142 : 14 : rInStrm >> mrPairData.first >> mrPairData.second;
143 : 14 : return true;
144 : : }
145 : :
146 : 25 : bool AxBinaryPropertyReader::StringProperty::readProperty( AxAlignedInputStream& rInStrm )
147 : : {
148 : 25 : return lclReadString( rInStrm, mrValue, mnSize, false );
149 : : }
150 : :
151 : 0 : bool AxBinaryPropertyReader::StringArrayProperty::readProperty( AxAlignedInputStream& rInStrm )
152 : : {
153 : 0 : sal_Int64 nEndPos = rInStrm.tell() + mnSize;
154 [ # # ]: 0 : while( rInStrm.tell() < nEndPos )
155 : : {
156 : 0 : OUString aString;
157 [ # # ][ # # ]: 0 : if( !lclReadString( rInStrm, aString, rInStrm.readuInt32(), true ) )
[ # # ]
158 : 0 : return false;
159 [ # # ]: 0 : mrArray.push_back( aString );
160 : : // every array string is aligned on 4 byte boundries
161 [ # # ][ # # ]: 0 : rInStrm.align( 4 );
162 : 0 : }
163 : 0 : return true;
164 : : }
165 : :
166 : 0 : bool AxBinaryPropertyReader::GuidProperty::readProperty( AxAlignedInputStream& rInStrm )
167 : : {
168 : 0 : mrGuid = OleHelper::importGuid( rInStrm );
169 : 0 : return true;
170 : : }
171 : :
172 : 0 : bool AxBinaryPropertyReader::FontProperty::readProperty( AxAlignedInputStream& rInStrm )
173 : : {
174 : 0 : return mrFontData.importGuidAndFont( rInStrm );
175 : : }
176 : :
177 : 0 : bool AxBinaryPropertyReader::PictureProperty::readProperty( AxAlignedInputStream& rInStrm )
178 : : {
179 : 0 : return OleHelper::importStdPic( mrPicData, rInStrm, true );
180 : : }
181 : :
182 : : // ----------------------------------------------------------------------------
183 : :
184 : 28 : AxBinaryPropertyReader::AxBinaryPropertyReader( BinaryInputStream& rInStrm, bool b64BitPropFlags ) :
185 : : maInStrm( rInStrm ),
186 [ + - ][ + - ]: 28 : mbValid( true )
[ + - ][ + - ]
[ + - ]
187 : : {
188 : : // version and size of property block
189 [ + - ]: 28 : maInStrm.skip( 2 );
190 [ + - ]: 28 : sal_uInt16 nBlockSize = maInStrm.readValue< sal_uInt16 >();
191 : 28 : mnPropsEnd = maInStrm.tell() + nBlockSize;
192 : : // flagfield containing existing properties
193 [ + + ]: 28 : if( b64BitPropFlags )
194 [ + - ]: 3 : maInStrm >> mnPropFlags;
195 : : else
196 [ + - ]: 25 : mnPropFlags = maInStrm.readuInt32();
197 : 28 : mnNextProp = 1;
198 : 28 : }
199 : :
200 : 11 : void AxBinaryPropertyReader::readBoolProperty( bool& orbValue, bool bReverse )
201 : : {
202 : : // there is no data, the boolean value is equivalent to the property flag itself
203 : 11 : orbValue = startNextProperty() != bReverse;
204 : 11 : }
205 : :
206 : 14 : void AxBinaryPropertyReader::readPairProperty( AxPairData& orPairData )
207 : : {
208 [ + - ]: 14 : if( startNextProperty() )
209 [ + - ][ + - ]: 14 : maLargeProps.push_back( ComplexPropVector::value_type( new PairProperty( orPairData ) ) );
210 : 14 : }
211 : :
212 : 34 : void AxBinaryPropertyReader::readStringProperty( OUString& orValue )
213 : : {
214 [ + + ]: 34 : if( startNextProperty() )
215 : : {
216 : 25 : sal_uInt32 nSize = maInStrm.readAligned< sal_uInt32 >();
217 [ + - ][ + - ]: 25 : maLargeProps.push_back( ComplexPropVector::value_type( new StringProperty( orValue, nSize ) ) );
218 : : }
219 : 34 : }
220 : :
221 : 0 : void AxBinaryPropertyReader::readStringArrayProperty( AxStringArray& orArray )
222 : : {
223 [ # # ]: 0 : if( startNextProperty() )
224 : : {
225 : 0 : sal_uInt32 nSize = maInStrm.readAligned< sal_uInt32 >();
226 [ # # ][ # # ]: 0 : maLargeProps.push_back( ComplexPropVector::value_type( new StringArrayProperty( orArray, nSize ) ) );
227 : : }
228 : 0 : }
229 : :
230 : 0 : void AxBinaryPropertyReader::readGuidProperty( ::rtl::OUString& orGuid )
231 : : {
232 [ # # ]: 0 : if( startNextProperty() )
233 [ # # ][ # # ]: 0 : maLargeProps.push_back( ComplexPropVector::value_type( new GuidProperty( orGuid ) ) );
234 : 0 : }
235 : :
236 : 0 : void AxBinaryPropertyReader::readFontProperty( AxFontData& orFontData )
237 : : {
238 [ # # ]: 0 : if( startNextProperty() )
239 : : {
240 : 0 : sal_Int16 nData = maInStrm.readAligned< sal_Int16 >();
241 [ # # ]: 0 : if( ensureValid( nData == -1 ) )
242 [ # # ][ # # ]: 0 : maStreamProps.push_back( ComplexPropVector::value_type( new FontProperty( orFontData ) ) );
243 : : }
244 : 0 : }
245 : :
246 : 28 : void AxBinaryPropertyReader::readPictureProperty( StreamDataSequence& orPicData )
247 : : {
248 [ - + ]: 28 : if( startNextProperty() )
249 : : {
250 : 0 : sal_Int16 nData = maInStrm.readAligned< sal_Int16 >();
251 [ # # ]: 0 : if( ensureValid( nData == -1 ) )
252 [ # # ][ # # ]: 0 : maStreamProps.push_back( ComplexPropVector::value_type( new PictureProperty( orPicData ) ) );
253 : : }
254 : 28 : }
255 : :
256 : 28 : bool AxBinaryPropertyReader::finalizeImport()
257 : : {
258 : : // read large properties
259 : 28 : maInStrm.align( 4 );
260 [ + + ][ + + ]: 28 : if( ensureValid( mnPropFlags == 0 ) && !maLargeProps.empty() )
[ + - ]
261 : : {
262 [ + - ][ + - ]: 58 : for( ComplexPropVector::iterator aIt = maLargeProps.begin(), aEnd = maLargeProps.end(); ensureValid() && (aIt != aEnd); ++aIt )
[ + + ][ + + ]
263 : : {
264 [ + - ]: 39 : ensureValid( (*aIt)->readProperty( maInStrm ) );
265 [ + - ]: 39 : maInStrm.align( 4 );
266 : : }
267 : : }
268 : 28 : maInStrm.seek( mnPropsEnd );
269 : :
270 : : // read stream properties (no stream alignment between properties!)
271 [ - + ][ - + ]: 28 : if( ensureValid() && !maStreamProps.empty() )
[ + - ]
272 [ # # ][ # # ]: 0 : for( ComplexPropVector::iterator aIt = maStreamProps.begin(), aEnd = maStreamProps.end(); ensureValid() && (aIt != aEnd); ++aIt )
[ # # ][ # # ]
273 [ # # ]: 0 : ensureValid( (*aIt)->readProperty( maInStrm ) );
274 : :
275 : 28 : return mbValid;
276 : : }
277 : :
278 : 491 : bool AxBinaryPropertyReader::ensureValid( bool bCondition )
279 : : {
280 [ + - ][ + - ]: 491 : mbValid = mbValid && bCondition && !maInStrm.isEof();
[ + - ]
281 : 491 : return mbValid;
282 : : }
283 : :
284 : 332 : bool AxBinaryPropertyReader::startNextProperty()
285 : : {
286 : 332 : bool bHasProp = getFlag( mnPropFlags, mnNextProp );
287 : 332 : setFlag( mnPropFlags, mnNextProp, false );
288 : 332 : mnNextProp <<= 1;
289 [ + + ][ + - ]: 332 : return ensureValid() && bHasProp;
290 : : }
291 : :
292 : : // ============================================================================
293 : :
294 : : } // namespace ole
295 [ + - ][ + - ]: 285 : } // namespace oox
296 : :
297 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|