Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
20 : #include <string.h>
21 :
22 : #include <cassert>
23 : #include <set>
24 : #include <stack>
25 :
26 : #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
27 : #include <com/sun/star/lang/XServiceInfo.hpp>
28 : #include <com/sun/star/uno/XComponentContext.hpp>
29 : #include <com/sun/star/util/XCloneable.hpp>
30 : #include <com/sun/star/xml/sax/XParser.hpp>
31 : #include <com/sun/star/xml/sax/SAXParseException.hpp>
32 : #include <com/sun/star/xml/sax/SAXInvalidCharacterException.hpp>
33 : #include <com/sun/star/xml/sax/XWriter.hpp>
34 :
35 : #include <com/sun/star/io/XActiveDataSource.hpp>
36 :
37 : #include <cppuhelper/weak.hxx>
38 : #include <cppuhelper/implbase2.hxx>
39 : #include <cppuhelper/supportsservice.hxx>
40 :
41 : #include <osl/diagnose.h>
42 : #include <rtl/ref.hxx>
43 : #include <rtl/ustrbuf.hxx>
44 :
45 : using namespace ::std;
46 : using namespace ::osl;
47 : using namespace ::cppu;
48 : using namespace ::com::sun::star::uno;
49 : using namespace ::com::sun::star::lang;
50 : using namespace ::com::sun::star::xml::sax;
51 : using namespace ::com::sun::star::util;
52 : using namespace ::com::sun::star::io;
53 :
54 : #include "xml2utf.hxx"
55 : #include <boost/scoped_array.hpp>
56 :
57 : #define LINEFEED 10
58 : #define SEQUENCESIZE 1024
59 : #define MAXCOLUMNCOUNT 72
60 :
61 : /******
62 : *
63 : *
64 : * Character conversion functions
65 : *
66 : *
67 : *****/
68 :
69 : namespace {
70 :
71 : enum SaxInvalidCharacterError
72 : {
73 : SAX_NONE,
74 : SAX_WARNING,
75 : SAX_ERROR
76 : };
77 :
78 : class SaxWriterHelper
79 : {
80 : #ifdef DBG_UTIL
81 : public:
82 : ::std::stack<OUString> m_DebugStartedElements;
83 : #endif
84 :
85 : private:
86 : Reference< XOutputStream > m_out;
87 : Sequence < sal_Int8 > m_Sequence;
88 : sal_Int8* mp_Sequence;
89 :
90 : sal_Int32 nLastLineFeedPos; // is negative after writing a sequence
91 : sal_uInt32 nCurrentPos;
92 : bool m_bStartElementFinished;
93 :
94 : inline sal_uInt32 writeSequence() throw( SAXException );
95 :
96 : // use only if to insert the bytes more space in the sequence is needed and
97 : // so the sequence has to write out and reset rPos to 0
98 : // writes sequence only on overflow, sequence could be full on the end (rPos == SEQUENCESIZE)
99 : inline void AddBytes(sal_Int8* pTarget, sal_uInt32& rPos,
100 : const sal_Int8* pBytes, sal_uInt32 nBytesCount) throw( SAXException );
101 : inline bool convertToXML(const sal_Unicode * pStr,
102 : sal_Int32 nStrLen,
103 : bool bDoNormalization,
104 : bool bNormalizeWhitespace,
105 : sal_Int8 *pTarget,
106 : sal_uInt32& rPos) throw( SAXException );
107 : inline void FinishStartElement() throw( SAXException );
108 : public:
109 7025 : explicit SaxWriterHelper(Reference< XOutputStream > m_TempOut)
110 : : m_out(m_TempOut)
111 : , m_Sequence(SEQUENCESIZE)
112 : , mp_Sequence(NULL)
113 : , nLastLineFeedPos(0)
114 : , nCurrentPos(0)
115 7025 : , m_bStartElementFinished(true)
116 : {
117 : OSL_ENSURE(SEQUENCESIZE > 50, "Sequence cache size to small");
118 7025 : mp_Sequence = m_Sequence.getArray();
119 7025 : }
120 7023 : ~SaxWriterHelper()
121 7023 : {
122 : OSL_ENSURE(!nCurrentPos, "cached Sequence not written");
123 : OSL_ENSURE(m_bStartElementFinished, "StartElement not complettly written");
124 7023 : }
125 :
126 : inline void insertIndentation(sal_uInt32 m_nLevel) throw( SAXException );
127 :
128 : // returns whether it works correct or invalid characters were in the string
129 : // If there are invalid characters in the string it returns sal_False.
130 : // Than the calling method has to throw the needed Exception.
131 : inline bool writeString(const OUString& rWriteOutString,
132 : bool bDoNormalization,
133 : bool bNormalizeWhitespace) throw( SAXException );
134 :
135 0 : sal_uInt32 GetLastColumnCount() const throw()
136 0 : { return (sal_uInt32)(nCurrentPos - nLastLineFeedPos); }
137 :
138 : inline void startDocument() throw( SAXException );
139 :
140 : // returns whether it works correct or invalid characters were in the strings
141 : // If there are invalid characters in one of the strings it returns sal_False.
142 : // Than the calling method has to throw the needed Exception.
143 : inline SaxInvalidCharacterError startElement(const OUString& rName, const Reference< XAttributeList >& xAttribs) throw( SAXException );
144 : inline bool FinishEmptyElement() throw( SAXException );
145 :
146 : // returns whether it works correct or invalid characters were in the string
147 : // If there are invalid characters in the string it returns sal_False.
148 : // Than the calling method has to throw the needed Exception.
149 : inline bool endElement(const OUString& rName) throw( SAXException );
150 : inline void endDocument() throw( SAXException );
151 :
152 : // returns whether it works correct or invalid characters were in the strings
153 : // If there are invalid characters in the string it returns sal_False.
154 : // Than the calling method has to throw the needed Exception.
155 : inline bool processingInstruction(const OUString& rTarget, const OUString& rData) throw( SAXException );
156 : inline void startCDATA() throw( SAXException );
157 : inline void endCDATA() throw( SAXException );
158 :
159 : // returns whether it works correct or invalid characters were in the strings
160 : // If there are invalid characters in the string it returns sal_False.
161 : // Than the calling method has to throw the needed Exception.
162 : inline bool comment(const OUString& rComment) throw( SAXException );
163 :
164 : inline void clearBuffer() throw( SAXException );
165 : };
166 :
167 : const sal_Bool g_bValidCharsBelow32[32] =
168 : {
169 : // 0 1 2 3 4 5 6 7
170 : 0,0,0,0,0,0,0,0, //0
171 : 0,1,1,0,0,1,0,0, //8
172 : 0,0,0,0,0,0,0,0, //16
173 : 0,0,0,0,0,0,0,0
174 : };
175 :
176 16367510 : inline bool IsInvalidChar(const sal_Unicode aChar)
177 : {
178 16367510 : bool bRet(false);
179 : // check first for the most common characters
180 16367510 : if( aChar < 32 || aChar >= 0xd800 )
181 2792 : bRet = ( (aChar < 32 && ! g_bValidCharsBelow32[aChar]) ||
182 9128 : aChar == 0xffff ||
183 4564 : aChar == 0xfffe );
184 16367510 : return bRet;
185 : }
186 :
187 : /********
188 : * write through to the output stream
189 : *
190 : *****/
191 22651 : inline sal_uInt32 SaxWriterHelper::writeSequence() throw( SAXException )
192 : {
193 : try
194 : {
195 22651 : m_out->writeBytes( m_Sequence );
196 : }
197 0 : catch (const IOException & e)
198 : {
199 0 : Any a;
200 0 : a <<= e;
201 : throw SAXException(
202 : "IO exception during writing",
203 : Reference< XInterface > (),
204 0 : a );
205 : }
206 22651 : nLastLineFeedPos -= SEQUENCESIZE;
207 22651 : return 0;
208 : }
209 :
210 16 : inline void SaxWriterHelper::AddBytes(sal_Int8* pTarget, sal_uInt32& rPos,
211 : const sal_Int8* pBytes, sal_uInt32 nBytesCount) throw( SAXException )
212 : {
213 : OSL_ENSURE((rPos + nBytesCount) > SEQUENCESIZE, "wrong use of AddBytesMethod");
214 16 : sal_uInt32 nCount(SEQUENCESIZE - rPos);
215 16 : memcpy( &(pTarget[rPos]) , pBytes, nCount);
216 :
217 : OSL_ENSURE(rPos + nCount == SEQUENCESIZE, "the position should be the at the end");
218 :
219 16 : rPos = writeSequence();
220 16 : sal_uInt32 nRestCount(nBytesCount - nCount);
221 16 : if ((rPos + nRestCount) <= SEQUENCESIZE)
222 : {
223 16 : memcpy( &(pTarget[rPos]), &pBytes[nCount], nRestCount);
224 16 : rPos += nRestCount;
225 : }
226 : else
227 0 : AddBytes(pTarget, rPos, &pBytes[nCount], nRestCount);
228 16 : }
229 :
230 : /** Converts an UTF16 string to UTF8 and does XML normalization
231 :
232 : @param pTarget
233 : Pointer to a piece of memory, to where the output should be written. The caller
234 : must call calcXMLByteLength on the same string, to ensure,
235 : that there is enough memory for converting.
236 : */
237 1363820 : inline bool SaxWriterHelper::convertToXML( const sal_Unicode * pStr,
238 : sal_Int32 nStrLen,
239 : bool bDoNormalization,
240 : bool bNormalizeWhitespace,
241 : sal_Int8 *pTarget,
242 : sal_uInt32& rPos ) throw( SAXException )
243 : {
244 1363820 : bool bRet(true);
245 1363820 : sal_uInt32 nSurrogate = 0;
246 :
247 17731330 : for( sal_Int32 i = 0 ; i < nStrLen ; i ++ )
248 : {
249 16367510 : sal_uInt16 c = pStr[i];
250 16367510 : if (IsInvalidChar(c))
251 0 : bRet = false;
252 16367510 : else if( (c >= 0x0001) && (c <= 0x007F) )
253 : {
254 32704458 : if( bDoNormalization )
255 : {
256 6528341 : switch( c )
257 : {
258 : case '&': // resemble to &
259 : {
260 40 : if ((rPos + 5) > SEQUENCESIZE)
261 0 : AddBytes(pTarget, rPos, reinterpret_cast<sal_Int8 const *>("&"), 5);
262 : else
263 : {
264 40 : memcpy( &(pTarget[rPos]) , "&", 5 );
265 40 : rPos += 5;
266 : }
267 : }
268 40 : break;
269 : case '<':
270 : {
271 219 : if ((rPos + 4) > SEQUENCESIZE)
272 1 : AddBytes(pTarget, rPos, reinterpret_cast<sal_Int8 const *>("<"), 4);
273 : else
274 : {
275 218 : memcpy( &(pTarget[rPos]) , "<" , 4 );
276 218 : rPos += 4; // <
277 : }
278 : }
279 219 : break;
280 : case '>':
281 : {
282 258 : if ((rPos + 4) > SEQUENCESIZE)
283 0 : AddBytes(pTarget, rPos, reinterpret_cast<sal_Int8 const *>(">"), 4);
284 : else
285 : {
286 258 : memcpy( &(pTarget[rPos]) , ">" , 4 );
287 258 : rPos += 4; // >
288 : }
289 : }
290 258 : break;
291 : case 39: // 39 == '''
292 : {
293 3750 : if ((rPos + 6) > SEQUENCESIZE)
294 12 : AddBytes(pTarget, rPos, reinterpret_cast<sal_Int8 const *>("'"), 6);
295 : else
296 : {
297 3738 : memcpy( &(pTarget[rPos]) , "'" , 6 );
298 3738 : rPos += 6; // '
299 : }
300 : }
301 3750 : break;
302 : case '"':
303 : {
304 350 : if ((rPos + 6) > SEQUENCESIZE)
305 2 : AddBytes(pTarget, rPos, reinterpret_cast<sal_Int8 const *>("""), 6);
306 : else
307 : {
308 348 : memcpy( &(pTarget[rPos]) , """ , 6 );
309 348 : rPos += 6; // "
310 : }
311 : }
312 350 : break;
313 : case 13:
314 : {
315 0 : if ((rPos + 6) > SEQUENCESIZE)
316 0 : AddBytes(pTarget, rPos, reinterpret_cast<sal_Int8 const *>("
"), 6);
317 : else
318 : {
319 0 : memcpy( &(pTarget[rPos]) , "
" , 6 );
320 0 : rPos += 6;
321 : }
322 : }
323 0 : break;
324 : case LINEFEED:
325 : {
326 1392 : if( bNormalizeWhitespace )
327 : {
328 5 : if ((rPos + 6) > SEQUENCESIZE)
329 0 : AddBytes(pTarget, rPos, reinterpret_cast<sal_Int8 const *>("
"), 6);
330 : else
331 : {
332 5 : memcpy( &(pTarget[rPos]) , "
" , 6 );
333 5 : rPos += 6;
334 : }
335 : }
336 : else
337 : {
338 1387 : pTarget[rPos] = LINEFEED;
339 1387 : nLastLineFeedPos = rPos;
340 1387 : rPos ++;
341 : }
342 : }
343 1392 : break;
344 : case 9:
345 : {
346 1400 : if( bNormalizeWhitespace )
347 : {
348 0 : if ((rPos + 6) > SEQUENCESIZE)
349 0 : AddBytes(pTarget, rPos, reinterpret_cast<sal_Int8 const *>("	"), 6);
350 : else
351 : {
352 0 : memcpy( &(pTarget[rPos]) , "	" , 6 );
353 0 : rPos += 6;
354 : }
355 : }
356 : else
357 : {
358 1400 : pTarget[rPos] = 9;
359 1400 : rPos ++;
360 : }
361 : }
362 1400 : break;
363 : default:
364 : {
365 6520932 : pTarget[rPos] = (sal_Int8)c;
366 6520932 : rPos ++;
367 : }
368 6520932 : break;
369 : }
370 : }
371 : else
372 : {
373 9823888 : pTarget[rPos] = (sal_Int8)c;
374 9823888 : if ((sal_Int8)c == LINEFEED)
375 0 : nLastLineFeedPos = rPos;
376 9823888 : rPos ++;
377 : }
378 : }
379 15281 : else if( c >= 0xd800 && c < 0xdc00 )
380 : {
381 : // 1. surrogate: save (until 2. surrogate)
382 : OSL_ENSURE( nSurrogate == 0, "left-over Unicode surrogate" );
383 0 : nSurrogate = ( ( c & 0x03ff ) + 0x0040 );
384 : }
385 15281 : else if( c >= 0xdc00 && c < 0xe000 )
386 : {
387 : // 2. surrogate: write as UTF-8
388 : OSL_ENSURE( nSurrogate != 0, "lone 2nd Unicode surrogate" );
389 :
390 0 : nSurrogate = ( nSurrogate << 10 ) | ( c & 0x03ff );
391 0 : if( nSurrogate >= 0x00010000 && nSurrogate <= 0x0010FFFF )
392 : {
393 0 : sal_Int8 aBytes[] = { sal_Int8(0xF0 | ((nSurrogate >> 18) & 0x0F)),
394 0 : sal_Int8(0x80 | ((nSurrogate >> 12) & 0x3F)),
395 0 : sal_Int8(0x80 | ((nSurrogate >> 6) & 0x3F)),
396 0 : sal_Int8(0x80 | ((nSurrogate >> 0) & 0x3F)) };
397 0 : if ((rPos + 4) > SEQUENCESIZE)
398 0 : AddBytes(pTarget, rPos, aBytes, 4);
399 : else
400 : {
401 0 : pTarget[rPos] = aBytes[0];
402 0 : rPos ++;
403 0 : pTarget[rPos] = aBytes[1];
404 0 : rPos ++;
405 0 : pTarget[rPos] = aBytes[2];
406 0 : rPos ++;
407 0 : pTarget[rPos] = aBytes[3];
408 0 : rPos ++;
409 0 : }
410 : }
411 : else
412 : {
413 : OSL_FAIL( "illegal Unicode character" );
414 0 : bRet = false;
415 : }
416 :
417 : // reset surrogate
418 0 : nSurrogate = 0;
419 : }
420 15281 : else if( c > 0x07FF )
421 : {
422 : sal_Int8 aBytes[] = { sal_Int8(0xE0 | ((c >> 12) & 0x0F)),
423 13787 : sal_Int8(0x80 | ((c >> 6) & 0x3F)),
424 27574 : sal_Int8(0x80 | ((c >> 0) & 0x3F)) };
425 13787 : if ((rPos + 3) > SEQUENCESIZE)
426 1 : AddBytes(pTarget, rPos, aBytes, 3);
427 : else
428 : {
429 13786 : pTarget[rPos] = aBytes[0];
430 13786 : rPos ++;
431 13786 : pTarget[rPos] = aBytes[1];
432 13786 : rPos ++;
433 13786 : pTarget[rPos] = aBytes[2];
434 13786 : rPos ++;
435 : }
436 : }
437 : else
438 : {
439 1494 : sal_Int8 aBytes[] = { sal_Int8(0xC0 | ((c >> 6) & 0x1F)),
440 1494 : sal_Int8(0x80 | ((c >> 0) & 0x3F)) };
441 1494 : if ((rPos + 2) > SEQUENCESIZE)
442 0 : AddBytes(pTarget, rPos, aBytes, 2);
443 : else
444 : {
445 1494 : pTarget[rPos] = aBytes[0];
446 1494 : rPos ++;
447 1494 : pTarget[rPos] = aBytes[1];
448 1494 : rPos ++;
449 : }
450 : }
451 : OSL_ENSURE(rPos <= SEQUENCESIZE, "not reset current position");
452 16367510 : if (rPos == SEQUENCESIZE)
453 13187 : rPos = writeSequence();
454 :
455 : // reset left-over surrogate
456 16367510 : if( ( nSurrogate != 0 ) && !( c >= 0xd800 && c < 0xdc00 ) )
457 : {
458 : OSL_ENSURE( nSurrogate != 0, "left-over Unicode surrogate" );
459 0 : nSurrogate = 0;
460 0 : bRet = false;
461 : }
462 : }
463 1363820 : return bRet;
464 : }
465 :
466 1755755 : inline void SaxWriterHelper::FinishStartElement() throw( SAXException )
467 : {
468 1755755 : if (!m_bStartElementFinished)
469 : {
470 136568 : mp_Sequence[nCurrentPos] = '>';
471 136568 : nCurrentPos++;
472 136568 : if (nCurrentPos == SEQUENCESIZE)
473 93 : nCurrentPos = writeSequence();
474 136568 : m_bStartElementFinished = true;
475 : }
476 1755755 : }
477 :
478 4723 : inline void SaxWriterHelper::insertIndentation(sal_uInt32 m_nLevel) throw( SAXException )
479 : {
480 4723 : FinishStartElement();
481 4723 : if (m_nLevel > 0)
482 : {
483 1583 : if ((nCurrentPos + m_nLevel + 1) <= SEQUENCESIZE)
484 : {
485 1583 : mp_Sequence[nCurrentPos] = LINEFEED;
486 1583 : nLastLineFeedPos = nCurrentPos;
487 1583 : nCurrentPos++;
488 1583 : memset( &(mp_Sequence[nCurrentPos]) , 32 , m_nLevel );
489 1583 : nCurrentPos += m_nLevel;
490 1583 : if (nCurrentPos == SEQUENCESIZE)
491 0 : nCurrentPos = writeSequence();
492 : }
493 : else
494 : {
495 0 : sal_uInt32 nCount(m_nLevel + 1);
496 0 : boost::scoped_array<sal_Int8> pBytes(new sal_Int8[nCount]);
497 0 : pBytes[0] = LINEFEED;
498 0 : memset( &(pBytes[1]), 32, m_nLevel );
499 0 : AddBytes(mp_Sequence, nCurrentPos, pBytes.get(), nCount);
500 0 : pBytes.reset();
501 0 : nLastLineFeedPos = nCurrentPos - nCount;
502 0 : if (nCurrentPos == SEQUENCESIZE)
503 0 : nCurrentPos = writeSequence();
504 : }
505 : }
506 : else
507 : {
508 3140 : mp_Sequence[nCurrentPos] = LINEFEED;
509 3140 : nLastLineFeedPos = nCurrentPos;
510 3140 : nCurrentPos++;
511 3140 : if (nCurrentPos == SEQUENCESIZE)
512 0 : nCurrentPos = writeSequence();
513 : }
514 4723 : }
515 :
516 1363820 : inline bool SaxWriterHelper::writeString( const OUString& rWriteOutString,
517 : bool bDoNormalization,
518 : bool bNormalizeWhitespace ) throw( SAXException )
519 : {
520 1363820 : FinishStartElement();
521 : return convertToXML(rWriteOutString.getStr(),
522 : rWriteOutString.getLength(),
523 : bDoNormalization,
524 : bNormalizeWhitespace,
525 : mp_Sequence,
526 1363820 : nCurrentPos);
527 : }
528 :
529 7012 : inline void SaxWriterHelper::startDocument() throw( SAXException )
530 : {
531 7012 : const char pc[] = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
532 7012 : const int nLen = strlen( pc );
533 7012 : if ((nCurrentPos + nLen) <= SEQUENCESIZE)
534 : {
535 7012 : memcpy( mp_Sequence, pc , nLen );
536 7012 : nCurrentPos += nLen;
537 : }
538 : else
539 : {
540 0 : AddBytes(mp_Sequence, nCurrentPos, reinterpret_cast<sal_Int8 const *>(pc), nLen);
541 : }
542 : OSL_ENSURE(nCurrentPos <= SEQUENCESIZE, "not reset current position");
543 7012 : if (nCurrentPos == SEQUENCESIZE)
544 0 : nCurrentPos = writeSequence();
545 7012 : mp_Sequence[nCurrentPos] = LINEFEED;
546 7012 : nCurrentPos++;
547 7012 : if (nCurrentPos == SEQUENCESIZE)
548 0 : nCurrentPos = writeSequence();
549 7012 : }
550 :
551 250629 : inline SaxInvalidCharacterError SaxWriterHelper::startElement(const OUString& rName, const Reference< XAttributeList >& xAttribs) throw( SAXException )
552 : {
553 250629 : FinishStartElement();
554 :
555 : #ifdef DBG_UTIL
556 : m_DebugStartedElements.push(rName);
557 : ::std::set<OUString> DebugAttributes;
558 : #endif
559 :
560 250629 : mp_Sequence[nCurrentPos] = '<';
561 250629 : nCurrentPos++;
562 250629 : if (nCurrentPos == SEQUENCESIZE)
563 472 : nCurrentPos = writeSequence();
564 :
565 250629 : SaxInvalidCharacterError eRet(SAX_NONE);
566 250629 : if (!writeString(rName, false, false))
567 0 : eRet = SAX_ERROR;
568 :
569 250629 : sal_Int16 nAttribCount = xAttribs.is() ? static_cast<sal_Int16>(xAttribs->getLength()) : 0;
570 708794 : for(sal_Int16 i = 0 ; i < nAttribCount ; i++ )
571 : {
572 458165 : mp_Sequence[nCurrentPos] = ' ';
573 458165 : nCurrentPos++;
574 458165 : if (nCurrentPos == SEQUENCESIZE)
575 354 : nCurrentPos = writeSequence();
576 :
577 458165 : OUString const& rAttrName(xAttribs->getNameByIndex(i));
578 : #ifdef DBG_UTIL
579 : // Well-formedness constraint: Unique Att Spec
580 : assert(DebugAttributes.find(rAttrName) == DebugAttributes.end());
581 : DebugAttributes.insert(rAttrName);
582 : #endif
583 458165 : if (!writeString(rAttrName, false, false))
584 0 : eRet = SAX_ERROR;
585 :
586 458165 : mp_Sequence[nCurrentPos] = '=';
587 458165 : nCurrentPos++;
588 458165 : if (nCurrentPos == SEQUENCESIZE)
589 448 : nCurrentPos = writeSequence();
590 458165 : mp_Sequence[nCurrentPos] = '"';
591 458165 : nCurrentPos++;
592 458165 : if (nCurrentPos == SEQUENCESIZE)
593 463 : nCurrentPos = writeSequence();
594 :
595 458165 : if (!writeString(xAttribs->getValueByIndex( i ), true, true) &&
596 : !(eRet == SAX_ERROR))
597 0 : eRet = SAX_WARNING;
598 :
599 458165 : mp_Sequence[nCurrentPos] = '"';
600 458165 : nCurrentPos++;
601 458165 : if (nCurrentPos == SEQUENCESIZE)
602 304 : nCurrentPos = writeSequence();
603 458165 : }
604 :
605 250629 : m_bStartElementFinished = false; // because the '>' character is not added,
606 : // because it is possible, that the "/>"
607 : // characters have to add
608 250629 : return eRet;
609 : }
610 :
611 250629 : inline bool SaxWriterHelper::FinishEmptyElement() throw( SAXException )
612 : {
613 250629 : if (m_bStartElementFinished)
614 136568 : return false;
615 :
616 114061 : mp_Sequence[nCurrentPos] = '/';
617 114061 : nCurrentPos++;
618 114061 : if (nCurrentPos == SEQUENCESIZE)
619 53 : nCurrentPos = writeSequence();
620 114061 : mp_Sequence[nCurrentPos] = '>';
621 114061 : nCurrentPos++;
622 114061 : if (nCurrentPos == SEQUENCESIZE)
623 38 : nCurrentPos = writeSequence();
624 :
625 114061 : m_bStartElementFinished = true;
626 :
627 114061 : return true;
628 : }
629 :
630 136568 : inline bool SaxWriterHelper::endElement(const OUString& rName) throw( SAXException )
631 : {
632 136568 : FinishStartElement();
633 :
634 136568 : mp_Sequence[nCurrentPos] = '<';
635 136568 : nCurrentPos++;
636 136568 : if (nCurrentPos == SEQUENCESIZE)
637 55 : nCurrentPos = writeSequence();
638 136568 : mp_Sequence[nCurrentPos] = '/';
639 136568 : nCurrentPos++;
640 136568 : if (nCurrentPos == SEQUENCESIZE)
641 95 : nCurrentPos = writeSequence();
642 :
643 136568 : bool bRet(writeString( rName, false, false));
644 :
645 136568 : mp_Sequence[nCurrentPos] = '>';
646 136568 : nCurrentPos++;
647 136568 : if (nCurrentPos == SEQUENCESIZE)
648 61 : nCurrentPos = writeSequence();
649 :
650 136568 : return bRet;
651 : }
652 :
653 7012 : inline void SaxWriterHelper::endDocument() throw( SAXException )
654 : {
655 7012 : if (nCurrentPos > 0)
656 : {
657 7012 : m_Sequence.realloc(nCurrentPos);
658 7012 : nCurrentPos = writeSequence();
659 : //m_Sequence.realloc(SEQUENCESIZE);
660 : }
661 7012 : }
662 :
663 0 : inline void SaxWriterHelper::clearBuffer() throw( SAXException )
664 : {
665 0 : FinishStartElement();
666 0 : if (nCurrentPos > 0)
667 : {
668 0 : m_Sequence.realloc(nCurrentPos);
669 0 : nCurrentPos = writeSequence();
670 0 : m_Sequence.realloc(SEQUENCESIZE);
671 : // Be sure to update the array pointer after the reallocation.
672 0 : mp_Sequence = m_Sequence.getArray();
673 : }
674 0 : }
675 :
676 12 : inline bool SaxWriterHelper::processingInstruction(const OUString& rTarget, const OUString& rData) throw( SAXException )
677 : {
678 12 : FinishStartElement();
679 12 : mp_Sequence[nCurrentPos] = '<';
680 12 : nCurrentPos++;
681 12 : if (nCurrentPos == SEQUENCESIZE)
682 0 : nCurrentPos = writeSequence();
683 12 : mp_Sequence[nCurrentPos] = '?';
684 12 : nCurrentPos++;
685 12 : if (nCurrentPos == SEQUENCESIZE)
686 0 : nCurrentPos = writeSequence();
687 :
688 12 : bool bRet(writeString( rTarget, false, false ));
689 :
690 12 : mp_Sequence[nCurrentPos] = ' ';
691 12 : nCurrentPos++;
692 12 : if (nCurrentPos == SEQUENCESIZE)
693 0 : nCurrentPos = writeSequence();
694 :
695 12 : if (!writeString( rData, false, false ))
696 0 : bRet = false;
697 :
698 12 : mp_Sequence[nCurrentPos] = '?';
699 12 : nCurrentPos++;
700 12 : if (nCurrentPos == SEQUENCESIZE)
701 0 : nCurrentPos = writeSequence();
702 12 : mp_Sequence[nCurrentPos] = '>';
703 12 : nCurrentPos++;
704 12 : if (nCurrentPos == SEQUENCESIZE)
705 0 : nCurrentPos = writeSequence();
706 :
707 12 : return bRet;
708 : }
709 :
710 0 : inline void SaxWriterHelper::startCDATA() throw( SAXException )
711 : {
712 0 : FinishStartElement();
713 0 : if ((nCurrentPos + 9) <= SEQUENCESIZE)
714 : {
715 0 : memcpy( &(mp_Sequence[nCurrentPos]), "<![CDATA[" , 9 );
716 0 : nCurrentPos += 9;
717 : }
718 : else
719 0 : AddBytes(mp_Sequence, nCurrentPos, reinterpret_cast<sal_Int8 const *>("<![CDATA["), 9);
720 0 : if (nCurrentPos == SEQUENCESIZE)
721 0 : nCurrentPos = writeSequence();
722 0 : }
723 :
724 0 : inline void SaxWriterHelper::endCDATA() throw( SAXException )
725 : {
726 0 : FinishStartElement();
727 0 : if ((nCurrentPos + 3) <= SEQUENCESIZE)
728 : {
729 0 : memcpy( &(mp_Sequence[nCurrentPos]), "]]>" , 3 );
730 0 : nCurrentPos += 3;
731 : }
732 : else
733 0 : AddBytes(mp_Sequence, nCurrentPos, reinterpret_cast<sal_Int8 const *>("]]>"), 3);
734 0 : if (nCurrentPos == SEQUENCESIZE)
735 0 : nCurrentPos = writeSequence();
736 0 : }
737 :
738 3 : inline bool SaxWriterHelper::comment(const OUString& rComment) throw( SAXException )
739 : {
740 3 : FinishStartElement();
741 3 : mp_Sequence[nCurrentPos] = '<';
742 3 : nCurrentPos++;
743 3 : if (nCurrentPos == SEQUENCESIZE)
744 0 : nCurrentPos = writeSequence();
745 3 : mp_Sequence[nCurrentPos] = '!';
746 3 : nCurrentPos++;
747 3 : if (nCurrentPos == SEQUENCESIZE)
748 0 : nCurrentPos = writeSequence();
749 3 : mp_Sequence[nCurrentPos] = '-';
750 3 : nCurrentPos++;
751 3 : if (nCurrentPos == SEQUENCESIZE)
752 0 : nCurrentPos = writeSequence();
753 3 : mp_Sequence[nCurrentPos] = '-';
754 3 : nCurrentPos++;
755 3 : if (nCurrentPos == SEQUENCESIZE)
756 0 : nCurrentPos = writeSequence();
757 :
758 3 : bool bRet(writeString( rComment, false, false));
759 :
760 3 : mp_Sequence[nCurrentPos] = '-';
761 3 : nCurrentPos++;
762 3 : if (nCurrentPos == SEQUENCESIZE)
763 0 : nCurrentPos = writeSequence();
764 3 : mp_Sequence[nCurrentPos] = '-';
765 3 : nCurrentPos++;
766 3 : if (nCurrentPos == SEQUENCESIZE)
767 0 : nCurrentPos = writeSequence();
768 3 : mp_Sequence[nCurrentPos] = '>';
769 3 : nCurrentPos++;
770 3 : if (nCurrentPos == SEQUENCESIZE)
771 0 : nCurrentPos = writeSequence();
772 :
773 3 : return bRet;
774 : }
775 :
776 0 : inline sal_Int32 calcXMLByteLength( const sal_Unicode *pStr, sal_Int32 nStrLen,
777 : bool bDoNormalization,
778 : bool bNormalizeWhitespace )
779 : {
780 0 : sal_Int32 nOutputLength = 0;
781 0 : sal_uInt32 nSurrogate = 0;
782 :
783 0 : for( sal_Int32 i = 0 ; i < nStrLen ; i++ )
784 : {
785 0 : sal_uInt16 c = pStr[i];
786 0 : if( !IsInvalidChar(c) && (c >= 0x0001) && (c <= 0x007F) )
787 : {
788 0 : if( bDoNormalization )
789 : {
790 0 : switch( c )
791 : {
792 : case '&': // resemble to &
793 0 : nOutputLength +=5;
794 0 : break;
795 : case '<': // <
796 : case '>': // >
797 0 : nOutputLength +=4;
798 0 : break;
799 : case 39: // 39 == ''', '
800 : case '"': // "
801 : case 13: // 
802 0 : nOutputLength += 6;
803 0 : break;
804 :
805 : case 10: // 

806 : case 9: // 	
807 0 : if( bNormalizeWhitespace )
808 : {
809 0 : nOutputLength += 6;
810 : }
811 : else
812 : {
813 0 : nOutputLength ++;
814 : }
815 0 : break;
816 : default:
817 0 : nOutputLength ++;
818 : }
819 : }
820 : else
821 : {
822 0 : nOutputLength ++;
823 : }
824 : }
825 0 : else if( c >= 0xd800 && c < 0xdc00 )
826 : {
827 : // save surrogate
828 0 : nSurrogate = ( ( c & 0x03ff ) + 0x0040 );
829 : }
830 0 : else if( c >= 0xdc00 && c < 0xe000 )
831 : {
832 : // 2. surrogate: write as UTF-8 (if range is OK
833 0 : nSurrogate = ( nSurrogate << 10 ) | ( c & 0x03ff );
834 0 : if( nSurrogate >= 0x00010000 && nSurrogate <= 0x0010FFFF )
835 0 : nOutputLength += 4;
836 0 : nSurrogate = 0;
837 : }
838 0 : else if( c > 0x07FF )
839 : {
840 0 : nOutputLength += 3;
841 : }
842 : else
843 : {
844 0 : nOutputLength += 2;
845 : }
846 :
847 : // surrogate processing
848 0 : if( ( nSurrogate != 0 ) && !( c >= 0xd800 && c < 0xdc00 ) )
849 0 : nSurrogate = 0;
850 : }
851 :
852 0 : return nOutputLength;
853 : }
854 :
855 : /** returns position of first ascii 10 within the string, -1 when no 10 in string.
856 : */
857 0 : static inline sal_Int32 getFirstLineBreak( const OUString & str ) throw ()
858 : {
859 0 : const sal_Unicode *pSource = str.getStr();
860 0 : sal_Int32 nLen = str.getLength();
861 :
862 0 : for( int n = 0; n < nLen ; n ++ )
863 : {
864 0 : if( LINEFEED == pSource[n] ) {
865 0 : return n;
866 : }
867 : }
868 0 : return -1;
869 : }
870 :
871 : class SAXWriter :
872 : public WeakImplHelper2<
873 : XWriter,
874 : XServiceInfo >
875 : {
876 : public:
877 6286 : SAXWriter()
878 : : m_pSaxWriterHelper(NULL)
879 : , m_bDocStarted(false)
880 : , m_bIsCDATA(false)
881 : , m_bForceLineBreak(false)
882 : , m_bAllowLineBreak(false)
883 6286 : , m_nLevel(0)
884 : {
885 6286 : }
886 12568 : virtual ~SAXWriter()
887 12568 : {
888 6284 : delete m_pSaxWriterHelper;
889 12568 : }
890 :
891 : public: // XActiveDataSource
892 7025 : virtual void SAL_CALL setOutputStream(const Reference< XOutputStream > & aStream)
893 : throw (RuntimeException, std::exception) SAL_OVERRIDE
894 : {
895 : try
896 : {
897 : // temporary: set same stream again to clear buffer
898 7025 : if ( m_out == aStream && m_pSaxWriterHelper && m_bDocStarted )
899 0 : m_pSaxWriterHelper->clearBuffer();
900 : else
901 : {
902 7025 : m_out = aStream;
903 7025 : delete m_pSaxWriterHelper;
904 7025 : m_pSaxWriterHelper = new SaxWriterHelper(m_out);
905 7025 : m_bDocStarted = false;
906 7025 : m_nLevel = 0;
907 7025 : m_bIsCDATA = false;
908 : }
909 : }
910 0 : catch (const SAXException& e)
911 : {
912 : throw css::lang::WrappedTargetRuntimeException(
913 : e.Message,
914 : static_cast < OWeakObject * > ( this ),
915 0 : e.WrappedException);
916 : }
917 7025 : }
918 0 : virtual Reference< XOutputStream > SAL_CALL getOutputStream()
919 : throw(RuntimeException, std::exception) SAL_OVERRIDE
920 : {
921 0 : return m_out;
922 : }
923 :
924 : public: // XDocumentHandler
925 : virtual void SAL_CALL startDocument()
926 : throw(SAXException, RuntimeException, std::exception) SAL_OVERRIDE;
927 :
928 : virtual void SAL_CALL endDocument()
929 : throw(SAXException, RuntimeException, std::exception) SAL_OVERRIDE;
930 :
931 : virtual void SAL_CALL startElement(const OUString& aName,
932 : const Reference< XAttributeList > & xAttribs)
933 : throw (SAXException, RuntimeException, std::exception) SAL_OVERRIDE;
934 :
935 : virtual void SAL_CALL endElement(const OUString& aName)
936 : throw(SAXException, RuntimeException, std::exception) SAL_OVERRIDE;
937 :
938 : virtual void SAL_CALL characters(const OUString& aChars)
939 : throw(SAXException, RuntimeException, std::exception) SAL_OVERRIDE;
940 :
941 : virtual void SAL_CALL ignorableWhitespace(const OUString& aWhitespaces)
942 : throw(SAXException, RuntimeException, std::exception) SAL_OVERRIDE;
943 : virtual void SAL_CALL processingInstruction(const OUString& aTarget,
944 : const OUString& aData)
945 : throw(SAXException, RuntimeException, std::exception) SAL_OVERRIDE;
946 : virtual void SAL_CALL setDocumentLocator(const Reference< XLocator > & xLocator)
947 : throw(SAXException, RuntimeException, std::exception) SAL_OVERRIDE;
948 :
949 : public: // XExtendedDocumentHandler
950 : virtual void SAL_CALL startCDATA() throw(SAXException, RuntimeException, std::exception) SAL_OVERRIDE;
951 : virtual void SAL_CALL endCDATA() throw(SAXException,RuntimeException, std::exception) SAL_OVERRIDE;
952 : virtual void SAL_CALL comment(const OUString& sComment)
953 : throw(SAXException, RuntimeException, std::exception) SAL_OVERRIDE;
954 : virtual void SAL_CALL unknown(const OUString& sString)
955 : throw(SAXException, RuntimeException, std::exception) SAL_OVERRIDE;
956 : virtual void SAL_CALL allowLineBreak()
957 : throw(SAXException,RuntimeException, std::exception) SAL_OVERRIDE;
958 :
959 : public: // XServiceInfo
960 : OUString SAL_CALL getImplementationName() throw(std::exception) SAL_OVERRIDE;
961 : Sequence< OUString > SAL_CALL getSupportedServiceNames() throw(std::exception) SAL_OVERRIDE;
962 : sal_Bool SAL_CALL supportsService(const OUString& ServiceName) throw(std::exception) SAL_OVERRIDE;
963 :
964 : private:
965 : sal_Int32 getIndentPrefixLength( sal_Int32 nFirstLineBreakOccurrence ) throw();
966 :
967 : Reference< XOutputStream > m_out;
968 : SaxWriterHelper* m_pSaxWriterHelper;
969 :
970 : // Status information
971 : bool m_bDocStarted : 1;
972 : bool m_bIsCDATA : 1;
973 : bool m_bForceLineBreak : 1;
974 : bool m_bAllowLineBreak : 1;
975 : sal_Int32 m_nLevel;
976 : };
977 :
978 447478 : sal_Int32 SAXWriter::getIndentPrefixLength( sal_Int32 nFirstLineBreakOccurrence ) throw()
979 : {
980 447478 : sal_Int32 nLength =-1;
981 447478 : if (m_pSaxWriterHelper)
982 : {
983 452201 : if ( m_bForceLineBreak ||
984 0 : (m_bAllowLineBreak &&
985 0 : ((nFirstLineBreakOccurrence + m_pSaxWriterHelper->GetLastColumnCount()) > MAXCOLUMNCOUNT)) )
986 4723 : nLength = m_nLevel;
987 : }
988 447478 : m_bForceLineBreak = false;
989 447478 : m_bAllowLineBreak = false;
990 447478 : return nLength;
991 : }
992 :
993 0 : static inline bool isFirstCharWhitespace( const sal_Unicode *p ) throw()
994 : {
995 0 : return *p == ' ';
996 : }
997 :
998 : // XServiceInfo
999 1 : OUString SAXWriter::getImplementationName() throw(std::exception)
1000 : {
1001 1 : return OUString("com.sun.star.extensions.xml.sax.Writer");
1002 : }
1003 :
1004 : // XServiceInfo
1005 0 : sal_Bool SAXWriter::supportsService(const OUString& ServiceName) throw(std::exception)
1006 : {
1007 0 : return cppu::supportsService(this, ServiceName);
1008 : }
1009 :
1010 : // XServiceInfo
1011 1 : Sequence< OUString > SAXWriter::getSupportedServiceNames() throw (std::exception)
1012 : {
1013 1 : Sequence<OUString> seq(1);
1014 1 : seq[0] = "com.sun.star.xml.sax.Writer";
1015 1 : return seq;
1016 : }
1017 :
1018 7012 : void SAXWriter::startDocument() throw(SAXException, RuntimeException, std::exception )
1019 : {
1020 7012 : if( m_bDocStarted || ! m_out.is() || !m_pSaxWriterHelper ) {
1021 0 : throw SAXException();
1022 : }
1023 7012 : m_bDocStarted = true;
1024 7012 : m_pSaxWriterHelper->startDocument();
1025 7012 : }
1026 :
1027 :
1028 7012 : void SAXWriter::endDocument() throw(SAXException, RuntimeException, std::exception)
1029 : {
1030 7012 : if( ! m_bDocStarted )
1031 : {
1032 : throw SAXException(
1033 : "endDocument called before startDocument",
1034 0 : Reference< XInterface >() , Any() );
1035 : }
1036 7012 : if( m_nLevel ) {
1037 : throw SAXException(
1038 : "unexpected end of document",
1039 0 : Reference< XInterface >() , Any() );
1040 : }
1041 7012 : m_pSaxWriterHelper->endDocument();
1042 : try
1043 : {
1044 7012 : m_out->closeOutput();
1045 : }
1046 0 : catch (const IOException & e)
1047 : {
1048 0 : Any a;
1049 0 : a <<= e;
1050 : throw SAXException(
1051 : "IO exception during closing the IO Stream",
1052 : Reference< XInterface > (),
1053 0 : a );
1054 : }
1055 7012 : }
1056 :
1057 :
1058 250629 : void SAXWriter::startElement(const OUString& aName, const Reference< XAttributeList >& xAttribs)
1059 : throw(SAXException, RuntimeException, std::exception)
1060 : {
1061 250629 : if( ! m_bDocStarted )
1062 : {
1063 0 : SAXException except;
1064 0 : except.Message = "startElement called before startDocument";
1065 0 : throw except;
1066 : }
1067 250629 : if( m_bIsCDATA )
1068 : {
1069 0 : SAXException except;
1070 0 : except.Message = "startElement call not allowed with CDATA sections";
1071 0 : throw except;
1072 : }
1073 :
1074 250629 : sal_Int32 nLength(0);
1075 250629 : if (m_bAllowLineBreak)
1076 : {
1077 0 : sal_Int32 nAttribCount = xAttribs.is() ? xAttribs->getLength() : 0;
1078 :
1079 0 : nLength ++; // "<"
1080 : nLength += calcXMLByteLength( aName.getStr() , aName.getLength(),
1081 0 : false, false ); // the tag name
1082 :
1083 : sal_Int16 n;
1084 0 : for( n = 0 ; n < static_cast<sal_Int16>(nAttribCount) ; n ++ ) {
1085 0 : nLength ++; // " "
1086 0 : OUString tmp = xAttribs->getNameByIndex( n );
1087 :
1088 0 : nLength += calcXMLByteLength( tmp.getStr() , tmp.getLength() , false, false );
1089 :
1090 0 : nLength += 2; // ="
1091 :
1092 0 : tmp = xAttribs->getValueByIndex( n );
1093 :
1094 0 : nLength += calcXMLByteLength( tmp.getStr(), tmp.getLength(), true, true );
1095 :
1096 0 : nLength += 1; // "
1097 0 : }
1098 :
1099 0 : nLength ++; // '>'
1100 : }
1101 :
1102 : // Is there a new indentation necesarry ?
1103 250629 : sal_Int32 nPrefix(getIndentPrefixLength( nLength ));
1104 :
1105 : // write into sequence
1106 250629 : if( nPrefix >= 0 )
1107 1573 : m_pSaxWriterHelper->insertIndentation( nPrefix );
1108 :
1109 250629 : SaxInvalidCharacterError eRet(m_pSaxWriterHelper->startElement(aName, xAttribs));
1110 :
1111 250629 : m_nLevel++;
1112 :
1113 250629 : if (eRet == SAX_WARNING)
1114 : {
1115 0 : SAXInvalidCharacterException except;
1116 0 : except.Message = "Invalid character during XML-Export in a attribute value";
1117 0 : throw except;
1118 : }
1119 250629 : else if (eRet == SAX_ERROR)
1120 : {
1121 0 : SAXException except;
1122 0 : except.Message = "Invalid character during XML-Export";
1123 0 : throw except;
1124 : }
1125 250629 : }
1126 :
1127 250629 : void SAXWriter::endElement(const OUString& aName) throw (SAXException, RuntimeException, std::exception)
1128 : {
1129 250629 : if( ! m_bDocStarted ) {
1130 0 : throw SAXException ();
1131 : }
1132 250629 : m_nLevel --;
1133 :
1134 250629 : if( m_nLevel < 0 ) {
1135 0 : throw SAXException();
1136 : }
1137 250629 : bool bRet(true);
1138 :
1139 : // check here because Helper's endElement is not always called
1140 : #ifdef DBG_UTIL
1141 : assert(!m_pSaxWriterHelper->m_DebugStartedElements.empty());
1142 : // Well-formedness constraint: Element Type Match
1143 : assert(aName == m_pSaxWriterHelper->m_DebugStartedElements.top());
1144 : m_pSaxWriterHelper->m_DebugStartedElements.pop();
1145 : #endif
1146 :
1147 250629 : if( m_pSaxWriterHelper->FinishEmptyElement() )
1148 114061 : m_bForceLineBreak = false;
1149 : else
1150 : {
1151 : // only ascii chars allowed
1152 136568 : sal_Int32 nLength(0);
1153 136568 : if (m_bAllowLineBreak)
1154 0 : nLength = 3 + calcXMLByteLength( aName.getStr(), aName.getLength(), false, false );
1155 136568 : sal_Int32 nPrefix = getIndentPrefixLength( nLength );
1156 :
1157 136568 : if( nPrefix >= 0 )
1158 3150 : m_pSaxWriterHelper->insertIndentation( nPrefix );
1159 :
1160 136568 : bRet = m_pSaxWriterHelper->endElement(aName);
1161 : }
1162 :
1163 250629 : if (!bRet)
1164 : {
1165 0 : SAXException except;
1166 0 : except.Message = "Invalid character during XML-Export";
1167 0 : throw except;
1168 : }
1169 250629 : }
1170 :
1171 60371 : void SAXWriter::characters(const OUString& aChars) throw(SAXException, RuntimeException, std::exception)
1172 : {
1173 60371 : if( ! m_bDocStarted )
1174 : {
1175 0 : SAXException except;
1176 0 : except.Message = "characters method called before startDocument";
1177 0 : throw except;
1178 : }
1179 :
1180 60371 : bool bThrowException(false);
1181 60371 : if( !aChars.isEmpty() )
1182 : {
1183 60254 : if( m_bIsCDATA )
1184 0 : bThrowException = !m_pSaxWriterHelper->writeString( aChars, false, false );
1185 : else
1186 : {
1187 : // Note : nFirstLineBreakOccurrence is not exact, because we don't know, how
1188 : // many 2 and 3 byte chars are inbetween. However this whole stuff
1189 : // is eitherway for pretty printing only, so it does not need to be exact.
1190 60254 : sal_Int32 nLength(0);
1191 60254 : sal_Int32 nIndentPrefix(-1);
1192 60254 : if (m_bAllowLineBreak)
1193 : {
1194 0 : sal_Int32 nFirstLineBreakOccurrence = getFirstLineBreak( aChars );
1195 :
1196 : nLength = calcXMLByteLength( aChars.getStr(), aChars.getLength(),
1197 0 : ! m_bIsCDATA , false );
1198 : nIndentPrefix = getIndentPrefixLength(
1199 0 : nFirstLineBreakOccurrence >= 0 ? nFirstLineBreakOccurrence : nLength );
1200 : }
1201 : else
1202 60254 : nIndentPrefix = getIndentPrefixLength(nLength);
1203 :
1204 : // insert indentation
1205 60254 : if( nIndentPrefix >= 0 )
1206 : {
1207 0 : if( isFirstCharWhitespace( aChars.getStr() ) )
1208 0 : m_pSaxWriterHelper->insertIndentation( nIndentPrefix - 1 );
1209 : else
1210 0 : m_pSaxWriterHelper->insertIndentation( nIndentPrefix );
1211 : }
1212 60254 : bThrowException = !m_pSaxWriterHelper->writeString(aChars, true , false);
1213 : }
1214 : }
1215 60371 : if (bThrowException)
1216 : {
1217 0 : SAXInvalidCharacterException except;
1218 0 : except.Message = "Invalid character during XML-Export";
1219 0 : throw except;
1220 : }
1221 60371 : }
1222 :
1223 :
1224 22610 : void SAXWriter::ignorableWhitespace(const OUString&) throw(SAXException, RuntimeException, std::exception)
1225 : {
1226 22610 : if( ! m_bDocStarted )
1227 : {
1228 0 : throw SAXException ();
1229 : }
1230 :
1231 22610 : m_bForceLineBreak = true;
1232 22610 : }
1233 :
1234 12 : void SAXWriter::processingInstruction(const OUString& aTarget, const OUString& aData)
1235 : throw (SAXException, RuntimeException, std::exception)
1236 : {
1237 12 : if( ! m_bDocStarted || m_bIsCDATA )
1238 : {
1239 0 : throw SAXException();
1240 : }
1241 :
1242 12 : sal_Int32 nLength(0);
1243 12 : if (m_bAllowLineBreak)
1244 : {
1245 0 : nLength = 2; // "<?"
1246 0 : nLength += calcXMLByteLength( aTarget.getStr(), aTarget.getLength(), false, false );
1247 :
1248 0 : nLength += 1; // " "
1249 :
1250 0 : nLength += calcXMLByteLength( aData.getStr(), aData.getLength(), false, false );
1251 :
1252 0 : nLength += 2; // "?>"
1253 : }
1254 :
1255 12 : sal_Int32 nPrefix = getIndentPrefixLength( nLength );
1256 :
1257 12 : if( nPrefix >= 0 )
1258 0 : m_pSaxWriterHelper->insertIndentation( nPrefix );
1259 :
1260 12 : if (!m_pSaxWriterHelper->processingInstruction(aTarget, aData))
1261 : {
1262 0 : SAXException except;
1263 0 : except.Message = "Invalid character during XML-Export";
1264 0 : throw except;
1265 : }
1266 12 : }
1267 :
1268 :
1269 0 : void SAXWriter::setDocumentLocator(const Reference< XLocator >&)
1270 : throw (SAXException, RuntimeException, std::exception)
1271 : {
1272 :
1273 0 : }
1274 :
1275 0 : void SAXWriter::startCDATA() throw(SAXException, RuntimeException, std::exception)
1276 : {
1277 0 : if( ! m_bDocStarted || m_bIsCDATA)
1278 : {
1279 0 : throw SAXException ();
1280 : }
1281 :
1282 0 : sal_Int32 nLength = 9;
1283 0 : sal_Int32 nPrefix = getIndentPrefixLength( nLength );
1284 0 : if( nPrefix >= 0 )
1285 0 : m_pSaxWriterHelper->insertIndentation( nPrefix );
1286 :
1287 0 : m_pSaxWriterHelper->startCDATA();
1288 :
1289 0 : m_bIsCDATA = true;
1290 0 : }
1291 :
1292 0 : void SAXWriter::endCDATA() throw (SAXException,RuntimeException, std::exception)
1293 : {
1294 0 : if( ! m_bDocStarted || ! m_bIsCDATA)
1295 : {
1296 0 : SAXException except;
1297 0 : except.Message = "endCDATA was called without startCDATA";
1298 0 : throw except;
1299 : }
1300 :
1301 0 : sal_Int32 nLength = 3;
1302 0 : sal_Int32 nPrefix = getIndentPrefixLength( nLength );
1303 0 : if( nPrefix >= 0 )
1304 0 : m_pSaxWriterHelper->insertIndentation( nPrefix );
1305 :
1306 0 : m_pSaxWriterHelper->endCDATA();
1307 :
1308 0 : m_bIsCDATA = false;
1309 0 : }
1310 :
1311 :
1312 3 : void SAXWriter::comment(const OUString& sComment) throw(SAXException, RuntimeException, std::exception)
1313 : {
1314 3 : if( ! m_bDocStarted || m_bIsCDATA )
1315 : {
1316 0 : throw SAXException();
1317 : }
1318 :
1319 3 : sal_Int32 nLength(0);
1320 3 : if (m_bAllowLineBreak)
1321 : {
1322 0 : nLength = 4; // "<!--"
1323 0 : nLength += calcXMLByteLength( sComment.getStr(), sComment.getLength(), false, false);
1324 :
1325 0 : nLength += 3;
1326 : }
1327 :
1328 3 : sal_Int32 nPrefix = getIndentPrefixLength( nLength );
1329 3 : if( nPrefix >= 0 )
1330 0 : m_pSaxWriterHelper->insertIndentation( nPrefix );
1331 :
1332 3 : if (!m_pSaxWriterHelper->comment(sComment))
1333 : {
1334 0 : SAXException except;
1335 0 : except.Message = "Invalid character during XML-Export";
1336 0 : throw except;
1337 : }
1338 3 : }
1339 :
1340 :
1341 0 : void SAXWriter::allowLineBreak( ) throw ( SAXException , RuntimeException, std::exception)
1342 : {
1343 0 : if( ! m_bDocStarted || m_bAllowLineBreak ) {
1344 0 : throw SAXException();
1345 : }
1346 :
1347 0 : m_bAllowLineBreak = true;
1348 0 : }
1349 :
1350 12 : void SAXWriter::unknown(const OUString& sString) throw (SAXException, RuntimeException, std::exception)
1351 : {
1352 :
1353 12 : if( ! m_bDocStarted )
1354 : {
1355 0 : throw SAXException ();
1356 : }
1357 12 : if( m_bIsCDATA )
1358 : {
1359 0 : throw SAXException();
1360 : }
1361 :
1362 12 : if( sString.startsWith( "<?xml" ) )
1363 12 : return;
1364 :
1365 12 : sal_Int32 nLength(0);
1366 12 : if (m_bAllowLineBreak)
1367 0 : nLength = calcXMLByteLength( sString.getStr(), sString.getLength(), false, false );
1368 :
1369 12 : sal_Int32 nPrefix = getIndentPrefixLength( nLength );
1370 12 : if( nPrefix >= 0 )
1371 0 : m_pSaxWriterHelper->insertIndentation( nPrefix );
1372 :
1373 12 : if (!m_pSaxWriterHelper->writeString( sString, false, false))
1374 : {
1375 0 : SAXException except;
1376 0 : except.Message = "Invalid character during XML-Export";
1377 0 : throw except;
1378 : }
1379 : }
1380 :
1381 : } // namespace
1382 :
1383 : extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * SAL_CALL
1384 6286 : com_sun_star_extensions_xml_sax_Writer_get_implementation(
1385 : css::uno::XComponentContext *,
1386 : css::uno::Sequence<css::uno::Any> const &)
1387 : {
1388 6286 : return cppu::acquire(new SAXWriter);
1389 : }
1390 :
1391 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|