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