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

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