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/XServiceInfo.hpp>
27 : #include <com/sun/star/util/XCloneable.hpp>
28 : #include <com/sun/star/xml/sax/XParser.hpp>
29 : #include <com/sun/star/xml/sax/SAXParseException.hpp>
30 : #include <com/sun/star/xml/sax/SAXInvalidCharacterException.hpp>
31 : #include <com/sun/star/xml/sax/XWriter.hpp>
32 :
33 : #include <com/sun/star/io/XActiveDataSource.hpp>
34 :
35 : #include <cppuhelper/weak.hxx>
36 : #include <cppuhelper/implbase2.hxx>
37 : #include <cppuhelper/supportsservice.hxx>
38 :
39 : #include <rtl/ref.hxx>
40 : #include <rtl/ustrbuf.hxx>
41 :
42 : using namespace ::std;
43 : using namespace ::osl;
44 : using namespace ::cppu;
45 : using namespace ::com::sun::star::uno;
46 : using namespace ::com::sun::star::lang;
47 : using namespace ::com::sun::star::xml::sax;
48 : using namespace ::com::sun::star::util;
49 : using namespace ::com::sun::star::io;
50 :
51 : #include "xml2utf.hxx"
52 :
53 : namespace com { namespace sun { namespace star { namespace uno {
54 : class XComponentContext;
55 : } } } }
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 0 : 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 0 : m_bStartElementFinished(true)
116 : {
117 : OSL_ENSURE(SEQUENCESIZE > 50, "Sequence cache size to small");
118 0 : mp_Sequence = m_Sequence.getArray();
119 0 : }
120 0 : ~SaxWriterHelper()
121 0 : {
122 : OSL_ENSURE(!nCurrentPos, "cached Sequence not written");
123 : OSL_ENSURE(m_bStartElementFinished, "StartElement not complettly written");
124 0 : }
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
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 0 : inline bool IsInvalidChar(const sal_Unicode aChar)
177 : {
178 0 : bool bRet(false);
179 : // check first for the most common characters
180 0 : if( aChar < 32 || aChar >= 0xd800 )
181 0 : bRet = ( (aChar < 32 && ! g_bValidCharsBelow32[aChar]) ||
182 0 : aChar == 0xffff ||
183 0 : aChar == 0xfffe );
184 0 : return bRet;
185 : }
186 :
187 : /********
188 : * write through to the output stream
189 : *
190 : *****/
191 0 : inline sal_uInt32 SaxWriterHelper::writeSequence() throw( SAXException )
192 : {
193 : try
194 : {
195 0 : 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 : OUString("io exception during writing"),
203 : Reference< XInterface > (),
204 0 : a );
205 : }
206 0 : nLastLineFeedPos -= SEQUENCESIZE;
207 0 : return 0;
208 : }
209 :
210 0 : 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 0 : sal_uInt32 nCount(SEQUENCESIZE - rPos);
215 0 : memcpy( &(pTarget[rPos]) , pBytes, nCount);
216 :
217 : OSL_ENSURE(rPos + nCount == SEQUENCESIZE, "the position should be the at the end");
218 :
219 0 : rPos = writeSequence();
220 0 : sal_uInt32 nRestCount(nBytesCount - nCount);
221 0 : if ((rPos + nRestCount) <= SEQUENCESIZE)
222 : {
223 0 : memcpy( &(pTarget[rPos]), &pBytes[nCount], nRestCount);
224 0 : rPos += nRestCount;
225 : }
226 : else
227 0 : AddBytes(pTarget, rPos, &pBytes[nCount], nRestCount);
228 0 : }
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 0 : 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 0 : bool bRet(true);
245 0 : sal_uInt32 nSurrogate = 0;
246 :
247 0 : for( sal_Int32 i = 0 ; i < nStrLen ; i ++ )
248 : {
249 0 : sal_uInt16 c = pStr[i];
250 0 : if (IsInvalidChar(c))
251 0 : bRet = false;
252 0 : else if( (c >= 0x0001) && (c <= 0x007F) )
253 : {
254 0 : if( bDoNormalization )
255 : {
256 0 : switch( c )
257 : {
258 : case '&': // resemble to &
259 : {
260 0 : if ((rPos + 5) > SEQUENCESIZE)
261 0 : AddBytes(pTarget, rPos, (sal_Int8*)"&", 5);
262 : else
263 : {
264 0 : memcpy( &(pTarget[rPos]) , "&", 5 );
265 0 : rPos += 5;
266 : }
267 : }
268 0 : break;
269 : case '<':
270 : {
271 0 : if ((rPos + 4) > SEQUENCESIZE)
272 0 : AddBytes(pTarget, rPos, (sal_Int8*)"<", 4);
273 : else
274 : {
275 0 : memcpy( &(pTarget[rPos]) , "<" , 4 );
276 0 : rPos += 4; // <
277 : }
278 : }
279 0 : break;
280 : case '>':
281 : {
282 0 : if ((rPos + 4) > SEQUENCESIZE)
283 0 : AddBytes(pTarget, rPos, (sal_Int8*)">", 4);
284 : else
285 : {
286 0 : memcpy( &(pTarget[rPos]) , ">" , 4 );
287 0 : rPos += 4; // >
288 : }
289 : }
290 0 : break;
291 : case 39: // 39 == '''
292 : {
293 0 : if ((rPos + 6) > SEQUENCESIZE)
294 0 : AddBytes(pTarget, rPos, (sal_Int8*)"'", 6);
295 : else
296 : {
297 0 : memcpy( &(pTarget[rPos]) , "'" , 6 );
298 0 : rPos += 6; // '
299 : }
300 : }
301 0 : break;
302 : case '"':
303 : {
304 0 : if ((rPos + 6) > SEQUENCESIZE)
305 0 : AddBytes(pTarget, rPos, (sal_Int8*)""", 6);
306 : else
307 : {
308 0 : memcpy( &(pTarget[rPos]) , """ , 6 );
309 0 : rPos += 6; // "
310 : }
311 : }
312 0 : break;
313 : case 13:
314 : {
315 0 : if ((rPos + 6) > SEQUENCESIZE)
316 0 : AddBytes(pTarget, rPos, (sal_Int8*)"
", 6);
317 : else
318 : {
319 0 : memcpy( &(pTarget[rPos]) , "
" , 6 );
320 0 : rPos += 6;
321 : }
322 : }
323 0 : break;
324 : case LINEFEED:
325 : {
326 0 : if( bNormalizeWhitespace )
327 : {
328 0 : if ((rPos + 6) > SEQUENCESIZE)
329 0 : AddBytes(pTarget, rPos, (sal_Int8*)"
" , 6);
330 : else
331 : {
332 0 : memcpy( &(pTarget[rPos]) , "
" , 6 );
333 0 : rPos += 6;
334 : }
335 : }
336 : else
337 : {
338 0 : pTarget[rPos] = LINEFEED;
339 0 : nLastLineFeedPos = rPos;
340 0 : rPos ++;
341 : }
342 : }
343 0 : break;
344 : case 9:
345 : {
346 0 : if( bNormalizeWhitespace )
347 : {
348 0 : if ((rPos + 6) > SEQUENCESIZE)
349 0 : AddBytes(pTarget, rPos, (sal_Int8*)"	" , 6);
350 : else
351 : {
352 0 : memcpy( &(pTarget[rPos]) , "	" , 6 );
353 0 : rPos += 6;
354 : }
355 : }
356 : else
357 : {
358 0 : pTarget[rPos] = 9;
359 0 : rPos ++;
360 : }
361 : }
362 0 : break;
363 : default:
364 : {
365 0 : pTarget[rPos] = (sal_Int8)c;
366 0 : rPos ++;
367 : }
368 0 : break;
369 : }
370 : }
371 : else
372 : {
373 0 : pTarget[rPos] = (sal_Int8)c;
374 0 : if ((sal_Int8)c == LINEFEED)
375 0 : nLastLineFeedPos = rPos;
376 0 : rPos ++;
377 : }
378 : }
379 0 : 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 0 : 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 0 : else if( c > 0x07FF )
421 : {
422 : sal_Int8 aBytes[] = { sal_Int8(0xE0 | ((c >> 12) & 0x0F)),
423 0 : sal_Int8(0x80 | ((c >> 6) & 0x3F)),
424 0 : sal_Int8(0x80 | ((c >> 0) & 0x3F)) };
425 0 : if ((rPos + 3) > SEQUENCESIZE)
426 0 : AddBytes(pTarget, rPos, aBytes, 3);
427 : else
428 : {
429 0 : pTarget[rPos] = aBytes[0];
430 0 : rPos ++;
431 0 : pTarget[rPos] = aBytes[1];
432 0 : rPos ++;
433 0 : pTarget[rPos] = aBytes[2];
434 0 : rPos ++;
435 : }
436 : }
437 : else
438 : {
439 0 : sal_Int8 aBytes[] = { sal_Int8(0xC0 | ((c >> 6) & 0x1F)),
440 0 : sal_Int8(0x80 | ((c >> 0) & 0x3F)) };
441 0 : if ((rPos + 2) > SEQUENCESIZE)
442 0 : AddBytes(pTarget, rPos, aBytes, 2);
443 : else
444 : {
445 0 : pTarget[rPos] = aBytes[0];
446 0 : rPos ++;
447 0 : pTarget[rPos] = aBytes[1];
448 0 : rPos ++;
449 : }
450 : }
451 : OSL_ENSURE(rPos <= SEQUENCESIZE, "not reset current position");
452 0 : if (rPos == SEQUENCESIZE)
453 0 : rPos = writeSequence();
454 :
455 : // reset left-over surrogate
456 0 : 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 0 : return bRet;
464 : }
465 :
466 0 : inline void SaxWriterHelper::FinishStartElement() throw( SAXException )
467 : {
468 0 : if (!m_bStartElementFinished)
469 : {
470 0 : mp_Sequence[nCurrentPos] = '>';
471 0 : nCurrentPos++;
472 0 : if (nCurrentPos == SEQUENCESIZE)
473 0 : nCurrentPos = writeSequence();
474 0 : m_bStartElementFinished = true;
475 : }
476 0 : }
477 :
478 0 : inline void SaxWriterHelper::insertIndentation(sal_uInt32 m_nLevel) throw( SAXException )
479 : {
480 0 : FinishStartElement();
481 0 : if (m_nLevel > 0)
482 : {
483 0 : if ((nCurrentPos + m_nLevel + 1) <= SEQUENCESIZE)
484 : {
485 0 : mp_Sequence[nCurrentPos] = LINEFEED;
486 0 : nLastLineFeedPos = nCurrentPos;
487 0 : nCurrentPos++;
488 0 : memset( &(mp_Sequence[nCurrentPos]) , 32 , m_nLevel );
489 0 : nCurrentPos += m_nLevel;
490 0 : if (nCurrentPos == SEQUENCESIZE)
491 0 : nCurrentPos = writeSequence();
492 : }
493 : else
494 : {
495 0 : sal_uInt32 nCount(m_nLevel + 1);
496 0 : 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, nCount);
500 0 : delete[] pBytes;
501 0 : nLastLineFeedPos = nCurrentPos - nCount;
502 0 : if (nCurrentPos == SEQUENCESIZE)
503 0 : nCurrentPos = writeSequence();
504 : }
505 : }
506 : else
507 : {
508 0 : mp_Sequence[nCurrentPos] = LINEFEED;
509 0 : nLastLineFeedPos = nCurrentPos;
510 0 : nCurrentPos++;
511 0 : if (nCurrentPos == SEQUENCESIZE)
512 0 : nCurrentPos = writeSequence();
513 : }
514 0 : }
515 :
516 0 : inline bool SaxWriterHelper::writeString( const OUString& rWriteOutString,
517 : bool bDoNormalization,
518 : bool bNormalizeWhitespace ) throw( SAXException )
519 : {
520 0 : FinishStartElement();
521 : return convertToXML(rWriteOutString.getStr(),
522 : rWriteOutString.getLength(),
523 : bDoNormalization,
524 : bNormalizeWhitespace,
525 : mp_Sequence,
526 0 : nCurrentPos);
527 : }
528 :
529 0 : inline void SaxWriterHelper::startDocument() throw( SAXException )
530 : {
531 0 : const char pc[] = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
532 0 : const int nLen = strlen( pc );
533 0 : if ((nCurrentPos + nLen) <= SEQUENCESIZE)
534 : {
535 0 : memcpy( mp_Sequence, pc , nLen );
536 0 : nCurrentPos += nLen;
537 : }
538 : else
539 : {
540 0 : AddBytes(mp_Sequence, nCurrentPos, (sal_Int8*)pc, nLen);
541 : }
542 : OSL_ENSURE(nCurrentPos <= SEQUENCESIZE, "not reset current position");
543 0 : if (nCurrentPos == SEQUENCESIZE)
544 0 : nCurrentPos = writeSequence();
545 0 : mp_Sequence[nCurrentPos] = LINEFEED;
546 0 : nCurrentPos++;
547 0 : if (nCurrentPos == SEQUENCESIZE)
548 0 : nCurrentPos = writeSequence();
549 0 : }
550 :
551 0 : inline SaxInvalidCharacterError SaxWriterHelper::startElement(const OUString& rName, const Reference< XAttributeList >& xAttribs) throw( SAXException )
552 : {
553 0 : FinishStartElement();
554 :
555 : #ifdef DBG_UTIL
556 : m_DebugStartedElements.push(rName);
557 : ::std::set<OUString> DebugAttributes;
558 : #endif
559 :
560 0 : mp_Sequence[nCurrentPos] = '<';
561 0 : nCurrentPos++;
562 0 : if (nCurrentPos == SEQUENCESIZE)
563 0 : nCurrentPos = writeSequence();
564 :
565 0 : SaxInvalidCharacterError eRet(SAX_NONE);
566 0 : if (!writeString(rName, false, false))
567 0 : eRet = SAX_ERROR;
568 :
569 0 : sal_Int16 nAttribCount = xAttribs.is() ? static_cast<sal_Int16>(xAttribs->getLength()) : 0;
570 0 : for(sal_Int16 i = 0 ; i < nAttribCount ; i++ )
571 : {
572 0 : mp_Sequence[nCurrentPos] = ' ';
573 0 : nCurrentPos++;
574 0 : if (nCurrentPos == SEQUENCESIZE)
575 0 : nCurrentPos = writeSequence();
576 :
577 0 : 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 0 : if (!writeString(rAttrName, false, false))
584 0 : eRet = SAX_ERROR;
585 :
586 0 : mp_Sequence[nCurrentPos] = '=';
587 0 : nCurrentPos++;
588 0 : if (nCurrentPos == SEQUENCESIZE)
589 0 : nCurrentPos = writeSequence();
590 0 : mp_Sequence[nCurrentPos] = '"';
591 0 : nCurrentPos++;
592 0 : if (nCurrentPos == SEQUENCESIZE)
593 0 : nCurrentPos = writeSequence();
594 :
595 0 : if (!writeString(xAttribs->getValueByIndex( i ), true, true) &&
596 : !(eRet == SAX_ERROR))
597 0 : eRet = SAX_WARNING;
598 :
599 0 : mp_Sequence[nCurrentPos] = '"';
600 0 : nCurrentPos++;
601 0 : if (nCurrentPos == SEQUENCESIZE)
602 0 : nCurrentPos = writeSequence();
603 0 : }
604 :
605 0 : m_bStartElementFinished = false; // because the '>' character is not added,
606 : // because it is possible, that the "/>"
607 : // characters have to add
608 0 : return eRet;
609 : }
610 :
611 0 : inline bool SaxWriterHelper::FinishEmptyElement() throw( SAXException )
612 : {
613 0 : if (m_bStartElementFinished)
614 0 : return false;
615 :
616 0 : mp_Sequence[nCurrentPos] = '/';
617 0 : nCurrentPos++;
618 0 : if (nCurrentPos == SEQUENCESIZE)
619 0 : nCurrentPos = writeSequence();
620 0 : mp_Sequence[nCurrentPos] = '>';
621 0 : nCurrentPos++;
622 0 : if (nCurrentPos == SEQUENCESIZE)
623 0 : nCurrentPos = writeSequence();
624 :
625 0 : m_bStartElementFinished = true;
626 :
627 0 : return true;
628 : }
629 :
630 0 : inline bool SaxWriterHelper::endElement(const OUString& rName) throw( SAXException )
631 : {
632 0 : FinishStartElement();
633 :
634 0 : mp_Sequence[nCurrentPos] = '<';
635 0 : nCurrentPos++;
636 0 : if (nCurrentPos == SEQUENCESIZE)
637 0 : nCurrentPos = writeSequence();
638 0 : mp_Sequence[nCurrentPos] = '/';
639 0 : nCurrentPos++;
640 0 : if (nCurrentPos == SEQUENCESIZE)
641 0 : nCurrentPos = writeSequence();
642 :
643 0 : bool bRet(writeString( rName, false, false));
644 :
645 0 : mp_Sequence[nCurrentPos] = '>';
646 0 : nCurrentPos++;
647 0 : if (nCurrentPos == SEQUENCESIZE)
648 0 : nCurrentPos = writeSequence();
649 :
650 0 : return bRet;
651 : }
652 :
653 0 : inline void SaxWriterHelper::endDocument() throw( SAXException )
654 : {
655 0 : if (nCurrentPos > 0)
656 : {
657 0 : m_Sequence.realloc(nCurrentPos);
658 0 : nCurrentPos = writeSequence();
659 : //m_Sequence.realloc(SEQUENCESIZE);
660 : }
661 0 : }
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 0 : inline bool SaxWriterHelper::processingInstruction(const OUString& rTarget, const OUString& rData) throw( SAXException )
677 : {
678 0 : FinishStartElement();
679 0 : mp_Sequence[nCurrentPos] = '<';
680 0 : nCurrentPos++;
681 0 : if (nCurrentPos == SEQUENCESIZE)
682 0 : nCurrentPos = writeSequence();
683 0 : mp_Sequence[nCurrentPos] = '?';
684 0 : nCurrentPos++;
685 0 : if (nCurrentPos == SEQUENCESIZE)
686 0 : nCurrentPos = writeSequence();
687 :
688 0 : bool bRet(writeString( rTarget, false, false ));
689 :
690 0 : mp_Sequence[nCurrentPos] = ' ';
691 0 : nCurrentPos++;
692 0 : if (nCurrentPos == SEQUENCESIZE)
693 0 : nCurrentPos = writeSequence();
694 :
695 0 : if (!writeString( rData, false, false ))
696 0 : bRet = false;
697 :
698 0 : mp_Sequence[nCurrentPos] = '?';
699 0 : nCurrentPos++;
700 0 : if (nCurrentPos == SEQUENCESIZE)
701 0 : nCurrentPos = writeSequence();
702 0 : mp_Sequence[nCurrentPos] = '>';
703 0 : nCurrentPos++;
704 0 : if (nCurrentPos == SEQUENCESIZE)
705 0 : nCurrentPos = writeSequence();
706 :
707 0 : 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, (sal_Int8*)"<![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, (sal_Int8*)"]]>" , 3);
734 0 : if (nCurrentPos == SEQUENCESIZE)
735 0 : nCurrentPos = writeSequence();
736 0 : }
737 :
738 0 : inline bool SaxWriterHelper::comment(const OUString& rComment) throw( SAXException )
739 : {
740 0 : FinishStartElement();
741 0 : mp_Sequence[nCurrentPos] = '<';
742 0 : nCurrentPos++;
743 0 : if (nCurrentPos == SEQUENCESIZE)
744 0 : nCurrentPos = writeSequence();
745 0 : mp_Sequence[nCurrentPos] = '!';
746 0 : nCurrentPos++;
747 0 : if (nCurrentPos == SEQUENCESIZE)
748 0 : nCurrentPos = writeSequence();
749 0 : mp_Sequence[nCurrentPos] = '-';
750 0 : nCurrentPos++;
751 0 : if (nCurrentPos == SEQUENCESIZE)
752 0 : nCurrentPos = writeSequence();
753 0 : mp_Sequence[nCurrentPos] = '-';
754 0 : nCurrentPos++;
755 0 : if (nCurrentPos == SEQUENCESIZE)
756 0 : nCurrentPos = writeSequence();
757 :
758 0 : bool bRet(writeString( rComment, false, false));
759 :
760 0 : mp_Sequence[nCurrentPos] = '-';
761 0 : nCurrentPos++;
762 0 : if (nCurrentPos == SEQUENCESIZE)
763 0 : nCurrentPos = writeSequence();
764 0 : mp_Sequence[nCurrentPos] = '-';
765 0 : nCurrentPos++;
766 0 : if (nCurrentPos == SEQUENCESIZE)
767 0 : nCurrentPos = writeSequence();
768 0 : mp_Sequence[nCurrentPos] = '>';
769 0 : nCurrentPos++;
770 0 : if (nCurrentPos == SEQUENCESIZE)
771 0 : nCurrentPos = writeSequence();
772 :
773 0 : 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 0 : SAXWriter()
878 : : m_seqStartElement()
879 : , m_pSaxWriterHelper(NULL)
880 : , m_bDocStarted(false)
881 : , m_bIsCDATA(false)
882 : , m_bForceLineBreak(false)
883 : , m_bAllowLineBreak(false)
884 0 : , m_nLevel(0)
885 : {
886 0 : }
887 0 : virtual ~SAXWriter()
888 0 : {
889 0 : delete m_pSaxWriterHelper;
890 0 : }
891 :
892 : public: // XActiveDataSource
893 0 : virtual void SAL_CALL setOutputStream(const Reference< XOutputStream > & aStream)
894 : throw (RuntimeException, std::exception) SAL_OVERRIDE
895 : {
896 : // temporary: set same stream again to clear buffer
897 0 : if ( m_out == aStream && m_pSaxWriterHelper && m_bDocStarted )
898 0 : m_pSaxWriterHelper->clearBuffer();
899 : else
900 : {
901 :
902 0 : m_out = aStream;
903 0 : delete m_pSaxWriterHelper;
904 0 : m_pSaxWriterHelper = new SaxWriterHelper(m_out);
905 0 : m_bDocStarted = false;
906 0 : m_nLevel = 0;
907 0 : m_bIsCDATA = false;
908 :
909 : }
910 0 : }
911 0 : virtual Reference< XOutputStream > SAL_CALL getOutputStream(void)
912 : throw(RuntimeException, std::exception) SAL_OVERRIDE
913 0 : { return m_out; }
914 :
915 : public: // XDocumentHandler
916 : virtual void SAL_CALL startDocument(void)
917 : throw(SAXException, RuntimeException, std::exception) SAL_OVERRIDE;
918 :
919 : virtual void SAL_CALL endDocument(void)
920 : throw(SAXException, RuntimeException, std::exception) SAL_OVERRIDE;
921 :
922 : virtual void SAL_CALL startElement(const OUString& aName,
923 : const Reference< XAttributeList > & xAttribs)
924 : throw (SAXException, RuntimeException, std::exception) SAL_OVERRIDE;
925 :
926 : virtual void SAL_CALL endElement(const OUString& aName)
927 : throw(SAXException, RuntimeException, std::exception) SAL_OVERRIDE;
928 :
929 : virtual void SAL_CALL characters(const OUString& aChars)
930 : throw(SAXException, RuntimeException, std::exception) SAL_OVERRIDE;
931 :
932 : virtual void SAL_CALL ignorableWhitespace(const OUString& aWhitespaces)
933 : throw(SAXException, RuntimeException, std::exception) SAL_OVERRIDE;
934 : virtual void SAL_CALL processingInstruction(const OUString& aTarget,
935 : const OUString& aData)
936 : throw(SAXException, RuntimeException, std::exception) SAL_OVERRIDE;
937 : virtual void SAL_CALL setDocumentLocator(const Reference< XLocator > & xLocator)
938 : throw(SAXException, RuntimeException, std::exception) SAL_OVERRIDE;
939 :
940 : public: // XExtendedDocumentHandler
941 : virtual void SAL_CALL startCDATA(void) throw(SAXException, RuntimeException, std::exception) SAL_OVERRIDE;
942 : virtual void SAL_CALL endCDATA(void) throw(SAXException,RuntimeException, std::exception) SAL_OVERRIDE;
943 : virtual void SAL_CALL comment(const OUString& sComment)
944 : throw(SAXException, RuntimeException, std::exception) SAL_OVERRIDE;
945 : virtual void SAL_CALL unknown(const OUString& sString)
946 : throw(SAXException, RuntimeException, std::exception) SAL_OVERRIDE;
947 : virtual void SAL_CALL allowLineBreak(void)
948 : throw(SAXException,RuntimeException, std::exception) SAL_OVERRIDE;
949 :
950 : public: // XServiceInfo
951 : OUString SAL_CALL getImplementationName() throw(std::exception) SAL_OVERRIDE;
952 : Sequence< OUString > SAL_CALL getSupportedServiceNames(void) throw(std::exception) SAL_OVERRIDE;
953 : sal_Bool SAL_CALL supportsService(const OUString& ServiceName) throw(std::exception) SAL_OVERRIDE;
954 :
955 : private:
956 : sal_Int32 getIndentPrefixLength( sal_Int32 nFirstLineBreakOccurrence ) throw();
957 :
958 : Reference< XOutputStream > m_out;
959 : Sequence < sal_Int8 > m_seqStartElement;
960 : SaxWriterHelper* m_pSaxWriterHelper;
961 :
962 : // Status information
963 : bool m_bDocStarted : 1;
964 : bool m_bIsCDATA : 1;
965 : bool m_bForceLineBreak : 1;
966 : bool m_bAllowLineBreak : 1;
967 : sal_Int32 m_nLevel;
968 : };
969 :
970 0 : sal_Int32 SAXWriter::getIndentPrefixLength( sal_Int32 nFirstLineBreakOccurrence ) throw()
971 : {
972 0 : sal_Int32 nLength =-1;
973 0 : if (m_pSaxWriterHelper)
974 : {
975 0 : if ( m_bForceLineBreak ||
976 0 : (m_bAllowLineBreak &&
977 0 : ((nFirstLineBreakOccurrence + m_pSaxWriterHelper->GetLastColumnCount()) > MAXCOLUMNCOUNT)) )
978 0 : nLength = m_nLevel;
979 : }
980 0 : m_bForceLineBreak = false;
981 0 : m_bAllowLineBreak = false;
982 0 : return nLength;
983 : }
984 :
985 0 : static inline bool isFirstCharWhitespace( const sal_Unicode *p ) throw()
986 : {
987 0 : return *p == ' ';
988 : }
989 :
990 : // XServiceInfo
991 0 : OUString SAXWriter::getImplementationName() throw(std::exception)
992 : {
993 0 : return OUString("com.sun.star.extensions.xml.sax.Writer");
994 : }
995 :
996 : // XServiceInfo
997 0 : sal_Bool SAXWriter::supportsService(const OUString& ServiceName) throw(std::exception)
998 : {
999 0 : return cppu::supportsService(this, ServiceName);
1000 : }
1001 :
1002 : // XServiceInfo
1003 0 : Sequence< OUString > SAXWriter::getSupportedServiceNames(void) throw (std::exception)
1004 : {
1005 0 : Sequence<OUString> seq(1);
1006 0 : seq[0] = "com.sun.star.xml.sax.Writer";
1007 0 : return seq;
1008 : }
1009 :
1010 0 : void SAXWriter::startDocument() throw(SAXException, RuntimeException, std::exception )
1011 : {
1012 0 : if( m_bDocStarted || ! m_out.is() || !m_pSaxWriterHelper ) {
1013 0 : throw SAXException();
1014 : }
1015 0 : m_bDocStarted = true;
1016 0 : m_pSaxWriterHelper->startDocument();
1017 0 : }
1018 :
1019 :
1020 0 : void SAXWriter::endDocument(void) throw(SAXException, RuntimeException, std::exception)
1021 : {
1022 0 : if( ! m_bDocStarted )
1023 : {
1024 : throw SAXException(
1025 : OUString("endDocument called before startDocument"),
1026 0 : Reference< XInterface >() , Any() );
1027 : }
1028 0 : if( m_nLevel ) {
1029 : throw SAXException(
1030 : OUString("unexpected end of document"),
1031 0 : Reference< XInterface >() , Any() );
1032 : }
1033 0 : m_pSaxWriterHelper->endDocument();
1034 : try
1035 : {
1036 0 : m_out->closeOutput();
1037 : }
1038 0 : catch (const IOException & e)
1039 : {
1040 0 : Any a;
1041 0 : a <<= e;
1042 : throw SAXException(
1043 : OUString("IO exception during closing the IO Stream"),
1044 : Reference< XInterface > (),
1045 0 : a );
1046 : }
1047 0 : }
1048 :
1049 :
1050 0 : void SAXWriter::startElement(const OUString& aName, const Reference< XAttributeList >& xAttribs)
1051 : throw(SAXException, RuntimeException, std::exception)
1052 : {
1053 0 : if( ! m_bDocStarted )
1054 : {
1055 0 : SAXException except;
1056 0 : except.Message = "startElement called before startDocument";
1057 0 : throw except;
1058 : }
1059 0 : if( m_bIsCDATA )
1060 : {
1061 0 : SAXException except;
1062 0 : except.Message = "startElement call not allowed with CDATA sections";
1063 0 : throw except;
1064 : }
1065 :
1066 0 : sal_Int32 nLength(0);
1067 0 : if (m_bAllowLineBreak)
1068 : {
1069 0 : sal_Int32 nAttribCount = xAttribs.is() ? xAttribs->getLength() : 0;
1070 :
1071 0 : nLength ++; // "<"
1072 : nLength += calcXMLByteLength( aName.getStr() , aName.getLength(),
1073 0 : false, false ); // the tag name
1074 :
1075 : sal_Int16 n;
1076 0 : for( n = 0 ; n < static_cast<sal_Int16>(nAttribCount) ; n ++ ) {
1077 0 : nLength ++; // " "
1078 0 : OUString tmp = xAttribs->getNameByIndex( n );
1079 :
1080 0 : nLength += calcXMLByteLength( tmp.getStr() , tmp.getLength() , false, false );
1081 :
1082 0 : nLength += 2; // ="
1083 :
1084 0 : tmp = xAttribs->getValueByIndex( n );
1085 :
1086 0 : nLength += calcXMLByteLength( tmp.getStr(), tmp.getLength(), true, true );
1087 :
1088 0 : nLength += 1; // "
1089 0 : }
1090 :
1091 0 : nLength ++; // '>'
1092 : }
1093 :
1094 : // Is there a new indentation necesarry ?
1095 0 : sal_Int32 nPrefix(getIndentPrefixLength( nLength ));
1096 :
1097 : // write into sequence
1098 0 : if( nPrefix >= 0 )
1099 0 : m_pSaxWriterHelper->insertIndentation( nPrefix );
1100 :
1101 0 : SaxInvalidCharacterError eRet(m_pSaxWriterHelper->startElement(aName, xAttribs));
1102 :
1103 0 : m_nLevel++;
1104 :
1105 0 : if (eRet == SAX_WARNING)
1106 : {
1107 0 : SAXInvalidCharacterException except;
1108 0 : except.Message = "Invalid character during XML-Export in a attribute value";
1109 0 : throw except;
1110 : }
1111 0 : else if (eRet == SAX_ERROR)
1112 : {
1113 0 : SAXException except;
1114 0 : except.Message = "Invalid character during XML-Export";
1115 0 : throw except;
1116 : }
1117 0 : }
1118 :
1119 0 : void SAXWriter::endElement(const OUString& aName) throw (SAXException, RuntimeException, std::exception)
1120 : {
1121 0 : if( ! m_bDocStarted ) {
1122 0 : throw SAXException ();
1123 : }
1124 0 : m_nLevel --;
1125 :
1126 0 : if( m_nLevel < 0 ) {
1127 0 : throw SAXException();
1128 : }
1129 0 : bool bRet(true);
1130 :
1131 : // check here because Helper's endElement is not always called
1132 : #ifdef DBG_UTIL
1133 : assert(!m_pSaxWriterHelper->m_DebugStartedElements.empty());
1134 : // Well-formedness constraint: Element Type Match
1135 : assert(aName == m_pSaxWriterHelper->m_DebugStartedElements.top());
1136 : m_pSaxWriterHelper->m_DebugStartedElements.pop();
1137 : #endif
1138 :
1139 0 : if( m_pSaxWriterHelper->FinishEmptyElement() )
1140 0 : m_bForceLineBreak = false;
1141 : else
1142 : {
1143 : // only ascii chars allowed
1144 0 : sal_Int32 nLength(0);
1145 0 : if (m_bAllowLineBreak)
1146 0 : nLength = 3 + calcXMLByteLength( aName.getStr(), aName.getLength(), false, false );
1147 0 : sal_Int32 nPrefix = getIndentPrefixLength( nLength );
1148 :
1149 0 : if( nPrefix >= 0 )
1150 0 : m_pSaxWriterHelper->insertIndentation( nPrefix );
1151 :
1152 0 : bRet = m_pSaxWriterHelper->endElement(aName);
1153 : }
1154 :
1155 0 : if (!bRet)
1156 : {
1157 0 : SAXException except;
1158 0 : except.Message = "Invalid character during XML-Export";
1159 0 : throw except;
1160 : }
1161 0 : }
1162 :
1163 0 : void SAXWriter::characters(const OUString& aChars) throw(SAXException, RuntimeException, std::exception)
1164 : {
1165 0 : if( ! m_bDocStarted )
1166 : {
1167 0 : SAXException except;
1168 0 : except.Message = "characters method called before startDocument";
1169 0 : throw except;
1170 : }
1171 :
1172 0 : bool bThrowException(false);
1173 0 : if( !aChars.isEmpty() )
1174 : {
1175 0 : if( m_bIsCDATA )
1176 0 : bThrowException = !m_pSaxWriterHelper->writeString( aChars, false, false );
1177 : else
1178 : {
1179 : // Note : nFirstLineBreakOccurrence is not exact, because we don't know, how
1180 : // many 2 and 3 byte chars are inbetween. However this whole stuff
1181 : // is eitherway for pretty printing only, so it does not need to be exact.
1182 0 : sal_Int32 nLength(0);
1183 0 : sal_Int32 nIndentPrefix(-1);
1184 0 : if (m_bAllowLineBreak)
1185 : {
1186 0 : sal_Int32 nFirstLineBreakOccurrence = getFirstLineBreak( aChars );
1187 :
1188 : nLength = calcXMLByteLength( aChars.getStr(), aChars.getLength(),
1189 0 : ! m_bIsCDATA , false );
1190 : nIndentPrefix = getIndentPrefixLength(
1191 0 : nFirstLineBreakOccurrence >= 0 ? nFirstLineBreakOccurrence : nLength );
1192 : }
1193 : else
1194 0 : nIndentPrefix = getIndentPrefixLength(nLength);
1195 :
1196 : // insert indentation
1197 0 : if( nIndentPrefix >= 0 )
1198 : {
1199 0 : if( isFirstCharWhitespace( aChars.getStr() ) )
1200 0 : m_pSaxWriterHelper->insertIndentation( nIndentPrefix - 1 );
1201 : else
1202 0 : m_pSaxWriterHelper->insertIndentation( nIndentPrefix );
1203 : }
1204 0 : bThrowException = !m_pSaxWriterHelper->writeString(aChars, true , false);
1205 : }
1206 : }
1207 0 : if (bThrowException)
1208 : {
1209 0 : SAXInvalidCharacterException except;
1210 0 : except.Message = "Invalid character during XML-Export";
1211 0 : throw except;
1212 : }
1213 0 : }
1214 :
1215 :
1216 0 : void SAXWriter::ignorableWhitespace(const OUString&) throw(SAXException, RuntimeException, std::exception)
1217 : {
1218 0 : if( ! m_bDocStarted )
1219 : {
1220 0 : throw SAXException ();
1221 : }
1222 :
1223 0 : m_bForceLineBreak = true;
1224 0 : }
1225 :
1226 0 : void SAXWriter::processingInstruction(const OUString& aTarget, const OUString& aData)
1227 : throw (SAXException, RuntimeException, std::exception)
1228 : {
1229 0 : if( ! m_bDocStarted || m_bIsCDATA )
1230 : {
1231 0 : throw SAXException();
1232 : }
1233 :
1234 0 : sal_Int32 nLength(0);
1235 0 : if (m_bAllowLineBreak)
1236 : {
1237 0 : nLength = 2; // "<?"
1238 0 : nLength += calcXMLByteLength( aTarget.getStr(), aTarget.getLength(), false, false );
1239 :
1240 0 : nLength += 1; // " "
1241 :
1242 0 : nLength += calcXMLByteLength( aData.getStr(), aData.getLength(), false, false );
1243 :
1244 0 : nLength += 2; // "?>"
1245 : }
1246 :
1247 0 : sal_Int32 nPrefix = getIndentPrefixLength( nLength );
1248 :
1249 0 : if( nPrefix >= 0 )
1250 0 : m_pSaxWriterHelper->insertIndentation( nPrefix );
1251 :
1252 0 : if (!m_pSaxWriterHelper->processingInstruction(aTarget, aData))
1253 : {
1254 0 : SAXException except;
1255 0 : except.Message = "Invalid character during XML-Export";
1256 0 : throw except;
1257 : }
1258 0 : }
1259 :
1260 :
1261 0 : void SAXWriter::setDocumentLocator(const Reference< XLocator >&)
1262 : throw (SAXException, RuntimeException, std::exception)
1263 : {
1264 :
1265 0 : }
1266 :
1267 0 : void SAXWriter::startCDATA(void) throw(SAXException, RuntimeException, std::exception)
1268 : {
1269 0 : if( ! m_bDocStarted || m_bIsCDATA)
1270 : {
1271 0 : throw SAXException ();
1272 : }
1273 :
1274 0 : sal_Int32 nLength = 9;
1275 0 : sal_Int32 nPrefix = getIndentPrefixLength( nLength );
1276 0 : if( nPrefix >= 0 )
1277 0 : m_pSaxWriterHelper->insertIndentation( nPrefix );
1278 :
1279 0 : m_pSaxWriterHelper->startCDATA();
1280 :
1281 0 : m_bIsCDATA = true;
1282 0 : }
1283 :
1284 0 : void SAXWriter::endCDATA(void) throw (SAXException,RuntimeException, std::exception)
1285 : {
1286 0 : if( ! m_bDocStarted || ! m_bIsCDATA)
1287 : {
1288 0 : SAXException except;
1289 0 : except.Message = "endCDATA was called without startCDATA";
1290 0 : throw except;
1291 : }
1292 :
1293 0 : sal_Int32 nLength = 3;
1294 0 : sal_Int32 nPrefix = getIndentPrefixLength( nLength );
1295 0 : if( nPrefix >= 0 )
1296 0 : m_pSaxWriterHelper->insertIndentation( nPrefix );
1297 :
1298 0 : m_pSaxWriterHelper->endCDATA();
1299 :
1300 0 : m_bIsCDATA = false;
1301 0 : }
1302 :
1303 :
1304 0 : void SAXWriter::comment(const OUString& sComment) throw(SAXException, RuntimeException, std::exception)
1305 : {
1306 0 : if( ! m_bDocStarted || m_bIsCDATA )
1307 : {
1308 0 : throw SAXException();
1309 : }
1310 :
1311 0 : sal_Int32 nLength(0);
1312 0 : if (m_bAllowLineBreak)
1313 : {
1314 0 : nLength = 4; // "<!--"
1315 0 : nLength += calcXMLByteLength( sComment.getStr(), sComment.getLength(), false, false);
1316 :
1317 0 : nLength += 3;
1318 : }
1319 :
1320 0 : sal_Int32 nPrefix = getIndentPrefixLength( nLength );
1321 0 : if( nPrefix >= 0 )
1322 0 : m_pSaxWriterHelper->insertIndentation( nPrefix );
1323 :
1324 0 : if (!m_pSaxWriterHelper->comment(sComment))
1325 : {
1326 0 : SAXException except;
1327 0 : except.Message = "Invalid character during XML-Export";
1328 0 : throw except;
1329 : }
1330 0 : }
1331 :
1332 :
1333 0 : void SAXWriter::allowLineBreak( ) throw ( SAXException , RuntimeException, std::exception)
1334 : {
1335 0 : if( ! m_bDocStarted || m_bAllowLineBreak ) {
1336 0 : throw SAXException();
1337 : }
1338 :
1339 0 : m_bAllowLineBreak = true;
1340 0 : }
1341 :
1342 0 : void SAXWriter::unknown(const OUString& sString) throw (SAXException, RuntimeException, std::exception)
1343 : {
1344 :
1345 0 : if( ! m_bDocStarted )
1346 : {
1347 0 : throw SAXException ();
1348 : }
1349 0 : if( m_bIsCDATA )
1350 : {
1351 0 : throw SAXException();
1352 : }
1353 :
1354 0 : if( sString.matchAsciiL( "<?xml", 5 ) )
1355 0 : return;
1356 :
1357 0 : sal_Int32 nLength(0);
1358 0 : if (m_bAllowLineBreak)
1359 0 : nLength = calcXMLByteLength( sString.getStr(), sString.getLength(), false, false );
1360 :
1361 0 : sal_Int32 nPrefix = getIndentPrefixLength( nLength );
1362 0 : if( nPrefix >= 0 )
1363 0 : m_pSaxWriterHelper->insertIndentation( nPrefix );
1364 :
1365 0 : if (!m_pSaxWriterHelper->writeString( sString, false, false))
1366 : {
1367 0 : SAXException except;
1368 0 : except.Message = "Invalid character during XML-Export";
1369 0 : throw except;
1370 : }
1371 : }
1372 :
1373 : } // namespace
1374 :
1375 : extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * SAL_CALL
1376 0 : com_sun_star_extensions_xml_sax_Writer_get_implementation(
1377 : css::uno::XComponentContext *,
1378 : css::uno::Sequence<css::uno::Any> const &)
1379 : {
1380 0 : return cppu::acquire(new SAXWriter);
1381 : }
1382 :
1383 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|