xref: /trunk/main/sc/source/filter/excel/xestream.cxx (revision b77af630)
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 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include <stdarg.h>
26 #include <stdio.h>
27 #include <string.h>
28 #include <utility>
29 
30 #include <rtl/ustring.hxx>
31 #include <rtl/ustrbuf.hxx>
32 #include <rtl/random.h>
33 #include <sax/fshelper.hxx>
34 #include <unotools/streamwrap.hxx>
35 
36 #include "precompiled_scfilt.hxx"
37 #include "docuno.hxx"
38 #include "xestream.hxx"
39 #include "xladdress.hxx"
40 #include "xlstring.hxx"
41 #include "xeroot.hxx"
42 #include "xestyle.hxx"
43 #include "rangelst.hxx"
44 #include "compiler.hxx"
45 
46 #include <oox/xls/excelvbaproject.hxx>
47 #include <formula/grammar.hxx>
48 
49 #define DEBUG_XL_ENCRYPTION 0
50 
51 using ::rtl::OString;
52 using ::rtl::OUString;
53 using ::rtl::OUStringBuffer;
54 using ::utl::OStreamWrapper;
55 using ::std::vector;
56 
57 using namespace ::com::sun::star::beans;
58 using namespace ::com::sun::star::io;
59 using namespace ::com::sun::star::lang;
60 using namespace ::com::sun::star::sheet;
61 using namespace ::com::sun::star::uno;
62 using namespace ::formula;
63 using namespace ::oox;
64 
65 // ============================================================================
66 
XclExpStream(SvStream & rOutStrm,const XclExpRoot & rRoot,sal_uInt16 nMaxRecSize)67 XclExpStream::XclExpStream( SvStream& rOutStrm, const XclExpRoot& rRoot, sal_uInt16 nMaxRecSize ) :
68     mrStrm( rOutStrm ),
69     mrRoot( rRoot ),
70     mnMaxRecSize( nMaxRecSize ),
71     mnCurrMaxSize( 0 ),
72     mnMaxSliceSize( 0 ),
73     mnHeaderSize( 0 ),
74     mnCurrSize( 0 ),
75     mnSliceSize( 0 ),
76     mnPredictSize( 0 ),
77     mnLastSizePos( 0 ),
78     mbInRec( false )
79 {
80     if( mnMaxRecSize == 0 )
81         mnMaxRecSize = (mrRoot.GetBiff() <= EXC_BIFF5) ? EXC_MAXRECSIZE_BIFF5 : EXC_MAXRECSIZE_BIFF8;
82     mnMaxContSize = mnMaxRecSize;
83 }
84 
~XclExpStream()85 XclExpStream::~XclExpStream()
86 {
87     mrStrm.Flush();
88 }
89 
StartRecord(sal_uInt16 nRecId,sal_Size nRecSize)90 void XclExpStream::StartRecord( sal_uInt16 nRecId, sal_Size nRecSize )
91 {
92     DBG_ASSERT( !mbInRec, "XclExpStream::StartRecord - another record still open" );
93     DisableEncryption();
94     mnMaxContSize = mnCurrMaxSize = mnMaxRecSize;
95     mnPredictSize = nRecSize;
96     mbInRec = true;
97     InitRecord( nRecId );
98     SetSliceSize( 0 );
99     EnableEncryption();
100 }
101 
EndRecord()102 void XclExpStream::EndRecord()
103 {
104     DBG_ASSERT( mbInRec, "XclExpStream::EndRecord - no record open" );
105     DisableEncryption();
106     UpdateRecSize();
107     mrStrm.Seek( STREAM_SEEK_TO_END );
108     mbInRec = false;
109 }
110 
SetSliceSize(sal_uInt16 nSize)111 void XclExpStream::SetSliceSize( sal_uInt16 nSize )
112 {
113     mnMaxSliceSize = nSize;
114     mnSliceSize = 0;
115 }
116 
operator <<(sal_Int8 nValue)117 XclExpStream& XclExpStream::operator<<( sal_Int8 nValue )
118 {
119     PrepareWrite( 1 );
120     if (mbUseEncrypter && HasValidEncrypter())
121         mxEncrypter->Encrypt(mrStrm, nValue);
122     else
123         mrStrm << nValue;
124     return *this;
125 }
126 
operator <<(sal_uInt8 nValue)127 XclExpStream& XclExpStream::operator<<( sal_uInt8 nValue )
128 {
129     PrepareWrite( 1 );
130     if (mbUseEncrypter && HasValidEncrypter())
131         mxEncrypter->Encrypt(mrStrm, nValue);
132     else
133         mrStrm << nValue;
134     return *this;
135 }
136 
operator <<(sal_Int16 nValue)137 XclExpStream& XclExpStream::operator<<( sal_Int16 nValue )
138 {
139     PrepareWrite( 2 );
140     if (mbUseEncrypter && HasValidEncrypter())
141         mxEncrypter->Encrypt(mrStrm, nValue);
142     else
143         mrStrm << nValue;
144     return *this;
145 }
146 
operator <<(sal_uInt16 nValue)147 XclExpStream& XclExpStream::operator<<( sal_uInt16 nValue )
148 {
149     PrepareWrite( 2 );
150     if (mbUseEncrypter && HasValidEncrypter())
151         mxEncrypter->Encrypt(mrStrm, nValue);
152     else
153         mrStrm << nValue;
154     return *this;
155 }
156 
operator <<(sal_Int32 nValue)157 XclExpStream& XclExpStream::operator<<( sal_Int32 nValue )
158 {
159     PrepareWrite( 4 );
160     if (mbUseEncrypter && HasValidEncrypter())
161         mxEncrypter->Encrypt(mrStrm, nValue);
162     else
163         mrStrm << nValue;
164     return *this;
165 }
166 
operator <<(sal_uInt32 nValue)167 XclExpStream& XclExpStream::operator<<( sal_uInt32 nValue )
168 {
169     PrepareWrite( 4 );
170     if (mbUseEncrypter && HasValidEncrypter())
171         mxEncrypter->Encrypt(mrStrm, nValue);
172     else
173         mrStrm << nValue;
174     return *this;
175 }
176 
operator <<(float fValue)177 XclExpStream& XclExpStream::operator<<( float fValue )
178 {
179     PrepareWrite( 4 );
180     if (mbUseEncrypter && HasValidEncrypter())
181         mxEncrypter->Encrypt(mrStrm, fValue);
182     else
183         mrStrm << fValue;
184     return *this;
185 }
186 
operator <<(double fValue)187 XclExpStream& XclExpStream::operator<<( double fValue )
188 {
189     PrepareWrite( 8 );
190     if (mbUseEncrypter && HasValidEncrypter())
191         mxEncrypter->Encrypt(mrStrm, fValue);
192     else
193         mrStrm << fValue;
194     return *this;
195 }
196 
Write(const void * pData,sal_Size nBytes)197 sal_Size XclExpStream::Write( const void* pData, sal_Size nBytes )
198 {
199     sal_Size nRet = 0;
200     if( pData && (nBytes > 0) )
201     {
202         if( mbInRec )
203         {
204             const sal_uInt8* pBuffer = reinterpret_cast< const sal_uInt8* >( pData );
205             sal_Size nBytesLeft = nBytes;
206             bool bValid = true;
207 
208             while( bValid && (nBytesLeft > 0) )
209             {
210                 sal_Size nWriteLen = ::std::min< sal_Size >( PrepareWrite(), nBytesLeft );
211                 sal_Size nWriteRet = nWriteLen;
212                 if (mbUseEncrypter && HasValidEncrypter())
213                 {
214                     DBG_ASSERT(nWriteLen > 0, "XclExpStream::Write: write length is 0!");
215                     vector<sal_uInt8> aBytes(nWriteLen);
216                     memcpy(&aBytes[0], pBuffer, nWriteLen);
217                     mxEncrypter->EncryptBytes(mrStrm, aBytes);
218                     // TODO: How do I check if all the bytes have been successfully written ?
219                 }
220                 else
221                 {
222                     nWriteRet = mrStrm.Write( pBuffer, nWriteLen );
223                 bValid = (nWriteLen == nWriteRet);
224                 DBG_ASSERT( bValid, "XclExpStream::Write - stream write error" );
225                 }
226                 pBuffer += nWriteRet;
227                 nRet += nWriteRet;
228                 nBytesLeft -= nWriteRet;
229                 UpdateSizeVars( nWriteRet );
230             }
231         }
232         else
233             nRet = mrStrm.Write( pData, nBytes );
234     }
235     return nRet;
236 }
237 
WriteZeroBytes(sal_Size nBytes)238 void XclExpStream::WriteZeroBytes( sal_Size nBytes )
239 {
240     if( mbInRec )
241     {
242         sal_Size nBytesLeft = nBytes;
243         while( nBytesLeft > 0 )
244         {
245             sal_Size nWriteLen = ::std::min< sal_Size >( PrepareWrite(), nBytesLeft );
246             WriteRawZeroBytes( nWriteLen );
247             nBytesLeft -= nWriteLen;
248             UpdateSizeVars( nWriteLen );
249         }
250     }
251     else
252         WriteRawZeroBytes( nBytes );
253 }
254 
WriteZeroBytesToRecord(sal_Size nBytes)255 void XclExpStream::WriteZeroBytesToRecord( sal_Size nBytes )
256 {
257     if (!mbInRec)
258         // not in record.
259         return;
260 
261     sal_uInt8 nZero = 0;
262     for (sal_Size i = 0; i < nBytes; ++i)
263         *this << nZero;
264 }
265 
CopyFromStream(SvStream & rInStrm,sal_Size nBytes)266 sal_Size XclExpStream::CopyFromStream( SvStream& rInStrm, sal_Size nBytes )
267 {
268     sal_Size nStrmPos = rInStrm.Tell();
269     rInStrm.Seek( STREAM_SEEK_TO_END );
270     sal_Size nStrmSize = rInStrm.Tell();
271     rInStrm.Seek( nStrmPos );
272 
273     sal_Size nBytesLeft = ::std::min( nBytes, nStrmSize - nStrmPos );
274     sal_Size nRet = 0;
275     if( nBytesLeft > 0 )
276     {
277         const sal_Size nMaxBuffer = 4096;
278         sal_uInt8* pBuffer = new sal_uInt8[ ::std::min( nBytesLeft, nMaxBuffer ) ];
279         bool bValid = true;
280 
281         while( bValid && (nBytesLeft > 0) )
282         {
283             sal_Size nWriteLen = ::std::min( nBytesLeft, nMaxBuffer );
284             rInStrm.Read( pBuffer, nWriteLen );
285             sal_Size nWriteRet = Write( pBuffer, nWriteLen );
286             bValid = (nWriteLen == nWriteRet);
287             nRet += nWriteRet;
288             nBytesLeft -= nWriteRet;
289         }
290         delete[] pBuffer;
291     }
292     return nRet;
293 }
294 
295 //UNUSED2008-05  void XclExpStream::WriteUnicodeBuffer( const sal_uInt16* pBuffer, sal_Size nChars, sal_uInt8 nFlags )
296 //UNUSED2008-05  {
297 //UNUSED2008-05      SetSliceSize( 0 );
298 //UNUSED2008-05      if( pBuffer && (nChars > 0) )
299 //UNUSED2008-05      {
300 //UNUSED2008-05          sal_uInt16 nCharLen = (nFlags & EXC_STRF_16BIT) ? 2 : 1;
301 //UNUSED2008-05          for( sal_Size nIndex = 0; nIndex < nChars; ++nIndex )
302 //UNUSED2008-05          {
303 //UNUSED2008-05              if( mbInRec && (mnCurrSize + nCharLen > mnCurrMaxSize) )
304 //UNUSED2008-05              {
305 //UNUSED2008-05                  StartContinue();
306 //UNUSED2008-05                  // repeat only 16bit flag
307 //UNUSED2008-05                  operator<<( static_cast< sal_uInt8 >( nFlags & EXC_STRF_16BIT ) );
308 //UNUSED2008-05              }
309 //UNUSED2008-05              if( nCharLen == 2 )
310 //UNUSED2008-05                  operator<<( pBuffer[ nIndex ] );
311 //UNUSED2008-05              else
312 //UNUSED2008-05                  operator<<( static_cast< sal_uInt8 >( pBuffer[ nIndex ] ) );
313 //UNUSED2008-05          }
314 //UNUSED2008-05      }
315 //UNUSED2008-05  }
316 
WriteUnicodeBuffer(const ScfUInt16Vec & rBuffer,sal_uInt8 nFlags)317 void XclExpStream::WriteUnicodeBuffer( const ScfUInt16Vec& rBuffer, sal_uInt8 nFlags )
318 {
319     SetSliceSize( 0 );
320     nFlags &= EXC_STRF_16BIT;   // repeat only 16bit flag
321     sal_uInt16 nCharLen = nFlags ? 2 : 1;
322 
323     ScfUInt16Vec::const_iterator aEnd = rBuffer.end();
324     for( ScfUInt16Vec::const_iterator aIter = rBuffer.begin(); aIter != aEnd; ++aIter )
325     {
326         if( mbInRec && (mnCurrSize + nCharLen > mnCurrMaxSize) )
327         {
328             StartContinue();
329             operator<<( nFlags );
330         }
331         if( nCharLen == 2 )
332             operator<<( *aIter );
333         else
334             operator<<( static_cast< sal_uInt8 >( *aIter ) );
335     }
336 }
337 
338 //UNUSED2008-05  void XclExpStream::WriteByteStringBuffer( const ByteString& rString, sal_uInt16 nMaxLen )
339 //UNUSED2008-05  {
340 //UNUSED2008-05      SetSliceSize( 0 );
341 //UNUSED2008-05      Write( rString.GetBuffer(), ::std::min< sal_Size >( rString.Len(), nMaxLen ) );
342 //UNUSED2008-05  }
343 
344 // ER: #71367# Xcl has an obscure sense of whether starting a new record or not,
345 // and crashes if it encounters the string header at the very end of a record.
346 // Thus we add 1 to give some room, seems like they do it that way but with another count (10?)
WriteByteString(const ByteString & rString,sal_uInt16 nMaxLen,bool b16BitCount)347 void XclExpStream::WriteByteString( const ByteString& rString, sal_uInt16 nMaxLen, bool b16BitCount )
348 {
349     SetSliceSize( 0 );
350     sal_Size nLen = ::std::min< sal_Size >( rString.Len(), nMaxLen );
351     if( !b16BitCount )
352         nLen = ::std::min< sal_Size >( nLen, 0xFF );
353 
354     sal_uInt16 nLeft = PrepareWrite();
355     sal_uInt16 nLenFieldSize = b16BitCount ? 2 : 1;
356     if( mbInRec && (nLeft <= nLenFieldSize) )
357         StartContinue();
358 
359     if( b16BitCount )
360         operator<<( static_cast< sal_uInt16 >( nLen ) );
361     else
362         operator<<( static_cast< sal_uInt8 >( nLen ) );
363     Write( rString.GetBuffer(), nLen );
364 }
365 
WriteCharBuffer(const ScfUInt8Vec & rBuffer)366 void XclExpStream::WriteCharBuffer( const ScfUInt8Vec& rBuffer )
367 {
368     SetSliceSize( 0 );
369     Write( &rBuffer[ 0 ], rBuffer.size() );
370 }
371 
SetEncrypter(XclExpEncrypterRef xEncrypter)372 void XclExpStream::SetEncrypter( XclExpEncrypterRef xEncrypter )
373 {
374     mxEncrypter = xEncrypter;
375 }
376 
HasValidEncrypter() const377 bool XclExpStream::HasValidEncrypter() const
378 {
379     return mxEncrypter.is() && mxEncrypter->IsValid();
380 }
381 
EnableEncryption(bool bEnable)382 void XclExpStream::EnableEncryption( bool bEnable )
383 {
384     mbUseEncrypter = bEnable && HasValidEncrypter();
385 }
386 
DisableEncryption()387 void XclExpStream::DisableEncryption()
388 {
389     EnableEncryption(false);
390 }
391 
SetSvStreamPos(sal_Size nPos)392 sal_Size XclExpStream::SetSvStreamPos( sal_Size nPos )
393 {
394     DBG_ASSERT( !mbInRec, "XclExpStream::SetSvStreamPos - not allowed inside of a record" );
395     return mbInRec ? 0 : mrStrm.Seek( nPos );
396 }
397 
398 // private --------------------------------------------------------------------
399 
InitRecord(sal_uInt16 nRecId)400 void XclExpStream::InitRecord( sal_uInt16 nRecId )
401 {
402     mrStrm.Seek( STREAM_SEEK_TO_END );
403     mrStrm << nRecId;
404 
405     mnLastSizePos = mrStrm.Tell();
406     mnHeaderSize = static_cast< sal_uInt16 >( ::std::min< sal_Size >( mnPredictSize, mnCurrMaxSize ) );
407     mrStrm << mnHeaderSize;
408     mnCurrSize = mnSliceSize = 0;
409 }
410 
UpdateRecSize()411 void XclExpStream::UpdateRecSize()
412 {
413     if( mnCurrSize != mnHeaderSize )
414     {
415         mrStrm.Seek( mnLastSizePos );
416         mrStrm << mnCurrSize;
417     }
418 }
419 
UpdateSizeVars(sal_Size nSize)420 void XclExpStream::UpdateSizeVars( sal_Size nSize )
421 {
422     DBG_ASSERT( mnCurrSize + nSize <= mnCurrMaxSize, "XclExpStream::UpdateSizeVars - record overwritten" );
423     mnCurrSize = mnCurrSize + static_cast< sal_uInt16 >( nSize );
424 
425     if( mnMaxSliceSize > 0 )
426     {
427         DBG_ASSERT( mnSliceSize + nSize <= mnMaxSliceSize, "XclExpStream::UpdateSizeVars - slice overwritten" );
428         mnSliceSize = mnSliceSize + static_cast< sal_uInt16 >( nSize );
429         if( mnSliceSize >= mnMaxSliceSize )
430             mnSliceSize = 0;
431     }
432 }
433 
StartContinue()434 void XclExpStream::StartContinue()
435 {
436     UpdateRecSize();
437     mnCurrMaxSize = mnMaxContSize;
438     mnPredictSize -= mnCurrSize;
439     InitRecord( EXC_ID_CONT );
440 }
441 
PrepareWrite(sal_uInt16 nSize)442 void XclExpStream::PrepareWrite( sal_uInt16 nSize )
443 {
444     if( mbInRec )
445     {
446         if( (mnCurrSize + nSize > mnCurrMaxSize) ||
447             ((mnMaxSliceSize > 0) && (mnSliceSize == 0) && (mnCurrSize + mnMaxSliceSize > mnCurrMaxSize)) )
448             StartContinue();
449         UpdateSizeVars( nSize );
450     }
451 }
452 
PrepareWrite()453 sal_uInt16 XclExpStream::PrepareWrite()
454 {
455     sal_uInt16 nRet = 0;
456     if( mbInRec )
457     {
458         if( (mnCurrSize >= mnCurrMaxSize) ||
459             ((mnMaxSliceSize > 0) && (mnSliceSize == 0) && (mnCurrSize + mnMaxSliceSize > mnCurrMaxSize)) )
460             StartContinue();
461         UpdateSizeVars( 0 );
462 
463         nRet = (mnMaxSliceSize > 0) ? (mnMaxSliceSize - mnSliceSize) : (mnCurrMaxSize - mnCurrSize);
464     }
465     return nRet;
466 }
467 
WriteRawZeroBytes(sal_Size nBytes)468 void XclExpStream::WriteRawZeroBytes( sal_Size nBytes )
469 {
470     const sal_uInt32 nData = 0;
471     sal_Size nBytesLeft = nBytes;
472     while( nBytesLeft >= sizeof( nData ) )
473     {
474         mrStrm << nData;
475         nBytesLeft -= sizeof( nData );
476     }
477     if( nBytesLeft )
478         mrStrm.Write( &nData, nBytesLeft );
479 }
480 
481 // ============================================================================
482 
XclExpBiff8Encrypter(const XclExpRoot & rRoot)483 XclExpBiff8Encrypter::XclExpBiff8Encrypter( const XclExpRoot& rRoot ) :
484     mrRoot(rRoot),
485     mnOldPos(STREAM_SEEK_TO_END),
486     mbValid(false)
487 {
488     Sequence< NamedValue > aEncryptionData = rRoot.GetEncryptionData();
489     if( !aEncryptionData.hasElements() )
490         // Empty password.  Get the default biff8 password.
491         aEncryptionData = rRoot.GenerateDefaultEncryptionData();
492     Init( aEncryptionData );
493 }
494 
~XclExpBiff8Encrypter()495 XclExpBiff8Encrypter::~XclExpBiff8Encrypter()
496 {
497 }
498 
IsValid() const499 bool XclExpBiff8Encrypter::IsValid() const
500 {
501     return mbValid;
502 }
503 
GetSaltDigest(sal_uInt8 pnSaltDigest[16]) const504 void XclExpBiff8Encrypter::GetSaltDigest( sal_uInt8 pnSaltDigest[16] ) const
505 {
506     if ( sizeof( mpnSaltDigest ) == 16 )
507         memcpy( pnSaltDigest, mpnSaltDigest, 16 );
508 }
509 
GetSalt(sal_uInt8 pnSalt[16]) const510 void XclExpBiff8Encrypter::GetSalt( sal_uInt8 pnSalt[16] ) const
511 {
512     if ( sizeof( mpnSalt ) == 16 )
513         memcpy( pnSalt, mpnSalt, 16 );
514 }
515 
GetDocId(sal_uInt8 pnDocId[16]) const516 void XclExpBiff8Encrypter::GetDocId( sal_uInt8 pnDocId[16] ) const
517 {
518     if ( sizeof( mpnDocId ) == 16 )
519     memcpy( pnDocId, mpnDocId, 16 );
520 }
521 
Encrypt(SvStream & rStrm,sal_uInt8 nData)522 void XclExpBiff8Encrypter::Encrypt( SvStream& rStrm, sal_uInt8 nData )
523 {
524     vector<sal_uInt8> aByte(1);
525     aByte[0] = nData;
526     EncryptBytes(rStrm, aByte);
527 }
528 
Encrypt(SvStream & rStrm,sal_uInt16 nData)529 void XclExpBiff8Encrypter::Encrypt( SvStream& rStrm, sal_uInt16 nData )
530 {
531     ::std::vector<sal_uInt8> pnBytes(2);
532     pnBytes[0] = nData & 0xFF;
533     pnBytes[1] = (nData >> 8) & 0xFF;
534     EncryptBytes(rStrm, pnBytes);
535 }
536 
Encrypt(SvStream & rStrm,sal_uInt32 nData)537 void XclExpBiff8Encrypter::Encrypt( SvStream& rStrm, sal_uInt32 nData )
538 {
539     ::std::vector<sal_uInt8> pnBytes(4);
540     pnBytes[0] = nData & 0xFF;
541     pnBytes[1] = (nData >>  8) & 0xFF;
542     pnBytes[2] = (nData >> 16) & 0xFF;
543     pnBytes[3] = (nData >> 24) & 0xFF;
544     EncryptBytes(rStrm, pnBytes);
545 }
546 
Encrypt(SvStream & rStrm,float fValue)547 void XclExpBiff8Encrypter::Encrypt( SvStream& rStrm, float fValue )
548 {
549     ::std::vector<sal_uInt8> pnBytes(4);
550     memcpy(&pnBytes[0], &fValue, 4);
551     EncryptBytes(rStrm, pnBytes);
552 }
553 
Encrypt(SvStream & rStrm,double fValue)554 void XclExpBiff8Encrypter::Encrypt( SvStream& rStrm, double fValue )
555 {
556     ::std::vector<sal_uInt8> pnBytes(8);
557     memcpy(&pnBytes[0], &fValue, 8);
558     EncryptBytes(rStrm, pnBytes);
559 }
560 
Encrypt(SvStream & rStrm,sal_Int8 nData)561 void XclExpBiff8Encrypter::Encrypt( SvStream& rStrm, sal_Int8 nData )
562 {
563     Encrypt(rStrm, static_cast<sal_uInt8>(nData));
564 }
565 
Encrypt(SvStream & rStrm,sal_Int16 nData)566 void XclExpBiff8Encrypter::Encrypt( SvStream& rStrm, sal_Int16 nData )
567 {
568     Encrypt(rStrm, static_cast<sal_uInt16>(nData));
569 }
570 
Encrypt(SvStream & rStrm,sal_Int32 nData)571 void XclExpBiff8Encrypter::Encrypt( SvStream& rStrm, sal_Int32 nData )
572 {
573     Encrypt(rStrm, static_cast<sal_uInt32>(nData));
574 }
575 
Init(const Sequence<NamedValue> & rEncryptionData)576 void XclExpBiff8Encrypter::Init( const Sequence< NamedValue >& rEncryptionData )
577 {
578     mbValid = false;
579 
580     if( maCodec.InitCodec( rEncryptionData ) )
581     {
582         maCodec.GetDocId( mpnDocId );
583 
584         // generate the salt here
585         TimeValue aTime;
586         osl_getSystemTime( &aTime );
587         rtlRandomPool aRandomPool = rtl_random_createPool ();
588         rtl_random_addBytes( aRandomPool, &aTime, 8 );
589         rtl_random_getBytes( aRandomPool, mpnSalt, 16 );
590         rtl_random_destroyPool( aRandomPool );
591 
592         memset( mpnSaltDigest, 0, sizeof( mpnSaltDigest ) );
593 
594         // generate salt hash.
595         ::msfilter::MSCodec_Std97 aCodec;
596         aCodec.InitCodec( rEncryptionData );
597         aCodec.CreateSaltDigest( mpnSalt, mpnSaltDigest );
598 
599         // verify to make sure it's in good shape.
600         mbValid = maCodec.VerifyKey( mpnSalt, mpnSaltDigest );
601     }
602 }
603 
GetBlockPos(sal_Size nStrmPos) const604 sal_uInt32 XclExpBiff8Encrypter::GetBlockPos( sal_Size nStrmPos ) const
605 {
606     return static_cast< sal_uInt32 >( nStrmPos / EXC_ENCR_BLOCKSIZE );
607 }
608 
GetOffsetInBlock(sal_Size nStrmPos) const609 sal_uInt16 XclExpBiff8Encrypter::GetOffsetInBlock( sal_Size nStrmPos ) const
610 {
611     return static_cast< sal_uInt16 >( nStrmPos % EXC_ENCR_BLOCKSIZE );
612 }
613 
EncryptBytes(SvStream & rStrm,vector<sal_uInt8> & aBytes)614 void XclExpBiff8Encrypter::EncryptBytes( SvStream& rStrm, vector<sal_uInt8>& aBytes )
615 {
616     sal_Size nStrmPos = rStrm.Tell();
617     sal_uInt16 nBlockOffset = GetOffsetInBlock(nStrmPos);
618     sal_uInt32 nBlockPos = GetBlockPos(nStrmPos);
619 
620 #if DEBUG_XL_ENCRYPTION
621     fprintf(stdout, "XclExpBiff8Encrypter::EncryptBytes: stream pos = %ld  offset in block = %d  block pos = %ld\n",
622             nStrmPos, nBlockOffset, nBlockPos);
623 #endif
624 
625     sal_uInt16 nSize = static_cast< sal_uInt16 >( aBytes.size() );
626     if (nSize == 0)
627         return;
628 
629 #if DEBUG_XL_ENCRYPTION
630     fprintf(stdout, "RAW: ");
631     for (sal_uInt16 i = 0; i < nSize; ++i)
632         fprintf(stdout, "%2.2X ", aBytes[i]);
633     fprintf(stdout, "\n");
634 #endif
635 
636     if (mnOldPos != nStrmPos)
637     {
638         sal_uInt16 nOldOffset = GetOffsetInBlock(mnOldPos);
639         sal_uInt32 nOldBlockPos = GetBlockPos(mnOldPos);
640 
641         if ( (nBlockPos != nOldBlockPos) || (nBlockOffset < nOldOffset) )
642         {
643             maCodec.InitCipher(nBlockPos);
644             nOldOffset = 0;
645         }
646 
647         if (nBlockOffset > nOldOffset)
648             maCodec.Skip(nBlockOffset - nOldOffset);
649     }
650 
651     sal_uInt16 nBytesLeft = nSize;
652     sal_uInt16 nPos = 0;
653     while (nBytesLeft > 0)
654     {
655         sal_uInt16 nBlockLeft = EXC_ENCR_BLOCKSIZE - nBlockOffset;
656         sal_uInt16 nEncBytes = ::std::min(nBlockLeft, nBytesLeft);
657 
658         bool bRet = maCodec.Encode(&aBytes[nPos], nEncBytes, &aBytes[nPos], nEncBytes);
659         DBG_ASSERT(bRet, "XclExpBiff8Encrypter::EncryptBytes: encryption failed!!");
660         bRet = bRet; // to remove a silly compiler warning.
661 
662         sal_Size nRet = rStrm.Write(&aBytes[nPos], nEncBytes);
663         DBG_ASSERT(nRet == nEncBytes, "XclExpBiff8Encrypter::EncryptBytes: fail to write to stream!!");
664         nRet = nRet; // to remove a silly compiler warning.
665 
666         nStrmPos = rStrm.Tell();
667         nBlockOffset = GetOffsetInBlock(nStrmPos);
668         nBlockPos = GetBlockPos(nStrmPos);
669         if (nBlockOffset == 0)
670             maCodec.InitCipher(nBlockPos);
671 
672         nBytesLeft -= nEncBytes;
673         nPos += nEncBytes;
674     }
675     mnOldPos = nStrmPos;
676 }
677 
GetStreamName(const char * sStreamDir,const char * sStream,sal_Int32 nId)678 OUString XclXmlUtils::GetStreamName( const char* sStreamDir, const char* sStream, sal_Int32 nId )
679 {
680     OUStringBuffer sBuf;
681     if( sStreamDir )
682         sBuf.appendAscii( sStreamDir );
683     sBuf.appendAscii( sStream );
684     if( nId )
685         sBuf.append( nId );
686     sBuf.appendAscii( ".xml" );
687     return sBuf.makeStringAndClear();
688 }
689 
ToOString(const Color & rColor)690 OString XclXmlUtils::ToOString( const Color& rColor )
691 {
692     char buf[9];
693     sprintf( buf, "%.2X%.2X%.2X%.2X", rColor.GetTransparency(), rColor.GetRed(), rColor.GetGreen(), rColor.GetBlue() );
694     buf[8] = '\0';
695     return OString( buf );
696 }
697 
ToOString(const OUString & s)698 OString XclXmlUtils::ToOString( const OUString& s )
699 {
700     return OUStringToOString( s, RTL_TEXTENCODING_UTF8  );
701 }
702 
ToOString(const String & s)703 OString XclXmlUtils::ToOString( const String& s )
704 {
705     return OString( s.GetBuffer(), s.Len(), RTL_TEXTENCODING_UTF8 );
706 }
707 
ToOString(const ScAddress & rAddress)708 OString XclXmlUtils::ToOString( const ScAddress& rAddress )
709 {
710     String sAddress;
711     rAddress.Format( sAddress, SCA_VALID, NULL, ScAddress::Details( FormulaGrammar::CONV_XL_A1 ) );
712     return ToOString( sAddress );
713 }
714 
ToOString(const ScfUInt16Vec & rBuffer)715 OString XclXmlUtils::ToOString( const ScfUInt16Vec& rBuffer )
716 {
717     const sal_uInt16* pBuffer = &rBuffer [0];
718     return OString( pBuffer, rBuffer.size(), RTL_TEXTENCODING_UTF8 );
719 }
720 
ToOString(const ScRange & rRange)721 OString XclXmlUtils::ToOString( const ScRange& rRange )
722 {
723     String sRange;
724     rRange.Format( sRange, SCA_VALID, NULL, ScAddress::Details( FormulaGrammar::CONV_XL_A1 ) );
725     return ToOString( sRange );
726 }
727 
ToOString(const ScRangeList & rRangeList)728 OString XclXmlUtils::ToOString( const ScRangeList& rRangeList )
729 {
730     String s;
731     rRangeList.Format( s, SCA_VALID, NULL, FormulaGrammar::CONV_XL_A1, ' ' );
732     return ToOString( s );
733 }
734 
lcl_ToAddress(const XclAddress & rAddress)735 static ScAddress lcl_ToAddress( const XclAddress& rAddress )
736 {
737     ScAddress aAddress;
738 
739     // For some reason, ScRange::Format() returns omits row numbers if
740     // the row is >= MAXROW or the column is >= MAXCOL, and Excel doesn't
741     // like "A:IV" (i.e. no row numbers).  Prevent this.
742     aAddress.SetRow( std::min<sal_Int32>( rAddress.mnRow, MAXROW-1 ) );
743     aAddress.SetCol( static_cast<sal_Int16>(std::min<sal_Int32>( rAddress.mnCol, MAXCOL-1 )) );
744 
745     return aAddress;
746 }
747 
ToOString(const XclAddress & rAddress)748 OString XclXmlUtils::ToOString( const XclAddress& rAddress )
749 {
750     return ToOString( lcl_ToAddress( rAddress ) );
751 }
752 
ToOString(const XclExpString & s)753 OString XclXmlUtils::ToOString( const XclExpString& s )
754 {
755     DBG_ASSERT( !s.IsRich(), "XclXmlUtils::ToOString(XclExpString): rich text string found!" );
756     return ToOString( s.GetUnicodeBuffer() );
757 }
758 
lcl_ToRange(const XclRange & rRange)759 static ScRange lcl_ToRange( const XclRange& rRange )
760 {
761     ScRange aRange;
762 
763     aRange.aStart = lcl_ToAddress( rRange.maFirst );
764     aRange.aEnd   = lcl_ToAddress( rRange.maLast );
765 
766     return aRange;
767 }
768 
ToOString(const XclRangeList & rRanges)769 OString XclXmlUtils::ToOString( const XclRangeList& rRanges )
770 {
771     ScRangeList aRanges;
772     for( XclRangeList::const_iterator i = rRanges.begin(), end = rRanges.end();
773             i != end; ++i )
774     {
775         aRanges.Append( lcl_ToRange( *i ) );
776     }
777     return ToOString( aRanges );
778 }
779 
ToOUString(const char * s)780 OUString XclXmlUtils::ToOUString( const char* s )
781 {
782     return OUString( s, (sal_Int32) strlen( s ), RTL_TEXTENCODING_ASCII_US );
783 }
784 
ToOUString(const ScfUInt16Vec & rBuf,sal_Int32 nStart,sal_Int32 nLength)785 OUString XclXmlUtils::ToOUString( const ScfUInt16Vec& rBuf, sal_Int32 nStart, sal_Int32 nLength )
786 {
787     if( nLength == -1 )
788         nLength = rBuf.size();
789 
790     return OUString( &rBuf[nStart], nLength );
791 }
792 
ToOUString(const String & s)793 OUString XclXmlUtils::ToOUString( const String& s )
794 {
795     return OUString( s.GetBuffer(), s.Len() );
796 }
797 
ToOUString(ScDocument & rDocument,const ScAddress & rAddress,ScTokenArray * pTokenArray)798 OUString XclXmlUtils::ToOUString( ScDocument& rDocument, const ScAddress& rAddress, ScTokenArray* pTokenArray )
799 {
800     ScCompiler aCompiler( &rDocument, rAddress, *pTokenArray);
801     aCompiler.SetGrammar(FormulaGrammar::GRAM_NATIVE_XL_A1);
802     String s;
803     aCompiler.CreateStringFromTokenArray( s );
804     return ToOUString( s );
805 }
806 
ToOUString(const XclExpString & s)807 OUString XclXmlUtils::ToOUString( const XclExpString& s )
808 {
809     DBG_ASSERT( !s.IsRich(), "XclXmlUtils::ToOString(XclExpString): rich text string found!" );
810     return ToOUString( s.GetUnicodeBuffer() );
811 }
812 
ToPsz(bool b)813 const char* XclXmlUtils::ToPsz( bool b )
814 {
815     return b ? "true" : "false";
816 }
817 
818 // ============================================================================
819 
XclExpXmlStream(const Reference<XComponentContext> & rxContext,SvStream & rStrm,const XclExpRoot & rRoot)820 XclExpXmlStream::XclExpXmlStream( const Reference< XComponentContext >& rxContext, SvStream& rStrm, const XclExpRoot& rRoot )
821     : XmlFilterBase( rxContext )
822     , mrRoot( rRoot )
823 {
824     Sequence< PropertyValue > aArgs( 1 );
825     const OUString sStream( RTL_CONSTASCII_USTRINGPARAM( "StreamForOutput" ) );
826     aArgs[0].Name  = sStream;
827     aArgs[0].Value <<= Reference< XStream > ( new OStreamWrapper( rStrm ) );
828 
829     XServiceInfo* pInfo = rRoot.GetDocModelObj();
830     Reference< XComponent > aComponent( pInfo, UNO_QUERY );
831     setSourceDocument( aComponent );
832     filter( aArgs );
833 
834     PushStream( CreateOutputStream(
835                 OUString::createFromAscii( "xl/workbook.xml" ),
836                 OUString::createFromAscii( "xl/workbook.xml" ),
837                 Reference< XOutputStream >(),
838                 "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml",
839                 "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" ) );
840 }
841 
~XclExpXmlStream()842 XclExpXmlStream::~XclExpXmlStream()
843 {
844 }
845 
GetCurrentStream()846 sax_fastparser::FSHelperPtr& XclExpXmlStream::GetCurrentStream()
847 {
848     DBG_ASSERT( !maStreams.empty(), "XclExpXmlStream::GetCurrentStream - no current stream" );
849     return maStreams.top();
850 }
851 
PushStream(sax_fastparser::FSHelperPtr aStream)852 void XclExpXmlStream::PushStream( sax_fastparser::FSHelperPtr aStream )
853 {
854     maStreams.push( aStream );
855 }
856 
PopStream()857 void XclExpXmlStream::PopStream()
858 {
859     DBG_ASSERT( !maStreams.empty(), "XclExpXmlStream::PopStream - stack is empty!" );
860     maStreams.pop();
861 }
862 
GetIdForPath(const OUString & sPath)863 OUString XclExpXmlStream::GetIdForPath( const OUString& sPath )
864 {
865     if( maOpenedStreamMap.find( sPath ) == maOpenedStreamMap.end() )
866         return OUString();
867     return maOpenedStreamMap[ sPath ].first;
868 }
869 
GetStreamForPath(const OUString & sPath)870 sax_fastparser::FSHelperPtr XclExpXmlStream::GetStreamForPath( const OUString& sPath )
871 {
872     if( maOpenedStreamMap.find( sPath ) == maOpenedStreamMap.end() )
873         return sax_fastparser::FSHelperPtr();
874     return maOpenedStreamMap[ sPath ].second;
875 }
876 
WriteAttributes(sal_Int32 nAttribute,...)877 sax_fastparser::FSHelperPtr& XclExpXmlStream::WriteAttributes( sal_Int32 nAttribute, ... )
878 {
879     sax_fastparser::FSHelperPtr& rStream = GetCurrentStream();
880 
881     va_list args;
882     va_start( args, nAttribute );
883     do {
884         const char* pValue = va_arg( args, const char* );
885         if( pValue )
886         {
887             rStream->write( " " )
888                 ->writeId( nAttribute )
889                 ->write( "=\"" )
890                 ->writeEscaped( pValue )
891                 ->write( "\"" );
892         }
893 
894         nAttribute = va_arg( args, sal_Int32 );
895         if( nAttribute == FSEND )
896             break;
897     } while( true );
898     va_end( args );
899 
900     return rStream;
901 }
902 
lcl_WriteValue(sax_fastparser::FSHelperPtr & rStream,sal_Int32 nElement,const char * pValue)903 static void lcl_WriteValue( sax_fastparser::FSHelperPtr& rStream, sal_Int32 nElement, const char* pValue )
904 {
905     if( !pValue )
906         return;
907     rStream->singleElement( nElement,
908             XML_val, pValue,
909             FSEND );
910 }
911 
lcl_GetUnderlineStyle(FontUnderline eUnderline,bool & bHaveUnderline)912 static const char* lcl_GetUnderlineStyle( FontUnderline eUnderline, bool& bHaveUnderline )
913 {
914     bHaveUnderline = true;
915     switch( eUnderline )
916     {
917         // OOXTODO: doubleAccounting, singleAccounting
918         // OOXTODO: what should be done with the other FontUnderline values?
919         case UNDERLINE_SINGLE:  return "single";
920         case UNDERLINE_DOUBLE:  return "double";
921         case UNDERLINE_NONE:
922         default:                bHaveUnderline = false; return "none";
923     }
924 }
925 
lcl_ToVerticalAlignmentRun(SvxEscapement eEscapement,bool & bHaveAlignment)926 static const char* lcl_ToVerticalAlignmentRun( SvxEscapement eEscapement, bool& bHaveAlignment )
927 {
928     bHaveAlignment = true;
929     switch( eEscapement )
930     {
931         case SVX_ESCAPEMENT_SUPERSCRIPT:    return "superscript";
932         case SVX_ESCAPEMENT_SUBSCRIPT:      return "subscript";
933         case SVX_ESCAPEMENT_OFF:
934         default:                            bHaveAlignment = false; return "baseline";
935     }
936 }
937 
WriteFontData(const XclFontData & rFontData,sal_Int32 nFontId)938 sax_fastparser::FSHelperPtr& XclExpXmlStream::WriteFontData( const XclFontData& rFontData, sal_Int32 nFontId )
939 {
940     bool bHaveUnderline, bHaveVertAlign;
941     const char* pUnderline = lcl_GetUnderlineStyle( rFontData.GetScUnderline(), bHaveUnderline );
942     const char* pVertAlign = lcl_ToVerticalAlignmentRun( rFontData.GetScEscapement(), bHaveVertAlign );
943 
944     sax_fastparser::FSHelperPtr& rStream = GetCurrentStream();
945 
946     lcl_WriteValue( rStream, nFontId,        XclXmlUtils::ToOString( rFontData.maName ).getStr() );
947     lcl_WriteValue( rStream, XML_charset,    rFontData.mnCharSet != 0 ? OString::valueOf( (sal_Int32) rFontData.mnCharSet ).getStr() : NULL );
948     lcl_WriteValue( rStream, XML_family,     OString::valueOf( (sal_Int32) rFontData.mnFamily ).getStr() );
949     lcl_WriteValue( rStream, XML_b,          rFontData.mnWeight > 400 ? XclXmlUtils::ToPsz( rFontData.mnWeight > 400 ) : NULL );
950     lcl_WriteValue( rStream, XML_i,          rFontData.mbItalic ? XclXmlUtils::ToPsz( rFontData.mbItalic ) : NULL );
951     lcl_WriteValue( rStream, XML_strike,     rFontData.mbStrikeout ? XclXmlUtils::ToPsz( rFontData.mbStrikeout ) : NULL );
952     lcl_WriteValue( rStream, XML_outline,    rFontData.mbOutline ? XclXmlUtils::ToPsz( rFontData.mbOutline ) : NULL );
953     lcl_WriteValue( rStream, XML_shadow,     rFontData.mbShadow ? XclXmlUtils::ToPsz( rFontData.mbShadow ) : NULL );
954     // OOXTODO: lcl_WriteValue( rStream, XML_condense, );    // mac compatibility setting
955     // OOXTODO: lcl_WriteValue( rStream, XML_extend, );      // compatibility setting
956     if( rFontData.maColor != Color( 0xFF, 0xFF, 0xFF, 0xFF ) )
957         rStream->singleElement( XML_color,
958                 // OOXTODO: XML_auto,       bool
959                 // OOXTODO: XML_indexed,    uint
960                 XML_rgb,    XclXmlUtils::ToOString( rFontData.maColor ).getStr(),
961                 // OOXTODO: XML_theme,      index into <clrScheme/>
962                 // OOXTODO: XML_tint,       double
963                 FSEND );
964     lcl_WriteValue( rStream, XML_sz,         OString::valueOf( (double) (rFontData.mnHeight / 20.0) ).getStr() );  // Twips->Points
965     lcl_WriteValue( rStream, XML_u,          bHaveUnderline ? pUnderline : NULL );
966     lcl_WriteValue( rStream, XML_vertAlign,  bHaveVertAlign ? pVertAlign : NULL );
967 
968     return rStream;
969 }
970 
CreateOutputStream(const OUString & sFullStream,const OUString & sRelativeStream,const Reference<XOutputStream> & xParentRelation,const char * sContentType,const char * sRelationshipType,OUString * pRelationshipId)971 sax_fastparser::FSHelperPtr XclExpXmlStream::CreateOutputStream (
972     const OUString& sFullStream,
973     const OUString& sRelativeStream,
974     const Reference< XOutputStream >& xParentRelation,
975     const char* sContentType,
976     const char* sRelationshipType,
977     OUString* pRelationshipId )
978 {
979     OUString sRelationshipId;
980     if (xParentRelation.is())
981         sRelationshipId = addRelation( xParentRelation, OUString::createFromAscii( sRelationshipType), sRelativeStream );
982     else
983         sRelationshipId = addRelation( OUString::createFromAscii( sRelationshipType ), sRelativeStream );
984 
985     if( pRelationshipId )
986         *pRelationshipId = sRelationshipId;
987 
988     sax_fastparser::FSHelperPtr p = openFragmentStreamWithSerializer( sFullStream, OUString::createFromAscii( sContentType ) );
989 
990     maOpenedStreamMap[ sFullStream ] = std::make_pair( sRelationshipId, p );
991 
992     return p;
993 }
994 
importDocument()995 bool XclExpXmlStream::importDocument() throw()
996 {
997     return false;
998 }
999 
getVmlDrawing()1000 oox::vml::Drawing* XclExpXmlStream::getVmlDrawing()
1001 {
1002     return 0;
1003 }
1004 
getCurrentTheme() const1005 const oox::drawingml::Theme* XclExpXmlStream::getCurrentTheme() const
1006 {
1007     return 0;
1008 }
1009 
getTableStyles()1010 const oox::drawingml::table::TableStyleListPtr XclExpXmlStream::getTableStyles()
1011 {
1012     return oox::drawingml::table::TableStyleListPtr();
1013 }
1014 
getChartConverter()1015 oox::drawingml::chart::ChartConverter& XclExpXmlStream::getChartConverter()
1016 {
1017     // DO NOT CALL
1018     return * (oox::drawingml::chart::ChartConverter*) NULL;
1019 }
1020 
exportDocument()1021 bool XclExpXmlStream::exportDocument() throw()
1022 {
1023     return false;
1024 }
1025 
implCreateVbaProject() const1026 ::oox::ole::VbaProject* XclExpXmlStream::implCreateVbaProject() const
1027 {
1028     return new ::oox::xls::ExcelVbaProject( getComponentContext(), Reference< XSpreadsheetDocument >( getModel(), UNO_QUERY ) );
1029 }
1030 
implGetImplementationName() const1031 OUString XclExpXmlStream::implGetImplementationName() const
1032 {
1033     return CREATE_OUSTRING( "TODO" );
1034 }
1035 
Trace(const char * format,...)1036 void XclExpXmlStream::Trace( const char* format, ...)
1037 {
1038     va_list ap;
1039     va_start( ap, format );
1040     vfprintf( stderr, format, ap );
1041     va_end( ap );
1042 }
1043 
1044