1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23 #include <string.h>
24
25 #include <com/sun/star/lang/XServiceInfo.hpp>
26 #include <com/sun/star/util/XCloneable.hpp>
27 #include <com/sun/star/xml/sax/XExtendedDocumentHandler.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
32 #include <com/sun/star/io/XActiveDataSource.hpp>
33
34 #include <cppuhelper/factory.hxx>
35 #include <cppuhelper/weak.hxx>
36 #include <cppuhelper/implbase3.hxx>
37
38 #include <rtl/strbuf.hxx>
39 #include <rtl/byteseq.hxx>
40 #include <rtl/ustrbuf.hxx>
41
42 using namespace ::rtl;
43 using namespace ::std;
44 using namespace ::osl;
45 using namespace ::cppu;
46 using namespace ::com::sun::star::uno;
47 using namespace ::com::sun::star::lang;
48 using namespace ::com::sun::star::registry;
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 "factory.hxx"
54 #include "xml2utf.hxx"
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 sax_expatwrap {
69 /*****
70 *
71 * Calculates the length of the sequence after conversion, but the conversion is not done.
72 * .g. &<>"' plus some more are
73 * special characters in XML that need to be transformed
74 *
75 * @param bConvertAll For Attributes it is necessary to convert every symbol (including line feed and tab)
76 * Set this to true, if you want to perform this special conversion
77 * @return The returned value is equal to the length of the incoming sequence, when no
78 + conversion is necessary, otherwise it is larger than the length of the sequence.
79 ****/
80 // inline sal_Int32 CalcXMLLen( const Sequence<sal_Int8> & seq , sal_Bool bConvertAll ) throw()
81 // {
82 // sal_Int32 nLen = 0;
83 // const sal_Int8 *pArray = seq.getConstArray();
84
85 // for( int i = 0 ; i < seq.getLength() ; i ++ ) {
86
87 // sal_Int8 c = pArray[i];
88 // switch( c )
89 // {
90 // case '&': // resemble to &
91 // nLen +=5;
92 // break;
93 // case '<': // <
94 // case '>': // >
95 // nLen +=4;
96 // break;
97 // case 39: // 39 == ''', '
98 // case '"': // "
99 // case 13: // 
100 // nLen += 6;
101 // break;
102
103 // case 10: // 

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

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