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 .
20 #include "oox/dump/dumperbase.hxx"
23 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
24 #include <com/sun/star/io/XActiveDataSource.hpp>
25 #include <com/sun/star/io/TextOutputStream.hpp>
26 #include <com/sun/star/ucb/SimpleFileAccess.hpp>
27 #include <comphelper/docpasswordhelper.hxx>
28 #include <osl/file.hxx>
29 #include <rtl/math.hxx>
30 #include <rtl/tencinfo.h>
31 #include "oox/core/filterbase.hxx"
32 #include "oox/helper/binaryoutputstream.hxx"
33 #include "oox/helper/textinputstream.hxx"
34 #include <tools/time.hxx>
36 #if OOX_INCLUDE_DUMPER
41 using namespace ::com::sun::star
;
42 using namespace ::com::sun::star::beans
;
43 using namespace ::com::sun::star::io
;
44 using namespace ::com::sun::star::lang
;
45 using namespace ::com::sun::star::ucb
;
46 using namespace ::com::sun::star::uno
;
48 using ::oox::core::FilterBase
;
52 const sal_Unicode OOX_DUMP_BOM
= 0xFEFF;
53 const sal_Int32 OOX_DUMP_MAXSTRLEN
= 80;
54 const sal_Int32 OOX_DUMP_INDENT
= 2;
55 const sal_Unicode OOX_DUMP_BINDOT
= '.';
56 const sal_Unicode OOX_DUMP_CFG_LISTSEP
= ',';
57 const sal_Unicode OOX_DUMP_CFG_QUOTE
= '\'';
58 const sal_Unicode OOX_DUMP_LF
= '\n';
59 const sal_Unicode OOX_DUMP_ITEMSEP
= '=';
60 const sal_Int32 OOX_DUMP_BYTESPERLINE
= 16;
61 const sal_Int64 OOX_DUMP_MAXARRAY
= 16;
65 // file names -----------------------------------------------------------------
67 OUString
InputOutputHelper::convertFileNameToUrl( const OUString
& rFileName
)
70 if( ::osl::FileBase::getFileURLFromSystemPath( rFileName
, aFileUrl
) == ::osl::FileBase::E_None
)
75 sal_Int32
InputOutputHelper::getFileNamePos( const OUString
& rFileUrl
)
77 sal_Int32 nSepPos
= rFileUrl
.lastIndexOf( '/' );
78 return (nSepPos
< 0) ? 0 : (nSepPos
+ 1);
81 OUString
InputOutputHelper::getFileNameExtension( const OUString
& rFileUrl
)
83 sal_Int32 nNamePos
= getFileNamePos( rFileUrl
);
84 sal_Int32 nExtPos
= rFileUrl
.lastIndexOf( '.' );
85 if( nExtPos
>= nNamePos
)
86 return rFileUrl
.copy( nExtPos
+ 1 );
90 // input streams --------------------------------------------------------------
92 Reference
< XInputStream
> InputOutputHelper::openInputStream(
93 const Reference
< XComponentContext
>& rxContext
, const OUString
& rFileName
)
95 Reference
< XInputStream
> xInStrm
;
96 if( rxContext
.is() ) try
98 Reference
<XSimpleFileAccess3
> xFileAccess(SimpleFileAccess::create(rxContext
));
99 xInStrm
= xFileAccess
->openFileRead( rFileName
);
107 // output streams -------------------------------------------------------------
109 Reference
< XOutputStream
> InputOutputHelper::openOutputStream(
110 const Reference
< XComponentContext
>& rxContext
, const OUString
& rFileName
)
112 Reference
< XOutputStream
> xOutStrm
;
113 if( rxContext
.is() ) try
115 Reference
<XSimpleFileAccess3
> xFileAccess(SimpleFileAccess::create(rxContext
));
116 xOutStrm
= xFileAccess
->openFileWrite( rFileName
);
124 Reference
< XTextOutputStream2
> InputOutputHelper::openTextOutputStream(
125 const Reference
< XComponentContext
>& rxContext
, const Reference
< XOutputStream
>& rxOutStrm
, rtl_TextEncoding eTextEnc
)
127 Reference
< XTextOutputStream2
> xTextOutStrm
;
128 const char* pcCharset
= rtl_getMimeCharsetFromTextEncoding( eTextEnc
);
129 if( rxContext
.is() && rxOutStrm
.is() && pcCharset
) try
131 xTextOutStrm
= TextOutputStream::create(rxContext
);
132 xTextOutStrm
->setOutputStream( rxOutStrm
);
133 xTextOutStrm
->setEncoding( OUString::createFromAscii( pcCharset
) );
141 Reference
< XTextOutputStream2
> InputOutputHelper::openTextOutputStream(
142 const Reference
< XComponentContext
>& rxContext
, const OUString
& rFileName
, rtl_TextEncoding eTextEnc
)
144 return openTextOutputStream( rxContext
, openOutputStream( rxContext
, rFileName
), eTextEnc
);
147 ItemFormat::ItemFormat() :
148 meDataType( DATATYPE_VOID
),
149 meFmtType( FORMATTYPE_NONE
)
153 void ItemFormat::set( DataType eDataType
, FormatType eFmtType
, const OUString
& rItemName
)
155 meDataType
= eDataType
;
156 meFmtType
= eFmtType
;
157 maItemName
= rItemName
;
161 OUStringVector::const_iterator
ItemFormat::parse( const OUStringVector
& rFormatVec
)
163 set( DATATYPE_VOID
, FORMATTYPE_NONE
, OUString() );
165 OUStringVector::const_iterator aIt
= rFormatVec
.begin(), aEnd
= rFormatVec
.end();
166 OUString aDataType
, aFmtType
;
167 if( aIt
!= aEnd
) aDataType
= *aIt
++;
168 if( aIt
!= aEnd
) aFmtType
= *aIt
++;
169 if( aIt
!= aEnd
) maItemName
= *aIt
++;
170 if( aIt
!= aEnd
) maListName
= *aIt
++;
172 meDataType
= StringHelper::convertToDataType( aDataType
);
173 meFmtType
= StringHelper::convertToFormatType( aFmtType
);
175 if( meFmtType
== FORMATTYPE_NONE
)
177 if ( aFmtType
== "unused" )
178 set( meDataType
, FORMATTYPE_HEX
, OOX_DUMP_UNUSED
);
179 else if ( aFmtType
== "unknown" )
180 set( meDataType
, FORMATTYPE_HEX
, OOX_DUMP_UNKNOWN
);
186 OUStringVector
ItemFormat::parse( const OUString
& rFormatStr
)
188 OUStringVector aFormatVec
;
189 StringHelper::convertStringToStringList( aFormatVec
, rFormatStr
, false );
190 OUStringVector::const_iterator aIt
= parse( aFormatVec
);
191 return OUStringVector( aIt
, const_cast< const OUStringVector
& >( aFormatVec
).end() );
194 // append string to string ----------------------------------------------------
196 void StringHelper::appendChar( OUStringBuffer
& rStr
, sal_Unicode cChar
, sal_Int32 nCount
)
198 for( sal_Int32 nIndex
= 0; nIndex
< nCount
; ++nIndex
)
199 rStr
.append( cChar
);
202 void StringHelper::appendString( OUStringBuffer
& rStr
, const OUString
& rData
, sal_Int32 nWidth
, sal_Unicode cFill
)
204 appendChar( rStr
, cFill
, nWidth
- rData
.getLength() );
205 rStr
.append( rData
);
208 // append decimal -------------------------------------------------------------
210 void StringHelper::appendDec( OUStringBuffer
& rStr
, sal_uInt8 nData
, sal_Int32 nWidth
, sal_Unicode cFill
)
212 appendString( rStr
, OUString::number( nData
), nWidth
, cFill
);
215 void StringHelper::appendDec( OUStringBuffer
& rStr
, sal_Int8 nData
, sal_Int32 nWidth
, sal_Unicode cFill
)
217 appendString( rStr
, OUString::number( nData
), nWidth
, cFill
);
220 void StringHelper::appendDec( OUStringBuffer
& rStr
, sal_uInt16 nData
, sal_Int32 nWidth
, sal_Unicode cFill
)
222 appendString( rStr
, OUString::number( nData
), nWidth
, cFill
);
225 void StringHelper::appendDec( OUStringBuffer
& rStr
, sal_Int16 nData
, sal_Int32 nWidth
, sal_Unicode cFill
)
227 appendString( rStr
, OUString::number( nData
), nWidth
, cFill
);
230 void StringHelper::appendDec( OUStringBuffer
& rStr
, sal_uInt32 nData
, sal_Int32 nWidth
, sal_Unicode cFill
)
232 appendString( rStr
, OUString::number( nData
), nWidth
, cFill
);
235 void StringHelper::appendDec( OUStringBuffer
& rStr
, sal_Int32 nData
, sal_Int32 nWidth
, sal_Unicode cFill
)
237 appendString( rStr
, OUString::number( nData
), nWidth
, cFill
);
240 void StringHelper::appendDec( OUStringBuffer
& rStr
, sal_uInt64 nData
, sal_Int32 nWidth
, sal_Unicode cFill
)
242 /* Values greater than biggest signed 64bit integer will change to
243 negative when converting to sal_Int64. Therefore, the trailing digit
244 will be written separately. */
245 OUStringBuffer aBuffer
;
247 aBuffer
.append( OUString::number( nData
/ 10 ) );
248 aBuffer
.append( static_cast< sal_Unicode
>( '0' + (nData
% 10) ) );
249 appendString( rStr
, aBuffer
.makeStringAndClear(), nWidth
, cFill
);
252 void StringHelper::appendDec( OUStringBuffer
& rStr
, sal_Int64 nData
, sal_Int32 nWidth
, sal_Unicode cFill
)
254 appendString( rStr
, OUString::number( nData
), nWidth
, cFill
);
257 void StringHelper::appendDec( OUStringBuffer
& rStr
, double fData
, sal_Int32 nWidth
, sal_Unicode cFill
)
259 appendString( rStr
, ::rtl::math::doubleToUString( fData
, rtl_math_StringFormat_G
, 15, '.', true ), nWidth
, cFill
);
262 // append hexadecimal ---------------------------------------------------------
264 void StringHelper::appendHex( OUStringBuffer
& rStr
, sal_uInt8 nData
, bool bPrefix
)
266 static const sal_Unicode spcHexDigits
[] = { '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F' };
268 rStr
.appendAscii( "0x" );
269 rStr
.append( spcHexDigits
[ (nData
>> 4) & 0x0F ] ).append( spcHexDigits
[ nData
& 0x0F ] );
272 void StringHelper::appendHex( OUStringBuffer
& rStr
, sal_Int8 nData
, bool bPrefix
)
274 appendHex( rStr
, static_cast< sal_uInt8
>( nData
), bPrefix
);
277 void StringHelper::appendHex( OUStringBuffer
& rStr
, sal_uInt16 nData
, bool bPrefix
)
279 appendHex( rStr
, static_cast< sal_uInt8
>( nData
>> 8 ), bPrefix
);
280 appendHex( rStr
, static_cast< sal_uInt8
>( nData
), false );
283 void StringHelper::appendHex( OUStringBuffer
& rStr
, sal_Int16 nData
, bool bPrefix
)
285 appendHex( rStr
, static_cast< sal_uInt16
>( nData
), bPrefix
);
288 void StringHelper::appendHex( OUStringBuffer
& rStr
, sal_uInt32 nData
, bool bPrefix
)
290 appendHex( rStr
, static_cast< sal_uInt16
>( nData
>> 16 ), bPrefix
);
291 appendHex( rStr
, static_cast< sal_uInt16
>( nData
), false );
294 void StringHelper::appendHex( OUStringBuffer
& rStr
, sal_Int32 nData
, bool bPrefix
)
296 appendHex( rStr
, static_cast< sal_uInt32
>( nData
), bPrefix
);
299 void StringHelper::appendHex( OUStringBuffer
& rStr
, sal_uInt64 nData
, bool bPrefix
)
301 appendHex( rStr
, static_cast< sal_uInt32
>( nData
>> 32 ), bPrefix
);
302 appendHex( rStr
, static_cast< sal_uInt32
>( nData
), false );
305 void StringHelper::appendHex( OUStringBuffer
& rStr
, sal_Int64 nData
, bool bPrefix
)
307 appendHex( rStr
, static_cast< sal_uInt64
>( nData
), bPrefix
);
311 lcl_ConvertDouble(double const f
)
313 sal_uInt64 i
= sal_uInt64();
314 for (size_t j
= 0; j
< sizeof(double); ++j
)
315 { // hopefully both endian independent and strict aliasing safe
316 reinterpret_cast<char *>(&i
)[j
] = reinterpret_cast<char const *>(&f
)[j
];
321 void StringHelper::appendHex( OUStringBuffer
& rStr
, double fData
, bool bPrefix
)
323 appendHex( rStr
, lcl_ConvertDouble(fData
), bPrefix
);
326 // append shortened hexadecimal -----------------------------------------------
328 void StringHelper::appendShortHex( OUStringBuffer
& rStr
, sal_uInt8 nData
, bool bPrefix
)
330 appendHex( rStr
, nData
, bPrefix
);
333 void StringHelper::appendShortHex( OUStringBuffer
& rStr
, sal_Int8 nData
, bool bPrefix
)
335 appendHex( rStr
, nData
, bPrefix
);
338 void StringHelper::appendShortHex( OUStringBuffer
& rStr
, sal_uInt16 nData
, bool bPrefix
)
340 if( nData
> SAL_MAX_UINT8
)
341 appendHex( rStr
, nData
, bPrefix
);
343 appendHex( rStr
, static_cast< sal_uInt8
>( nData
), bPrefix
);
346 void StringHelper::appendShortHex( OUStringBuffer
& rStr
, sal_Int16 nData
, bool bPrefix
)
348 appendShortHex( rStr
, static_cast< sal_uInt16
>( nData
), bPrefix
);
351 void StringHelper::appendShortHex( OUStringBuffer
& rStr
, sal_uInt32 nData
, bool bPrefix
)
353 if( nData
> SAL_MAX_UINT16
)
354 appendHex( rStr
, nData
, bPrefix
);
356 appendShortHex( rStr
, static_cast< sal_uInt16
>( nData
), bPrefix
);
359 void StringHelper::appendShortHex( OUStringBuffer
& rStr
, sal_Int32 nData
, bool bPrefix
)
361 appendShortHex( rStr
, static_cast< sal_uInt32
>( nData
), bPrefix
);
364 void StringHelper::appendShortHex( OUStringBuffer
& rStr
, sal_uInt64 nData
, bool bPrefix
)
366 if( nData
> SAL_MAX_UINT32
)
367 appendHex( rStr
, nData
, bPrefix
);
369 appendShortHex( rStr
, static_cast< sal_uInt32
>( nData
), bPrefix
);
372 void StringHelper::appendShortHex( OUStringBuffer
& rStr
, sal_Int64 nData
, bool bPrefix
)
374 appendShortHex( rStr
, static_cast< sal_uInt64
>( nData
), bPrefix
);
377 void StringHelper::appendShortHex( OUStringBuffer
& rStr
, double fData
, bool bPrefix
)
379 appendHex( rStr
, fData
, bPrefix
);
382 // append binary --------------------------------------------------------------
384 void StringHelper::appendBin( OUStringBuffer
& rStr
, sal_uInt8 nData
, bool bDots
)
386 for( sal_uInt8 nMask
= 0x80; nMask
!= 0; (nMask
>>= 1) &= 0x7F )
388 rStr
.append( static_cast< sal_Unicode
>( (nData
& nMask
) ? '1' : '0' ) );
389 if( bDots
&& (nMask
== 0x10) )
390 rStr
.append( OOX_DUMP_BINDOT
);
394 void StringHelper::appendBin( OUStringBuffer
& rStr
, sal_Int8 nData
, bool bDots
)
396 appendBin( rStr
, static_cast< sal_uInt8
>( nData
), bDots
);
399 void StringHelper::appendBin( OUStringBuffer
& rStr
, sal_uInt16 nData
, bool bDots
)
401 appendBin( rStr
, static_cast< sal_uInt8
>( nData
>> 8 ), bDots
);
403 rStr
.append( OOX_DUMP_BINDOT
);
404 appendBin( rStr
, static_cast< sal_uInt8
>( nData
), bDots
);
407 void StringHelper::appendBin( OUStringBuffer
& rStr
, sal_Int16 nData
, bool bDots
)
409 appendBin( rStr
, static_cast< sal_uInt16
>( nData
), bDots
);
412 void StringHelper::appendBin( OUStringBuffer
& rStr
, sal_uInt32 nData
, bool bDots
)
414 appendBin( rStr
, static_cast< sal_uInt16
>( nData
>> 16 ), bDots
);
416 rStr
.append( OOX_DUMP_BINDOT
);
417 appendBin( rStr
, static_cast< sal_uInt16
>( nData
), bDots
);
420 void StringHelper::appendBin( OUStringBuffer
& rStr
, sal_Int32 nData
, bool bDots
)
422 appendBin( rStr
, static_cast< sal_uInt32
>( nData
), bDots
);
425 void StringHelper::appendBin( OUStringBuffer
& rStr
, sal_uInt64 nData
, bool bDots
)
427 appendBin( rStr
, static_cast< sal_uInt32
>( nData
>> 32 ), bDots
);
429 rStr
.append( OOX_DUMP_BINDOT
);
430 appendBin( rStr
, static_cast< sal_uInt32
>( nData
), bDots
);
433 void StringHelper::appendBin( OUStringBuffer
& rStr
, sal_Int64 nData
, bool bDots
)
435 appendBin( rStr
, static_cast< sal_uInt64
>( nData
), bDots
);
438 void StringHelper::appendBin( OUStringBuffer
& rStr
, double fData
, bool bDots
)
440 appendBin( rStr
, lcl_ConvertDouble(fData
), bDots
);
443 // append formatted value -----------------------------------------------------
445 void StringHelper::appendBool( OUStringBuffer
& rStr
, bool bData
)
447 rStr
.appendAscii( bData
? "true" : "false" );
450 // encoded text output --------------------------------------------------------
452 void StringHelper::appendCChar( OUStringBuffer
& rStr
, sal_Unicode cChar
, bool bPrefix
)
457 rStr
.appendAscii( "\\u" );
458 appendHex( rStr
, static_cast< sal_uInt16
>( cChar
), false );
463 rStr
.appendAscii( "\\x" );
464 appendHex( rStr
, static_cast< sal_uInt8
>( cChar
), false );
468 void StringHelper::appendEncChar( OUStringBuffer
& rStr
, sal_Unicode cChar
, sal_Int32 nCount
, bool bPrefix
)
473 OUStringBuffer aCode
;
474 appendCChar( aCode
, cChar
, bPrefix
);
475 OUString aCodeStr
= aCode
.makeStringAndClear();
476 for( sal_Int32 nIdx
= 0; nIdx
< nCount
; ++nIdx
)
477 rStr
.append( aCodeStr
);
481 appendChar( rStr
, cChar
, nCount
);
485 void StringHelper::appendEncString( OUStringBuffer
& rStr
, const OUString
& rData
, bool bPrefix
)
489 sal_Int32 nEnd
= rData
.getLength();
492 // find next character that needs encoding
493 while( (nIdx
< nEnd
) && (rData
[ nIdx
] >= 0x20) ) ++nIdx
;
497 if( (nBeg
== 0) && (nIdx
== nEnd
) )
498 rStr
.append( rData
);
500 rStr
.append( rData
.copy( nBeg
, nIdx
- nBeg
) );
502 // append characters to be encoded
503 while( (nIdx
< nEnd
) && (rData
[ nIdx
] < 0x20) )
505 appendCChar( rStr
, rData
[ nIdx
], bPrefix
);
513 // token list -----------------------------------------------------------------
515 void StringHelper::appendToken( OUStringBuffer
& rStr
, const OUString
& rToken
, sal_Unicode cSep
)
517 if( (rStr
.getLength() > 0) && (!rToken
.isEmpty()) )
519 rStr
.append( rToken
);
522 void StringHelper::appendIndex( OUStringBuffer
& rStr
, const OUString
& rIdx
)
524 rStr
.append( '[' ).append( rIdx
).append( ']' );
527 void StringHelper::appendIndex( OUStringBuffer
& rStr
, sal_Int64 nIdx
)
529 OUStringBuffer aToken
;
530 appendDec( aToken
, nIdx
);
531 appendIndex( rStr
, aToken
.makeStringAndClear() );
534 OUString
StringHelper::getToken( const OUString
& rData
, sal_Int32
& rnPos
, sal_Unicode cSep
)
536 return trimSpaces( rData
.getToken( 0, cSep
, rnPos
) );
539 void StringHelper::enclose( OUStringBuffer
& rStr
, sal_Unicode cOpen
, sal_Unicode cClose
)
541 rStr
.insert( 0, cOpen
).append( cClose
? cClose
: cOpen
);
544 // string conversion ----------------------------------------------------------
548 sal_Int32
lclIndexOf( const OUString
& rStr
, sal_Unicode cChar
, sal_Int32 nStartPos
)
550 sal_Int32 nIndex
= rStr
.indexOf( cChar
, nStartPos
);
551 return (nIndex
< 0) ? rStr
.getLength() : nIndex
;
554 OUString
lclTrimQuotedStringList( const OUString
& rStr
)
556 OUStringBuffer aBuffer
;
558 sal_Int32 nLen
= rStr
.getLength();
561 if( rStr
[ nPos
] == OOX_DUMP_CFG_QUOTE
)
563 // quoted string, skip leading quote character
565 // process quoted text and ambedded literal quote characters
566 OUStringBuffer aToken
;
569 // seek to next quote character and add text portion to token buffer
570 sal_Int32 nEnd
= lclIndexOf( rStr
, OOX_DUMP_CFG_QUOTE
, nPos
);
571 aToken
.append( rStr
.copy( nPos
, nEnd
- nPos
) );
572 // process literal quotes
573 while( (nEnd
+ 1 < nLen
) && (rStr
[ nEnd
] == OOX_DUMP_CFG_QUOTE
) && (rStr
[ nEnd
+ 1 ] == OOX_DUMP_CFG_QUOTE
) )
575 aToken
.append( OOX_DUMP_CFG_QUOTE
);
578 // nEnd is start of possible next text portion
581 while( (nPos
< nLen
) && (rStr
[ nPos
] != OOX_DUMP_CFG_QUOTE
) );
582 // add token, seek to list separator, ignore text following closing quote
583 aBuffer
.append( aToken
.makeStringAndClear() );
584 nPos
= lclIndexOf( rStr
, OOX_DUMP_CFG_LISTSEP
, nPos
);
586 aBuffer
.append( OOX_DUMP_LF
);
587 // set current position behind list separator
592 // find list separator, add token text to buffer
593 sal_Int32 nEnd
= lclIndexOf( rStr
, OOX_DUMP_CFG_LISTSEP
, nPos
);
594 aBuffer
.append( rStr
.copy( nPos
, nEnd
- nPos
) );
596 aBuffer
.append( OOX_DUMP_LF
);
597 // set current position behind list separator
602 return aBuffer
.makeStringAndClear();
607 OUString
StringHelper::trimSpaces( const OUString
& rStr
)
610 while( (nBeg
< rStr
.getLength()) && ((rStr
[ nBeg
] == ' ') || (rStr
[ nBeg
] == '\t')) )
612 sal_Int32 nEnd
= rStr
.getLength();
613 while( (nEnd
> nBeg
) && ((rStr
[ nEnd
- 1 ] == ' ') || (rStr
[ nEnd
- 1 ] == '\t')) )
615 return rStr
.copy( nBeg
, nEnd
- nBeg
);
618 OUString
StringHelper::trimTrailingNul( const OUString
& rStr
)
620 sal_Int32 nLastPos
= rStr
.getLength() - 1;
621 if( (nLastPos
>= 0) && (rStr
[ nLastPos
] == 0) )
622 return rStr
.copy( 0, nLastPos
);
626 OString
StringHelper::convertToUtf8( const OUString
& rStr
)
628 return OUStringToOString( rStr
, RTL_TEXTENCODING_UTF8
);
631 DataType
StringHelper::convertToDataType( const OUString
& rStr
)
633 DataType eType
= DATATYPE_VOID
;
634 if ( rStr
== "int8" )
635 eType
= DATATYPE_INT8
;
636 else if ( rStr
== "uint8" )
637 eType
= DATATYPE_UINT8
;
638 else if ( rStr
== "int16" )
639 eType
= DATATYPE_INT16
;
640 else if ( rStr
== "uint16" )
641 eType
= DATATYPE_UINT16
;
642 else if ( rStr
== "int32" )
643 eType
= DATATYPE_INT32
;
644 else if ( rStr
== "uint32" )
645 eType
= DATATYPE_UINT32
;
646 else if ( rStr
== "int64" )
647 eType
= DATATYPE_INT64
;
648 else if ( rStr
== "uint64" )
649 eType
= DATATYPE_UINT64
;
650 else if ( rStr
== "float" )
651 eType
= DATATYPE_FLOAT
;
652 else if ( rStr
== "double" )
653 eType
= DATATYPE_DOUBLE
;
657 FormatType
StringHelper::convertToFormatType( const OUString
& rStr
)
659 FormatType eType
= FORMATTYPE_NONE
;
661 eType
= FORMATTYPE_DEC
;
662 else if ( rStr
== "hex" )
663 eType
= FORMATTYPE_HEX
;
664 else if ( rStr
== "shorthex" )
665 eType
= FORMATTYPE_SHORTHEX
;
666 else if ( rStr
== "bin" )
667 eType
= FORMATTYPE_BIN
;
668 else if ( rStr
== "fix" )
669 eType
= FORMATTYPE_FIX
;
670 else if ( rStr
== "bool" )
671 eType
= FORMATTYPE_BOOL
;
675 bool StringHelper::convertFromDec( sal_Int64
& ornData
, const OUString
& rData
)
678 sal_Int32 nLen
= rData
.getLength();
680 if( (nLen
> 0) && (rData
[ 0 ] == '-') )
686 for( ; nPos
< nLen
; ++nPos
)
688 sal_Unicode cChar
= rData
[ nPos
];
689 if( (cChar
< '0') || (cChar
> '9') )
691 (ornData
*= 10) += (cChar
- '0');
698 bool StringHelper::convertFromHex( sal_Int64
& ornData
, const OUString
& rData
)
701 for( sal_Int32 nPos
= 0, nLen
= rData
.getLength(); nPos
< nLen
; ++nPos
)
703 sal_Unicode cChar
= rData
[ nPos
];
704 if( ('0' <= cChar
) && (cChar
<= '9') )
706 else if( ('A' <= cChar
) && (cChar
<= 'F') )
708 else if( ('a' <= cChar
) && (cChar
<= 'f') )
712 (ornData
<<= 4) += cChar
;
717 bool StringHelper::convertStringToInt( sal_Int64
& ornData
, const OUString
& rData
)
719 if( (rData
.getLength() > 2) && (rData
[ 0 ] == '0') && ((rData
[ 1 ] == 'X') || (rData
[ 1 ] == 'x')) )
720 return convertFromHex( ornData
, rData
.copy( 2 ) );
721 return convertFromDec( ornData
, rData
);
724 bool StringHelper::convertStringToDouble( double& orfData
, const OUString
& rData
)
726 rtl_math_ConversionStatus eStatus
= rtl_math_ConversionStatus_Ok
;
728 orfData
= rtl::math::stringToDouble( rData
, '.', '\0', &eStatus
, &nSize
);
729 return (eStatus
== rtl_math_ConversionStatus_Ok
) && (nSize
== rData
.getLength());
732 bool StringHelper::convertStringToBool( const OUString
& rData
)
734 if ( rData
== "true" )
736 if ( rData
== "false" )
739 return convertStringToInt( nData
, rData
) && (nData
!= 0);
742 OUStringPair
StringHelper::convertStringToPair( const OUString
& rString
, sal_Unicode cSep
)
745 if( !rString
.isEmpty() )
747 sal_Int32 nEqPos
= rString
.indexOf( cSep
);
750 aPair
.first
= rString
;
754 aPair
.first
= StringHelper::trimSpaces( rString
.copy( 0, nEqPos
) );
755 aPair
.second
= StringHelper::trimSpaces( rString
.copy( nEqPos
+ 1 ) );
761 void StringHelper::convertStringToStringList( OUStringVector
& orVec
, const OUString
& rData
, bool bIgnoreEmpty
)
764 OUString aUnquotedData
= lclTrimQuotedStringList( rData
);
766 sal_Int32 nLen
= aUnquotedData
.getLength();
767 while( (0 <= nPos
) && (nPos
< nLen
) )
769 OUString aToken
= getToken( aUnquotedData
, nPos
, OOX_DUMP_LF
);
770 if( !bIgnoreEmpty
|| !aToken
.isEmpty() )
771 orVec
.push_back( aToken
);
775 void StringHelper::convertStringToIntList( Int64Vector
& orVec
, const OUString
& rData
, bool bIgnoreEmpty
)
778 OUString aUnquotedData
= lclTrimQuotedStringList( rData
);
780 sal_Int32 nLen
= aUnquotedData
.getLength();
782 while( (0 <= nPos
) && (nPos
< nLen
) )
784 bool bOk
= convertStringToInt( nData
, getToken( aUnquotedData
, nPos
, OOX_DUMP_LF
) );
785 if( !bIgnoreEmpty
|| bOk
)
786 orVec
.push_back( bOk
? nData
: 0 );
794 ConfigItemBase::~ConfigItemBase()
798 void ConfigItemBase::readConfigBlock( TextInputStream
& rStrm
)
800 readConfigBlockContents( rStrm
);
803 void ConfigItemBase::implProcessConfigItemStr(
804 TextInputStream
& /*rStrm*/, const OUString
& /*rKey*/, const OUString
& /*rData*/ )
808 void ConfigItemBase::implProcessConfigItemInt(
809 TextInputStream
& /*rStrm*/, sal_Int64
/*nKey*/, const OUString
& /*rData*/ )
813 void ConfigItemBase::readConfigBlockContents( TextInputStream
& rStrm
)
816 while( bLoop
&& !rStrm
.isEof() )
818 OUString aKey
, aData
;
819 switch( readConfigLine( rStrm
, aKey
, aData
) )
822 processConfigItem( rStrm
, aKey
, aData
);
831 ConfigItemBase::LineType
ConfigItemBase::readConfigLine(
832 TextInputStream
& rStrm
, OUString
& orKey
, OUString
& orData
)
835 while( !rStrm
.isEof() && aLine
.isEmpty() )
837 aLine
= rStrm
.readLine();
838 if( !aLine
.isEmpty() && (aLine
[ 0 ] == OOX_DUMP_BOM
) )
839 aLine
= aLine
.copy( 1 );
840 aLine
= StringHelper::trimSpaces( aLine
);
841 if( !aLine
.isEmpty() )
843 // ignore comments (starting with hash or semicolon)
844 sal_Unicode cChar
= aLine
[ 0 ];
845 if( (cChar
== '#') || (cChar
== ';') )
850 OUStringPair aPair
= StringHelper::convertStringToPair( aLine
);
852 orData
= aPair
.second
;
853 return ( !orKey
.isEmpty() && (!orData
.isEmpty() || orKey
!= "end" )) ?
854 LINETYPE_DATA
: LINETYPE_END
;
857 void ConfigItemBase::processConfigItem(
858 TextInputStream
& rStrm
, const OUString
& rKey
, const OUString
& rData
)
861 if( StringHelper::convertStringToInt( nKey
, rKey
) )
862 implProcessConfigItemInt( rStrm
, nKey
, rData
);
864 implProcessConfigItemStr( rStrm
, rKey
, rData
);
867 NameListBase::~NameListBase()
871 void NameListBase::setName( sal_Int64 nKey
, const String
& rName
)
873 implSetName( nKey
, rName
);
876 void NameListBase::includeList( const NameListRef
& rxList
)
880 for( const_iterator aIt
= rxList
->begin(), aEnd
= rxList
->end(); aIt
!= aEnd
; ++aIt
)
881 maMap
[ aIt
->first
] = aIt
->second
;
882 implIncludeList( *rxList
);
886 bool NameListBase::implIsValid() const
891 void NameListBase::implProcessConfigItemStr(
892 TextInputStream
& rStrm
, const OUString
& rKey
, const OUString
& rData
)
894 if ( rKey
== "include" )
896 else if ( rKey
== "exclude" )
899 ConfigItemBase::implProcessConfigItemStr( rStrm
, rKey
, rData
);
902 void NameListBase::implProcessConfigItemInt(
903 TextInputStream
& /*rStrm*/, sal_Int64 nKey
, const OUString
& rData
)
905 implSetName( nKey
, rData
);
908 void NameListBase::insertRawName( sal_Int64 nKey
, const OUString
& rName
)
910 maMap
[ nKey
] = rName
;
913 const OUString
* NameListBase::findRawName( sal_Int64 nKey
) const
915 const_iterator aIt
= maMap
.find( nKey
);
916 return (aIt
== end()) ? 0 : &aIt
->second
;
919 void NameListBase::include( const OUString
& rListKeys
)
922 StringHelper::convertStringToStringList( aVec
, rListKeys
, true );
923 for( OUStringVector::const_iterator aIt
= aVec
.begin(), aEnd
= aVec
.end(); aIt
!= aEnd
; ++aIt
)
924 includeList( mrCfgData
.getNameList( *aIt
) );
927 void NameListBase::exclude( const OUString
& rKeys
)
930 StringHelper::convertStringToIntList( aVec
, rKeys
, true );
931 for( Int64Vector::const_iterator aIt
= aVec
.begin(), aEnd
= aVec
.end(); aIt
!= aEnd
; ++aIt
)
935 void ItemFormatMap::insertFormats( const NameListRef
& rxNameList
)
937 if( Base::isValid( rxNameList
) )
938 for( NameListBase::const_iterator aIt
= rxNameList
->begin(), aEnd
= rxNameList
->end(); aIt
!= aEnd
; ++aIt
)
939 maMap
[ aIt
->first
].parse( aIt
->second
);
942 ConstList::ConstList( const SharedConfigData
& rCfgData
) :
943 NameListBase( rCfgData
),
944 maDefName( OOX_DUMP_ERR_NONAME
),
945 mbQuoteNames( false )
949 void ConstList::implProcessConfigItemStr(
950 TextInputStream
& rStrm
, const OUString
& rKey
, const OUString
& rData
)
952 if ( rKey
== "default" )
953 setDefaultName( rData
);
954 else if ( rKey
== "quote-names" )
955 setQuoteNames( StringHelper::convertStringToBool( rData
) );
957 NameListBase::implProcessConfigItemStr( rStrm
, rKey
, rData
);
960 void ConstList::implSetName( sal_Int64 nKey
, const OUString
& rName
)
962 insertRawName( nKey
, rName
);
965 OUString
ConstList::implGetName( const Config
& /*rCfg*/, sal_Int64 nKey
) const
967 const OUString
* pName
= findRawName( nKey
);
968 OUString aName
= pName
? *pName
: maDefName
;
971 OUStringBuffer
aBuffer( aName
);
972 StringHelper::enclose( aBuffer
, OOX_DUMP_STRQUOTE
);
973 aName
= aBuffer
.makeStringAndClear();
978 OUString
ConstList::implGetNameDbl( const Config
& /*rCfg*/, double /*fValue*/ ) const
983 void ConstList::implIncludeList( const NameListBase
& rList
)
985 if( const ConstList
* pConstList
= dynamic_cast< const ConstList
* >( &rList
) )
987 maDefName
= pConstList
->maDefName
;
988 mbQuoteNames
= pConstList
->mbQuoteNames
;
992 MultiList::MultiList( const SharedConfigData
& rCfgData
) :
993 ConstList( rCfgData
),
994 mbIgnoreEmpty( true )
998 void MultiList::setNamesFromVec( sal_Int64 nStartKey
, const OUStringVector
& rNames
)
1000 sal_Int64 nKey
= nStartKey
;
1001 for( OUStringVector::const_iterator aIt
= rNames
.begin(), aEnd
= rNames
.end(); aIt
!= aEnd
; ++aIt
, ++nKey
)
1002 if( !mbIgnoreEmpty
|| !aIt
->isEmpty() )
1003 insertRawName( nKey
, *aIt
);
1006 void MultiList::implProcessConfigItemStr(
1007 TextInputStream
& rStrm
, const OUString
& rKey
, const OUString
& rData
)
1009 if ( rKey
== "ignore-empty" )
1010 mbIgnoreEmpty
= StringHelper::convertStringToBool( rData
);
1012 ConstList::implProcessConfigItemStr( rStrm
, rKey
, rData
);
1015 void MultiList::implSetName( sal_Int64 nKey
, const OUString
& rName
)
1017 OUStringVector aNames
;
1018 StringHelper::convertStringToStringList( aNames
, rName
, false );
1019 setNamesFromVec( nKey
, aNames
);
1022 FlagsList::FlagsList( const SharedConfigData
& rCfgData
) :
1023 NameListBase( rCfgData
),
1028 void FlagsList::implProcessConfigItemStr(
1029 TextInputStream
& rStrm
, const OUString
& rKey
, const OUString
& rData
)
1031 if ( rKey
== "ignore" )
1034 if( StringHelper::convertStringToInt( nIgnore
, rData
) )
1035 setIgnoreFlags( nIgnore
);
1039 NameListBase::implProcessConfigItemStr( rStrm
, rKey
, rData
);
1043 void FlagsList::implSetName( sal_Int64 nKey
, const OUString
& rName
)
1045 if( (nKey
!= 0) && ((nKey
& (nKey
- 1)) == 0) ) // only a single bit set?
1046 insertRawName( nKey
, rName
);
1049 OUString
FlagsList::implGetName( const Config
& /*rCfg*/, sal_Int64 nKey
) const
1051 sal_Int64 nFound
= mnIgnore
;
1052 OUStringBuffer aName
;
1054 for( const_iterator aIt
= begin(), aEnd
= end(); aIt
!= aEnd
; ++aIt
)
1056 sal_Int64 nMask
= aIt
->first
;
1057 setFlag( nFound
, nMask
);
1058 if( !getFlag( mnIgnore
, nMask
) )
1060 const OUString
& rFlagName
= aIt
->second
;
1061 bool bOnOff
= rFlagName
.startsWith(":");
1062 bool bFlag
= getFlag( nKey
, nMask
);
1065 StringHelper::appendToken( aName
, rFlagName
.copy( 1 ) );
1066 aName
.appendAscii( bFlag
? ":on" : ":off" );
1070 bool bNegated
= rFlagName
.startsWith("!");
1071 sal_Int32 nBothSep
= bNegated
? rFlagName
.indexOf( '!', 1 ) : -1;
1075 StringHelper::appendToken( aName
, rFlagName
);
1076 else if( nBothSep
> 0 )
1077 StringHelper::appendToken( aName
, rFlagName
.copy( nBothSep
+ 1 ) );
1082 StringHelper::appendToken( aName
, rFlagName
.copy( 1, nBothSep
- 1 ) );
1084 StringHelper::appendToken( aName
, rFlagName
.copy( 1 ) );
1089 // add unknown flags
1090 setFlag( nKey
, nFound
, false );
1093 OUStringBuffer
aUnknown( OOX_DUMP_UNKNOWN
);
1094 aUnknown
.append( OOX_DUMP_ITEMSEP
);
1095 StringHelper::appendShortHex( aUnknown
, nKey
, true );
1096 StringHelper::enclose( aUnknown
, '(', ')' );
1097 StringHelper::appendToken( aName
, aUnknown
.makeStringAndClear() );
1099 return aName
.makeStringAndClear();
1102 OUString
FlagsList::implGetNameDbl( const Config
& /*rCfg*/, double /*fValue*/ ) const
1107 void FlagsList::implIncludeList( const NameListBase
& rList
)
1109 if( const FlagsList
* pFlagsList
= dynamic_cast< const FlagsList
* >( &rList
) )
1110 mnIgnore
= pFlagsList
->mnIgnore
;
1113 bool CombiList::ExtItemFormatKey::operator<( const ExtItemFormatKey
& rRight
) const
1115 return (mnKey
< rRight
.mnKey
) || ((mnKey
== rRight
.mnKey
) && (maFilter
< rRight
.maFilter
));
1118 CombiList::CombiList( const SharedConfigData
& rCfgData
) :
1119 FlagsList( rCfgData
)
1123 void CombiList::implSetName( sal_Int64 nKey
, const OUString
& rName
)
1125 if( (nKey
& (nKey
- 1)) != 0 ) // more than a single bit set?
1127 typedef ::std::set
< ExtItemFormatKey
> ExtItemFormatKeySet
;
1128 ::std::set
< ExtItemFormatKey
> aItemKeys
;
1129 ExtItemFormat aItemFmt
;
1130 OUStringVector aRemain
= aItemFmt
.parse( rName
);
1131 for( OUStringVector::iterator aIt
= aRemain
.begin(), aEnd
= aRemain
.end(); aIt
!= aEnd
; ++aIt
)
1133 OUStringPair aPair
= StringHelper::convertStringToPair( *aIt
);
1134 if ( aPair
.first
== "noshift" )
1136 aItemFmt
.mbShiftValue
= StringHelper::convertStringToBool( aPair
.second
);
1138 else if ( aPair
.first
== "filter" )
1140 OUStringPair aFilter
= StringHelper::convertStringToPair( aPair
.second
, '~' );
1141 ExtItemFormatKey
aKey( nKey
);
1142 if( !aFilter
.first
.isEmpty() && StringHelper::convertStringToInt( aKey
.maFilter
.first
, aFilter
.first
) &&
1143 !aFilter
.second
.isEmpty() && StringHelper::convertStringToInt( aKey
.maFilter
.second
, aFilter
.second
) )
1145 if( aKey
.maFilter
.first
== 0 )
1146 aKey
.maFilter
.second
= 0;
1147 aItemKeys
.insert( aKey
);
1151 if( aItemKeys
.empty() )
1152 aItemKeys
.insert( ExtItemFormatKey( nKey
) );
1153 for( ExtItemFormatKeySet::iterator aIt
= aItemKeys
.begin(), aEnd
= aItemKeys
.end(); aIt
!= aEnd
; ++aIt
)
1154 maFmtMap
[ *aIt
] = aItemFmt
;
1158 FlagsList::implSetName( nKey
, rName
);
1162 OUString
CombiList::implGetName( const Config
& rCfg
, sal_Int64 nKey
) const
1164 sal_Int64 nFound
= 0;
1165 OUStringBuffer aName
;
1166 // add known flag fields
1167 for( ExtItemFormatMap::const_iterator aIt
= maFmtMap
.begin(), aEnd
= maFmtMap
.end(); aIt
!= aEnd
; ++aIt
)
1169 const ExtItemFormatKey
& rMapKey
= aIt
->first
;
1170 sal_Int64 nMask
= rMapKey
.mnKey
;
1171 if( (nMask
!= 0) && ((nKey
& rMapKey
.maFilter
.first
) == rMapKey
.maFilter
.second
) )
1173 const ExtItemFormat
& rItemFmt
= aIt
->second
;
1175 sal_uInt64 nUFlags
= static_cast< sal_uInt64
>( nKey
);
1176 sal_uInt64 nUMask
= static_cast< sal_uInt64
>( nMask
);
1177 if( rItemFmt
.mbShiftValue
)
1178 while( (nUMask
& 1) == 0 ) { nUFlags
>>= 1; nUMask
>>= 1; }
1180 sal_uInt64 nUValue
= nUFlags
& nUMask
;
1181 sal_Int64 nSValue
= static_cast< sal_Int64
>( nUValue
);
1182 if( getFlag
< sal_uInt64
>( nUValue
, (nUMask
+ 1) >> 1 ) )
1183 setFlag( nSValue
, static_cast< sal_Int64
>( ~nUMask
) );
1185 OUStringBuffer
aItem( rItemFmt
.maItemName
);
1186 OUStringBuffer aValue
;
1187 switch( rItemFmt
.meDataType
)
1189 case DATATYPE_INT8
: StringHelper::appendValue( aValue
, static_cast< sal_Int8
>( nSValue
), rItemFmt
.meFmtType
); break;
1190 case DATATYPE_UINT8
: StringHelper::appendValue( aValue
, static_cast< sal_uInt8
>( nUValue
), rItemFmt
.meFmtType
); break;
1191 case DATATYPE_INT16
: StringHelper::appendValue( aValue
, static_cast< sal_Int16
>( nSValue
), rItemFmt
.meFmtType
); break;
1192 case DATATYPE_UINT16
: StringHelper::appendValue( aValue
, static_cast< sal_uInt16
>( nUValue
), rItemFmt
.meFmtType
); break;
1193 case DATATYPE_INT32
: StringHelper::appendValue( aValue
, static_cast< sal_Int32
>( nSValue
), rItemFmt
.meFmtType
); break;
1194 case DATATYPE_UINT32
: StringHelper::appendValue( aValue
, static_cast< sal_uInt32
>( nUValue
), rItemFmt
.meFmtType
); break;
1195 case DATATYPE_INT64
: StringHelper::appendValue( aValue
, nSValue
, rItemFmt
.meFmtType
); break;
1196 case DATATYPE_UINT64
: StringHelper::appendValue( aValue
, nUValue
, rItemFmt
.meFmtType
); break;
1197 case DATATYPE_FLOAT
: StringHelper::appendValue( aValue
, static_cast< float >( nSValue
), rItemFmt
.meFmtType
); break;
1198 case DATATYPE_DOUBLE
: StringHelper::appendValue( aValue
, static_cast< double >( nSValue
), rItemFmt
.meFmtType
); break;
1201 StringHelper::appendToken( aItem
, aValue
.makeStringAndClear(), OOX_DUMP_ITEMSEP
);
1202 if( !rItemFmt
.maListName
.isEmpty() )
1204 OUString aValueName
= rCfg
.getName( rItemFmt
.maListName
, static_cast< sal_Int64
>( nUValue
) );
1205 StringHelper::appendToken( aItem
, aValueName
, OOX_DUMP_ITEMSEP
);
1207 StringHelper::enclose( aItem
, '(', ')' );
1208 StringHelper::appendToken( aName
, aItem
.makeStringAndClear() );
1209 setFlag( nFound
, nMask
);
1212 setFlag( nKey
, nFound
, false );
1213 StringHelper::appendToken( aName
, FlagsList::implGetName( rCfg
, nKey
) );
1214 return aName
.makeStringAndClear();
1217 void CombiList::implIncludeList( const NameListBase
& rList
)
1219 if( const CombiList
* pCombiList
= dynamic_cast< const CombiList
* >( &rList
) )
1220 maFmtMap
= pCombiList
->maFmtMap
;
1221 FlagsList::implIncludeList( rList
);
1224 UnitConverter::UnitConverter( const SharedConfigData
& rCfgData
) :
1225 NameListBase( rCfgData
),
1230 void UnitConverter::implSetName( sal_Int64
/*nKey*/, const OUString
& /*rName*/ )
1235 OUString
UnitConverter::implGetName( const Config
& rCfg
, sal_Int64 nKey
) const
1237 return implGetNameDbl( rCfg
, static_cast< double >( nKey
) );
1240 OUString
UnitConverter::implGetNameDbl( const Config
& /*rCfg*/, double fValue
) const
1242 OUStringBuffer aValue
;
1243 StringHelper::appendDec( aValue
, mfFactor
* fValue
);
1244 aValue
.append( maUnitName
);
1245 return aValue
.makeStringAndClear();
1248 void UnitConverter::implIncludeList( const NameListBase
& /*rList*/ )
1252 NameListRef
NameListWrapper::getNameList( const Config
& rCfg
) const
1254 return mxList
.get() ? mxList
: (mxList
= rCfg
.getNameList( maName
));
1257 SharedConfigData::SharedConfigData( const OUString
& rFileName
,
1258 const Reference
< XComponentContext
>& rxContext
, const StorageRef
& rxRootStrg
,
1259 const OUString
& rSysFileName
) :
1260 mxContext( rxContext
),
1261 mxRootStrg( rxRootStrg
),
1262 maSysFileName( rSysFileName
),
1264 mbPwCancelled( false )
1266 OUString aFileUrl
= InputOutputHelper::convertFileNameToUrl( rFileName
);
1267 if( !aFileUrl
.isEmpty() )
1269 sal_Int32 nNamePos
= InputOutputHelper::getFileNamePos( aFileUrl
);
1270 maConfigPath
= aFileUrl
.copy( 0, nNamePos
);
1271 mbLoaded
= readConfigFile( aFileUrl
);
1275 SharedConfigData::~SharedConfigData()
1279 void SharedConfigData::setOption( const OUString
& rKey
, const OUString
& rData
)
1281 maConfigData
[ rKey
] = rData
;
1284 const OUString
* SharedConfigData::getOption( const OUString
& rKey
) const
1286 ConfigDataMap::const_iterator aIt
= maConfigData
.find( rKey
);
1287 return (aIt
== maConfigData
.end()) ? 0 : &aIt
->second
;
1290 void SharedConfigData::setNameList( const OUString
& rListName
, const NameListRef
& rxList
)
1292 if( !rListName
.isEmpty() )
1293 maNameLists
[ rListName
] = rxList
;
1296 void SharedConfigData::eraseNameList( const OUString
& rListName
)
1298 maNameLists
.erase( rListName
);
1301 NameListRef
SharedConfigData::getNameList( const OUString
& rListName
) const
1304 NameListMap::const_iterator aIt
= maNameLists
.find( rListName
);
1305 if( aIt
!= maNameLists
.end() )
1306 xList
= aIt
->second
;
1310 bool SharedConfigData::implIsValid() const
1312 return mbLoaded
&& mxContext
.is() && mxRootStrg
.get() && !maSysFileName
.isEmpty();
1315 void SharedConfigData::implProcessConfigItemStr(
1316 TextInputStream
& rStrm
, const OUString
& rKey
, const OUString
& rData
)
1318 if ( rKey
== "include-config-file" )
1319 readConfigFile( maConfigPath
+ rData
);
1320 else if ( rKey
== "constlist" )
1321 readNameList
< ConstList
>( rStrm
, rData
);
1322 else if ( rKey
== "multilist" )
1323 readNameList
< MultiList
>( rStrm
, rData
);
1324 else if ( rKey
== "flagslist" )
1325 readNameList
< FlagsList
>( rStrm
, rData
);
1326 else if ( rKey
== "combilist" )
1327 readNameList
< CombiList
>( rStrm
, rData
);
1328 else if ( rKey
== "shortlist" )
1329 createShortList( rData
);
1330 else if ( rKey
== "unitconverter" )
1331 createUnitConverter( rData
);
1333 setOption( rKey
, rData
);
1336 bool SharedConfigData::readConfigFile( const OUString
& rFileUrl
)
1338 bool bLoaded
= maConfigFiles
.count( rFileUrl
) > 0;
1341 Reference
< XInputStream
> xInStrm
= InputOutputHelper::openInputStream( mxContext
, rFileUrl
);
1342 TextInputStream
aTxtStrm( mxContext
, xInStrm
, RTL_TEXTENCODING_UTF8
);
1343 if( !aTxtStrm
.isEof() )
1345 maConfigFiles
.insert( rFileUrl
);
1346 readConfigBlockContents( aTxtStrm
);
1353 void SharedConfigData::createShortList( const OUString
& rData
)
1355 OUStringVector aDataVec
;
1356 StringHelper::convertStringToStringList( aDataVec
, rData
, false );
1357 if( aDataVec
.size() >= 3 )
1359 sal_Int64 nStartKey
;
1360 if( StringHelper::convertStringToInt( nStartKey
, aDataVec
[ 1 ] ) )
1362 std::shared_ptr
< MultiList
> xList
= createNameList
< MultiList
>( aDataVec
[ 0 ] );
1365 aDataVec
.erase( aDataVec
.begin(), aDataVec
.begin() + 2 );
1366 xList
->setNamesFromVec( nStartKey
, aDataVec
);
1372 void SharedConfigData::createUnitConverter( const OUString
& rData
)
1374 OUStringVector aDataVec
;
1375 StringHelper::convertStringToStringList( aDataVec
, rData
, false );
1376 if( aDataVec
.size() >= 2 )
1378 OUString aFactor
= aDataVec
[ 1 ];
1379 bool bRecip
= aFactor
.startsWith("/");
1381 aFactor
= aFactor
.copy( 1 );
1383 if( StringHelper::convertStringToDouble( fFactor
, aFactor
) && (fFactor
!= 0.0) )
1385 std::shared_ptr
< UnitConverter
> xList
= createNameList
< UnitConverter
>( aDataVec
[ 0 ] );
1388 xList
->setFactor( bRecip
? (1.0 / fFactor
) : fFactor
);
1389 if( aDataVec
.size() >= 3 )
1390 xList
->setUnitName( aDataVec
[ 2 ] );
1396 Config::Config( const Config
& rParent
) :
1397 Base() // c'tor needs to be called explicitly to avoid compiler warning
1399 construct( rParent
);
1402 Config::Config( const sal_Char
* pcEnvVar
, const FilterBase
& rFilter
)
1404 construct( pcEnvVar
, rFilter
);
1407 Config::Config( const sal_Char
* pcEnvVar
, const Reference
< XComponentContext
>& rxContext
, const StorageRef
& rxRootStrg
, const OUString
& rSysFileName
)
1409 construct( pcEnvVar
, rxContext
, rxRootStrg
, rSysFileName
);
1416 void Config::construct( const Config
& rParent
)
1421 void Config::construct( const sal_Char
* pcEnvVar
, const FilterBase
& rFilter
)
1423 if( !rFilter
.getFileUrl().isEmpty() )
1424 construct( pcEnvVar
, rFilter
.getComponentContext(), rFilter
.getStorage(), rFilter
.getFileUrl() );
1427 void Config::construct( const sal_Char
* pcEnvVar
, const Reference
< XComponentContext
>& rxContext
, const StorageRef
& rxRootStrg
, const OUString
& rSysFileName
)
1429 if( pcEnvVar
&& rxRootStrg
.get() && !rSysFileName
.isEmpty() )
1430 if( const sal_Char
* pcFileName
= ::getenv( pcEnvVar
) )
1431 mxCfgData
.reset( new SharedConfigData( OUString::createFromAscii( pcFileName
), rxContext
, rxRootStrg
, rSysFileName
) );
1434 const OUString
& Config::getStringOption( const String
& rKey
, const OUString
& rDefault
) const
1436 const OUString
* pData
= implGetOption( rKey
);
1437 return pData
? *pData
: rDefault
;
1440 bool Config::getBoolOption( const String
& rKey
, bool bDefault
) const
1442 const OUString
* pData
= implGetOption( rKey
);
1443 return pData
? StringHelper::convertStringToBool( *pData
) : bDefault
;
1446 bool Config::isDumperEnabled() const
1448 return getBoolOption( "enable-dumper", false );
1451 bool Config::isImportEnabled() const
1453 return getBoolOption( "enable-import", true );
1456 void Config::eraseNameList( const String
& rListName
)
1458 mxCfgData
->eraseNameList( rListName
);
1461 NameListRef
Config::getNameList( const String
& rListName
) const
1463 return implGetNameList( rListName
);
1466 bool Config::isPasswordCancelled() const
1468 return mxCfgData
->isPasswordCancelled();
1471 bool Config::implIsValid() const
1473 return isValid( mxCfgData
);
1476 const OUString
* Config::implGetOption( const OUString
& rKey
) const
1478 return mxCfgData
->getOption( rKey
);
1481 NameListRef
Config::implGetNameList( const OUString
& rListName
) const
1483 return mxCfgData
->getNameList( rListName
);
1486 Output::Output( const Reference
< XComponentContext
>& rxContext
, const OUString
& rFileName
) :
1487 mxStrm( InputOutputHelper::openTextOutputStream( rxContext
, rFileName
, RTL_TEXTENCODING_UTF8
) ),
1495 mxStrm
->writeString( OUString( OOX_DUMP_BOM
) );
1498 void Output::newLine()
1500 if( maLine
.getLength() > 0 )
1502 mxStrm
->writeString( maIndent
);
1503 maLine
.append( '\n' );
1504 mxStrm
->writeString( maLine
.makeStringAndClear() );
1510 void Output::emptyLine( size_t nCount
)
1512 for( size_t nIdx
= 0; nIdx
< nCount
; ++nIdx
)
1513 mxStrm
->writeString( OUString( '\n' ) );
1516 void Output::incIndent()
1518 OUStringBuffer
aBuffer( maIndent
);
1519 StringHelper::appendChar( aBuffer
, ' ', OOX_DUMP_INDENT
);
1520 maIndent
= aBuffer
.makeStringAndClear();
1523 void Output::decIndent()
1525 if( maIndent
.getLength() >= OOX_DUMP_INDENT
)
1526 maIndent
= maIndent
.copy( OOX_DUMP_INDENT
);
1529 void Output::startTable( sal_Int32 nW1
)
1531 startTable( 1, &nW1
);
1534 void Output::startTable( sal_Int32 nW1
, sal_Int32 nW2
)
1536 sal_Int32 pnColWidths
[ 2 ];
1537 pnColWidths
[ 0 ] = nW1
;
1538 pnColWidths
[ 1 ] = nW2
;
1539 startTable( 2, pnColWidths
);
1542 void Output::startTable( sal_Int32 nW1
, sal_Int32 nW2
, sal_Int32 nW3
, sal_Int32 nW4
)
1544 sal_Int32 pnColWidths
[ 4 ];
1545 pnColWidths
[ 0 ] = nW1
;
1546 pnColWidths
[ 1 ] = nW2
;
1547 pnColWidths
[ 2 ] = nW3
;
1548 pnColWidths
[ 3 ] = nW4
;
1549 startTable( 4, pnColWidths
);
1552 void Output::startTable( size_t nColCount
, const sal_Int32
* pnColWidths
)
1555 maColPos
.push_back( 0 );
1556 sal_Int32 nColPos
= 0;
1557 for( size_t nCol
= 0; nCol
< nColCount
; ++nCol
)
1559 nColPos
= nColPos
+ pnColWidths
[ nCol
];
1560 maColPos
.push_back( nColPos
);
1569 void Output::tab( size_t nCol
)
1572 if( mnCol
< maColPos
.size() )
1574 sal_Int32 nColPos
= maColPos
[ mnCol
];
1575 if( maLine
.getLength() >= nColPos
)
1576 maLine
.setLength( ::std::max
< sal_Int32
>( nColPos
- 1, 0 ) );
1577 StringHelper::appendChar( maLine
, ' ', nColPos
- maLine
.getLength() );
1581 StringHelper::appendChar( maLine
, ' ', 2 );
1585 void Output::endTable()
1590 void Output::resetItemIndex( sal_Int64 nIdx
)
1595 void Output::startItem( const String
& rItemName
)
1597 if( mnItemLevel
== 0 )
1599 if( (mnMultiLevel
> 0) && (maLine
.getLength() > 0) )
1601 if( rItemName
.has() )
1603 writeItemName( rItemName
);
1604 writeChar( OOX_DUMP_ITEMSEP
);
1608 mnLastItem
= maLine
.getLength();
1611 void Output::contItem()
1613 if( mnItemLevel
> 0 )
1615 if( (maLine
.getLength() == 0) || (maLine
[ maLine
.getLength() - 1 ] != OOX_DUMP_ITEMSEP
) )
1616 writeChar( OOX_DUMP_ITEMSEP
);
1617 mnLastItem
= maLine
.getLength();
1621 void Output::endItem()
1623 if( mnItemLevel
> 0 )
1625 maLastItem
= OUString( maLine
.getStr() + mnLastItem
);
1626 if( maLastItem
.isEmpty() && mnLastItem
> 0 && maLine
[ mnLastItem
- 1 ] == OOX_DUMP_ITEMSEP
)
1627 maLine
.setLength( mnLastItem
- 1 );
1630 if( mnItemLevel
== 0 )
1632 if( mnMultiLevel
== 0 )
1639 void Output::startMultiItems()
1644 void Output::endMultiItems()
1646 if( mnMultiLevel
> 0 )
1648 if( mnMultiLevel
== 0 )
1652 void Output::writeChar( sal_Unicode cChar
, sal_Int32 nCount
)
1654 StringHelper::appendEncChar( maLine
, cChar
, nCount
);
1657 void Output::writeAscii( const sal_Char
* pcStr
)
1660 maLine
.appendAscii( pcStr
);
1663 void Output::writeString( const OUString
& rStr
)
1665 StringHelper::appendEncString( maLine
, rStr
);
1668 void Output::writeArray( const sal_uInt8
* pnData
, sal_Size nSize
, sal_Unicode cSep
)
1670 const sal_uInt8
* pnEnd
= pnData
? (pnData
+ nSize
) : 0;
1671 for( const sal_uInt8
* pnByte
= pnData
; pnByte
< pnEnd
; ++pnByte
)
1673 if( pnByte
> pnData
)
1675 writeHex( *pnByte
, false );
1679 void Output::writeBool( bool bData
)
1681 StringHelper::appendBool( maLine
, bData
);
1684 void Output::writeDateTime( const util::DateTime
& rDateTime
)
1686 writeDec( rDateTime
.Year
, 4, '0' );
1688 writeDec( rDateTime
.Month
, 2, '0' );
1690 writeDec( rDateTime
.Day
, 2, '0' );
1692 writeDec( rDateTime
.Hours
, 2, '0' );
1694 writeDec( rDateTime
.Minutes
, 2, '0' );
1696 writeDec( rDateTime
.Seconds
, 2, '0' );
1699 bool Output::implIsValid() const
1704 void Output::writeItemName( const String
& rItemName
)
1706 if( rItemName
.has() && (rItemName
[ 0 ] == '#') )
1708 writeString( rItemName
.copy( 1 ) );
1709 StringHelper::appendIndex( maLine
, mnItemIdx
++ );
1712 writeString( rItemName
);
1715 StorageIterator::StorageIterator( const StorageRef
& rxStrg
) :
1719 mxStrg
->getElementNames( maNames
);
1720 maIt
= maNames
.begin();
1723 StorageIterator::~StorageIterator()
1727 StorageIterator
& StorageIterator::operator++()
1729 if( maIt
!= maNames
.end() )
1734 OUString
StorageIterator::getName() const
1737 if( maIt
!= maNames
.end() )
1742 bool StorageIterator::isStream() const
1744 return isValid() && mxStrg
->openInputStream( *maIt
).is();
1747 bool StorageIterator::isStorage() const
1751 StorageRef xStrg
= mxStrg
->openSubStorage( *maIt
, false );
1752 return xStrg
.get() && xStrg
->isStorage();
1755 bool StorageIterator::implIsValid() const
1757 return mxStrg
.get() && mxStrg
->isStorage() && (maIt
!= maNames
.end());
1760 ObjectBase::~ObjectBase()
1764 void ObjectBase::construct( const ConfigRef
& rxConfig
)
1766 mxConfig
= rxConfig
;
1769 void ObjectBase::construct( const ObjectBase
& rParent
)
1774 void ObjectBase::dump()
1780 bool ObjectBase::implIsValid() const
1782 return isValid( mxConfig
);
1785 void ObjectBase::implDump()
1789 void StorageObjectBase::construct( const ObjectBase
& rParent
, const StorageRef
& rxStrg
, const OUString
& rSysPath
)
1791 ObjectBase::construct( rParent
);
1793 maSysPath
= rSysPath
;
1796 void StorageObjectBase::construct( const ObjectBase
& rParent
)
1798 ObjectBase::construct( rParent
);
1799 if( ObjectBase::implIsValid() )
1801 mxStrg
= cfg().getRootStorage();
1802 maSysPath
= cfg().getSysFileName();
1806 bool StorageObjectBase::implIsValid() const
1808 return mxStrg
.get() && !maSysPath
.isEmpty() && ObjectBase::implIsValid();
1811 void StorageObjectBase::implDump()
1813 bool bIsStrg
= mxStrg
->isStorage();
1814 bool bIsRoot
= mxStrg
->isRootStorage();
1815 Reference
< XInputStream
> xBaseStrm
;
1817 xBaseStrm
= mxStrg
->openInputStream( OUString() );
1819 OUString aSysOutPath
= maSysPath
;
1822 aSysOutPath
+= OOX_DUMP_DUMPEXT
;
1823 Reference
<XSimpleFileAccess3
> xFileAccess(SimpleFileAccess::create(getContext()));
1824 xFileAccess
->kill( aSysOutPath
);
1832 extractStorage( mxStrg
, OUString(), aSysOutPath
);
1834 else if( xBaseStrm
.is() )
1836 BinaryInputStreamRef
xInStrm( new BinaryXInputStream( xBaseStrm
, false ) );
1837 xInStrm
->seekToStart();
1838 implDumpBaseStream( xInStrm
, aSysOutPath
);
1842 void StorageObjectBase::implDumpStream( const Reference
< XInputStream
>&, const OUString
&, const OUString
&, const OUString
& )
1846 void StorageObjectBase::implDumpStorage( const StorageRef
& rxStrg
, const OUString
& rStrgPath
, const OUString
& rSysPath
)
1848 extractStorage( rxStrg
, rStrgPath
, rSysPath
);
1851 void StorageObjectBase::implDumpBaseStream( const BinaryInputStreamRef
&, const OUString
& )
1855 void StorageObjectBase::addPreferredStream( const String
& rStrmName
)
1857 if( rStrmName
.has() )
1858 maPreferred
.push_back( PreferredItem( rStrmName
, false ) );
1861 void StorageObjectBase::addPreferredStorage( const String
& rStrgPath
)
1863 if( rStrgPath
.has() )
1864 maPreferred
.push_back( PreferredItem( rStrgPath
, true ) );
1867 OUString
StorageObjectBase::getSysFileName( const OUString
& rStrmName
, const OUString
& rSysOutPath
)
1869 // encode all characters < 0x20
1870 OUStringBuffer aBuffer
;
1871 StringHelper::appendEncString( aBuffer
, rStrmName
, false );
1873 // replace all characters reserved in file system
1874 OUString aFileName
= aBuffer
.makeStringAndClear();
1875 static const sal_Unicode spcReserved
[] = { '/', '\\', ':', '*', '?', '<', '>', '|' };
1876 for( const sal_Unicode
* pcChar
= spcReserved
; pcChar
< STATIC_ARRAY_END( spcReserved
); ++pcChar
)
1877 aFileName
= aFileName
.replace( *pcChar
, '_' );
1880 return rSysOutPath
+ "/" + aFileName
;
1883 void StorageObjectBase::extractStream( StorageBase
& rStrg
, const OUString
& rStrgPath
, const OUString
& rStrmName
, const OUString
& rSysFileName
)
1885 BinaryXInputStream
aInStrm( rStrg
.openInputStream( rStrmName
), true );
1886 if( !aInStrm
.isEof() )
1888 BinaryXOutputStream
aOutStrm( InputOutputHelper::openOutputStream( getContext(), rSysFileName
), true );
1889 if( !aOutStrm
.isEof() )
1890 aInStrm
.copyToStream( aOutStrm
);
1892 Reference
< XInputStream
> xDumpStrm
= InputOutputHelper::openInputStream( getContext(), rSysFileName
);
1893 if( xDumpStrm
.is() )
1894 implDumpStream( xDumpStrm
, rStrgPath
, rStrmName
, rSysFileName
);
1897 void StorageObjectBase::extractStorage( const StorageRef
& rxStrg
, const OUString
& rStrgPath
, const OUString
& rSysPath
)
1899 // create directory in file system
1900 ::osl::FileBase::RC eRes
= ::osl::Directory::create( rSysPath
);
1901 if( (eRes
!= ::osl::FileBase::E_None
) && (eRes
!= ::osl::FileBase::E_EXIST
) )
1904 // process preferred storages and streams in root storage first
1905 if( rStrgPath
.isEmpty() )
1906 for( PreferredItemVector::iterator aIt
= maPreferred
.begin(), aEnd
= maPreferred
.end(); aIt
!= aEnd
; ++aIt
)
1907 extractItem( rxStrg
, rStrgPath
, aIt
->maName
, rSysPath
, aIt
->mbStorage
, !aIt
->mbStorage
);
1909 // process children of the storage
1910 for( StorageIterator
aIt( rxStrg
); aIt
.isValid(); ++aIt
)
1912 // skip processed preferred items
1913 OUString aItemName
= aIt
.getName();
1914 bool bFound
= false;
1915 if( rStrgPath
.isEmpty() )
1916 for( PreferredItemVector::iterator aIIt
= maPreferred
.begin(), aIEnd
= maPreferred
.end(); !bFound
&& (aIIt
!= aIEnd
); ++aIIt
)
1917 bFound
= aIIt
->maName
== aItemName
;
1919 extractItem( rxStrg
, rStrgPath
, aItemName
, rSysPath
, aIt
.isStorage(), aIt
.isStream() );
1923 void StorageObjectBase::extractItem( const StorageRef
& rxStrg
, const OUString
& rStrgPath
, const OUString
& rItemName
, const OUString
& rSysPath
, bool bIsStrg
, bool bIsStrm
)
1925 OUString aSysFileName
= getSysFileName( rItemName
, rSysPath
);
1928 OUStringBuffer
aStrgPath( rStrgPath
);
1929 StringHelper::appendToken( aStrgPath
, rItemName
, '/' );
1930 implDumpStorage( rxStrg
->openSubStorage( rItemName
, false ), aStrgPath
.makeStringAndClear(), aSysFileName
);
1934 extractStream( *rxStrg
, rStrgPath
, rItemName
, aSysFileName
);
1938 OutputObjectBase::~OutputObjectBase()
1942 void OutputObjectBase::construct( const ObjectBase
& rParent
, const OUString
& rSysFileName
)
1944 ObjectBase::construct( rParent
);
1945 if( ObjectBase::implIsValid() )
1947 maSysFileName
= rSysFileName
;
1948 mxOut
.reset( new Output( getContext(), rSysFileName
+ OOX_DUMP_DUMPEXT
) );
1952 void OutputObjectBase::construct( const OutputObjectBase
& rParent
)
1957 bool OutputObjectBase::implIsValid() const
1959 return isValid( mxOut
) && ObjectBase::implIsValid();
1962 void OutputObjectBase::writeEmptyItem( const String
& rName
)
1964 ItemGuard
aItem( mxOut
, rName
);
1967 void OutputObjectBase::writeInfoItem( const String
& rName
, const String
& rData
)
1969 ItemGuard
aItem( mxOut
, rName
);
1970 mxOut
->writeString( rData
);
1973 void OutputObjectBase::writeCharItem( const String
& rName
, sal_Unicode cData
)
1975 ItemGuard
aItem( mxOut
, rName
);
1976 mxOut
->writeChar( OOX_DUMP_STRQUOTE
);
1977 mxOut
->writeChar( cData
);
1978 mxOut
->writeChar( OOX_DUMP_STRQUOTE
);
1981 void OutputObjectBase::writeStringItem( const String
& rName
, const OUString
& rData
)
1983 ItemGuard
aItem( mxOut
, rName
);
1984 mxOut
->writeAscii( "(len=" );
1985 mxOut
->writeDec( rData
.getLength() );
1986 mxOut
->writeAscii( ")," );
1987 OUStringBuffer
aValue( rData
.copy( 0, ::std::min( rData
.getLength(), OOX_DUMP_MAXSTRLEN
) ) );
1988 StringHelper::enclose( aValue
, OOX_DUMP_STRQUOTE
);
1989 mxOut
->writeString( aValue
.makeStringAndClear() );
1990 if( rData
.getLength() > OOX_DUMP_MAXSTRLEN
)
1991 mxOut
->writeAscii( ",cut" );
1994 void OutputObjectBase::writeArrayItem( const String
& rName
, const sal_uInt8
* pnData
, sal_Size nSize
, sal_Unicode cSep
)
1996 ItemGuard
aItem( mxOut
, rName
);
1997 mxOut
->writeArray( pnData
, nSize
, cSep
);
2000 void OutputObjectBase::writeDateTimeItem( const String
& rName
, const util::DateTime
& rDateTime
)
2002 ItemGuard
aItem( mxOut
, rName
);
2003 mxOut
->writeDateTime( rDateTime
);
2006 void OutputObjectBase::writeGuidItem( const String
& rName
, const OUString
& rGuid
)
2008 ItemGuard
aItem( mxOut
, rName
);
2009 mxOut
->writeString( rGuid
);
2011 mxOut
->writeString( cfg().getStringOption( rGuid
, OUString() ) );
2014 InputObjectBase::~InputObjectBase()
2018 void InputObjectBase::construct( const ObjectBase
& rParent
, const BinaryInputStreamRef
& rxStrm
, const OUString
& rSysFileName
)
2020 OutputObjectBase::construct( rParent
, rSysFileName
);
2024 void InputObjectBase::construct( const OutputObjectBase
& rParent
, const BinaryInputStreamRef
& rxStrm
)
2026 OutputObjectBase::construct( rParent
);
2030 void InputObjectBase::construct( const InputObjectBase
& rParent
)
2035 bool InputObjectBase::implIsValid() const
2037 return mxStrm
.get() && OutputObjectBase::implIsValid();
2040 void InputObjectBase::skipBlock( sal_Int64 nBytes
, bool bShowSize
)
2042 sal_Int64 nEndPos
= ::std::min
< sal_Int64
>( mxStrm
->tell() + nBytes
, mxStrm
->size() );
2043 if( mxStrm
->tell() < nEndPos
)
2046 writeDecItem( "skipped-data-size", static_cast< sal_uInt64
>( nEndPos
- mxStrm
->tell() ) );
2047 mxStrm
->seek( nEndPos
);
2051 void InputObjectBase::dumpRawBinary( sal_Int64 nBytes
, bool bShowOffset
, bool bStream
)
2053 TableGuard
aTabGuard( mxOut
,
2054 bShowOffset
? 12 : 0,
2055 3 * OOX_DUMP_BYTESPERLINE
/ 2 + 1,
2056 3 * OOX_DUMP_BYTESPERLINE
/ 2 + 1,
2057 OOX_DUMP_BYTESPERLINE
/ 2 + 1 );
2059 sal_Int64 nMaxShowSize
= cfg().getIntOption
< sal_Int64
>(
2060 bStream
? "max-binary-stream-size" : "max-binary-data-size", SAL_MAX_INT64
);
2062 bool bSeekable
= mxStrm
->size() >= 0;
2063 sal_Int64 nEndPos
= bSeekable
? ::std::min
< sal_Int64
>( mxStrm
->tell() + nBytes
, mxStrm
->size() ) : 0;
2064 sal_Int64 nDumpEnd
= bSeekable
? ::std::min
< sal_Int64
>( mxStrm
->tell() + nMaxShowSize
, nEndPos
) : nMaxShowSize
;
2065 sal_Int64 nPos
= bSeekable
? mxStrm
->tell() : 0;
2068 while( bLoop
&& (nPos
< nDumpEnd
) )
2070 mxOut
->writeHex( static_cast< sal_uInt32
>( nPos
) );
2073 sal_uInt8 pnLineData
[ OOX_DUMP_BYTESPERLINE
];
2074 sal_Int32 nLineSize
= bSeekable
? ::std::min( static_cast< sal_Int32
>( nDumpEnd
- mxStrm
->tell() ), OOX_DUMP_BYTESPERLINE
) : OOX_DUMP_BYTESPERLINE
;
2075 sal_Int32 nReadSize
= mxStrm
->readMemory( pnLineData
, nLineSize
);
2076 bLoop
= nReadSize
== nLineSize
;
2081 const sal_uInt8
* pnByte
= 0;
2082 const sal_uInt8
* pnEnd
= 0;
2083 for( pnByte
= pnLineData
, pnEnd
= pnLineData
+ nReadSize
; pnByte
!= pnEnd
; ++pnByte
)
2085 if( (pnByte
- pnLineData
) == (OOX_DUMP_BYTESPERLINE
/ 2) ) mxOut
->tab();
2086 mxOut
->writeHex( *pnByte
, false );
2087 mxOut
->writeChar( ' ' );
2091 for( pnByte
= pnLineData
, pnEnd
= pnLineData
+ nReadSize
; pnByte
!= pnEnd
; ++pnByte
)
2093 if( (pnByte
- pnLineData
) == (OOX_DUMP_BYTESPERLINE
/ 2) ) mxOut
->tab();
2094 mxOut
->writeChar( static_cast< sal_Unicode
>( (*pnByte
< 0x20) ? '.' : *pnByte
) );
2100 // skip undumped data
2102 skipBlock( nEndPos
- mxStrm
->tell() );
2105 void InputObjectBase::dumpBinary( const String
& rName
, sal_Int64 nBytes
, bool bShowOffset
)
2108 MultiItemsGuard
aMultiGuard( mxOut
);
2109 writeEmptyItem( rName
);
2110 writeDecItem( "size", nBytes
);
2112 IndentGuard
aIndGuard( mxOut
);
2113 dumpRawBinary( nBytes
, bShowOffset
);
2116 void InputObjectBase::dumpRemaining( sal_Int64 nBytes
)
2120 if( cfg().getBoolOption( "show-trailing-unknown", true ) )
2121 dumpBinary( "remaining-data", nBytes
, false );
2123 skipBlock( nBytes
);
2127 void InputObjectBase::dumpRemainingTo( sal_Int64 nPos
)
2129 if( mxStrm
->isEof() || (mxStrm
->tell() > nPos
) )
2130 writeInfoItem( "stream-state", OOX_DUMP_ERR_STREAM
);
2132 dumpRemaining( nPos
- mxStrm
->tell() );
2133 mxStrm
->seek( nPos
);
2136 void InputObjectBase::dumpRemainingStream()
2138 dumpRemainingTo( mxStrm
->size() );
2141 void InputObjectBase::dumpArray( const String
& rName
, sal_Int32 nBytes
, sal_Unicode cSep
)
2143 sal_Int32 nDumpSize
= getLimitedValue
< sal_Int32
, sal_Int64
>( mxStrm
->size() - mxStrm
->tell(), 0, nBytes
);
2144 if( nDumpSize
> OOX_DUMP_MAXARRAY
)
2146 dumpBinary( rName
, nBytes
, false );
2148 else if( nDumpSize
> 1 )
2150 sal_uInt8 pnData
[ OOX_DUMP_MAXARRAY
];
2151 mxStrm
->readMemory( pnData
, nDumpSize
);
2152 writeArrayItem( rName
, pnData
, nDumpSize
, cSep
);
2154 else if( nDumpSize
== 1 )
2155 dumpHex
< sal_uInt8
>( rName
);
2158 sal_Unicode
InputObjectBase::dumpUnicode( const String
& rName
)
2160 sal_uInt16 nChar
= mxStrm
->readuInt16();
2161 sal_Unicode cChar
= static_cast< sal_Unicode
>( nChar
);
2162 writeCharItem( rName( "char" ), cChar
);
2166 OUString
InputObjectBase::dumpCharArray( const String
& rName
, sal_Int32 nLen
, rtl_TextEncoding eTextEnc
, bool bHideTrailingNul
)
2168 sal_Int32 nDumpSize
= getLimitedValue
< sal_Int32
, sal_Int64
>( mxStrm
->size() - mxStrm
->tell(), 0, nLen
);
2172 ::std::vector
< sal_Char
> aBuffer( static_cast< sal_Size
>( nLen
) + 1 );
2173 sal_Int32 nCharsRead
= mxStrm
->readMemory( &aBuffer
.front(), nLen
);
2174 aBuffer
[ nCharsRead
] = 0;
2175 aString
= OStringToOUString( OString( &aBuffer
.front() ), eTextEnc
);
2177 if( bHideTrailingNul
)
2178 aString
= StringHelper::trimTrailingNul( aString
);
2179 writeStringItem( rName( "text" ), aString
);
2183 OUString
InputObjectBase::dumpUnicodeArray( const String
& rName
, sal_Int32 nLen
, bool bHideTrailingNul
)
2185 OUStringBuffer aBuffer
;
2186 for( sal_Int32 nIndex
= 0; !mxStrm
->isEof() && (nIndex
< nLen
); ++nIndex
)
2188 aBuffer
.append( static_cast< sal_Unicode
>( mxStrm
->readuInt16() ) );
2190 OUString aString
= aBuffer
.makeStringAndClear();
2191 if( bHideTrailingNul
)
2192 aString
= StringHelper::trimTrailingNul( aString
);
2193 writeStringItem( rName( "text" ), aString
);
2197 util::DateTime
InputObjectBase::dumpFileTime( const String
& rName
)
2199 util::DateTime aDateTime
;
2201 ItemGuard
aItem( mxOut
, rName( "file-time" ) );
2202 sal_Int64 nFileTime
= dumpDec
< sal_Int64
>( EMPTY_STRING
);
2203 // file time is in 10^-7 seconds (100 nanoseconds), convert to nanoseconds
2206 sal_Int64 nDays
= nFileTime
/ sal_Int64( ::tools::Time::nanoSecPerDay
);
2207 // number of entire years
2208 sal_Int64 nYears
= (nDays
- (nDays
/ (4 * 365)) + (nDays
/ (100 * 365)) - (nDays
/ (400 * 365))) / 365;
2209 // remaining days in the year
2210 sal_Int64 nDaysInYear
= nDays
- (nYears
* 365 + nYears
/ 4 - nYears
/ 100 + nYears
/ 400);
2211 // the year (file dates start from 1601-01-01)
2212 aDateTime
.Year
= static_cast< sal_uInt16
>( 1601 + nYears
);
2214 bool bLeap
= ((aDateTime
.Year
% 4 == 0) && (aDateTime
.Year
% 100 != 0)) || (aDateTime
.Year
% 400 == 0);
2215 // static arrays with number of days in month
2216 static const sal_Int64 spnDaysInMonth
[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
2217 static const sal_Int64 spnDaysInMonthL
[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
2218 const sal_Int64
* pnDaysInMonth
= bLeap
? spnDaysInMonthL
: spnDaysInMonth
;
2220 aDateTime
.Month
= 1;
2221 while( nDaysInYear
>= *pnDaysInMonth
)
2223 nDaysInYear
-= *pnDaysInMonth
++;
2227 aDateTime
.Day
= static_cast< sal_uInt16
>( nDaysInYear
+ 1 );
2228 // number of nanoseconds in the day
2229 sal_Int64 nTimeInDay
= nFileTime
% sal_Int64( ::tools::Time::nanoSecPerDay
);
2231 aDateTime
.NanoSeconds
= static_cast< sal_uInt32
>( nTimeInDay
% ::tools::Time::nanoSecPerSec
);
2232 nTimeInDay
/= ::tools::Time::nanoSecPerSec
;
2234 aDateTime
.Seconds
= static_cast< sal_uInt16
>( nTimeInDay
% ::tools::Time::secondPerMinute
);
2235 nTimeInDay
/= ::tools::Time::secondPerMinute
;
2237 aDateTime
.Minutes
= static_cast< sal_uInt16
>( nTimeInDay
% ::tools::Time::minutePerHour
);
2238 nTimeInDay
/= ::tools::Time::minutePerHour
;
2240 aDateTime
.Hours
= static_cast< sal_uInt16
>( nTimeInDay
);
2242 writeDateTimeItem( EMPTY_STRING
, aDateTime
);
2246 OUString
InputObjectBase::dumpGuid( const String
& rName
)
2248 OUStringBuffer aBuffer
;
2253 nData32
= mxStrm
->readuInt32();
2254 StringHelper::appendHex( aBuffer
, nData32
, false );
2255 aBuffer
.append( '-' );
2256 nData16
= mxStrm
->readuInt16();
2257 StringHelper::appendHex( aBuffer
, nData16
, false );
2258 aBuffer
.append( '-' );
2259 nData16
= mxStrm
->readuInt16();
2260 StringHelper::appendHex( aBuffer
, nData16
, false );
2261 aBuffer
.append( '-' );
2262 nData8
= mxStrm
->readuChar();
2263 StringHelper::appendHex( aBuffer
, nData8
, false );
2264 nData8
= mxStrm
->readuChar( );
2265 StringHelper::appendHex( aBuffer
, nData8
, false );
2266 aBuffer
.append( '-' );
2267 for( int nIndex
= 0; nIndex
< 6; ++nIndex
)
2269 nData8
= mxStrm
->readuChar( );
2270 StringHelper::appendHex( aBuffer
, nData8
, false );
2272 StringHelper::enclose( aBuffer
, '{', '}' );
2273 OUString aGuid
= aBuffer
.makeStringAndClear();
2274 writeGuidItem( rName( "guid" ), aGuid
);
2278 void InputObjectBase::dumpItem( const ItemFormat
& rItemFmt
)
2280 switch( rItemFmt
.meDataType
)
2282 case DATATYPE_VOID
: break;
2283 case DATATYPE_INT8
: dumpValue
< sal_Int8
>( rItemFmt
); break;
2284 case DATATYPE_UINT8
: dumpValue
< sal_uInt8
>( rItemFmt
); break;
2285 case DATATYPE_INT16
: dumpValue
< sal_Int16
>( rItemFmt
); break;
2286 case DATATYPE_UINT16
: dumpValue
< sal_uInt16
>( rItemFmt
); break;
2287 case DATATYPE_INT32
: dumpValue
< sal_Int32
>( rItemFmt
); break;
2288 case DATATYPE_UINT32
: dumpValue
< sal_uInt32
>( rItemFmt
); break;
2289 case DATATYPE_INT64
: dumpValue
< sal_Int64
>( rItemFmt
); break;
2290 case DATATYPE_UINT64
: dumpValue
< sal_uInt64
>( rItemFmt
); break;
2291 case DATATYPE_FLOAT
: dumpValue
< float >( rItemFmt
); break;
2292 case DATATYPE_DOUBLE
: dumpValue
< double >( rItemFmt
); break;
2297 BinaryStreamObject::BinaryStreamObject( const ObjectBase
& rParent
, const BinaryInputStreamRef
& rxStrm
, const OUString
& rSysFileName
)
2299 InputObjectBase::construct( rParent
, rxStrm
, rSysFileName
);
2302 void BinaryStreamObject::dumpBinaryStream( bool bShowOffset
)
2304 mxStrm
->seekToStart();
2305 dumpRawBinary( mxStrm
->size(), bShowOffset
, true );
2309 void BinaryStreamObject::implDump()
2314 void TextStreamObjectBase::construct( const ObjectBase
& rParent
,
2315 const BinaryInputStreamRef
& rxStrm
, rtl_TextEncoding eTextEnc
, const OUString
& rSysFileName
)
2317 InputObjectBase::construct( rParent
, rxStrm
, rSysFileName
);
2318 constructTextStrmObj( eTextEnc
);
2321 void TextStreamObjectBase::construct( const OutputObjectBase
& rParent
,
2322 const BinaryInputStreamRef
& rxStrm
, rtl_TextEncoding eTextEnc
)
2324 InputObjectBase::construct( rParent
, rxStrm
);
2325 constructTextStrmObj( eTextEnc
);
2328 bool TextStreamObjectBase::implIsValid() const
2330 return InputObjectBase::implIsValid() && mxTextStrm
.get();
2333 void TextStreamObjectBase::implDump()
2335 implDumpText( *mxTextStrm
);
2338 void TextStreamObjectBase::constructTextStrmObj( rtl_TextEncoding eTextEnc
)
2341 mxTextStrm
.reset( new TextInputStream( getContext(), *mxStrm
, eTextEnc
) );
2344 TextLineStreamObject::TextLineStreamObject( const ObjectBase
& rParent
,
2345 const BinaryInputStreamRef
& rxStrm
, rtl_TextEncoding eTextEnc
, const OUString
& rSysFileName
)
2347 TextStreamObjectBase::construct( rParent
, rxStrm
, eTextEnc
, rSysFileName
);
2350 TextLineStreamObject::TextLineStreamObject( const OutputObjectBase
& rParent
,
2351 const BinaryInputStreamRef
& rxStrm
, rtl_TextEncoding eTextEnc
)
2353 TextStreamObjectBase::construct( rParent
, rxStrm
, eTextEnc
);
2356 void TextLineStreamObject::implDumpText( TextInputStream
& rTextStrm
)
2358 sal_uInt32 nLine
= 0;
2359 while( !rTextStrm
.isEof() )
2361 OUString aLine
= rTextStrm
.readLine();
2362 if( !rTextStrm
.isEof() || !aLine
.isEmpty() )
2363 implDumpLine( aLine
, ++nLine
);
2367 void TextLineStreamObject::implDumpLine( const OUString
& rLine
, sal_uInt32 nLine
)
2369 TableGuard
aTabGuard( mxOut
, 8 );
2370 mxOut
->writeDec( nLine
, 6 );
2372 mxOut
->writeString( rLine
);
2376 XmlStreamObject::XmlStreamObject( const ObjectBase
& rParent
,
2377 const BinaryInputStreamRef
& rxStrm
, const OUString
& rSysFileName
)
2379 TextStreamObjectBase::construct( rParent
, rxStrm
, RTL_TEXTENCODING_UTF8
, rSysFileName
);
2382 void XmlStreamObject::implDumpText( TextInputStream
& rTextStrm
)
2384 /* Buffers a start element and the following element text. Needed to dump
2385 matching start/end elements and the element text on the same line. */
2386 OUStringBuffer aOldStartElem
;
2387 // special handling for VML
2388 bool bIsVml
= InputOutputHelper::getFileNameExtension( maSysFileName
).equalsIgnoreAsciiCase("vml");
2390 while( !rTextStrm
.isEof() )
2392 // get the next element and the following element text from text stream
2393 OUString aElem
= rTextStrm
.readToChar( '>', true ).trim();
2394 OUString aText
= rTextStrm
.readToChar( '<', false );
2396 // remove multiple whitespace from element
2398 while( nPos
< aElem
.getLength() )
2400 while( (nPos
< aElem
.getLength()) && (aElem
[ nPos
] >= 32) ) ++nPos
;
2401 if( nPos
< aElem
.getLength() )
2402 aElem
= OUStringBuffer( aElem
.copy( 0, nPos
) ).append( ' ' ).append( aElem
.copy( nPos
).trim() ).makeStringAndClear();
2406 sal_Int32 nElemLen
= aElem
.getLength();
2407 if( (nElemLen
>= 2) && (aElem
[ 0 ] == '<') && (aElem
[ nElemLen
- 1 ] == '>') )
2409 // determine type of the element
2410 bool bSimpleElem
= (aElem
[ 1 ] == '!') || (aElem
[ 1 ] == '?') || (aElem
[ nElemLen
- 2 ] == '/') ||
2411 (bIsVml
&& (nElemLen
== 4) && (aElem
[ 1 ] == 'b') && (aElem
[ 2 ] == 'r'));
2412 bool bStartElem
= !bSimpleElem
&& (aElem
[ 1 ] != '/');
2413 bool bEndElem
= !bSimpleElem
&& !bStartElem
;
2415 /* Start element or simple element: flush old start element and
2416 its text from previous iteration, and start a new indentation
2417 level for the new element. Trim whitespace and line breaks from
2418 the text of the old start element. */
2419 if( (bSimpleElem
|| bStartElem
) && (aOldStartElem
.getLength() > 0) )
2421 mxOut
->writeString( aOldStartElem
.makeStringAndClear().trim() );
2426 /* Start element: remember it and its text, to be able to print the
2427 matching end element on the same line in the next iteration. */
2430 aOldStartElem
.append( aElem
).append( aText
);
2434 /* End element: if a start element has been remembered in the
2435 previous iteration, write it out here untrimmed, to show
2436 all whitespace in the element text, and without trailing
2437 line break. Code below will add the end element right after
2438 it. Otherwise, return to previous indentation level. */
2441 if( aOldStartElem
.getLength() == 0 )
2444 mxOut
->writeString( aOldStartElem
.makeStringAndClear() );
2447 /* Write the element. Write following element text in a new
2448 line, but only, if it does not contain of white space
2450 mxOut
->writeString( aElem
);
2452 if( !aText
.trim().isEmpty() )
2454 mxOut
->writeString( aText
);
2462 void RecordObjectBase::construct( const ObjectBase
& rParent
,
2463 const BinaryInputStreamRef
& rxBaseStrm
, const OUString
& rSysFileName
,
2464 const BinaryInputStreamRef
& rxRecStrm
, const String
& rRecNames
, const String
& rSimpleRecs
)
2466 InputObjectBase::construct( rParent
, rxRecStrm
, rSysFileName
);
2467 constructRecObjBase( rxBaseStrm
, rRecNames
, rSimpleRecs
);
2470 bool RecordObjectBase::implIsValid() const
2472 return mxBaseStrm
.get() && InputObjectBase::implIsValid();
2475 void RecordObjectBase::implDump()
2477 NameListRef xRecNames
= getRecNames();
2478 ItemFormatMap
aSimpleRecs( maSimpleRecs
.getNameList( cfg() ) );
2480 while( implStartRecord( *mxBaseStrm
, mnRecPos
, mnRecId
, mnRecSize
) )
2485 implWriteExtHeader();
2486 IndentGuard
aIndGuard( mxOut
);
2487 sal_Int64 nRecPos
= mxStrm
->tell();
2490 if( !mbBinaryOnly
&& cfg().hasName( xRecNames
, mnRecId
) )
2492 ::std::map
< sal_Int64
, ItemFormat
>::const_iterator aIt
= aSimpleRecs
.find( mnRecId
);
2493 if( aIt
!= aSimpleRecs
.end() )
2494 dumpItem( aIt
->second
);
2496 implDumpRecordBody();
2499 // remaining undumped data
2500 if( !mxStrm
->isEof() && (mxStrm
->tell() == nRecPos
) )
2501 dumpRawBinary( mnRecSize
, false );
2503 dumpRemainingTo( nRecPos
+ mnRecSize
);
2507 void RecordObjectBase::implWriteExtHeader()
2511 void RecordObjectBase::implDumpRecordBody()
2515 void RecordObjectBase::constructRecObjBase( const BinaryInputStreamRef
& rxBaseStrm
, const String
& rRecNames
, const String
& rSimpleRecs
)
2517 mxBaseStrm
= rxBaseStrm
;
2518 maRecNames
= rRecNames
;
2519 maSimpleRecs
= rSimpleRecs
;
2520 mnRecPos
= mnRecId
= mnRecSize
= 0;
2521 mbBinaryOnly
= false;
2522 if( InputObjectBase::implIsValid() )
2523 mbShowRecPos
= cfg().getBoolOption( "show-record-position", true );
2526 void RecordObjectBase::writeHeader()
2528 MultiItemsGuard
aMultiGuard( mxOut
);
2529 writeEmptyItem( "REC" );
2530 if( mbShowRecPos
&& mxBaseStrm
->isSeekable() )
2531 writeShortHexItem( "pos", mnRecPos
, "CONV-DEC" );
2532 writeShortHexItem( "size", mnRecSize
, "CONV-DEC" );
2533 ItemGuard
aItem( mxOut
, "id" );
2534 mxOut
->writeShortHex( mnRecId
);
2535 addNameToItem( mnRecId
, "CONV-DEC" );
2536 addNameToItem( mnRecId
, maRecNames
);
2539 void SequenceRecordObjectBase::construct( const ObjectBase
& rParent
,
2540 const BinaryInputStreamRef
& rxBaseStrm
, const OUString
& rSysFileName
,
2541 const String
& rRecNames
, const String
& rSimpleRecs
)
2543 BinaryInputStreamRef
xRecStrm( new SequenceInputStream( *mxRecData
) );
2544 RecordObjectBase::construct( rParent
, rxBaseStrm
, rSysFileName
, xRecStrm
, rRecNames
, rSimpleRecs
);
2547 bool SequenceRecordObjectBase::implStartRecord( BinaryInputStream
& rBaseStrm
, sal_Int64
& ornRecPos
, sal_Int64
& ornRecId
, sal_Int64
& ornRecSize
)
2550 if( rBaseStrm
.isSeekable() )
2552 ornRecPos
= rBaseStrm
.tell();
2553 // do not try to overread seekable streams, may cause assertions
2554 bValid
= ornRecPos
< rBaseStrm
.size();
2557 // read the record header
2559 bValid
= implReadRecordHeader( rBaseStrm
, ornRecId
, ornRecSize
) && !rBaseStrm
.isEof() && (0 <= ornRecSize
) && (ornRecSize
<= 0x00100000);
2561 // read record contents into data sequence
2564 sal_Int32 nRecSize
= static_cast< sal_Int32
>( ornRecSize
);
2565 mxRecData
->realloc( nRecSize
);
2566 bValid
= (nRecSize
== 0) || (rBaseStrm
.readData( *mxRecData
, nRecSize
) == nRecSize
);
2567 mxStrm
->seekToStart();
2572 DumperBase::~DumperBase()
2576 bool DumperBase::isImportEnabled() const
2578 return !isValid() || cfg().isImportEnabled();
2581 bool DumperBase::isImportCancelled() const
2583 return isValid() && cfg().isPasswordCancelled();
2586 void DumperBase::construct( const ConfigRef
& rxConfig
)
2588 if( isValid( rxConfig
) && rxConfig
->isDumperEnabled() )
2589 ObjectBase::construct( rxConfig
);
2597 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */