1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 #include "oox/helper/binaryinputstream.hxx"
25
26 #include <com/sun/star/io/XInputStream.hpp>
27 #include <com/sun/star/io/XSeekable.hpp>
28 #include <string.h>
29 #include <vector>
30 #include <rtl/strbuf.hxx>
31 #include <rtl/ustrbuf.hxx>
32 #include "oox/helper/binaryoutputstream.hxx"
33
34 namespace oox {
35
36 // ============================================================================
37
38 using namespace ::com::sun::star::io;
39 using namespace ::com::sun::star::uno;
40
41 using ::rtl::OString;
42 using ::rtl::OStringBuffer;
43 using ::rtl::OStringToOUString;
44 using ::rtl::OUString;
45 using ::rtl::OUStringBuffer;
46
47 namespace {
48
49 const sal_Int32 INPUTSTREAM_BUFFERSIZE = 0x8000;
50
51 } // namespace
52
53 // ============================================================================
54
readNulCharArray()55 OString BinaryInputStream::readNulCharArray()
56 {
57 OStringBuffer aBuffer;
58 for( sal_uInt8 nChar = readuInt8(); !mbEof && (nChar > 0); readValue( nChar ) )
59 aBuffer.append( static_cast< sal_Char >( nChar ) );
60 return aBuffer.makeStringAndClear();
61 }
62
readNulCharArrayUC(rtl_TextEncoding eTextEnc)63 OUString BinaryInputStream::readNulCharArrayUC( rtl_TextEncoding eTextEnc )
64 {
65 return OStringToOUString( readNulCharArray(), eTextEnc );
66 }
67
readNulUnicodeArray()68 OUString BinaryInputStream::readNulUnicodeArray()
69 {
70 OUStringBuffer aBuffer;
71 for( sal_uInt16 nChar = readuInt16(); !mbEof && (nChar > 0); readValue( nChar ) )
72 aBuffer.append( static_cast< sal_Unicode >( nChar ) );
73 return aBuffer.makeStringAndClear();
74 }
75
readCharArray(sal_Int32 nChars,bool bAllowNulChars)76 OString BinaryInputStream::readCharArray( sal_Int32 nChars, bool bAllowNulChars )
77 {
78 if( nChars <= 0 )
79 return OString();
80
81 ::std::vector< sal_uInt8 > aBuffer;
82 sal_Int32 nCharsRead = readArray( aBuffer, nChars );
83 if( nCharsRead <= 0 )
84 return OString();
85
86 aBuffer.resize( static_cast< size_t >( nCharsRead ) );
87 if( !bAllowNulChars )
88 ::std::replace( aBuffer.begin(), aBuffer.end(), '\0', '?' );
89
90 return OString( reinterpret_cast< sal_Char* >( &aBuffer.front() ), nCharsRead );
91 }
92
readCharArrayUC(sal_Int32 nChars,rtl_TextEncoding eTextEnc,bool bAllowNulChars)93 OUString BinaryInputStream::readCharArrayUC( sal_Int32 nChars, rtl_TextEncoding eTextEnc, bool bAllowNulChars )
94 {
95 return OStringToOUString( readCharArray( nChars, bAllowNulChars ), eTextEnc );
96 }
97
readUnicodeArray(sal_Int32 nChars,bool bAllowNulChars)98 OUString BinaryInputStream::readUnicodeArray( sal_Int32 nChars, bool bAllowNulChars )
99 {
100 if( nChars <= 0 )
101 return OUString();
102
103 ::std::vector< sal_uInt16 > aBuffer;
104 sal_Int32 nCharsRead = readArray( aBuffer, nChars );
105 if( nCharsRead <= 0 )
106 return OUString();
107
108 aBuffer.resize( static_cast< size_t >( nCharsRead ) );
109 if( !bAllowNulChars )
110 ::std::replace( aBuffer.begin(), aBuffer.begin() + nCharsRead, '\0', '?' );
111
112 OUStringBuffer aStringBuffer;
113 aStringBuffer.ensureCapacity( nCharsRead );
114 for( ::std::vector< sal_uInt16 >::iterator aIt = aBuffer.begin(), aEnd = aBuffer.end(); aIt != aEnd; ++aIt )
115 aStringBuffer.append( static_cast< sal_Unicode >( *aIt ) );
116 return aStringBuffer.makeStringAndClear();
117 }
118
readCompressedUnicodeArray(sal_Int32 nChars,bool bCompressed,bool bAllowNulChars)119 OUString BinaryInputStream::readCompressedUnicodeArray( sal_Int32 nChars, bool bCompressed, bool bAllowNulChars )
120 {
121 return bCompressed ?
122 // ISO-8859-1 maps all byte values 0xHH to the same Unicode code point U+00HH
123 readCharArrayUC( nChars, RTL_TEXTENCODING_ISO_8859_1, bAllowNulChars ) :
124 readUnicodeArray( nChars, bAllowNulChars );
125 }
126
copyToStream(BinaryOutputStream & rOutStrm,sal_Int64 nBytes,sal_Int32 nAtomSize)127 void BinaryInputStream::copyToStream( BinaryOutputStream& rOutStrm, sal_Int64 nBytes, sal_Int32 nAtomSize )
128 {
129 if( nBytes > 0 )
130 {
131 // make buffer size a multiple of the passed atom size
132 sal_Int32 nBufferSize = getLimitedValue< sal_Int32, sal_Int64 >( nBytes, 0, (INPUTSTREAM_BUFFERSIZE / nAtomSize) * nAtomSize );
133 StreamDataSequence aBuffer( nBufferSize );
134 while( nBytes > 0 )
135 {
136 sal_Int32 nReadSize = getLimitedValue< sal_Int32, sal_Int64 >( nBytes, 0, nBufferSize );
137 sal_Int32 nBytesRead = readData( aBuffer, nReadSize, nAtomSize );
138 rOutStrm.writeData( aBuffer );
139 if( nReadSize == nBytesRead )
140 nBytes -= nReadSize;
141 else
142 nBytes = 0;
143 }
144 }
145 }
146
147 // ============================================================================
148
BinaryXInputStream(const Reference<XInputStream> & rxInStrm,bool bAutoClose)149 BinaryXInputStream::BinaryXInputStream( const Reference< XInputStream >& rxInStrm, bool bAutoClose ) :
150 BinaryStreamBase( Reference< XSeekable >( rxInStrm, UNO_QUERY ).is() ),
151 BinaryXSeekableStream( Reference< XSeekable >( rxInStrm, UNO_QUERY ) ),
152 maBuffer( INPUTSTREAM_BUFFERSIZE ),
153 mxInStrm( rxInStrm ),
154 mbAutoClose( bAutoClose && rxInStrm.is() )
155 {
156 mbEof = !mxInStrm.is();
157 }
158
~BinaryXInputStream()159 BinaryXInputStream::~BinaryXInputStream()
160 {
161 close();
162 }
163
close()164 void BinaryXInputStream::close()
165 {
166 OSL_ENSURE( !mbAutoClose || mxInStrm.is(), "BinaryXInputStream::close - invalid call" );
167 if( mbAutoClose && mxInStrm.is() ) try
168 {
169 mxInStrm->closeInput();
170 }
171 catch( Exception& )
172 {
173 OSL_ENSURE( false, "BinaryXInputStream::close - closing input stream failed" );
174 }
175 mxInStrm.clear();
176 mbAutoClose = false;
177 BinaryXSeekableStream::close();
178 }
179
readData(StreamDataSequence & orData,sal_Int32 nBytes,size_t)180 sal_Int32 BinaryXInputStream::readData( StreamDataSequence& orData, sal_Int32 nBytes, size_t /*nAtomSize*/ )
181 {
182 sal_Int32 nRet = 0;
183 if( !mbEof && (nBytes > 0) ) try
184 {
185 nRet = mxInStrm->readBytes( orData, nBytes );
186 mbEof = nRet != nBytes;
187 }
188 catch( Exception& )
189 {
190 mbEof = true;
191 }
192 return nRet;
193 }
194
readMemory(void * opMem,sal_Int32 nBytes,size_t nAtomSize)195 sal_Int32 BinaryXInputStream::readMemory( void* opMem, sal_Int32 nBytes, size_t nAtomSize )
196 {
197 sal_Int32 nRet = 0;
198 if( !mbEof && (nBytes > 0) )
199 {
200 sal_Int32 nBufferSize = getLimitedValue< sal_Int32, sal_Int32 >( nBytes, 0, INPUTSTREAM_BUFFERSIZE );
201 sal_uInt8* opnMem = reinterpret_cast< sal_uInt8* >( opMem );
202 while( !mbEof && (nBytes > 0) )
203 {
204 sal_Int32 nReadSize = getLimitedValue< sal_Int32, sal_Int32 >( nBytes, 0, nBufferSize );
205 sal_Int32 nBytesRead = readData( maBuffer, nReadSize, nAtomSize );
206 if( nBytesRead > 0 )
207 memcpy( opnMem, maBuffer.getConstArray(), static_cast< size_t >( nBytesRead ) );
208 opnMem += nBytesRead;
209 nBytes -= nBytesRead;
210 nRet += nBytesRead;
211 }
212 }
213 return nRet;
214 }
215
skip(sal_Int32 nBytes,size_t)216 void BinaryXInputStream::skip( sal_Int32 nBytes, size_t /*nAtomSize*/ )
217 {
218 if( !mbEof ) try
219 {
220 mxInStrm->skipBytes( nBytes );
221 }
222 catch( Exception& )
223 {
224 mbEof = true;
225 }
226 }
227
228 // ============================================================================
229
SequenceInputStream(const StreamDataSequence & rData)230 SequenceInputStream::SequenceInputStream( const StreamDataSequence& rData ) :
231 BinaryStreamBase( true ),
232 SequenceSeekableStream( rData )
233 {
234 }
235
readData(StreamDataSequence & orData,sal_Int32 nBytes,size_t)236 sal_Int32 SequenceInputStream::readData( StreamDataSequence& orData, sal_Int32 nBytes, size_t /*nAtomSize*/ )
237 {
238 sal_Int32 nReadBytes = 0;
239 if( !mbEof )
240 {
241 nReadBytes = getMaxBytes( nBytes );
242 orData.realloc( nReadBytes );
243 if( nReadBytes > 0 )
244 memcpy( orData.getArray(), mpData->getConstArray() + mnPos, static_cast< size_t >( nReadBytes ) );
245 mnPos += nReadBytes;
246 mbEof = nReadBytes < nBytes;
247 }
248 return nReadBytes;
249 }
250
readMemory(void * opMem,sal_Int32 nBytes,size_t)251 sal_Int32 SequenceInputStream::readMemory( void* opMem, sal_Int32 nBytes, size_t /*nAtomSize*/ )
252 {
253 sal_Int32 nReadBytes = 0;
254 if( !mbEof )
255 {
256 nReadBytes = getMaxBytes( nBytes );
257 if( nReadBytes > 0 )
258 memcpy( opMem, mpData->getConstArray() + mnPos, static_cast< size_t >( nReadBytes ) );
259 mnPos += nReadBytes;
260 mbEof = nReadBytes < nBytes;
261 }
262 return nReadBytes;
263 }
264
skip(sal_Int32 nBytes,size_t)265 void SequenceInputStream::skip( sal_Int32 nBytes, size_t /*nAtomSize*/ )
266 {
267 if( !mbEof )
268 {
269 sal_Int32 nSkipBytes = getMaxBytes( nBytes );
270 mnPos += nSkipBytes;
271 mbEof = nSkipBytes < nBytes;
272 }
273 }
274
275 // ============================================================================
276
RelativeInputStream(BinaryInputStream & rInStrm,sal_Int64 nSize)277 RelativeInputStream::RelativeInputStream( BinaryInputStream& rInStrm, sal_Int64 nSize ) :
278 BinaryStreamBase( rInStrm.isSeekable() ),
279 mpInStrm( &rInStrm ),
280 mnStartPos( rInStrm.tell() ),
281 mnRelPos( 0 )
282 {
283 sal_Int64 nRemaining = rInStrm.getRemaining();
284 mnSize = (nRemaining >= 0) ? ::std::min( nSize, nRemaining ) : nSize;
285 mbEof = mbEof || rInStrm.isEof() || (mnSize < 0);
286 }
287
size() const288 sal_Int64 RelativeInputStream::size() const
289 {
290 return mpInStrm ? mnSize : -1;
291 }
292
tell() const293 sal_Int64 RelativeInputStream::tell() const
294 {
295 return mpInStrm ? mnRelPos : -1;
296 }
297
seek(sal_Int64 nPos)298 void RelativeInputStream::seek( sal_Int64 nPos )
299 {
300 if( mpInStrm && isSeekable() && (mnStartPos >= 0) )
301 {
302 mnRelPos = getLimitedValue< sal_Int64, sal_Int64 >( nPos, 0, mnSize );
303 mpInStrm->seek( mnStartPos + mnRelPos );
304 mbEof = (mnRelPos != nPos) || mpInStrm->isEof();
305 }
306 }
307
close()308 void RelativeInputStream::close()
309 {
310 mpInStrm = 0;
311 mbEof = true;
312 }
313
readData(StreamDataSequence & orData,sal_Int32 nBytes,size_t nAtomSize)314 sal_Int32 RelativeInputStream::readData( StreamDataSequence& orData, sal_Int32 nBytes, size_t nAtomSize )
315 {
316 sal_Int32 nReadBytes = 0;
317 if( !mbEof )
318 {
319 sal_Int32 nMaxBytes = getMaxBytes( nBytes );
320 nReadBytes = mpInStrm->readData( orData, nMaxBytes, nAtomSize );
321 mnRelPos += nReadBytes;
322 mbEof = (nMaxBytes < nBytes) || mpInStrm->isEof();
323 }
324 return nReadBytes;
325 }
326
readMemory(void * opMem,sal_Int32 nBytes,size_t nAtomSize)327 sal_Int32 RelativeInputStream::readMemory( void* opMem, sal_Int32 nBytes, size_t nAtomSize )
328 {
329 sal_Int32 nReadBytes = 0;
330 if( !mbEof )
331 {
332 sal_Int32 nMaxBytes = getMaxBytes( nBytes );
333 nReadBytes = mpInStrm->readMemory( opMem, nMaxBytes, nAtomSize );
334 mnRelPos += nReadBytes;
335 mbEof = (nMaxBytes < nBytes) || mpInStrm->isEof();
336 }
337 return nReadBytes;
338 }
339
skip(sal_Int32 nBytes,size_t nAtomSize)340 void RelativeInputStream::skip( sal_Int32 nBytes, size_t nAtomSize )
341 {
342 if( !mbEof )
343 {
344 sal_Int32 nSkipBytes = getMaxBytes( nBytes );
345 mpInStrm->skip( nSkipBytes, nAtomSize );
346 mnRelPos += nSkipBytes;
347 mbEof = nSkipBytes < nBytes;
348 }
349 }
350
351 // ============================================================================
352
353 } // namespace oox
354