1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
25 #include <rtl/ustring.hxx>
26 #include <rtl/ustrbuf.hxx>
27 #include <rtl/random.h>
28 #include <sax/fshelper.hxx>
29 #include <unotools/streamwrap.hxx>
32 #include "xestream.hxx"
33 #include "xladdress.hxx"
34 #include "xlstring.hxx"
36 #include "xestyle.hxx"
37 #include "xcl97rec.hxx"
38 #include "rangelst.hxx"
39 #include "compiler.hxx"
40 #include "formulacell.hxx"
41 #include "tokenarray.hxx"
43 #include <../../ui/inc/docsh.hxx>
44 #include <../../ui/inc/viewdata.hxx>
47 #include <oox/token/tokens.hxx>
48 #include <formula/grammar.hxx>
49 #include <oox/export/drawingml.hxx>
50 #include <excelvbaproject.hxx>
52 #include <sfx2/docfile.hxx>
53 #include <sfx2/objsh.hxx>
54 #include <sfx2/app.hxx>
55 #include <cppuhelper/implementationentry.hxx>
57 #define DEBUG_XL_ENCRYPTION 0
59 using ::com::sun::star::embed::XStorage
;
60 using ::com::sun::star::lang::XSingleServiceFactory
;
61 using ::com::sun::star::registry::InvalidRegistryException
;
62 using ::com::sun::star::registry::XRegistryKey
;
63 using ::com::sun::star::uno::Exception
;
64 using ::com::sun::star::uno::XInterface
;
65 using ::utl::OStreamWrapper
;
68 using namespace ::com::sun::star::beans
;
69 using namespace ::com::sun::star::io
;
70 using namespace ::com::sun::star::lang
;
71 using namespace ::com::sun::star::sheet
;
72 using namespace ::com::sun::star::uno
;
73 using namespace ::formula
;
74 using namespace ::oox
;
76 // ============================================================================
78 XclExpStream::XclExpStream( SvStream
& rOutStrm
, const XclExpRoot
& rRoot
, sal_uInt16 nMaxRecSize
) :
81 mnMaxRecSize( nMaxRecSize
),
91 if( mnMaxRecSize
== 0 )
92 mnMaxRecSize
= (mrRoot
.GetBiff() <= EXC_BIFF5
) ? EXC_MAXRECSIZE_BIFF5
: EXC_MAXRECSIZE_BIFF8
;
93 mnMaxContSize
= mnMaxRecSize
;
96 XclExpStream::~XclExpStream()
101 void XclExpStream::StartRecord( sal_uInt16 nRecId
, sal_Size nRecSize
)
103 OSL_ENSURE( !mbInRec
, "XclExpStream::StartRecord - another record still open" );
105 mnMaxContSize
= mnCurrMaxSize
= mnMaxRecSize
;
106 mnPredictSize
= nRecSize
;
108 InitRecord( nRecId
);
113 void XclExpStream::EndRecord()
115 OSL_ENSURE( mbInRec
, "XclExpStream::EndRecord - no record open" );
118 mrStrm
.Seek( STREAM_SEEK_TO_END
);
122 void XclExpStream::SetSliceSize( sal_uInt16 nSize
)
124 mnMaxSliceSize
= nSize
;
128 XclExpStream
& XclExpStream::operator<<( sal_Int8 nValue
)
131 if (mbUseEncrypter
&& HasValidEncrypter())
132 mxEncrypter
->Encrypt(mrStrm
, nValue
);
138 XclExpStream
& XclExpStream::operator<<( sal_uInt8 nValue
)
141 if (mbUseEncrypter
&& HasValidEncrypter())
142 mxEncrypter
->Encrypt(mrStrm
, nValue
);
148 XclExpStream
& XclExpStream::operator<<( sal_Int16 nValue
)
151 if (mbUseEncrypter
&& HasValidEncrypter())
152 mxEncrypter
->Encrypt(mrStrm
, nValue
);
158 XclExpStream
& XclExpStream::operator<<( sal_uInt16 nValue
)
161 if (mbUseEncrypter
&& HasValidEncrypter())
162 mxEncrypter
->Encrypt(mrStrm
, nValue
);
168 XclExpStream
& XclExpStream::operator<<( sal_Int32 nValue
)
171 if (mbUseEncrypter
&& HasValidEncrypter())
172 mxEncrypter
->Encrypt(mrStrm
, nValue
);
178 XclExpStream
& XclExpStream::operator<<( sal_uInt32 nValue
)
181 if (mbUseEncrypter
&& HasValidEncrypter())
182 mxEncrypter
->Encrypt(mrStrm
, nValue
);
188 XclExpStream
& XclExpStream::operator<<( float fValue
)
191 if (mbUseEncrypter
&& HasValidEncrypter())
192 mxEncrypter
->Encrypt(mrStrm
, fValue
);
198 XclExpStream
& XclExpStream::operator<<( double fValue
)
201 if (mbUseEncrypter
&& HasValidEncrypter())
202 mxEncrypter
->Encrypt(mrStrm
, fValue
);
208 sal_Size
XclExpStream::Write( const void* pData
, sal_Size nBytes
)
211 if( pData
&& (nBytes
> 0) )
215 const sal_uInt8
* pBuffer
= reinterpret_cast< const sal_uInt8
* >( pData
);
216 sal_Size nBytesLeft
= nBytes
;
219 while( bValid
&& (nBytesLeft
> 0) )
221 sal_Size nWriteLen
= ::std::min
< sal_Size
>( PrepareWrite(), nBytesLeft
);
222 sal_Size nWriteRet
= nWriteLen
;
223 if (mbUseEncrypter
&& HasValidEncrypter())
225 OSL_ENSURE(nWriteLen
> 0, "XclExpStream::Write: write length is 0!");
226 vector
<sal_uInt8
> aBytes(nWriteLen
);
227 memcpy(&aBytes
[0], pBuffer
, nWriteLen
);
228 mxEncrypter
->EncryptBytes(mrStrm
, aBytes
);
229 // TODO: How do I check if all the bytes have been successfully written ?
233 nWriteRet
= mrStrm
.Write( pBuffer
, nWriteLen
);
234 bValid
= (nWriteLen
== nWriteRet
);
235 OSL_ENSURE( bValid
, "XclExpStream::Write - stream write error" );
237 pBuffer
+= nWriteRet
;
239 nBytesLeft
-= nWriteRet
;
240 UpdateSizeVars( nWriteRet
);
244 nRet
= mrStrm
.Write( pData
, nBytes
);
249 void XclExpStream::WriteZeroBytes( sal_Size nBytes
)
253 sal_Size nBytesLeft
= nBytes
;
254 while( nBytesLeft
> 0 )
256 sal_Size nWriteLen
= ::std::min
< sal_Size
>( PrepareWrite(), nBytesLeft
);
257 WriteRawZeroBytes( nWriteLen
);
258 nBytesLeft
-= nWriteLen
;
259 UpdateSizeVars( nWriteLen
);
263 WriteRawZeroBytes( nBytes
);
266 void XclExpStream::WriteZeroBytesToRecord( sal_Size nBytes
)
273 for (sal_Size i
= 0; i
< nBytes
; ++i
)
277 sal_Size
XclExpStream::CopyFromStream( SvStream
& rInStrm
, sal_Size nBytes
)
279 sal_Size nStrmPos
= rInStrm
.Tell();
280 rInStrm
.Seek( STREAM_SEEK_TO_END
);
281 sal_Size nStrmSize
= rInStrm
.Tell();
282 rInStrm
.Seek( nStrmPos
);
284 sal_Size nBytesLeft
= ::std::min( nBytes
, nStrmSize
- nStrmPos
);
288 const sal_Size nMaxBuffer
= 4096;
289 sal_uInt8
* pBuffer
= new sal_uInt8
[ ::std::min( nBytesLeft
, nMaxBuffer
) ];
292 while( bValid
&& (nBytesLeft
> 0) )
294 sal_Size nWriteLen
= ::std::min( nBytesLeft
, nMaxBuffer
);
295 rInStrm
.Read( pBuffer
, nWriteLen
);
296 sal_Size nWriteRet
= Write( pBuffer
, nWriteLen
);
297 bValid
= (nWriteLen
== nWriteRet
);
299 nBytesLeft
-= nWriteRet
;
306 void XclExpStream::WriteUnicodeBuffer( const ScfUInt16Vec
& rBuffer
, sal_uInt8 nFlags
)
309 nFlags
&= EXC_STRF_16BIT
; // repeat only 16bit flag
310 sal_uInt16 nCharLen
= nFlags
? 2 : 1;
312 ScfUInt16Vec::const_iterator aEnd
= rBuffer
.end();
313 for( ScfUInt16Vec::const_iterator aIter
= rBuffer
.begin(); aIter
!= aEnd
; ++aIter
)
315 if( mbInRec
&& (mnCurrSize
+ nCharLen
> mnCurrMaxSize
) )
318 operator<<( nFlags
);
321 operator<<( *aIter
);
323 operator<<( static_cast< sal_uInt8
>( *aIter
) );
327 // Xcl has an obscure sense of whether starting a new record or not,
328 // and crashes if it encounters the string header at the very end of a record.
329 // Thus we add 1 to give some room, seems like they do it that way but with another count (10?)
330 void XclExpStream::WriteByteString( const OString
& rString
, sal_uInt16 nMaxLen
, bool b16BitCount
)
333 sal_Size nLen
= ::std::min
< sal_Size
>( rString
.getLength(), nMaxLen
);
335 nLen
= ::std::min
< sal_Size
>( nLen
, 0xFF );
337 sal_uInt16 nLeft
= PrepareWrite();
338 sal_uInt16 nLenFieldSize
= b16BitCount
? 2 : 1;
339 if( mbInRec
&& (nLeft
<= nLenFieldSize
) )
343 operator<<( static_cast< sal_uInt16
>( nLen
) );
345 operator<<( static_cast< sal_uInt8
>( nLen
) );
346 Write( rString
.getStr(), nLen
);
349 void XclExpStream::WriteCharBuffer( const ScfUInt8Vec
& rBuffer
)
352 Write( &rBuffer
[ 0 ], rBuffer
.size() );
355 void XclExpStream::SetEncrypter( XclExpEncrypterRef xEncrypter
)
357 mxEncrypter
= xEncrypter
;
360 bool XclExpStream::HasValidEncrypter() const
362 return mxEncrypter
&& mxEncrypter
->IsValid();
365 void XclExpStream::EnableEncryption( bool bEnable
)
367 mbUseEncrypter
= bEnable
&& HasValidEncrypter();
370 void XclExpStream::DisableEncryption()
372 EnableEncryption(false);
375 sal_Size
XclExpStream::SetSvStreamPos( sal_Size nPos
)
377 OSL_ENSURE( !mbInRec
, "XclExpStream::SetSvStreamPos - not allowed inside of a record" );
378 return mbInRec
? 0 : mrStrm
.Seek( nPos
);
381 // private --------------------------------------------------------------------
383 void XclExpStream::InitRecord( sal_uInt16 nRecId
)
385 mrStrm
.Seek( STREAM_SEEK_TO_END
);
388 mnLastSizePos
= mrStrm
.Tell();
389 mnHeaderSize
= static_cast< sal_uInt16
>( ::std::min
< sal_Size
>( mnPredictSize
, mnCurrMaxSize
) );
390 mrStrm
<< mnHeaderSize
;
391 mnCurrSize
= mnSliceSize
= 0;
394 void XclExpStream::UpdateRecSize()
396 if( mnCurrSize
!= mnHeaderSize
)
398 mrStrm
.Seek( mnLastSizePos
);
399 mrStrm
<< mnCurrSize
;
403 void XclExpStream::UpdateSizeVars( sal_Size nSize
)
405 OSL_ENSURE( mnCurrSize
+ nSize
<= mnCurrMaxSize
, "XclExpStream::UpdateSizeVars - record overwritten" );
406 mnCurrSize
= mnCurrSize
+ static_cast< sal_uInt16
>( nSize
);
408 if( mnMaxSliceSize
> 0 )
410 OSL_ENSURE( mnSliceSize
+ nSize
<= mnMaxSliceSize
, "XclExpStream::UpdateSizeVars - slice overwritten" );
411 mnSliceSize
= mnSliceSize
+ static_cast< sal_uInt16
>( nSize
);
412 if( mnSliceSize
>= mnMaxSliceSize
)
417 void XclExpStream::StartContinue()
420 mnCurrMaxSize
= mnMaxContSize
;
421 mnPredictSize
-= mnCurrSize
;
422 InitRecord( EXC_ID_CONT
);
425 void XclExpStream::PrepareWrite( sal_uInt16 nSize
)
429 if( (mnCurrSize
+ nSize
> mnCurrMaxSize
) ||
430 ((mnMaxSliceSize
> 0) && (mnSliceSize
== 0) && (mnCurrSize
+ mnMaxSliceSize
> mnCurrMaxSize
)) )
432 UpdateSizeVars( nSize
);
436 sal_uInt16
XclExpStream::PrepareWrite()
441 if( (mnCurrSize
>= mnCurrMaxSize
) ||
442 ((mnMaxSliceSize
> 0) && (mnSliceSize
== 0) && (mnCurrSize
+ mnMaxSliceSize
> mnCurrMaxSize
)) )
446 nRet
= (mnMaxSliceSize
> 0) ? (mnMaxSliceSize
- mnSliceSize
) : (mnCurrMaxSize
- mnCurrSize
);
451 void XclExpStream::WriteRawZeroBytes( sal_Size nBytes
)
453 const sal_uInt32 nData
= 0;
454 sal_Size nBytesLeft
= nBytes
;
455 while( nBytesLeft
>= sizeof( nData
) )
458 nBytesLeft
-= sizeof( nData
);
461 mrStrm
.Write( &nData
, nBytesLeft
);
464 // ============================================================================
466 XclExpBiff8Encrypter::XclExpBiff8Encrypter( const XclExpRoot
& rRoot
) :
467 mnOldPos(STREAM_SEEK_TO_END
),
470 Sequence
< NamedValue
> aEncryptionData
= rRoot
.GetEncryptionData();
471 if( !aEncryptionData
.hasElements() )
472 // Empty password. Get the default biff8 password.
473 aEncryptionData
= rRoot
.GenerateDefaultEncryptionData();
474 Init( aEncryptionData
);
477 XclExpBiff8Encrypter::~XclExpBiff8Encrypter()
481 bool XclExpBiff8Encrypter::IsValid() const
486 void XclExpBiff8Encrypter::GetSaltDigest( sal_uInt8 pnSaltDigest
[16] ) const
488 if ( sizeof( mpnSaltDigest
) == 16 )
489 memcpy( pnSaltDigest
, mpnSaltDigest
, 16 );
492 void XclExpBiff8Encrypter::GetSalt( sal_uInt8 pnSalt
[16] ) const
494 if ( sizeof( mpnSalt
) == 16 )
495 memcpy( pnSalt
, mpnSalt
, 16 );
498 void XclExpBiff8Encrypter::GetDocId( sal_uInt8 pnDocId
[16] ) const
500 if ( sizeof( mpnDocId
) == 16 )
501 memcpy( pnDocId
, mpnDocId
, 16 );
504 void XclExpBiff8Encrypter::Encrypt( SvStream
& rStrm
, sal_uInt8 nData
)
506 vector
<sal_uInt8
> aByte(1);
508 EncryptBytes(rStrm
, aByte
);
511 void XclExpBiff8Encrypter::Encrypt( SvStream
& rStrm
, sal_uInt16 nData
)
513 ::std::vector
<sal_uInt8
> pnBytes(2);
514 pnBytes
[0] = nData
& 0xFF;
515 pnBytes
[1] = (nData
>> 8) & 0xFF;
516 EncryptBytes(rStrm
, pnBytes
);
519 void XclExpBiff8Encrypter::Encrypt( SvStream
& rStrm
, sal_uInt32 nData
)
521 ::std::vector
<sal_uInt8
> pnBytes(4);
522 pnBytes
[0] = nData
& 0xFF;
523 pnBytes
[1] = (nData
>> 8) & 0xFF;
524 pnBytes
[2] = (nData
>> 16) & 0xFF;
525 pnBytes
[3] = (nData
>> 24) & 0xFF;
526 EncryptBytes(rStrm
, pnBytes
);
529 void XclExpBiff8Encrypter::Encrypt( SvStream
& rStrm
, float fValue
)
531 ::std::vector
<sal_uInt8
> pnBytes(4);
532 memcpy(&pnBytes
[0], &fValue
, 4);
533 EncryptBytes(rStrm
, pnBytes
);
536 void XclExpBiff8Encrypter::Encrypt( SvStream
& rStrm
, double fValue
)
538 ::std::vector
<sal_uInt8
> pnBytes(8);
539 memcpy(&pnBytes
[0], &fValue
, 8);
540 EncryptBytes(rStrm
, pnBytes
);
543 void XclExpBiff8Encrypter::Encrypt( SvStream
& rStrm
, sal_Int8 nData
)
545 Encrypt(rStrm
, static_cast<sal_uInt8
>(nData
));
548 void XclExpBiff8Encrypter::Encrypt( SvStream
& rStrm
, sal_Int16 nData
)
550 Encrypt(rStrm
, static_cast<sal_uInt16
>(nData
));
553 void XclExpBiff8Encrypter::Encrypt( SvStream
& rStrm
, sal_Int32 nData
)
555 Encrypt(rStrm
, static_cast<sal_uInt32
>(nData
));
558 void XclExpBiff8Encrypter::Init( const Sequence
< NamedValue
>& rEncryptionData
)
562 if( maCodec
.InitCodec( rEncryptionData
) )
564 maCodec
.GetDocId( mpnDocId
);
566 // generate the salt here
568 osl_getSystemTime( &aTime
);
569 rtlRandomPool aRandomPool
= rtl_random_createPool ();
570 rtl_random_addBytes( aRandomPool
, &aTime
, 8 );
571 rtl_random_getBytes( aRandomPool
, mpnSalt
, 16 );
572 rtl_random_destroyPool( aRandomPool
);
574 memset( mpnSaltDigest
, 0, sizeof( mpnSaltDigest
) );
576 // generate salt hash.
577 ::msfilter::MSCodec_Std97 aCodec
;
578 aCodec
.InitCodec( rEncryptionData
);
579 aCodec
.CreateSaltDigest( mpnSalt
, mpnSaltDigest
);
581 // verify to make sure it's in good shape.
582 mbValid
= maCodec
.VerifyKey( mpnSalt
, mpnSaltDigest
);
586 sal_uInt32
XclExpBiff8Encrypter::GetBlockPos( sal_Size nStrmPos
) const
588 return static_cast< sal_uInt32
>( nStrmPos
/ EXC_ENCR_BLOCKSIZE
);
591 sal_uInt16
XclExpBiff8Encrypter::GetOffsetInBlock( sal_Size nStrmPos
) const
593 return static_cast< sal_uInt16
>( nStrmPos
% EXC_ENCR_BLOCKSIZE
);
596 void XclExpBiff8Encrypter::EncryptBytes( SvStream
& rStrm
, vector
<sal_uInt8
>& aBytes
)
598 sal_Size nStrmPos
= rStrm
.Tell();
599 sal_uInt16 nBlockOffset
= GetOffsetInBlock(nStrmPos
);
600 sal_uInt32 nBlockPos
= GetBlockPos(nStrmPos
);
602 #if DEBUG_XL_ENCRYPTION
603 fprintf(stdout
, "XclExpBiff8Encrypter::EncryptBytes: stream pos = %ld offset in block = %d block pos = %ld\n",
604 nStrmPos
, nBlockOffset
, nBlockPos
);
607 sal_uInt16 nSize
= static_cast< sal_uInt16
>( aBytes
.size() );
611 #if DEBUG_XL_ENCRYPTION
612 fprintf(stdout
, "RAW: ");
613 for (sal_uInt16 i
= 0; i
< nSize
; ++i
)
614 fprintf(stdout
, "%2.2X ", aBytes
[i
]);
615 fprintf(stdout
, "\n");
618 if (mnOldPos
!= nStrmPos
)
620 sal_uInt16 nOldOffset
= GetOffsetInBlock(mnOldPos
);
621 sal_uInt32 nOldBlockPos
= GetBlockPos(mnOldPos
);
623 if ( (nBlockPos
!= nOldBlockPos
) || (nBlockOffset
< nOldOffset
) )
625 maCodec
.InitCipher(nBlockPos
);
629 if (nBlockOffset
> nOldOffset
)
630 maCodec
.Skip(nBlockOffset
- nOldOffset
);
633 sal_uInt16 nBytesLeft
= nSize
;
635 while (nBytesLeft
> 0)
637 sal_uInt16 nBlockLeft
= EXC_ENCR_BLOCKSIZE
- nBlockOffset
;
638 sal_uInt16 nEncBytes
= ::std::min(nBlockLeft
, nBytesLeft
);
640 bool bRet
= maCodec
.Encode(&aBytes
[nPos
], nEncBytes
, &aBytes
[nPos
], nEncBytes
);
641 OSL_ENSURE(bRet
, "XclExpBiff8Encrypter::EncryptBytes: encryption failed!!");
642 (void) bRet
; // to remove a silly compiler warning.
644 sal_Size nRet
= rStrm
.Write(&aBytes
[nPos
], nEncBytes
);
645 OSL_ENSURE(nRet
== nEncBytes
, "XclExpBiff8Encrypter::EncryptBytes: fail to write to stream!!");
646 (void) nRet
; // to remove a silly compiler warning.
648 nStrmPos
= rStrm
.Tell();
649 nBlockOffset
= GetOffsetInBlock(nStrmPos
);
650 nBlockPos
= GetBlockPos(nStrmPos
);
651 if (nBlockOffset
== 0)
652 maCodec
.InitCipher(nBlockPos
);
654 nBytesLeft
-= nEncBytes
;
660 static const char* lcl_GetErrorString( sal_uInt16 nScErrCode
)
662 sal_uInt8 nXclErrCode
= XclTools::GetXclErrorCode( nScErrCode
);
663 switch( nXclErrCode
)
665 case EXC_ERR_NULL
: return "#NULL!";
666 case EXC_ERR_DIV0
: return "#DIV/0!";
667 case EXC_ERR_VALUE
: return "#VALUE!";
668 case EXC_ERR_REF
: return "#REF!";
669 case EXC_ERR_NAME
: return "#NAME?";
670 case EXC_ERR_NUM
: return "#NUM!";
672 default: return "#N/A";
676 void XclXmlUtils::GetFormulaTypeAndValue( ScFormulaCell
& rCell
, const char*& rsType
, OUString
& rsValue
)
678 sal_uInt16 nScErrCode
= rCell
.GetErrCode();
682 rsValue
= ToOUString( lcl_GetErrorString( nScErrCode
) );
687 switch( rCell
.GetFormatType() )
689 case NUMBERFORMAT_NUMBER
:
691 // either value or error code
693 rsValue
= OUString::valueOf( rCell
.GetValue() );
697 case NUMBERFORMAT_TEXT
:
700 rsValue
= rCell
.GetString();
704 case NUMBERFORMAT_LOGICAL
:
707 rsValue
= ToOUString( rCell
.GetValue() == 0.0 ? "0" : "1" );
713 rsType
= "inlineStr";
714 rsValue
= rCell
.GetString();
720 OUString
XclXmlUtils::GetStreamName( const char* sStreamDir
, const char* sStream
, sal_Int32 nId
)
724 sBuf
.appendAscii( sStreamDir
);
725 sBuf
.appendAscii( sStream
);
728 if( strstr(sStream
, "vml") )
729 sBuf
.appendAscii( ".vml" );
731 sBuf
.appendAscii( ".xml" );
732 return sBuf
.makeStringAndClear();
735 OString
XclXmlUtils::ToOString( const Color
& rColor
)
738 sprintf( buf
, "%.2X%.2X%.2X%.2X", 0xFF-rColor
.GetTransparency(), rColor
.GetRed(), rColor
.GetGreen(), rColor
.GetBlue() );
740 return OString( buf
);
743 OString
XclXmlUtils::ToOString( const OUString
& s
)
745 return OUStringToOString( s
, RTL_TEXTENCODING_UTF8
);
748 OString
XclXmlUtils::ToOString( const String
& s
)
750 return OString( s
.GetBuffer(), s
.Len(), RTL_TEXTENCODING_UTF8
);
753 OString
XclXmlUtils::ToOString( const ScAddress
& rAddress
)
756 rAddress
.Format( sAddress
, SCA_VALID
, NULL
, ScAddress::Details( FormulaGrammar::CONV_XL_A1
) );
757 return ToOString( sAddress
);
760 OString
XclXmlUtils::ToOString( const ScfUInt16Vec
& rBuffer
)
762 const sal_uInt16
* pBuffer
= &rBuffer
[0];
763 return OString( pBuffer
, rBuffer
.size(), RTL_TEXTENCODING_UTF8
);
766 OString
XclXmlUtils::ToOString( const ScRange
& rRange
)
769 rRange
.Format( sRange
, SCA_VALID
, NULL
, ScAddress::Details( FormulaGrammar::CONV_XL_A1
) );
770 return ToOString( sRange
);
773 OString
XclXmlUtils::ToOString( const ScRangeList
& rRangeList
)
776 rRangeList
.Format( s
, SCA_VALID
, NULL
, FormulaGrammar::CONV_XL_A1
, ' ' );
777 return ToOString( s
);
780 static ScAddress
lcl_ToAddress( const XclAddress
& rAddress
)
784 // For some reason, ScRange::Format() returns omits row numbers if
785 // the row is >= MAXROW or the column is >= MAXCOL, and Excel doesn't
786 // like "A:IV" (i.e. no row numbers). Prevent this.
787 // KOHEI: Find out if the above comment is still true.
788 aAddress
.SetRow( std::min
<sal_Int32
>( rAddress
.mnRow
, MAXROW
) );
789 aAddress
.SetCol( static_cast<sal_Int16
>(std::min
<sal_Int32
>( rAddress
.mnCol
, MAXCOL
)) );
794 OString
XclXmlUtils::ToOString( const XclAddress
& rAddress
)
796 return ToOString( lcl_ToAddress( rAddress
) );
799 OString
XclXmlUtils::ToOString( const XclExpString
& s
)
801 OSL_ENSURE( !s
.IsRich(), "XclXmlUtils::ToOString(XclExpString): rich text string found!" );
802 return ToOString( s
.GetUnicodeBuffer() );
805 static ScRange
lcl_ToRange( const XclRange
& rRange
)
809 aRange
.aStart
= lcl_ToAddress( rRange
.maFirst
);
810 aRange
.aEnd
= lcl_ToAddress( rRange
.maLast
);
815 OString
XclXmlUtils::ToOString( const XclRange
& rRange
)
817 return ToOString( lcl_ToRange( rRange
) );
820 OString
XclXmlUtils::ToOString( const XclRangeList
& rRanges
)
823 for( XclRangeList::const_iterator i
= rRanges
.begin(), end
= rRanges
.end();
826 aRanges
.Append( lcl_ToRange( *i
) );
828 return ToOString( aRanges
);
831 OUString
XclXmlUtils::ToOUString( const char* s
)
833 return OUString( s
, (sal_Int32
) strlen( s
), RTL_TEXTENCODING_ASCII_US
);
836 OUString
XclXmlUtils::ToOUString( const ScfUInt16Vec
& rBuf
, sal_Int32 nStart
, sal_Int32 nLength
)
838 if( nLength
== -1 || ( nLength
> ((sal_Int32
)rBuf
.size() - nStart
) ) )
839 nLength
= (rBuf
.size() - nStart
);
841 return (nLength
> 0) ? OUString( &rBuf
[nStart
], nLength
) : OUString();
844 OUString
XclXmlUtils::ToOUString( const String
& s
)
846 return OUString( s
.GetBuffer(), s
.Len() );
849 OUString
XclXmlUtils::ToOUString( ScDocument
& rDocument
, const ScAddress
& rAddress
,
850 ScTokenArray
* pTokenArray
, const FormulaCompiler::OpCodeMapPtr
& xOpCodeMap
)
852 ScCompiler
aCompiler( &rDocument
, rAddress
, *pTokenArray
);
855 aCompiler
.SetFormulaLanguage( xOpCodeMap
);
856 /* TODO: The correct ref convention would be CONV_XL_OOX but that would
857 * need aCompiler.SetExternalLinks() and so far we don't have the links
859 aCompiler
.SetRefConvention( formula::FormulaGrammar::CONV_XL_A1
);
863 SAL_WARN( "sc", "XclXmlUtils::ToOUString - no opcodemap, dumb fallback to PODF");
864 aCompiler
.SetGrammar(FormulaGrammar::GRAM_ENGLISH_XL_A1
);
867 OUStringBuffer
aBuffer( pTokenArray
->GetLen() * 5 );
868 aCompiler
.CreateStringFromTokenArray( aBuffer
);
869 return aBuffer
.makeStringAndClear();
872 OUString
XclXmlUtils::ToOUString( const XclExpString
& s
)
874 OSL_ENSURE( !s
.IsRich(), "XclXmlUtils::ToOString(XclExpString): rich text string found!" );
875 return ToOUString( s
.GetUnicodeBuffer() );
878 const char* XclXmlUtils::ToPsz( bool b
)
880 return b
? "true" : "false";
883 sax_fastparser::FSHelperPtr
XclXmlUtils::WriteElement( sax_fastparser::FSHelperPtr pStream
, sal_Int32 nElement
, sal_Int32 nValue
)
885 pStream
->startElement( nElement
, FSEND
);
886 pStream
->write( nValue
);
887 pStream
->endElement( nElement
);
892 sax_fastparser::FSHelperPtr
XclXmlUtils::WriteElement( sax_fastparser::FSHelperPtr pStream
, sal_Int32 nElement
, sal_Int64 nValue
)
894 pStream
->startElement( nElement
, FSEND
);
895 pStream
->write( nValue
);
896 pStream
->endElement( nElement
);
901 sax_fastparser::FSHelperPtr
XclXmlUtils::WriteElement( sax_fastparser::FSHelperPtr pStream
, sal_Int32 nElement
, const char* sValue
)
903 pStream
->startElement( nElement
, FSEND
);
904 pStream
->write( sValue
);
905 pStream
->endElement( nElement
);
910 static void lcl_WriteValue( sax_fastparser::FSHelperPtr
& rStream
, sal_Int32 nElement
, const char* pValue
)
914 rStream
->singleElement( nElement
,
919 static const char* lcl_GetUnderlineStyle( FontUnderline eUnderline
, bool& bHaveUnderline
)
921 bHaveUnderline
= true;
924 // OOXTODO: doubleAccounting, singleAccounting
925 // OOXTODO: what should be done with the other FontUnderline values?
926 case UNDERLINE_SINGLE
: return "single";
927 case UNDERLINE_DOUBLE
: return "double";
929 default: bHaveUnderline
= false; return "none";
933 static const char* lcl_ToVerticalAlignmentRun( SvxEscapement eEscapement
, bool& bHaveAlignment
)
935 bHaveAlignment
= true;
936 switch( eEscapement
)
938 case SVX_ESCAPEMENT_SUPERSCRIPT
: return "superscript";
939 case SVX_ESCAPEMENT_SUBSCRIPT
: return "subscript";
940 case SVX_ESCAPEMENT_OFF
:
941 default: bHaveAlignment
= false; return "baseline";
945 sax_fastparser::FSHelperPtr
XclXmlUtils::WriteFontData( sax_fastparser::FSHelperPtr pStream
, const XclFontData
& rFontData
, sal_Int32 nFontId
)
947 bool bHaveUnderline
, bHaveVertAlign
;
948 const char* pUnderline
= lcl_GetUnderlineStyle( rFontData
.GetScUnderline(), bHaveUnderline
);
949 const char* pVertAlign
= lcl_ToVerticalAlignmentRun( rFontData
.GetScEscapement(), bHaveVertAlign
);
951 lcl_WriteValue( pStream
, XML_b
, rFontData
.mnWeight
> 400 ? XclXmlUtils::ToPsz( rFontData
.mnWeight
> 400 ) : NULL
);
952 lcl_WriteValue( pStream
, XML_i
, rFontData
.mbItalic
? XclXmlUtils::ToPsz( rFontData
.mbItalic
) : NULL
);
953 lcl_WriteValue( pStream
, XML_strike
, rFontData
.mbStrikeout
? XclXmlUtils::ToPsz( rFontData
.mbStrikeout
) : NULL
);
954 // OOXTODO: lcl_WriteValue( rStream, XML_condense, ); // mac compatibility setting
955 // OOXTODO: lcl_WriteValue( rStream, XML_extend, ); // compatibility setting
956 lcl_WriteValue( pStream
, XML_outline
, rFontData
.mbOutline
? XclXmlUtils::ToPsz( rFontData
.mbOutline
) : NULL
);
957 lcl_WriteValue( pStream
, XML_shadow
, rFontData
.mbShadow
? XclXmlUtils::ToPsz( rFontData
.mbShadow
) : NULL
);
958 lcl_WriteValue( pStream
, XML_u
, bHaveUnderline
? pUnderline
: NULL
);
959 lcl_WriteValue( pStream
, XML_vertAlign
, bHaveVertAlign
? pVertAlign
: NULL
);
960 lcl_WriteValue( pStream
, XML_sz
, OString::valueOf( (double) (rFontData
.mnHeight
/ 20.0) ).getStr() ); // Twips->Pt
961 if( rFontData
.maColor
!= Color( 0xFF, 0xFF, 0xFF, 0xFF ) )
962 pStream
->singleElement( XML_color
,
963 // OOXTODO: XML_auto, bool
964 // OOXTODO: XML_indexed, uint
965 XML_rgb
, XclXmlUtils::ToOString( rFontData
.maColor
).getStr(),
966 // OOXTODO: XML_theme, index into <clrScheme/>
967 // OOXTODO: XML_tint, double
969 lcl_WriteValue( pStream
, nFontId
, XclXmlUtils::ToOString( rFontData
.maName
).getStr() );
970 lcl_WriteValue( pStream
, XML_family
, OString::valueOf( (sal_Int32
) rFontData
.mnFamily
).getStr() );
971 lcl_WriteValue( pStream
, XML_charset
, rFontData
.mnCharSet
!= 0 ? OString::valueOf( (sal_Int32
) rFontData
.mnCharSet
).getStr() : NULL
);
977 // ============================================================================
979 XclExpXmlStream::XclExpXmlStream( const Reference
< XComponentContext
>& rCC
)
980 : XmlFilterBase( rCC
),
985 XclExpXmlStream::~XclExpXmlStream()
989 sax_fastparser::FSHelperPtr
& XclExpXmlStream::GetCurrentStream()
991 OSL_ENSURE( !maStreams
.empty(), "XclExpXmlStream::GetCurrentStream - no current stream" );
992 return maStreams
.top();
995 void XclExpXmlStream::PushStream( sax_fastparser::FSHelperPtr aStream
)
997 maStreams
.push( aStream
);
1000 void XclExpXmlStream::PopStream()
1002 OSL_ENSURE( !maStreams
.empty(), "XclExpXmlStream::PopStream - stack is empty!" );
1006 sax_fastparser::FSHelperPtr
XclExpXmlStream::GetStreamForPath( const OUString
& sPath
)
1008 if( maOpenedStreamMap
.find( sPath
) == maOpenedStreamMap
.end() )
1009 return sax_fastparser::FSHelperPtr();
1010 return maOpenedStreamMap
[ sPath
].second
;
1013 sax_fastparser::FSHelperPtr
& XclExpXmlStream::WriteAttributesInternal( sal_Int32 nAttribute
, ... )
1015 sax_fastparser::FSHelperPtr
& rStream
= GetCurrentStream();
1018 va_start( args
, nAttribute
);
1020 const char* pValue
= va_arg( args
, const char* );
1023 rStream
->write( " " )
1024 ->writeId( nAttribute
)
1026 ->writeEscaped( pValue
)
1030 nAttribute
= va_arg( args
, sal_Int32
);
1031 if( nAttribute
== FSEND_internal
)
1038 sax_fastparser::FSHelperPtr
XclExpXmlStream::CreateOutputStream (
1039 const OUString
& sFullStream
,
1040 const OUString
& sRelativeStream
,
1041 const Reference
< XOutputStream
>& xParentRelation
,
1042 const char* sContentType
,
1043 const char* sRelationshipType
,
1044 OUString
* pRelationshipId
)
1046 OUString sRelationshipId
;
1047 if (xParentRelation
.is())
1048 sRelationshipId
= addRelation( xParentRelation
, OUString::createFromAscii( sRelationshipType
), sRelativeStream
);
1050 sRelationshipId
= addRelation( OUString::createFromAscii( sRelationshipType
), sRelativeStream
);
1052 if( pRelationshipId
)
1053 *pRelationshipId
= sRelationshipId
;
1055 sax_fastparser::FSHelperPtr p
= openFragmentStreamWithSerializer( sFullStream
, OUString::createFromAscii( sContentType
) );
1057 maOpenedStreamMap
[ sFullStream
] = std::make_pair( sRelationshipId
, p
);
1062 bool XclExpXmlStream::importDocument() throw()
1067 oox::vml::Drawing
* XclExpXmlStream::getVmlDrawing()
1072 const oox::drawingml::Theme
* XclExpXmlStream::getCurrentTheme() const
1077 const oox::drawingml::table::TableStyleListPtr
XclExpXmlStream::getTableStyles()
1079 return oox::drawingml::table::TableStyleListPtr();
1082 oox::drawingml::chart::ChartConverter
* XclExpXmlStream::getChartConverter()
1088 ScDocShell
* XclExpXmlStream::getDocShell()
1090 Reference
< XInterface
> xModel( getModel(), UNO_QUERY
);
1092 ScModelObj
*pObj
= dynamic_cast < ScModelObj
* >( xModel
.get() );
1095 return static_cast < ScDocShell
* >( pObj
->GetEmbeddedObject() );
1100 bool XclExpXmlStream::exportDocument() throw()
1102 ScDocShell
* pShell
= getDocShell();
1103 ScDocument
* pDoc
= pShell
->GetDocument();
1104 // NOTE: Don't use SotStorage or SvStream any more, and never call
1105 // SfxMedium::GetOutStream() anywhere in the xlsx export filter code!
1106 // Instead, write via XOutputStream instance.
1107 SotStorageRef rStorage
= static_cast<SotStorage
*>(NULL
);
1108 XclExpObjList::ResetCounters();
1110 XclExpRootData
aData( EXC_BIFF8
, *pShell
->GetMedium (), rStorage
, *pDoc
, RTL_TEXTENCODING_DONTKNOW
);
1111 aData
.meOutput
= EXC_OUTPUT_XML_2007
;
1112 aData
.maXclMaxPos
.Set( EXC_MAXCOL_XML_2007
, EXC_MAXROW_XML_2007
, EXC_MAXTAB_XML_2007
);
1113 aData
.maMaxPos
.SetCol( ::std::min( aData
.maScMaxPos
.Col(), aData
.maXclMaxPos
.Col() ) );
1114 aData
.maMaxPos
.SetRow( ::std::min( aData
.maScMaxPos
.Row(), aData
.maXclMaxPos
.Row() ) );
1115 aData
.maMaxPos
.SetTab( ::std::min( aData
.maScMaxPos
.Tab(), aData
.maXclMaxPos
.Tab() ) );
1117 XclExpRoot
aRoot( aData
);
1120 aRoot
.GetOldRoot().pER
= &aRoot
;
1121 aRoot
.GetOldRoot().eDateiTyp
= Biff8
;
1122 // Get the viewsettings before processing
1123 if( pShell
->GetViewData() )
1124 pShell
->GetViewData()->WriteExtOptions( mpRoot
->GetExtDocOptions() );
1126 OUString
const workbook
= "xl/workbook.xml";
1127 PushStream( CreateOutputStream( workbook
, workbook
,
1128 Reference
<XOutputStream
>(),
1129 "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml",
1130 "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" ) );
1132 // destruct at the end of the block
1134 ExcDocument
aDocRoot( aRoot
);
1136 aDocRoot
.WriteXml( *this );
1143 //////////////////////////////////////////////////////////////////////////
1144 // UNO stuff so that the filter is registered
1145 //////////////////////////////////////////////////////////////////////////
1147 #define IMPL_NAME "com.sun.star.comp.oox.ExcelFilterExport"
1149 OUString
XlsxExport_getImplementationName()
1151 return OUString( IMPL_NAME
);
1154 ::oox::ole::VbaProject
* XclExpXmlStream::implCreateVbaProject() const
1156 return new ::oox::xls::ExcelVbaProject( getComponentContext(), Reference
< XSpreadsheetDocument
>( getModel(), UNO_QUERY
) );
1159 OUString
XclExpXmlStream::implGetImplementationName() const
1161 return OUString( "TODO" );
1165 Sequence
< OUString
> SAL_CALL
XlsxExport_getSupportedServiceNames() throw()
1167 const OUString
aServiceName( "com.sun.star.document.ExportFilter" );
1168 const Sequence
< OUString
> aSeq( &aServiceName
, 1 );
1172 Reference
< XInterface
> SAL_CALL
XlsxExport_createInstance(const Reference
< XComponentContext
> & rCC
) throw( Exception
)
1174 return (cppu::OWeakObject
*) new XclExpXmlStream( rCC
);
1177 namespace oox
{ namespace xls
{
1178 OUString SAL_CALL
ExcelFilter_getImplementationName() throw();
1179 Sequence
< OUString
> SAL_CALL
ExcelFilter_getSupportedServiceNames() throw();
1180 Reference
< XInterface
> SAL_CALL
ExcelFilter_createInstance(
1181 const Reference
< XComponentContext
>& rxContext
) throw( Exception
);
1183 OUString SAL_CALL
OOXMLFormulaParser_getImplementationName() throw();
1184 Sequence
< OUString
> SAL_CALL
OOXMLFormulaParser_getSupportedServiceNames() throw();
1185 Reference
< XInterface
> SAL_CALL
OOXMLFormulaParser_create(
1186 const Reference
< XComponentContext
>& rxContext
) throw();
1194 // ------------------------
1195 // - component_getFactory -
1196 // ------------------------
1197 ::cppu::ImplementationEntry entries
[] =
1200 XlsxExport_createInstance
, XlsxExport_getImplementationName
,
1201 XlsxExport_getSupportedServiceNames
, ::cppu::createSingleComponentFactory
,
1205 oox::xls::ExcelFilter_createInstance
, oox::xls::ExcelFilter_getImplementationName
,
1206 oox::xls::ExcelFilter_getSupportedServiceNames
, ::cppu::createSingleComponentFactory
,
1210 oox::xls::OOXMLFormulaParser_create
, oox::xls::OOXMLFormulaParser_getImplementationName
,
1211 oox::xls::OOXMLFormulaParser_getSupportedServiceNames
, ::cppu::createSingleComponentFactory
,
1214 { 0, 0, 0, 0, 0, 0 }
1217 SAL_DLLPUBLIC_EXPORT
void* SAL_CALL
scfilt_component_getFactory( const sal_Char
* pImplName
, XMultiServiceFactory
* pServiceManager
, XRegistryKey
* pRegistryKey
)
1219 return ::cppu::component_getFactoryHelper( pImplName
, pServiceManager
, pRegistryKey
, entries
);
1226 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */