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() throw( SAXException );
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) throw( SAXException );
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) throw( SAXException );
149 inline void FinishStartElement() throw( SAXException );
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) throw( SAXException );
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) throw( SAXException );
176
GetLastColumnCount()177 sal_uInt32 GetLastColumnCount() { return (sal_uInt32)(nCurrentPos - nLastLineFeedPos); }
178
179 inline void startDocument() throw( SAXException );
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) throw( SAXException );
185 inline sal_Bool FinishEmptyElement() throw( SAXException );
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) throw( SAXException );
191 inline void endDocument() throw( SAXException );
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) throw( SAXException );
197 inline void startCDATA() throw( SAXException );
198 inline void endCDATA() throw( SAXException );
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) throw( SAXException );
204
205 inline void clearBuffer() throw( SAXException );
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() throw( SAXException )
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) throw( SAXException )
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 ) throw( SAXException )
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() throw( SAXException )
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) throw( SAXException )
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 ) throw( SAXException )
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() throw( SAXException )
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) throw( SAXException )
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() throw( SAXException )
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) throw( SAXException )
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() throw( SAXException )
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() throw( SAXException )
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) throw( SAXException )
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() throw( SAXException )
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() throw( SAXException )
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) throw( SAXException )
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 throw (RuntimeException)
937 {
938 // temporary: set same stream again to clear buffer
939 if ( m_out == aStream && mp_SaxWriterHelper && m_bDocStarted )
940 mp_SaxWriterHelper->clearBuffer();
941 else
942 {
943
944 m_out = aStream;
945 delete mp_SaxWriterHelper;
946 mp_SaxWriterHelper = new SaxWriterHelper(m_out);
947 m_bDocStarted = sal_False;
948 m_nLevel = 0;
949 m_bIsCDATA = sal_False;
950
951 }
952 }
getOutputStream(void)953 virtual Reference< XOutputStream > SAL_CALL getOutputStream(void)
954 throw(RuntimeException)
955 { return m_out; }
956
957 public: // XDocumentHandler
958 virtual void SAL_CALL startDocument(void)
959 throw(SAXException, RuntimeException);
960
961 virtual void SAL_CALL endDocument(void)
962 throw(SAXException, RuntimeException);
963
964 virtual void SAL_CALL startElement(const OUString& aName,
965 const Reference< XAttributeList > & xAttribs)
966 throw (SAXException, RuntimeException);
967
968 virtual void SAL_CALL endElement(const OUString& aName)
969 throw(SAXException, RuntimeException);
970
971 virtual void SAL_CALL characters(const OUString& aChars)
972 throw(SAXException, RuntimeException);
973
974 virtual void SAL_CALL ignorableWhitespace(const OUString& aWhitespaces)
975 throw(SAXException, RuntimeException);
976 virtual void SAL_CALL processingInstruction(const OUString& aTarget,
977 const OUString& aData)
978 throw(SAXException, RuntimeException);
979 virtual void SAL_CALL setDocumentLocator(const Reference< XLocator > & xLocator)
980 throw(SAXException, RuntimeException);
981
982 public: // XExtendedDocumentHandler
983 virtual void SAL_CALL startCDATA(void) throw(SAXException, RuntimeException);
984 virtual void SAL_CALL endCDATA(void) throw(RuntimeException);
985 virtual void SAL_CALL comment(const OUString& sComment)
986 throw(SAXException, RuntimeException);
987 virtual void SAL_CALL unknown(const OUString& sString)
988 throw(SAXException, RuntimeException);
989 virtual void SAL_CALL allowLineBreak(void)
990 throw(SAXException,RuntimeException);
991
992 public: // XServiceInfo
993 OUString SAL_CALL getImplementationName() throw();
994 Sequence< OUString > SAL_CALL getSupportedServiceNames(void) throw();
995 sal_Bool SAL_CALL supportsService(const OUString& ServiceName) throw();
996
997 private:
998
999 void writeSequence( const Sequence<sal_Int8> & seq );
1000 sal_Int32 getIndentPrefixLength( sal_Int32 nFirstLineBreakOccurence ) throw();
1001
1002 Reference< XOutputStream > m_out;
1003 Sequence < sal_Int8 > m_seqStartElement;
1004 SaxWriterHelper* mp_SaxWriterHelper;
1005
1006 // Status information
1007 sal_Bool m_bDocStarted : 1;
1008 sal_Bool m_bIsCDATA : 1;
1009 sal_Bool m_bForceLineBreak : 1;
1010 sal_Bool m_bAllowLineBreak : 1;
1011 sal_Int32 m_nLevel;
1012 };
1013
1014
1015 //--------------------------------------
1016 // the extern interface
1017 //---------------------------------------
SaxWriter_CreateInstance(const Reference<XMultiServiceFactory> &)1018 Reference < XInterface > SAL_CALL SaxWriter_CreateInstance(
1019 const Reference < XMultiServiceFactory > & )
1020 throw (Exception)
1021 {
1022 SAXWriter *p = new SAXWriter;
1023 return Reference< XInterface > ( SAL_STATIC_CAST(OWeakObject *, p ) );
1024 }
1025
SaxWriter_getServiceName()1026 OUString SaxWriter_getServiceName() throw()
1027 {
1028 return OUString::createFromAscii( "com.sun.star.xml.sax.Writer" );
1029 }
1030
SaxWriter_getImplementationName()1031 OUString SaxWriter_getImplementationName() throw()
1032 {
1033 return OUString::createFromAscii( "com.sun.star.extensions.xml.sax.Writer" );
1034 }
1035
SaxWriter_getSupportedServiceNames(void)1036 Sequence< OUString > SaxWriter_getSupportedServiceNames(void) throw()
1037 {
1038 Sequence<OUString> aRet(1);
1039 aRet.getArray()[0] = SaxWriter_getServiceName();
1040 return aRet;
1041 }
1042
1043
getIndentPrefixLength(sal_Int32 nFirstLineBreakOccurence)1044 sal_Int32 SAXWriter::getIndentPrefixLength( sal_Int32 nFirstLineBreakOccurence ) throw()
1045 {
1046 sal_Int32 nLength =-1;
1047 if (mp_SaxWriterHelper)
1048 {
1049 if ( m_bForceLineBreak ||
1050 (m_bAllowLineBreak &&
1051 ((nFirstLineBreakOccurence + mp_SaxWriterHelper->GetLastColumnCount()) > MAXCOLUMNCOUNT)) )
1052 nLength = m_nLevel;
1053 }
1054 m_bForceLineBreak = sal_False;
1055 m_bAllowLineBreak = sal_False;
1056 return nLength;
1057 }
1058
isFirstCharWhitespace(const sal_Unicode * p)1059 static inline sal_Bool isFirstCharWhitespace( const sal_Unicode *p ) throw()
1060 {
1061 return *p == ' ';
1062 }
1063
1064
1065 // XServiceInfo
getImplementationName()1066 OUString SAXWriter::getImplementationName() throw()
1067 {
1068 return SaxWriter_getImplementationName();
1069 }
1070
1071 // XServiceInfo
supportsService(const OUString & ServiceName)1072 sal_Bool SAXWriter::supportsService(const OUString& ServiceName) throw()
1073 {
1074 Sequence< OUString > aSNL = getSupportedServiceNames();
1075 const OUString * pArray = aSNL.getConstArray();
1076
1077 for( sal_Int32 i = 0; i < aSNL.getLength(); i++ )
1078 if( pArray[i] == ServiceName )
1079 return sal_True;
1080
1081 return sal_False;
1082 }
1083
1084 // XServiceInfo
getSupportedServiceNames(void)1085 Sequence< OUString > SAXWriter::getSupportedServiceNames(void) throw ()
1086 {
1087 Sequence<OUString> seq(1);
1088 seq.getArray()[0] = SaxWriter_getServiceName();
1089 return seq;
1090 }
1091
1092
1093
startDocument()1094 void SAXWriter::startDocument() throw(SAXException, RuntimeException )
1095 {
1096 if( m_bDocStarted || ! m_out.is() || !mp_SaxWriterHelper ) {
1097 throw SAXException();
1098 }
1099 m_bDocStarted = sal_True;
1100 mp_SaxWriterHelper->startDocument();
1101 }
1102
1103
endDocument(void)1104 void SAXWriter::endDocument(void) throw(SAXException, RuntimeException)
1105 {
1106 if( ! m_bDocStarted )
1107 {
1108 throw SAXException(
1109 OUString::createFromAscii( "endDocument called before startDocument" ),
1110 Reference< XInterface >() , Any() );
1111 }
1112 if( m_nLevel ) {
1113 throw SAXException(
1114 OUString::createFromAscii( "unexpected end of document" ),
1115 Reference< XInterface >() , Any() );
1116 }
1117 mp_SaxWriterHelper->endDocument();
1118 try
1119 {
1120 m_out->closeOutput();
1121 }
1122 catch( IOException & e )
1123 {
1124 Any a;
1125 a <<= e;
1126 throw SAXException(
1127 OUString::createFromAscii( "IO exception during closing the IO Stream" ),
1128 Reference< XInterface > (),
1129 a );
1130 }
1131 }
1132
1133
startElement(const OUString & aName,const Reference<XAttributeList> & xAttribs)1134 void SAXWriter::startElement(const OUString& aName, const Reference< XAttributeList >& xAttribs)
1135 throw(SAXException, RuntimeException)
1136 {
1137 if( ! m_bDocStarted )
1138 {
1139 SAXException except;
1140 except.Message = OUString( RTL_CONSTASCII_USTRINGPARAM( "startElement called before startDocument" ));
1141 throw except;
1142 }
1143 if( m_bIsCDATA )
1144 {
1145 SAXException except;
1146 except.Message = OUString( RTL_CONSTASCII_USTRINGPARAM( "startElement call not allowed with CDATA sections" ));
1147 throw except;
1148 }
1149
1150 sal_Int32 nLength(0);
1151 if (m_bAllowLineBreak)
1152 {
1153 sal_Int32 nAttribCount = xAttribs.is() ? xAttribs->getLength() : 0;
1154
1155 nLength ++; // "<"
1156 nLength += calcXMLByteLength( aName.getStr() , aName.getLength(),
1157 sal_False, sal_False ); // the tag name
1158
1159 sal_Int16 n;
1160 for( n = 0 ; n < static_cast<sal_Int16>(nAttribCount) ; n ++ ) {
1161 nLength ++; // " "
1162 OUString tmp = xAttribs->getNameByIndex( n );
1163
1164 nLength += calcXMLByteLength( tmp.getStr() , tmp.getLength() , sal_False, sal_False );
1165
1166 nLength += 2; // ="
1167
1168 tmp = xAttribs->getValueByIndex( n );
1169
1170 nLength += calcXMLByteLength( tmp.getStr(), tmp.getLength(), sal_True, sal_True );
1171
1172 nLength += 1; // "
1173 }
1174
1175 nLength ++; // '>'
1176 }
1177
1178 // Is there a new indentation necesarry ?
1179 sal_Int32 nPrefix(getIndentPrefixLength( nLength ));
1180
1181 // write into sequence
1182 if( nPrefix >= 0 )
1183 mp_SaxWriterHelper->insertIndentation( nPrefix );
1184
1185 SaxInvalidCharacterError eRet(mp_SaxWriterHelper->startElement(aName, xAttribs));
1186
1187 m_nLevel++;
1188
1189 if (eRet == SAX_WARNING)
1190 {
1191 SAXInvalidCharacterException except;
1192 except.Message = OUString( RTL_CONSTASCII_USTRINGPARAM( "Invalid charcter during XML-Export in a attribute value" ) );
1193 throw except;
1194 }
1195 else if (eRet == SAX_ERROR)
1196 {
1197 SAXException except;
1198 except.Message = OUString( RTL_CONSTASCII_USTRINGPARAM( "Invalid charcter during XML-Export" ) );
1199 throw except;
1200 }
1201 }
1202
endElement(const OUString & aName)1203 void SAXWriter::endElement(const OUString& aName) throw (SAXException, RuntimeException)
1204 {
1205 if( ! m_bDocStarted ) {
1206 throw SAXException ();
1207 }
1208 m_nLevel --;
1209
1210 if( m_nLevel < 0 ) {
1211 throw SAXException();
1212 }
1213 sal_Bool bRet(sal_True);
1214
1215 if( mp_SaxWriterHelper->FinishEmptyElement() )
1216 m_bForceLineBreak = sal_False;
1217 else
1218 {
1219 // only ascii chars allowed
1220 sal_Int32 nLength(0);
1221 if (m_bAllowLineBreak)
1222 nLength = 3 + calcXMLByteLength( aName.getStr(), aName.getLength(), sal_False, sal_False );
1223 sal_Int32 nPrefix = getIndentPrefixLength( nLength );
1224
1225 if( nPrefix >= 0 )
1226 mp_SaxWriterHelper->insertIndentation( nPrefix );
1227
1228 bRet = mp_SaxWriterHelper->endElement(aName);
1229 }
1230
1231 if (!bRet)
1232 {
1233 SAXException except;
1234 except.Message = OUString( RTL_CONSTASCII_USTRINGPARAM( "Invalid charcter during XML-Export" ) );
1235 throw except;
1236 }
1237 }
1238
characters(const OUString & aChars)1239 void SAXWriter::characters(const OUString& aChars) throw(SAXException, RuntimeException)
1240 {
1241 if( ! m_bDocStarted )
1242 {
1243 SAXException except;
1244 except.Message = OUString( RTL_CONSTASCII_USTRINGPARAM( "characters method called before startDocument" ) );
1245 throw except;
1246 }
1247
1248 sal_Bool bThrowException(sal_False);
1249 if( aChars.getLength() )
1250 {
1251 if( m_bIsCDATA )
1252 bThrowException = !mp_SaxWriterHelper->writeString( aChars, sal_False, sal_False );
1253 else
1254 {
1255 // Note : nFirstLineBreakOccurence is not exact, because we don't know, how
1256 // many 2 and 3 byte chars are inbetween. However this whole stuff
1257 // is eitherway for pretty printing only, so it does not need to be exact.
1258 sal_Int32 nLength(0);
1259 sal_Int32 nIndentPrefix(-1);
1260 if (m_bAllowLineBreak)
1261 {
1262 sal_Int32 nFirstLineBreakOccurence = getFirstLineBreak( aChars );
1263
1264 nLength = calcXMLByteLength( aChars.getStr(), aChars.getLength(),
1265 ! m_bIsCDATA , sal_False );
1266 nIndentPrefix = getIndentPrefixLength(
1267 nFirstLineBreakOccurence >= 0 ? nFirstLineBreakOccurence : nLength );
1268 }
1269 else
1270 nIndentPrefix = getIndentPrefixLength(nLength);
1271
1272 // insert indentation
1273 if( nIndentPrefix >= 0 )
1274 {
1275 if( isFirstCharWhitespace( aChars.getStr() ) )
1276 mp_SaxWriterHelper->insertIndentation( nIndentPrefix - 1 );
1277 else
1278 mp_SaxWriterHelper->insertIndentation( nIndentPrefix );
1279 }
1280 bThrowException = !mp_SaxWriterHelper->writeString(aChars, sal_True , sal_False);
1281 }
1282 }
1283 if (bThrowException)
1284 {
1285 SAXInvalidCharacterException except;
1286 except.Message = OUString( RTL_CONSTASCII_USTRINGPARAM( "Invalid charcter during XML-Export" ) );
1287 throw except;
1288 }
1289 }
1290
1291
ignorableWhitespace(const OUString &)1292 void SAXWriter::ignorableWhitespace(const OUString&) throw(SAXException, RuntimeException)
1293 {
1294 if( ! m_bDocStarted )
1295 {
1296 throw SAXException ();
1297 }
1298
1299 m_bForceLineBreak = sal_True;
1300 }
1301
processingInstruction(const OUString & aTarget,const OUString & aData)1302 void SAXWriter::processingInstruction(const OUString& aTarget, const OUString& aData)
1303 throw (SAXException, RuntimeException)
1304 {
1305 if( ! m_bDocStarted || m_bIsCDATA )
1306 {
1307 throw SAXException();
1308 }
1309
1310 sal_Int32 nLength(0);
1311 if (m_bAllowLineBreak)
1312 {
1313 nLength = 2; // "<?"
1314 nLength += calcXMLByteLength( aTarget.getStr(), aTarget.getLength(), sal_False, sal_False );
1315
1316 nLength += 1; // " "
1317
1318 nLength += calcXMLByteLength( aData.getStr(), aData.getLength(), sal_False, sal_False );
1319
1320 nLength += 2; // "?>"
1321 }
1322
1323 sal_Int32 nPrefix = getIndentPrefixLength( nLength );
1324
1325 if( nPrefix >= 0 )
1326 mp_SaxWriterHelper->insertIndentation( nPrefix );
1327
1328 if (!mp_SaxWriterHelper->processingInstruction(aTarget, aData))
1329 {
1330 SAXException except;
1331 except.Message = OUString( RTL_CONSTASCII_USTRINGPARAM( "Invalid charcter during XML-Export" ) );
1332 throw except;
1333 }
1334 }
1335
1336
setDocumentLocator(const Reference<XLocator> &)1337 void SAXWriter::setDocumentLocator(const Reference< XLocator >&)
1338 throw (SAXException, RuntimeException)
1339 {
1340
1341 }
1342
startCDATA(void)1343 void SAXWriter::startCDATA(void) throw(SAXException, RuntimeException)
1344 {
1345 if( ! m_bDocStarted || m_bIsCDATA)
1346 {
1347 throw SAXException ();
1348 }
1349
1350 sal_Int32 nLength = 9;
1351 sal_Int32 nPrefix = getIndentPrefixLength( nLength );
1352 if( nPrefix >= 0 )
1353 mp_SaxWriterHelper->insertIndentation( nPrefix );
1354
1355 mp_SaxWriterHelper->startCDATA();
1356
1357 m_bIsCDATA = sal_True;
1358 }
1359
endCDATA(void)1360 void SAXWriter::endCDATA(void) throw (RuntimeException)
1361 {
1362 if( ! m_bDocStarted | ! m_bIsCDATA)
1363 {
1364 SAXException except;
1365 except.Message = OUString( RTL_CONSTASCII_USTRINGPARAM( "endCDATA was called without startCDATA" ) );
1366 throw except;
1367 }
1368
1369 sal_Int32 nLength = 3;
1370 sal_Int32 nPrefix = getIndentPrefixLength( nLength );
1371 if( nPrefix >= 0 )
1372 mp_SaxWriterHelper->insertIndentation( nPrefix );
1373
1374 mp_SaxWriterHelper->endCDATA();
1375
1376 m_bIsCDATA = sal_False;
1377 }
1378
1379
comment(const OUString & sComment)1380 void SAXWriter::comment(const OUString& sComment) throw(SAXException, RuntimeException)
1381 {
1382 if( ! m_bDocStarted || m_bIsCDATA )
1383 {
1384 throw SAXException();
1385 }
1386
1387 sal_Int32 nLength(0);
1388 if (m_bAllowLineBreak)
1389 {
1390 nLength = 4; // "<!--"
1391 nLength += calcXMLByteLength( sComment.getStr(), sComment.getLength(), sal_False, sal_False);
1392
1393 nLength += 3;
1394 }
1395
1396 sal_Int32 nPrefix = getIndentPrefixLength( nLength );
1397 if( nPrefix >= 0 )
1398 mp_SaxWriterHelper->insertIndentation( nPrefix );
1399
1400 if (!mp_SaxWriterHelper->comment(sComment))
1401 {
1402 SAXException except;
1403 except.Message = OUString( RTL_CONSTASCII_USTRINGPARAM( "Invalid charcter during XML-Export" ) );
1404 throw except;
1405 }
1406 }
1407
1408
allowLineBreak()1409 void SAXWriter::allowLineBreak( ) throw ( SAXException , RuntimeException)
1410 {
1411 if( ! m_bDocStarted || m_bAllowLineBreak ) {
1412 throw SAXException();
1413 }
1414
1415 m_bAllowLineBreak = sal_True;
1416 }
1417
unknown(const OUString & sString)1418 void SAXWriter::unknown(const OUString& sString) throw (SAXException, RuntimeException)
1419 {
1420
1421 if( ! m_bDocStarted )
1422 {
1423 throw SAXException ();
1424 }
1425 if( m_bIsCDATA )
1426 {
1427 throw SAXException();
1428 }
1429
1430 if( sString.matchAsciiL( "<?xml", 5 ) )
1431 return;
1432
1433 sal_Int32 nLength(0);
1434 if (m_bAllowLineBreak)
1435 nLength = calcXMLByteLength( sString.getStr(), sString.getLength(), sal_False, sal_False );
1436
1437 sal_Int32 nPrefix = getIndentPrefixLength( nLength );
1438 if( nPrefix >= 0 )
1439 mp_SaxWriterHelper->insertIndentation( nPrefix );
1440
1441 if (!mp_SaxWriterHelper->writeString( sString, sal_False, sal_False))
1442 {
1443 SAXException except;
1444 except.Message = OUString( RTL_CONSTASCII_USTRINGPARAM( "Invalid charcter during XML-Export" ) );
1445 throw except;
1446 }
1447 }
1448
1449 }
1450
1451