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 0 : AxAlignedInputStream::AxAlignedInputStream( BinaryInputStream& rInStrm ) :
39 : BinaryStreamBase( false ),
40 : mpInStrm( &rInStrm ),
41 : mnStrmPos( 0 ),
42 0 : mnStrmSize( rInStrm.getRemaining() )
43 : {
44 0 : mbEof = mbEof || rInStrm.isEof();
45 0 : }
46 :
47 0 : sal_Int64 AxAlignedInputStream::size() const
48 : {
49 0 : return mpInStrm ? mnStrmSize : -1;
50 : }
51 :
52 0 : sal_Int64 AxAlignedInputStream::tell() const
53 : {
54 0 : return mpInStrm ? mnStrmPos : -1;
55 : }
56 :
57 0 : void AxAlignedInputStream::seek( sal_Int64 nPos )
58 : {
59 0 : mbEof = mbEof || (nPos < mnStrmPos);
60 0 : if( !mbEof )
61 0 : skip( static_cast< sal_Int32 >( nPos - mnStrmPos ) );
62 0 : }
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 0 : sal_Int32 AxAlignedInputStream::readMemory( void* opMem, sal_Int32 nBytes, size_t nAtomSize )
83 : {
84 0 : sal_Int32 nReadSize = 0;
85 0 : if( !mbEof )
86 : {
87 0 : nReadSize = mpInStrm->readMemory( opMem, nBytes, nAtomSize );
88 0 : mnStrmPos += nReadSize;
89 0 : mbEof = mpInStrm->isEof();
90 : }
91 0 : return nReadSize;
92 : }
93 :
94 0 : void AxAlignedInputStream::skip( sal_Int32 nBytes, size_t nAtomSize )
95 : {
96 0 : if( !mbEof )
97 : {
98 0 : mpInStrm->skip( nBytes, nAtomSize );
99 0 : mnStrmPos += nBytes;
100 0 : mbEof = mpInStrm->isEof();
101 : }
102 0 : }
103 :
104 0 : void AxAlignedInputStream::align( size_t nSize )
105 : {
106 0 : skip( static_cast< sal_Int32 >( (nSize - (mnStrmPos % nSize)) % nSize ) );
107 0 : }
108 :
109 :
110 :
111 : namespace {
112 :
113 0 : bool lclReadString( AxAlignedInputStream& rInStrm, OUString& rValue, sal_uInt32 nSize, bool bArrayString )
114 : {
115 0 : bool bCompressed = getFlag( nSize, AX_STRING_COMPRESSED );
116 0 : sal_uInt32 nBufSize = nSize & AX_STRING_SIZEMASK;
117 : // Unicode: simple strings store byte count, array strings store char count
118 0 : sal_Int32 nChars = static_cast< sal_Int32 >( nBufSize / ((bCompressed || bArrayString) ? 1 : 2) );
119 0 : bool bValidChars = nChars <= 65536;
120 : OSL_ENSURE( bValidChars, "lclReadString - string too long" );
121 0 : sal_Int64 nEndPos = rInStrm.tell() + nChars * (bCompressed ? 1 : 2);
122 0 : nChars = ::std::min< sal_Int32 >( nChars, 65536 );
123 0 : rValue = rInStrm.readCompressedUnicodeArray( nChars, bCompressed );
124 0 : rInStrm.seek( nEndPos );
125 0 : return bValidChars;
126 : }
127 :
128 : } // namespace
129 :
130 :
131 :
132 0 : AxBinaryPropertyReader::ComplexProperty::~ComplexProperty()
133 : {
134 0 : }
135 :
136 0 : bool AxBinaryPropertyReader::PairProperty::readProperty( AxAlignedInputStream& rInStrm )
137 : {
138 0 : rInStrm >> mrPairData.first >> mrPairData.second;
139 0 : return true;
140 : }
141 :
142 0 : bool AxBinaryPropertyReader::StringProperty::readProperty( AxAlignedInputStream& rInStrm )
143 : {
144 0 : 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 0 : AxBinaryPropertyReader::AxBinaryPropertyReader( BinaryInputStream& rInStrm, bool b64BitPropFlags ) :
181 : maInStrm( rInStrm ),
182 0 : mbValid( true )
183 : {
184 : // version and size of property block
185 0 : maInStrm.skip( 2 );
186 0 : sal_uInt16 nBlockSize = maInStrm.readValue< sal_uInt16 >();
187 0 : mnPropsEnd = maInStrm.tell() + nBlockSize;
188 : // flagfield containing existing properties
189 0 : if( b64BitPropFlags )
190 0 : maInStrm >> mnPropFlags;
191 : else
192 0 : mnPropFlags = maInStrm.readuInt32();
193 0 : mnNextProp = 1;
194 0 : }
195 :
196 0 : void AxBinaryPropertyReader::readBoolProperty( bool& orbValue, bool bReverse )
197 : {
198 : // there is no data, the boolean value is equivalent to the property flag itself
199 0 : orbValue = startNextProperty() != bReverse;
200 0 : }
201 :
202 0 : void AxBinaryPropertyReader::readPairProperty( AxPairData& orPairData )
203 : {
204 0 : if( startNextProperty() )
205 0 : maLargeProps.push_back( ComplexPropVector::value_type( new PairProperty( orPairData ) ) );
206 0 : }
207 :
208 0 : void AxBinaryPropertyReader::readStringProperty( OUString& orValue )
209 : {
210 0 : if( startNextProperty() )
211 : {
212 0 : sal_uInt32 nSize = maInStrm.readAligned< sal_uInt32 >();
213 0 : maLargeProps.push_back( ComplexPropVector::value_type( new StringProperty( orValue, nSize ) ) );
214 : }
215 0 : }
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 0 : void AxBinaryPropertyReader::readFontProperty( AxFontData& orFontData )
233 : {
234 0 : 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 0 : }
241 :
242 0 : void AxBinaryPropertyReader::readPictureProperty( StreamDataSequence& orPicData )
243 : {
244 0 : 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 0 : }
251 :
252 0 : bool AxBinaryPropertyReader::finalizeImport()
253 : {
254 : // read large properties
255 0 : maInStrm.align( 4 );
256 0 : if( ensureValid( mnPropFlags == 0 ) && !maLargeProps.empty() )
257 : {
258 0 : for( ComplexPropVector::iterator aIt = maLargeProps.begin(), aEnd = maLargeProps.end(); ensureValid() && (aIt != aEnd); ++aIt )
259 : {
260 0 : ensureValid( (*aIt)->readProperty( maInStrm ) );
261 0 : maInStrm.align( 4 );
262 : }
263 : }
264 0 : maInStrm.seek( mnPropsEnd );
265 :
266 : // read stream properties (no stream alignment between properties!)
267 0 : 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 0 : return mbValid;
272 : }
273 :
274 0 : bool AxBinaryPropertyReader::ensureValid( bool bCondition )
275 : {
276 0 : mbValid = mbValid && bCondition && !maInStrm.isEof();
277 0 : return mbValid;
278 : }
279 :
280 0 : bool AxBinaryPropertyReader::startNextProperty()
281 : {
282 0 : bool bHasProp = getFlag( mnPropFlags, mnNextProp );
283 0 : setFlag( mnPropFlags, mnNextProp, false );
284 0 : mnNextProp <<= 1;
285 0 : return ensureValid() && bHasProp;
286 : }
287 :
288 :
289 :
290 : } // namespace ole
291 0 : } // namespace oox
292 :
293 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|