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_sc.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