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 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 63 OUString BinaryInputStream::readNulCharArrayUC( rtl_TextEncoding eTextEnc ) 64 { 65 return OStringToOUString( readNulCharArray(), eTextEnc ); 66 } 67 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 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 93 OUString BinaryInputStream::readCharArrayUC( sal_Int32 nChars, rtl_TextEncoding eTextEnc, bool bAllowNulChars ) 94 { 95 return OStringToOUString( readCharArray( nChars, bAllowNulChars ), eTextEnc ); 96 } 97 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 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 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 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 159 BinaryXInputStream::~BinaryXInputStream() 160 { 161 close(); 162 } 163 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 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 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 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 230 SequenceInputStream::SequenceInputStream( const StreamDataSequence& rData ) : 231 BinaryStreamBase( true ), 232 SequenceSeekableStream( rData ) 233 { 234 } 235 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 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 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 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 288 sal_Int64 RelativeInputStream::size() const 289 { 290 return mpInStrm ? mnSize : -1; 291 } 292 293 sal_Int64 RelativeInputStream::tell() const 294 { 295 return mpInStrm ? mnRelPos : -1; 296 } 297 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 308 void RelativeInputStream::close() 309 { 310 mpInStrm = 0; 311 mbEof = true; 312 } 313 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 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 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