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