update dev300-m58
[ooovba.git] / sc / source / filter / excel / xestream.cxx
blob45ced68de00626eafe33a1688192e93e4cd50ecb
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: xestream.cxx,v $
10 * $Revision: 1.11.30.2 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include <stdarg.h>
33 #include <stdio.h>
34 #include <string.h>
35 #include <utility>
37 #include <rtl/ustring.hxx>
38 #include <sax/fshelper.hxx>
39 #include <unotools/streamwrap.hxx>
41 #include "precompiled_sc.hxx"
42 #include "docuno.hxx"
43 #include "xestream.hxx"
44 #include "xladdress.hxx"
45 #include "xlstring.hxx"
46 #include "xeroot.hxx"
47 #include "xestyle.hxx"
48 #include "rangelst.hxx"
49 #include "compiler.hxx"
51 #include <oox/core/tokens.hxx>
52 #include <formula/grammar.hxx>
54 #define DEBUG_XL_ENCRYPTION 0
56 using ::com::sun::star::beans::PropertyValue;
57 using ::com::sun::star::io::XOutputStream;
58 using ::com::sun::star::io::XStream;
59 using ::com::sun::star::lang::XComponent;
60 using ::com::sun::star::lang::XMultiServiceFactory;
61 using ::com::sun::star::lang::XServiceInfo;
62 using ::com::sun::star::uno::Reference;
63 using ::com::sun::star::uno::Sequence;
64 using ::com::sun::star::uno::UNO_QUERY;
65 using ::rtl::OString;
66 using ::rtl::OUString;
67 using ::utl::OStreamWrapper;
68 using ::std::vector;
70 using namespace formula;
72 // ============================================================================
74 XclExpStream::XclExpStream( SvStream& rOutStrm, const XclExpRoot& rRoot, sal_uInt16 nMaxRecSize ) :
75 mrStrm( rOutStrm ),
76 mrRoot( rRoot ),
77 mnMaxRecSize( nMaxRecSize ),
78 mnCurrMaxSize( 0 ),
79 mnMaxSliceSize( 0 ),
80 mnHeaderSize( 0 ),
81 mnCurrSize( 0 ),
82 mnSliceSize( 0 ),
83 mnPredictSize( 0 ),
84 mnLastSizePos( 0 ),
85 mbInRec( false )
87 if( mnMaxRecSize == 0 )
88 mnMaxRecSize = (mrRoot.GetBiff() <= EXC_BIFF5) ? EXC_MAXRECSIZE_BIFF5 : EXC_MAXRECSIZE_BIFF8;
89 mnMaxContSize = mnMaxRecSize;
92 XclExpStream::~XclExpStream()
94 mrStrm.Flush();
97 void XclExpStream::StartRecord( sal_uInt16 nRecId, sal_Size nRecSize )
99 DBG_ASSERT( !mbInRec, "XclExpStream::StartRecord - another record still open" );
100 DisableEncryption();
101 mnMaxContSize = mnCurrMaxSize = mnMaxRecSize;
102 mnPredictSize = nRecSize;
103 mbInRec = true;
104 InitRecord( nRecId );
105 SetSliceSize( 0 );
106 EnableEncryption();
109 void XclExpStream::EndRecord()
111 DBG_ASSERT( mbInRec, "XclExpStream::EndRecord - no record open" );
112 DisableEncryption();
113 UpdateRecSize();
114 mrStrm.Seek( STREAM_SEEK_TO_END );
115 mbInRec = false;
118 void XclExpStream::SetSliceSize( sal_uInt16 nSize )
120 mnMaxSliceSize = nSize;
121 mnSliceSize = 0;
124 XclExpStream& XclExpStream::operator<<( sal_Int8 nValue )
126 PrepareWrite( 1 );
127 if (mbUseEncrypter && HasValidEncrypter())
128 mxEncrypter->Encrypt(mrStrm, nValue);
129 else
130 mrStrm << nValue;
131 return *this;
134 XclExpStream& XclExpStream::operator<<( sal_uInt8 nValue )
136 PrepareWrite( 1 );
137 if (mbUseEncrypter && HasValidEncrypter())
138 mxEncrypter->Encrypt(mrStrm, nValue);
139 else
140 mrStrm << nValue;
141 return *this;
144 XclExpStream& XclExpStream::operator<<( sal_Int16 nValue )
146 PrepareWrite( 2 );
147 if (mbUseEncrypter && HasValidEncrypter())
148 mxEncrypter->Encrypt(mrStrm, nValue);
149 else
150 mrStrm << nValue;
151 return *this;
154 XclExpStream& XclExpStream::operator<<( sal_uInt16 nValue )
156 PrepareWrite( 2 );
157 if (mbUseEncrypter && HasValidEncrypter())
158 mxEncrypter->Encrypt(mrStrm, nValue);
159 else
160 mrStrm << nValue;
161 return *this;
164 XclExpStream& XclExpStream::operator<<( sal_Int32 nValue )
166 PrepareWrite( 4 );
167 if (mbUseEncrypter && HasValidEncrypter())
168 mxEncrypter->Encrypt(mrStrm, nValue);
169 else
170 mrStrm << nValue;
171 return *this;
174 XclExpStream& XclExpStream::operator<<( sal_uInt32 nValue )
176 PrepareWrite( 4 );
177 if (mbUseEncrypter && HasValidEncrypter())
178 mxEncrypter->Encrypt(mrStrm, nValue);
179 else
180 mrStrm << nValue;
181 return *this;
184 XclExpStream& XclExpStream::operator<<( float fValue )
186 PrepareWrite( 4 );
187 if (mbUseEncrypter && HasValidEncrypter())
188 mxEncrypter->Encrypt(mrStrm, fValue);
189 else
190 mrStrm << fValue;
191 return *this;
194 XclExpStream& XclExpStream::operator<<( double fValue )
196 PrepareWrite( 8 );
197 if (mbUseEncrypter && HasValidEncrypter())
198 mxEncrypter->Encrypt(mrStrm, fValue);
199 else
200 mrStrm << fValue;
201 return *this;
204 sal_Size XclExpStream::Write( const void* pData, sal_Size nBytes )
206 sal_Size nRet = 0;
207 if( pData && (nBytes > 0) )
209 if( mbInRec )
211 const sal_uInt8* pBuffer = reinterpret_cast< const sal_uInt8* >( pData );
212 sal_Size nBytesLeft = nBytes;
213 bool bValid = true;
215 while( bValid && (nBytesLeft > 0) )
217 sal_Size nWriteLen = ::std::min< sal_Size >( PrepareWrite(), nBytesLeft );
218 sal_Size nWriteRet = nWriteLen;
219 if (mbUseEncrypter && HasValidEncrypter())
221 DBG_ASSERT(nWriteLen > 0, "XclExpStream::Write: write length is 0!");
222 vector<sal_uInt8> aBytes(nWriteLen);
223 memcpy(&aBytes[0], pBuffer, nWriteLen);
224 mxEncrypter->EncryptBytes(mrStrm, aBytes);
225 // TODO: How do I check if all the bytes have been successfully written ?
227 else
229 nWriteRet = mrStrm.Write( pBuffer, nWriteLen );
230 bValid = (nWriteLen == nWriteRet);
231 DBG_ASSERT( bValid, "XclExpStream::Write - stream write error" );
233 pBuffer += nWriteRet;
234 nRet += nWriteRet;
235 nBytesLeft -= nWriteRet;
236 UpdateSizeVars( nWriteRet );
239 else
240 nRet = mrStrm.Write( pData, nBytes );
242 return nRet;
245 void XclExpStream::WriteZeroBytes( sal_Size nBytes )
247 if( mbInRec )
249 sal_Size nBytesLeft = nBytes;
250 while( nBytesLeft > 0 )
252 sal_Size nWriteLen = ::std::min< sal_Size >( PrepareWrite(), nBytesLeft );
253 WriteRawZeroBytes( nWriteLen );
254 nBytesLeft -= nWriteLen;
255 UpdateSizeVars( nWriteLen );
258 else
259 WriteRawZeroBytes( nBytes );
262 sal_Size XclExpStream::CopyFromStream( SvStream& rInStrm, sal_Size nBytes )
264 sal_Size nStrmPos = rInStrm.Tell();
265 rInStrm.Seek( STREAM_SEEK_TO_END );
266 sal_Size nStrmSize = rInStrm.Tell();
267 rInStrm.Seek( nStrmPos );
269 sal_Size nBytesLeft = ::std::min( nBytes, nStrmSize - nStrmPos );
270 sal_Size nRet = 0;
271 if( nBytesLeft > 0 )
273 const sal_Size nMaxBuffer = 4096;
274 sal_uInt8* pBuffer = new sal_uInt8[ ::std::min( nBytesLeft, nMaxBuffer ) ];
275 bool bValid = true;
277 while( bValid && (nBytesLeft > 0) )
279 sal_Size nWriteLen = ::std::min( nBytesLeft, nMaxBuffer );
280 rInStrm.Read( pBuffer, nWriteLen );
281 sal_Size nWriteRet = Write( pBuffer, nWriteLen );
282 bValid = (nWriteLen == nWriteRet);
283 nRet += nWriteRet;
284 nBytesLeft -= nWriteRet;
286 delete[] pBuffer;
288 return nRet;
291 //UNUSED2008-05 void XclExpStream::WriteUnicodeBuffer( const sal_uInt16* pBuffer, sal_Size nChars, sal_uInt8 nFlags )
292 //UNUSED2008-05 {
293 //UNUSED2008-05 SetSliceSize( 0 );
294 //UNUSED2008-05 if( pBuffer && (nChars > 0) )
295 //UNUSED2008-05 {
296 //UNUSED2008-05 sal_uInt16 nCharLen = (nFlags & EXC_STRF_16BIT) ? 2 : 1;
297 //UNUSED2008-05 for( sal_Size nIndex = 0; nIndex < nChars; ++nIndex )
298 //UNUSED2008-05 {
299 //UNUSED2008-05 if( mbInRec && (mnCurrSize + nCharLen > mnCurrMaxSize) )
300 //UNUSED2008-05 {
301 //UNUSED2008-05 StartContinue();
302 //UNUSED2008-05 // repeat only 16bit flag
303 //UNUSED2008-05 operator<<( static_cast< sal_uInt8 >( nFlags & EXC_STRF_16BIT ) );
304 //UNUSED2008-05 }
305 //UNUSED2008-05 if( nCharLen == 2 )
306 //UNUSED2008-05 operator<<( pBuffer[ nIndex ] );
307 //UNUSED2008-05 else
308 //UNUSED2008-05 operator<<( static_cast< sal_uInt8 >( pBuffer[ nIndex ] ) );
309 //UNUSED2008-05 }
310 //UNUSED2008-05 }
311 //UNUSED2008-05 }
313 void XclExpStream::WriteUnicodeBuffer( const ScfUInt16Vec& rBuffer, sal_uInt8 nFlags )
315 SetSliceSize( 0 );
316 nFlags &= EXC_STRF_16BIT; // repeat only 16bit flag
317 sal_uInt16 nCharLen = nFlags ? 2 : 1;
319 ScfUInt16Vec::const_iterator aEnd = rBuffer.end();
320 for( ScfUInt16Vec::const_iterator aIter = rBuffer.begin(); aIter != aEnd; ++aIter )
322 if( mbInRec && (mnCurrSize + nCharLen > mnCurrMaxSize) )
324 StartContinue();
325 operator<<( nFlags );
327 if( nCharLen == 2 )
328 operator<<( *aIter );
329 else
330 operator<<( static_cast< sal_uInt8 >( *aIter ) );
334 //UNUSED2008-05 void XclExpStream::WriteByteStringBuffer( const ByteString& rString, sal_uInt16 nMaxLen )
335 //UNUSED2008-05 {
336 //UNUSED2008-05 SetSliceSize( 0 );
337 //UNUSED2008-05 Write( rString.GetBuffer(), ::std::min< sal_Size >( rString.Len(), nMaxLen ) );
338 //UNUSED2008-05 }
340 // ER: #71367# Xcl has an obscure sense of whether starting a new record or not,
341 // and crashes if it encounters the string header at the very end of a record.
342 // Thus we add 1 to give some room, seems like they do it that way but with another count (10?)
343 void XclExpStream::WriteByteString( const ByteString& rString, sal_uInt16 nMaxLen, bool b16BitCount )
345 SetSliceSize( 0 );
346 sal_Size nLen = ::std::min< sal_Size >( rString.Len(), nMaxLen );
347 if( !b16BitCount )
348 nLen = ::std::min< sal_Size >( nLen, 0xFF );
350 sal_uInt16 nLeft = PrepareWrite();
351 sal_uInt16 nLenFieldSize = b16BitCount ? 2 : 1;
352 if( mbInRec && (nLeft <= nLenFieldSize) )
353 StartContinue();
355 if( b16BitCount )
356 operator<<( static_cast< sal_uInt16 >( nLen ) );
357 else
358 operator<<( static_cast< sal_uInt8 >( nLen ) );
359 Write( rString.GetBuffer(), nLen );
362 void XclExpStream::WriteCharBuffer( const ScfUInt8Vec& rBuffer )
364 SetSliceSize( 0 );
365 Write( &rBuffer[ 0 ], rBuffer.size() );
368 void XclExpStream::SetEncrypter( XclExpEncrypterRef xEncrypter )
370 mxEncrypter = xEncrypter;
373 bool XclExpStream::HasValidEncrypter() const
375 return mxEncrypter.is() && mxEncrypter->IsValid();
378 void XclExpStream::EnableEncryption( bool bEnable )
380 mbUseEncrypter = bEnable && HasValidEncrypter();
383 void XclExpStream::DisableEncryption()
385 EnableEncryption(false);
388 sal_Size XclExpStream::SetSvStreamPos( sal_Size nPos )
390 DBG_ASSERT( !mbInRec, "XclExpStream::SetSvStreamPos - not allowed inside of a record" );
391 return mbInRec ? 0 : mrStrm.Seek( nPos );
394 // private --------------------------------------------------------------------
396 void XclExpStream::InitRecord( sal_uInt16 nRecId )
398 mrStrm.Seek( STREAM_SEEK_TO_END );
399 mrStrm << nRecId;
401 mnLastSizePos = mrStrm.Tell();
402 mnHeaderSize = static_cast< sal_uInt16 >( ::std::min< sal_Size >( mnPredictSize, mnCurrMaxSize ) );
403 mrStrm << mnHeaderSize;
404 mnCurrSize = mnSliceSize = 0;
407 void XclExpStream::UpdateRecSize()
409 if( mnCurrSize != mnHeaderSize )
411 mrStrm.Seek( mnLastSizePos );
412 mrStrm << mnCurrSize;
416 void XclExpStream::UpdateSizeVars( sal_Size nSize )
418 DBG_ASSERT( mnCurrSize + nSize <= mnCurrMaxSize, "XclExpStream::UpdateSizeVars - record overwritten" );
419 mnCurrSize = mnCurrSize + static_cast< sal_uInt16 >( nSize );
421 if( mnMaxSliceSize > 0 )
423 DBG_ASSERT( mnSliceSize + nSize <= mnMaxSliceSize, "XclExpStream::UpdateSizeVars - slice overwritten" );
424 mnSliceSize = mnSliceSize + static_cast< sal_uInt16 >( nSize );
425 if( mnSliceSize >= mnMaxSliceSize )
426 mnSliceSize = 0;
430 void XclExpStream::StartContinue()
432 UpdateRecSize();
433 mnCurrMaxSize = mnMaxContSize;
434 mnPredictSize -= mnCurrSize;
435 InitRecord( EXC_ID_CONT );
438 void XclExpStream::PrepareWrite( sal_uInt16 nSize )
440 if( mbInRec )
442 if( (mnCurrSize + nSize > mnCurrMaxSize) ||
443 ((mnMaxSliceSize > 0) && (mnSliceSize == 0) && (mnCurrSize + mnMaxSliceSize > mnCurrMaxSize)) )
444 StartContinue();
445 UpdateSizeVars( nSize );
449 sal_uInt16 XclExpStream::PrepareWrite()
451 sal_uInt16 nRet = 0;
452 if( mbInRec )
454 if( (mnCurrSize >= mnCurrMaxSize) ||
455 ((mnMaxSliceSize > 0) && (mnSliceSize == 0) && (mnCurrSize + mnMaxSliceSize > mnCurrMaxSize)) )
456 StartContinue();
457 UpdateSizeVars( 0 );
459 nRet = (mnMaxSliceSize > 0) ? (mnMaxSliceSize - mnSliceSize) : (mnCurrMaxSize - mnCurrSize);
461 return nRet;
464 void XclExpStream::WriteRawZeroBytes( sal_Size nBytes )
466 const sal_uInt32 nData = 0;
467 sal_Size nBytesLeft = nBytes;
468 while( nBytesLeft >= sizeof( nData ) )
470 mrStrm << nData;
471 nBytesLeft -= sizeof( nData );
473 if( nBytesLeft )
474 mrStrm.Write( &nData, nBytesLeft );
477 // ============================================================================
479 XclExpBiff8Encrypter::XclExpBiff8Encrypter( const XclExpRoot& rRoot, const sal_uInt8 nDocId[16],
480 const sal_uInt8 nSalt[16] ) :
481 mrRoot(rRoot),
482 mnOldPos(STREAM_SEEK_TO_END),
483 mbValid(false)
485 String aPass = rRoot.GetPassword();
486 if (aPass.Len() == 0)
487 // Empty password. Get the default biff8 password.
488 aPass = rRoot.GetDefaultPassword();
489 Init(aPass, nDocId, nSalt);
492 XclExpBiff8Encrypter::~XclExpBiff8Encrypter()
496 bool XclExpBiff8Encrypter::IsValid() const
498 return mbValid;
501 void XclExpBiff8Encrypter::GetSaltDigest( sal_uInt8 nSaltDigest[16] ) const
503 memcpy(nSaltDigest, mnSaltDigest, 16);
506 void XclExpBiff8Encrypter::Encrypt( SvStream& rStrm, sal_uInt8 nData )
508 vector<sal_uInt8> aByte(1);
509 aByte[0] = nData;
510 EncryptBytes(rStrm, aByte);
513 void XclExpBiff8Encrypter::Encrypt( SvStream& rStrm, sal_uInt16 nData )
515 ::std::vector<sal_uInt8> pnBytes(2);
516 pnBytes[0] = nData & 0xFF;
517 pnBytes[1] = (nData >> 8) & 0xFF;
518 EncryptBytes(rStrm, pnBytes);
521 void XclExpBiff8Encrypter::Encrypt( SvStream& rStrm, sal_uInt32 nData )
523 ::std::vector<sal_uInt8> pnBytes(4);
524 pnBytes[0] = nData & 0xFF;
525 pnBytes[1] = (nData >> 8) & 0xFF;
526 pnBytes[2] = (nData >> 16) & 0xFF;
527 pnBytes[3] = (nData >> 24) & 0xFF;
528 EncryptBytes(rStrm, pnBytes);
531 void XclExpBiff8Encrypter::Encrypt( SvStream& rStrm, float fValue )
533 ::std::vector<sal_uInt8> pnBytes(4);
534 memcpy(&pnBytes[0], &fValue, 4);
535 EncryptBytes(rStrm, pnBytes);
538 void XclExpBiff8Encrypter::Encrypt( SvStream& rStrm, double fValue )
540 ::std::vector<sal_uInt8> pnBytes(8);
541 memcpy(&pnBytes[0], &fValue, 8);
542 EncryptBytes(rStrm, pnBytes);
545 void XclExpBiff8Encrypter::Encrypt( SvStream& rStrm, sal_Int8 nData )
547 Encrypt(rStrm, static_cast<sal_uInt8>(nData));
550 void XclExpBiff8Encrypter::Encrypt( SvStream& rStrm, sal_Int16 nData )
552 Encrypt(rStrm, static_cast<sal_uInt16>(nData));
555 void XclExpBiff8Encrypter::Encrypt( SvStream& rStrm, sal_Int32 nData )
557 Encrypt(rStrm, static_cast<sal_uInt32>(nData));
560 void XclExpBiff8Encrypter::Init( const String& aPass, const sal_uInt8 nDocId[16],
561 const sal_uInt8 nSalt[16] )
563 memset(mnSaltDigest, 0, sizeof(mnSaltDigest));
565 xub_StrLen nLen = aPass.Len();
566 bool bValid = (0 < nLen) && (nLen < 16);
567 if ( bValid )
569 // transform String to sal_uInt16 array
570 memset(mnPassw, 0, sizeof(mnPassw));
571 for (xub_StrLen nChar = 0; nChar < nLen; ++nChar)
572 mnPassw[nChar] = static_cast<sal_uInt16>(aPass.GetChar(nChar));
574 // copy document ID
575 memcpy(mnDocId, nDocId, sizeof(mnDocId));
577 // init codec
578 maCodec.InitKey(mnPassw, mnDocId);
580 // generate salt hash.
581 ::svx::MSCodec_Std97 aCodec;
582 aCodec.InitKey(mnPassw, mnDocId);
583 aCodec.CreateSaltDigest(nSalt, mnSaltDigest);
585 // verify to make sure it's in good shape.
586 bValid = maCodec.VerifyKey(nSalt, mnSaltDigest);
589 mbValid = bValid;
592 sal_uInt32 XclExpBiff8Encrypter::GetBlockPos( sal_Size nStrmPos ) const
594 return static_cast<sal_uInt32>(nStrmPos / EXC_ENCR_BLOCKSIZE);
597 sal_uInt16 XclExpBiff8Encrypter::GetOffsetInBlock( sal_Size nStrmPos ) const
599 return static_cast<sal_uInt16>(nStrmPos % EXC_ENCR_BLOCKSIZE);
602 void XclExpBiff8Encrypter::EncryptBytes( SvStream& rStrm, vector<sal_uInt8>& aBytes )
604 sal_Size nStrmPos = rStrm.Tell();
605 sal_uInt16 nBlockOffset = GetOffsetInBlock(nStrmPos);
606 sal_uInt32 nBlockPos = GetBlockPos(nStrmPos);
608 #if DEBUG_XL_ENCRYPTION
609 fprintf(stdout, "XclExpBiff8Encrypter::EncryptBytes: stream pos = %ld offset in block = %d block pos = %ld\n",
610 nStrmPos, nBlockOffset, nBlockPos);
611 #endif
613 sal_uInt16 nSize = static_cast< sal_uInt16 >( aBytes.size() );
614 if (nSize == 0)
615 return;
617 #if DEBUG_XL_ENCRYPTION
618 fprintf(stdout, "RAW: ");
619 for (sal_uInt16 i = 0; i < nSize; ++i)
620 fprintf(stdout, "%2.2X ", aBytes[i]);
621 fprintf(stdout, "\n");
622 #endif
624 if (mnOldPos != nStrmPos)
626 sal_uInt16 nOldOffset = GetOffsetInBlock(mnOldPos);
627 sal_uInt32 nOldBlockPos = GetBlockPos(mnOldPos);
629 if ( (nBlockPos != nOldBlockPos) || (nBlockOffset < nOldOffset) )
631 maCodec.InitCipher(nBlockPos);
632 nOldOffset = 0;
635 if (nBlockOffset > nOldOffset)
636 maCodec.Skip(nBlockOffset - nOldOffset);
639 sal_uInt16 nBytesLeft = nSize;
640 sal_uInt16 nPos = 0;
641 while (nBytesLeft > 0)
643 sal_uInt16 nBlockLeft = EXC_ENCR_BLOCKSIZE - nBlockOffset;
644 sal_uInt16 nEncBytes = ::std::min(nBlockLeft, nBytesLeft);
646 bool bRet = maCodec.Encode(&aBytes[nPos], nEncBytes, &aBytes[nPos], nEncBytes);
647 DBG_ASSERT(bRet, "XclExpBiff8Encrypter::EncryptBytes: encryption failed!!");
648 bRet = bRet; // to remove a silly compiler warning.
650 sal_Size nRet = rStrm.Write(&aBytes[nPos], nEncBytes);
651 DBG_ASSERT(nRet == nEncBytes, "XclExpBiff8Encrypter::EncryptBytes: fail to write to stream!!");
652 nRet = nRet; // to remove a silly compiler warning.
654 nStrmPos = rStrm.Tell();
655 nBlockOffset = GetOffsetInBlock(nStrmPos);
656 nBlockPos = GetBlockPos(nStrmPos);
657 if (nBlockOffset == 0)
658 maCodec.InitCipher(nBlockPos);
660 nBytesLeft -= nEncBytes;
661 nPos += nEncBytes;
663 mnOldPos = nStrmPos;
666 rtl::OUString XclXmlUtils::GetStreamName( const char* sStreamDir, const char* sStream, sal_Int32 nId )
668 rtl::OUStringBuffer sBuf;
669 if( sStreamDir )
670 sBuf.appendAscii( sStreamDir );
671 sBuf.appendAscii( sStream );
672 if( nId )
673 sBuf.append( nId );
674 sBuf.appendAscii( ".xml" );
675 return sBuf.makeStringAndClear();
678 rtl::OString XclXmlUtils::ToOString( const Color& rColor )
680 char buf[9];
681 sprintf( buf, "%.2X%.2X%.2X%.2X", rColor.GetTransparency(), rColor.GetRed(), rColor.GetGreen(), rColor.GetBlue() );
682 buf[8] = '\0';
683 return OString( buf );
686 rtl::OString XclXmlUtils::ToOString( const ::rtl::OUString& s )
688 return OUStringToOString( s, RTL_TEXTENCODING_UTF8 );
691 rtl::OString XclXmlUtils::ToOString( const String& s )
693 return rtl::OString( s.GetBuffer(), s.Len(), RTL_TEXTENCODING_UTF8 );
696 rtl::OString XclXmlUtils::ToOString( const ScAddress& rAddress )
698 String sAddress;
699 rAddress.Format( sAddress, SCA_VALID, NULL, ScAddress::Details( FormulaGrammar::CONV_XL_A1 ) );
700 return ToOString( sAddress );
703 rtl::OString XclXmlUtils::ToOString( const ScfUInt16Vec& rBuffer )
705 const sal_uInt16* pBuffer = &rBuffer [0];
706 return ::rtl::OString( pBuffer, rBuffer.size(), RTL_TEXTENCODING_UTF8 );
709 rtl::OString XclXmlUtils::ToOString( const ScRange& rRange )
711 String sRange;
712 rRange.Format( sRange, SCA_VALID, NULL, ScAddress::Details( FormulaGrammar::CONV_XL_A1 ) );
713 return ToOString( sRange );
716 rtl::OString XclXmlUtils::ToOString( const ScRangeList& rRangeList )
718 String s;
719 rRangeList.Format( s, SCA_VALID, NULL, FormulaGrammar::CONV_XL_A1, ' ' );
720 return ToOString( s );
723 static ScAddress lcl_ToAddress( const XclAddress& rAddress )
725 ScAddress aAddress;
727 // For some reason, ScRange::Format() returns omits row numbers if
728 // the row is >= MAXROW or the column is >= MAXCOL, and Excel doesn't
729 // like "A:IV" (i.e. no row numbers). Prevent this.
730 aAddress.SetRow( std::min<sal_Int32>( rAddress.mnRow, MAXROW-1 ) );
731 aAddress.SetCol( static_cast<sal_Int16>(std::min<sal_Int32>( rAddress.mnCol, MAXCOL-1 )) );
733 return aAddress;
736 rtl::OString XclXmlUtils::ToOString( const XclAddress& rAddress )
738 return ToOString( lcl_ToAddress( rAddress ) );
741 rtl::OString XclXmlUtils::ToOString( const XclExpString& s )
743 DBG_ASSERT( !s.IsRich(), "XclXmlUtils::ToOString(XclExpString): rich text string found!" );
744 return ToOString( s.GetUnicodeBuffer() );
747 static ScRange lcl_ToRange( const XclRange& rRange )
749 ScRange aRange;
751 aRange.aStart = lcl_ToAddress( rRange.maFirst );
752 aRange.aEnd = lcl_ToAddress( rRange.maLast );
754 return aRange;
757 rtl::OString XclXmlUtils::ToOString( const XclRangeList& rRanges )
759 ScRangeList aRanges;
760 for( XclRangeList::const_iterator i = rRanges.begin(), end = rRanges.end();
761 i != end; ++i )
763 aRanges.Append( lcl_ToRange( *i ) );
765 return ToOString( aRanges );
768 OUString XclXmlUtils::ToOUString( const char* s )
770 return OUString( s, (sal_Int32) strlen( s ), RTL_TEXTENCODING_ASCII_US );
773 OUString XclXmlUtils::ToOUString( const ScfUInt16Vec& rBuf, sal_Int32 nStart, sal_Int32 nLength )
775 if( nLength == -1 )
776 nLength = rBuf.size();
778 return OUString( &rBuf[nStart], nLength );
781 OUString XclXmlUtils::ToOUString( const String& s )
783 return OUString( s.GetBuffer(), s.Len() );
786 rtl::OUString XclXmlUtils::ToOUString( ScDocument& rDocument, const ScAddress& rAddress, ScTokenArray* pTokenArray )
788 ScCompiler aCompiler( &rDocument, rAddress, *pTokenArray);
789 aCompiler.SetGrammar(FormulaGrammar::GRAM_NATIVE_XL_A1);
790 String s;
791 aCompiler.CreateStringFromTokenArray( s );
792 return ToOUString( s );
795 OUString XclXmlUtils::ToOUString( const XclExpString& s )
797 DBG_ASSERT( !s.IsRich(), "XclXmlUtils::ToOString(XclExpString): rich text string found!" );
798 return ToOUString( s.GetUnicodeBuffer() );
801 const char* XclXmlUtils::ToPsz( bool b )
803 return b ? "true" : "false";
806 // ============================================================================
808 XclExpXmlStream::XclExpXmlStream( const Reference< XMultiServiceFactory >& rSMgr, SvStream& rStrm, const XclExpRoot& rRoot )
809 : XmlFilterBase( rSMgr )
810 , mrRoot( rRoot )
812 Sequence< PropertyValue > aArgs( 1 );
813 const OUString sStream( RTL_CONSTASCII_USTRINGPARAM( "StreamForOutput" ) );
814 aArgs[0].Name = sStream;
815 aArgs[0].Value <<= Reference< XStream > ( new OStreamWrapper( rStrm ) );
817 XServiceInfo* pInfo = rRoot.GetDocModelObj();
818 Reference< XComponent > aComponent( pInfo, UNO_QUERY );
819 setSourceDocument( aComponent );
820 filter( aArgs );
822 PushStream( CreateOutputStream(
823 OUString::createFromAscii( "xl/workbook.xml" ),
824 OUString::createFromAscii( "xl/workbook.xml" ),
825 Reference< XOutputStream >(),
826 "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml",
827 "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" ) );
830 XclExpXmlStream::~XclExpXmlStream()
834 sax_fastparser::FSHelperPtr& XclExpXmlStream::GetCurrentStream()
836 DBG_ASSERT( !maStreams.empty(), "XclExpXmlStream::GetCurrentStream - no current stream" );
837 return maStreams.top();
840 void XclExpXmlStream::PushStream( sax_fastparser::FSHelperPtr aStream )
842 maStreams.push( aStream );
845 void XclExpXmlStream::PopStream()
847 DBG_ASSERT( !maStreams.empty(), "XclExpXmlStream::PopStream - stack is empty!" );
848 maStreams.pop();
851 OUString XclExpXmlStream::GetIdForPath( const OUString& sPath )
853 if( maOpenedStreamMap.find( sPath ) == maOpenedStreamMap.end() )
854 return OUString();
855 return maOpenedStreamMap[ sPath ].first;
858 sax_fastparser::FSHelperPtr XclExpXmlStream::GetStreamForPath( const OUString& sPath )
860 if( maOpenedStreamMap.find( sPath ) == maOpenedStreamMap.end() )
861 return sax_fastparser::FSHelperPtr();
862 return maOpenedStreamMap[ sPath ].second;
865 sax_fastparser::FSHelperPtr& XclExpXmlStream::WriteAttributes( sal_Int32 nAttribute, ... )
867 sax_fastparser::FSHelperPtr& rStream = GetCurrentStream();
869 va_list args;
870 va_start( args, nAttribute );
871 do {
872 const char* pValue = va_arg( args, const char* );
873 if( pValue )
875 rStream->write( " " )
876 ->writeId( nAttribute )
877 ->write( "=\"" )
878 ->writeEscaped( pValue )
879 ->write( "\"" );
882 nAttribute = va_arg( args, sal_Int32 );
883 if( nAttribute == FSEND )
884 break;
885 } while( true );
886 va_end( args );
888 return rStream;
891 static void lcl_WriteValue( sax_fastparser::FSHelperPtr& rStream, sal_Int32 nElement, const char* pValue )
893 if( !pValue )
894 return;
895 rStream->singleElement( nElement,
896 XML_val, pValue,
897 FSEND );
900 static const char* lcl_GetUnderlineStyle( FontUnderline eUnderline, bool& bHaveUnderline )
902 bHaveUnderline = true;
903 switch( eUnderline )
905 // OOXTODO: doubleAccounting, singleAccounting
906 // OOXTODO: what should be done with the other FontUnderline values?
907 case UNDERLINE_SINGLE: return "single";
908 case UNDERLINE_DOUBLE: return "double";
909 case UNDERLINE_NONE:
910 default: bHaveUnderline = false; return "none";
914 static const char* lcl_ToVerticalAlignmentRun( SvxEscapement eEscapement, bool& bHaveAlignment )
916 bHaveAlignment = true;
917 switch( eEscapement )
919 case SVX_ESCAPEMENT_SUPERSCRIPT: return "superscript";
920 case SVX_ESCAPEMENT_SUBSCRIPT: return "subscript";
921 case SVX_ESCAPEMENT_OFF:
922 default: bHaveAlignment = false; return "baseline";
926 sax_fastparser::FSHelperPtr& XclExpXmlStream::WriteFontData( const XclFontData& rFontData, sal_Int32 nFontId )
928 bool bHaveUnderline, bHaveVertAlign;
929 const char* pUnderline = lcl_GetUnderlineStyle( rFontData.GetScUnderline(), bHaveUnderline );
930 const char* pVertAlign = lcl_ToVerticalAlignmentRun( rFontData.GetScEscapement(), bHaveVertAlign );
932 sax_fastparser::FSHelperPtr& rStream = GetCurrentStream();
934 lcl_WriteValue( rStream, nFontId, XclXmlUtils::ToOString( rFontData.maName ).getStr() );
935 lcl_WriteValue( rStream, XML_charset, rFontData.mnCharSet != 0 ? OString::valueOf( (sal_Int32) rFontData.mnCharSet ).getStr() : NULL );
936 lcl_WriteValue( rStream, XML_family, OString::valueOf( (sal_Int32) rFontData.mnFamily ).getStr() );
937 lcl_WriteValue( rStream, XML_b, rFontData.mnWeight > 400 ? XclXmlUtils::ToPsz( rFontData.mnWeight > 400 ) : NULL );
938 lcl_WriteValue( rStream, XML_i, rFontData.mbItalic ? XclXmlUtils::ToPsz( rFontData.mbItalic ) : NULL );
939 lcl_WriteValue( rStream, XML_strike, rFontData.mbStrikeout ? XclXmlUtils::ToPsz( rFontData.mbStrikeout ) : NULL );
940 lcl_WriteValue( rStream, XML_outline, rFontData.mbOutline ? XclXmlUtils::ToPsz( rFontData.mbOutline ) : NULL );
941 lcl_WriteValue( rStream, XML_shadow, rFontData.mbShadow ? XclXmlUtils::ToPsz( rFontData.mbShadow ) : NULL );
942 // OOXTODO: lcl_WriteValue( rStream, XML_condense, ); // mac compatibility setting
943 // OOXTODO: lcl_WriteValue( rStream, XML_extend, ); // compatibility setting
944 if( rFontData.maColor != Color( 0xFF, 0xFF, 0xFF, 0xFF ) )
945 rStream->singleElement( XML_color,
946 // OOXTODO: XML_auto, bool
947 // OOXTODO: XML_indexed, uint
948 XML_rgb, XclXmlUtils::ToOString( rFontData.maColor ).getStr(),
949 // OOXTODO: XML_theme, index into <clrScheme/>
950 // OOXTODO: XML_tint, double
951 FSEND );
952 lcl_WriteValue( rStream, XML_sz, OString::valueOf( (double) (rFontData.mnHeight / 20.0) ) ); // Twips->Pt
953 lcl_WriteValue( rStream, XML_u, bHaveUnderline ? pUnderline : NULL );
954 lcl_WriteValue( rStream, XML_vertAlign, bHaveVertAlign ? pVertAlign : NULL );
956 return rStream;
959 sax_fastparser::FSHelperPtr XclExpXmlStream::CreateOutputStream (
960 const OUString& sFullStream,
961 const OUString& sRelativeStream,
962 const Reference< XOutputStream >& xParentRelation,
963 const char* sContentType,
964 const char* sRelationshipType,
965 ::rtl::OUString* pRelationshipId )
967 OUString sRelationshipId;
968 if (xParentRelation.is())
969 sRelationshipId = addRelation( xParentRelation, OUString::createFromAscii( sRelationshipType), sRelativeStream );
970 else
971 sRelationshipId = addRelation( OUString::createFromAscii( sRelationshipType ), sRelativeStream );
973 if( pRelationshipId )
974 *pRelationshipId = sRelationshipId;
976 sax_fastparser::FSHelperPtr p = openFragmentStreamWithSerializer( sFullStream, OUString::createFromAscii( sContentType ) );
978 maOpenedStreamMap[ sFullStream ] = std::make_pair( sRelationshipId, p );
980 return p;
983 bool XclExpXmlStream::importDocument() throw()
985 return false;
988 sal_Int32 XclExpXmlStream::getSchemeClr( sal_Int32 /*nColorSchemeToken*/ ) const
990 return -1;
993 oox::vml::Drawing* XclExpXmlStream::getVmlDrawing()
995 return 0;
998 const oox::drawingml::Theme* XclExpXmlStream::getCurrentTheme() const
1000 return 0;
1003 const oox::drawingml::table::TableStyleListPtr XclExpXmlStream::getTableStyles()
1005 return oox::drawingml::table::TableStyleListPtr();
1008 oox::drawingml::chart::ChartConverter& XclExpXmlStream::getChartConverter()
1010 // DO NOT CALL
1011 return * (oox::drawingml::chart::ChartConverter*) NULL;
1014 bool XclExpXmlStream::exportDocument() throw()
1016 return false;
1019 ::rtl::OUString XclExpXmlStream::implGetImplementationName() const
1021 return CREATE_OUSTRING( "TODO" );
1024 void XclExpXmlStream::Trace( const char* format, ...)
1026 va_list ap;
1027 va_start( ap, format );
1028 vfprintf( stderr, format, ap );
1029 va_end( ap );