1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 #include <string.h> 28 29 #include <com/sun/star/lang/XServiceInfo.hpp> 30 #include <com/sun/star/util/XCloneable.hpp> 31 #include <com/sun/star/xml/sax/XExtendedDocumentHandler.hpp> 32 #include <com/sun/star/xml/sax/XParser.hpp> 33 #include <com/sun/star/xml/sax/SAXParseException.hpp> 34 #include <com/sun/star/xml/sax/SAXInvalidCharacterException.hpp> 35 36 #include <com/sun/star/io/XActiveDataSource.hpp> 37 38 #include <cppuhelper/factory.hxx> 39 #include <cppuhelper/weak.hxx> 40 #include <cppuhelper/implbase3.hxx> 41 42 #include <rtl/strbuf.hxx> 43 #include <rtl/byteseq.hxx> 44 #include <rtl/ustrbuf.hxx> 45 46 using namespace ::rtl; 47 using namespace ::std; 48 using namespace ::osl; 49 using namespace ::cppu; 50 using namespace ::com::sun::star::uno; 51 using namespace ::com::sun::star::lang; 52 using namespace ::com::sun::star::registry; 53 using namespace ::com::sun::star::xml::sax; 54 using namespace ::com::sun::star::util; 55 using namespace ::com::sun::star::io; 56 57 #include "factory.hxx" 58 #include "xml2utf.hxx" 59 60 #define LINEFEED 10 61 #define SEQUENCESIZE 1024 62 #define MAXCOLUMNCOUNT 72 63 64 /****** 65 * 66 * 67 * Character conversion functions 68 * 69 * 70 *****/ 71 72 namespace sax_expatwrap { 73 /***** 74 * 75 * Calculates the length of the sequence after conversion, but the conversion is not done. 76 * .g. &<>"' plus some more are 77 * special characters in XML that need to be transformed 78 * 79 * @param bConvertAll For Attributes it is necessary to convert every symbol (including line feed and tab) 80 * Set this to true, if you want to perform this special conversion 81 * @return The returned value is equal to the length of the incoming sequence, when no 82 + conversion is necessary, otherwise it is larger than the length of the sequence. 83 ****/ 84 // inline sal_Int32 CalcXMLLen( const Sequence<sal_Int8> & seq , sal_Bool bConvertAll ) throw() 85 // { 86 // sal_Int32 nLen = 0; 87 // const sal_Int8 *pArray = seq.getConstArray(); 88 89 // for( int i = 0 ; i < seq.getLength() ; i ++ ) { 90 91 // sal_Int8 c = pArray[i]; 92 // switch( c ) 93 // { 94 // case '&': // resemble to & 95 // nLen +=5; 96 // break; 97 // case '<': // < 98 // case '>': // > 99 // nLen +=4; 100 // break; 101 // case 39: // 39 == ''', ' 102 // case '"': // " 103 // case 13: // 
 104 // nLen += 6; 105 // break; 106 107 // case 10: // 
 108 // case 9: // 	 109 // if( bConvertAll ) 110 // { 111 // nLen += 6; // 112 // } 113 // break; 114 // default: 115 // nLen ++; 116 // } 117 // } 118 119 // return nLen; 120 // } 121 122 enum SaxInvalidCharacterError 123 { 124 SAX_NONE, 125 SAX_WARNING, 126 SAX_ERROR 127 }; 128 129 class SaxWriterHelper 130 { 131 Reference< XOutputStream > m_out; 132 Sequence < sal_Int8 > m_Sequence; 133 sal_Int8* mp_Sequence; 134 135 sal_Int32 nLastLineFeedPos; // is negative after writing a sequence 136 sal_uInt32 nCurrentPos; 137 sal_Bool m_bStartElementFinished; 138 139 140 inline sal_uInt32 writeSequence() throw( SAXException ); 141 142 // use only if to insert the bytes more space in the sequence is needed and 143 // so the sequence has to write out and reset rPos to 0 144 // writes sequence only on overflow, sequence could be full on the end (rPos == SEQUENCESIZE) 145 inline void AddBytes(sal_Int8* pTarget, sal_uInt32& rPos, 146 const sal_Int8* pBytes, sal_uInt32 nBytesCount) throw( SAXException ); 147 inline sal_Bool convertToXML(const sal_Unicode * pStr, 148 sal_Int32 nStrLen, 149 sal_Bool bDoNormalization, 150 sal_Bool bNormalizeWhitespace, 151 sal_Int8 *pTarget, 152 sal_uInt32& rPos) throw( SAXException ); 153 inline void FinishStartElement() throw( SAXException ); 154 public: 155 SaxWriterHelper(Reference< XOutputStream > m_TempOut) : 156 m_out(m_TempOut), 157 m_Sequence(SEQUENCESIZE), 158 mp_Sequence(NULL), 159 nLastLineFeedPos(0), 160 nCurrentPos(0), 161 m_bStartElementFinished(sal_True) 162 { 163 OSL_ENSURE(SEQUENCESIZE > 50, "Sequence cache size to small"); 164 mp_Sequence = m_Sequence.getArray(); 165 } 166 ~SaxWriterHelper() 167 { 168 OSL_ENSURE(!nCurrentPos, "cached Sequence not written"); 169 OSL_ENSURE(m_bStartElementFinished, "StartElement not complettly written"); 170 } 171 172 inline void insertIndentation(sal_uInt32 m_nLevel) throw( SAXException ); 173 174 // returns whether it works correct or invalid characters were in the string 175 // If there are invalid characters in the string it returns sal_False. 176 // Than the calling method has to throw the needed Exception. 177 inline sal_Bool writeString(const rtl::OUString& rWriteOutString, 178 sal_Bool bDoNormalization, 179 sal_Bool bNormalizeWhitespace) throw( SAXException ); 180 181 sal_uInt32 GetLastColumnCount() { return (sal_uInt32)(nCurrentPos - nLastLineFeedPos); } 182 183 inline void startDocument() throw( SAXException ); 184 185 // returns whether it works correct or invalid characters were in the strings 186 // If there are invalid characters in one of the strings it returns sal_False. 187 // Than the calling method has to throw the needed Exception. 188 inline SaxInvalidCharacterError startElement(const rtl::OUString& rName, const Reference< XAttributeList >& xAttribs) throw( SAXException ); 189 inline sal_Bool FinishEmptyElement() throw( SAXException ); 190 191 // returns whether it works correct or invalid characters were in the string 192 // If there are invalid characters in the string it returns sal_False. 193 // Than the calling method has to throw the needed Exception. 194 inline sal_Bool endElement(const rtl::OUString& rName) throw( SAXException ); 195 inline void endDocument() throw( SAXException ); 196 197 // returns whether it works correct or invalid characters were in the strings 198 // If there are invalid characters in the string it returns sal_False. 199 // Than the calling method has to throw the needed Exception. 200 inline sal_Bool processingInstruction(const rtl::OUString& rTarget, const rtl::OUString& rData) throw( SAXException ); 201 inline void startCDATA() throw( SAXException ); 202 inline void endCDATA() throw( SAXException ); 203 204 // returns whether it works correct or invalid characters were in the strings 205 // If there are invalid characters in the string it returns sal_False. 206 // Than the calling method has to throw the needed Exception. 207 inline sal_Bool comment(const rtl::OUString& rComment) throw( SAXException ); 208 209 inline void clearBuffer() throw( SAXException ); 210 }; 211 212 const sal_Bool g_bValidCharsBelow32[32] = 213 { 214 // 0 1 2 3 4 5 6 7 215 0,0,0,0,0,0,0,0, //0 216 0,1,1,0,0,1,0,0, //8 217 0,0,0,0,0,0,0,0, //16 218 0,0,0,0,0,0,0,0 219 }; 220 221 inline sal_Bool IsInvalidChar(const sal_Unicode aChar) 222 { 223 sal_Bool bRet(sal_False); 224 // check first for the most common characters 225 if( aChar < 32 || aChar >= 0xd800 ) 226 bRet = ( (aChar < 32 && ! g_bValidCharsBelow32[aChar]) || 227 aChar == 0xffff || 228 aChar == 0xfffe ); 229 return bRet; 230 } 231 232 /******** 233 * write through to the output stream 234 * 235 *****/ 236 inline sal_uInt32 SaxWriterHelper::writeSequence() throw( SAXException ) 237 { 238 try 239 { 240 m_out->writeBytes( m_Sequence ); 241 } 242 catch( IOException & e ) 243 { 244 Any a; 245 a <<= e; 246 throw SAXException( 247 OUString::createFromAscii( "io exception during writing" ), 248 Reference< XInterface > (), 249 a ); 250 } 251 nLastLineFeedPos -= SEQUENCESIZE; 252 return 0; 253 } 254 255 inline void SaxWriterHelper::AddBytes(sal_Int8* pTarget, sal_uInt32& rPos, 256 const sal_Int8* pBytes, sal_uInt32 nBytesCount) throw( SAXException ) 257 { 258 OSL_ENSURE((rPos + nBytesCount) > SEQUENCESIZE, "wrong use of AddBytesMethod"); 259 sal_uInt32 nCount(SEQUENCESIZE - rPos); 260 memcpy( &(pTarget[rPos]) , pBytes, nCount); 261 262 OSL_ENSURE(rPos + nCount == SEQUENCESIZE, "the position should be the at the end"); 263 264 rPos = writeSequence(); 265 sal_uInt32 nRestCount(nBytesCount - nCount); 266 if ((rPos + nRestCount) <= SEQUENCESIZE) 267 { 268 memcpy( &(pTarget[rPos]), &pBytes[nCount], nRestCount); 269 rPos += nRestCount; 270 } 271 else 272 AddBytes(pTarget, rPos, &pBytes[nCount], nRestCount); 273 } 274 275 /** Converts an UTF16 string to UTF8 and does XML normalization 276 277 @param pTarget 278 Pointer to a piece of memory, to where the output should be written. The caller 279 must call calcXMLByteLength on the same string, to ensure, 280 that there is enough memory for converting. 281 */ 282 inline sal_Bool SaxWriterHelper::convertToXML( const sal_Unicode * pStr, 283 sal_Int32 nStrLen, 284 sal_Bool bDoNormalization, 285 sal_Bool bNormalizeWhitespace, 286 sal_Int8 *pTarget, 287 sal_uInt32& rPos ) throw( SAXException ) 288 { 289 sal_Bool bRet(sal_True); 290 sal_uInt32 nSurrogate = 0; 291 292 for( sal_Int32 i = 0 ; i < nStrLen ; i ++ ) 293 { 294 sal_uInt16 c = pStr[i]; 295 if (IsInvalidChar(c)) 296 bRet = sal_False; 297 else if( (c >= 0x0001) && (c <= 0x007F) ) 298 { 299 if( bDoNormalization ) 300 { 301 switch( c ) 302 { 303 case '&': // resemble to & 304 { 305 if ((rPos + 5) > SEQUENCESIZE) 306 AddBytes(pTarget, rPos, (sal_Int8*)"&", 5); 307 else 308 { 309 memcpy( &(pTarget[rPos]) , "&", 5 ); 310 rPos += 5; 311 } 312 } 313 break; 314 case '<': 315 { 316 if ((rPos + 4) > SEQUENCESIZE) 317 AddBytes(pTarget, rPos, (sal_Int8*)"<", 4); 318 else 319 { 320 memcpy( &(pTarget[rPos]) , "<" , 4 ); 321 rPos += 4; // < 322 } 323 } 324 break; 325 case '>': 326 { 327 if ((rPos + 4) > SEQUENCESIZE) 328 AddBytes(pTarget, rPos, (sal_Int8*)">", 4); 329 else 330 { 331 memcpy( &(pTarget[rPos]) , ">" , 4 ); 332 rPos += 4; // > 333 } 334 } 335 break; 336 case 39: // 39 == ''' 337 { 338 if ((rPos + 6) > SEQUENCESIZE) 339 AddBytes(pTarget, rPos, (sal_Int8*)"'", 6); 340 else 341 { 342 memcpy( &(pTarget[rPos]) , "'" , 6 ); 343 rPos += 6; // ' 344 } 345 } 346 break; 347 case '"': 348 { 349 if ((rPos + 6) > SEQUENCESIZE) 350 AddBytes(pTarget, rPos, (sal_Int8*)""", 6); 351 else 352 { 353 memcpy( &(pTarget[rPos]) , """ , 6 ); 354 rPos += 6; // " 355 } 356 } 357 break; 358 case 13: 359 { 360 if ((rPos + 6) > SEQUENCESIZE) 361 AddBytes(pTarget, rPos, (sal_Int8*)"
", 6); 362 else 363 { 364 memcpy( &(pTarget[rPos]) , "
" , 6 ); 365 rPos += 6; 366 } 367 } 368 break; 369 case LINEFEED: 370 { 371 if( bNormalizeWhitespace ) 372 { 373 if ((rPos + 6) > SEQUENCESIZE) 374 AddBytes(pTarget, rPos, (sal_Int8*)"
" , 6); 375 else 376 { 377 memcpy( &(pTarget[rPos]) , "
" , 6 ); 378 rPos += 6; 379 } 380 } 381 else 382 { 383 pTarget[rPos] = LINEFEED; 384 nLastLineFeedPos = rPos; 385 rPos ++; 386 } 387 } 388 break; 389 case 9: 390 { 391 if( bNormalizeWhitespace ) 392 { 393 if ((rPos + 6) > SEQUENCESIZE) 394 AddBytes(pTarget, rPos, (sal_Int8*)"	" , 6); 395 else 396 { 397 memcpy( &(pTarget[rPos]) , "	" , 6 ); 398 rPos += 6; 399 } 400 } 401 else 402 { 403 pTarget[rPos] = 9; 404 rPos ++; 405 } 406 } 407 break; 408 default: 409 { 410 pTarget[rPos] = (sal_Int8)c; 411 rPos ++; 412 } 413 break; 414 } 415 } 416 else 417 { 418 pTarget[rPos] = (sal_Int8)c; 419 if ((sal_Int8)c == LINEFEED) 420 nLastLineFeedPos = rPos; 421 rPos ++; 422 } 423 } 424 else if( c >= 0xd800 && c < 0xdc00 ) 425 { 426 // 1. surrogate: save (until 2. surrogate) 427 OSL_ENSURE( nSurrogate == 0, "left-over Unicode surrogate" ); 428 nSurrogate = ( ( c & 0x03ff ) + 0x0040 ); 429 } 430 else if( c >= 0xdc00 && c < 0xe000 ) 431 { 432 // 2. surrogate: write as UTF-8 433 OSL_ENSURE( nSurrogate != 0, "lone 2nd Unicode surrogate" ); 434 435 nSurrogate = ( nSurrogate << 10 ) | ( c & 0x03ff ); 436 if( nSurrogate >= 0x00010000 && nSurrogate <= 0x0010FFFF ) 437 { 438 sal_Int8 aBytes[] = { sal_Int8(0xF0 | ((nSurrogate >> 18) & 0x0F)), 439 sal_Int8(0x80 | ((nSurrogate >> 12) & 0x3F)), 440 sal_Int8(0x80 | ((nSurrogate >> 6) & 0x3F)), 441 sal_Int8(0x80 | ((nSurrogate >> 0) & 0x3F)) }; 442 if ((rPos + 4) > SEQUENCESIZE) 443 AddBytes(pTarget, rPos, aBytes, 4); 444 else 445 { 446 pTarget[rPos] = aBytes[0]; 447 rPos ++; 448 pTarget[rPos] = aBytes[1]; 449 rPos ++; 450 pTarget[rPos] = aBytes[2]; 451 rPos ++; 452 pTarget[rPos] = aBytes[3]; 453 rPos ++; 454 } 455 } 456 else 457 { 458 OSL_ENSURE( false, "illegal Unicode character" ); 459 bRet = sal_False; 460 } 461 462 // reset surrogate 463 nSurrogate = 0; 464 } 465 else if( c > 0x07FF ) 466 { 467 sal_Int8 aBytes[] = { sal_Int8(0xE0 | ((c >> 12) & 0x0F)), 468 sal_Int8(0x80 | ((c >> 6) & 0x3F)), 469 sal_Int8(0x80 | ((c >> 0) & 0x3F)) }; 470 if ((rPos + 3) > SEQUENCESIZE) 471 AddBytes(pTarget, rPos, aBytes, 3); 472 else 473 { 474 pTarget[rPos] = aBytes[0]; 475 rPos ++; 476 pTarget[rPos] = aBytes[1]; 477 rPos ++; 478 pTarget[rPos] = aBytes[2]; 479 rPos ++; 480 } 481 } 482 else 483 { 484 sal_Int8 aBytes[] = { sal_Int8(0xC0 | ((c >> 6) & 0x1F)), 485 sal_Int8(0x80 | ((c >> 0) & 0x3F)) }; 486 if ((rPos + 2) > SEQUENCESIZE) 487 AddBytes(pTarget, rPos, aBytes, 2); 488 else 489 { 490 pTarget[rPos] = aBytes[0]; 491 rPos ++; 492 pTarget[rPos] = aBytes[1]; 493 rPos ++; 494 } 495 } 496 OSL_ENSURE(rPos <= SEQUENCESIZE, "not reset current position"); 497 if (rPos == SEQUENCESIZE) 498 rPos = writeSequence(); 499 500 // reset left-over surrogate 501 if( ( nSurrogate != 0 ) && !( c >= 0xd800 && c < 0xdc00 ) ) 502 { 503 OSL_ENSURE( nSurrogate != 0, "left-over Unicode surrogate" ); 504 nSurrogate = 0; 505 bRet = sal_False; 506 } 507 } 508 return bRet; 509 } 510 511 inline void SaxWriterHelper::FinishStartElement() throw( SAXException ) 512 { 513 if (!m_bStartElementFinished) 514 { 515 mp_Sequence[nCurrentPos] = '>'; 516 nCurrentPos++; 517 if (nCurrentPos == SEQUENCESIZE) 518 nCurrentPos = writeSequence(); 519 m_bStartElementFinished = sal_True; 520 } 521 } 522 523 inline void SaxWriterHelper::insertIndentation(sal_uInt32 m_nLevel) throw( SAXException ) 524 { 525 FinishStartElement(); 526 if (m_nLevel > 0) 527 { 528 if ((nCurrentPos + m_nLevel + 1) <= SEQUENCESIZE) 529 { 530 mp_Sequence[nCurrentPos] = LINEFEED; 531 nLastLineFeedPos = nCurrentPos; 532 nCurrentPos++; 533 memset( &(mp_Sequence[nCurrentPos]) , 32 , m_nLevel ); 534 nCurrentPos += m_nLevel; 535 if (nCurrentPos == SEQUENCESIZE) 536 nCurrentPos = writeSequence(); 537 } 538 else 539 { 540 sal_uInt32 nCount(m_nLevel + 1); 541 sal_Int8* pBytes = new sal_Int8[nCount]; 542 pBytes[0] = LINEFEED; 543 memset( &(pBytes[1]), 32, m_nLevel ); 544 AddBytes(mp_Sequence, nCurrentPos, pBytes, nCount); 545 delete[] pBytes; 546 nLastLineFeedPos = nCurrentPos - nCount; 547 if (nCurrentPos == SEQUENCESIZE) 548 nCurrentPos = writeSequence(); 549 } 550 } 551 else 552 { 553 mp_Sequence[nCurrentPos] = LINEFEED; 554 nLastLineFeedPos = nCurrentPos; 555 nCurrentPos++; 556 if (nCurrentPos == SEQUENCESIZE) 557 nCurrentPos = writeSequence(); 558 } 559 } 560 561 inline sal_Bool SaxWriterHelper::writeString( const rtl::OUString& rWriteOutString, 562 sal_Bool bDoNormalization, 563 sal_Bool bNormalizeWhitespace ) throw( SAXException ) 564 { 565 FinishStartElement(); 566 return convertToXML(rWriteOutString.getStr(), 567 rWriteOutString.getLength(), 568 bDoNormalization, 569 bNormalizeWhitespace, 570 mp_Sequence, 571 nCurrentPos); 572 } 573 574 inline void SaxWriterHelper::startDocument() throw( SAXException ) 575 { 576 const char pc[] = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"; 577 const int nLen = strlen( pc ); 578 if ((nCurrentPos + nLen) <= SEQUENCESIZE) 579 { 580 memcpy( mp_Sequence, pc , nLen ); 581 nCurrentPos += nLen; 582 } 583 else 584 { 585 AddBytes(mp_Sequence, nCurrentPos, (sal_Int8*)pc, nLen); 586 } 587 OSL_ENSURE(nCurrentPos <= SEQUENCESIZE, "not reset current position"); 588 if (nCurrentPos == SEQUENCESIZE) 589 nCurrentPos = writeSequence(); 590 mp_Sequence[nCurrentPos] = LINEFEED; 591 nCurrentPos++; 592 if (nCurrentPos == SEQUENCESIZE) 593 nCurrentPos = writeSequence(); 594 } 595 596 inline SaxInvalidCharacterError SaxWriterHelper::startElement(const rtl::OUString& rName, const Reference< XAttributeList >& xAttribs) throw( SAXException ) 597 { 598 FinishStartElement(); 599 mp_Sequence[nCurrentPos] = '<'; 600 nCurrentPos++; 601 if (nCurrentPos == SEQUENCESIZE) 602 nCurrentPos = writeSequence(); 603 604 SaxInvalidCharacterError eRet(SAX_NONE); 605 if (!writeString(rName, sal_False, sal_False)) 606 eRet = SAX_ERROR; 607 608 sal_Int16 nAttribCount = xAttribs.is() ? static_cast<sal_Int16>(xAttribs->getLength()) : 0; 609 for(sal_Int16 i = 0 ; i < nAttribCount ; i++ ) 610 { 611 mp_Sequence[nCurrentPos] = ' '; 612 nCurrentPos++; 613 if (nCurrentPos == SEQUENCESIZE) 614 nCurrentPos = writeSequence(); 615 616 if (!writeString(xAttribs->getNameByIndex( i ), sal_False, sal_False)) 617 eRet = SAX_ERROR; 618 619 mp_Sequence[nCurrentPos] = '='; 620 nCurrentPos++; 621 if (nCurrentPos == SEQUENCESIZE) 622 nCurrentPos = writeSequence(); 623 mp_Sequence[nCurrentPos] = '"'; 624 nCurrentPos++; 625 if (nCurrentPos == SEQUENCESIZE) 626 nCurrentPos = writeSequence(); 627 628 if (!writeString(xAttribs->getValueByIndex( i ), sal_True, sal_True) && 629 !(eRet == SAX_ERROR)) 630 eRet = SAX_WARNING; 631 632 mp_Sequence[nCurrentPos] = '"'; 633 nCurrentPos++; 634 if (nCurrentPos == SEQUENCESIZE) 635 nCurrentPos = writeSequence(); 636 } 637 638 m_bStartElementFinished = sal_False; // because the '>' character is not added, 639 // because it is possible, that the "/>" 640 // characters have to add 641 return eRet; 642 } 643 644 inline sal_Bool SaxWriterHelper::FinishEmptyElement() throw( SAXException ) 645 { 646 if (m_bStartElementFinished) 647 return sal_False; 648 649 mp_Sequence[nCurrentPos] = '/'; 650 nCurrentPos++; 651 if (nCurrentPos == SEQUENCESIZE) 652 nCurrentPos = writeSequence(); 653 mp_Sequence[nCurrentPos] = '>'; 654 nCurrentPos++; 655 if (nCurrentPos == SEQUENCESIZE) 656 nCurrentPos = writeSequence(); 657 658 m_bStartElementFinished = sal_True; 659 660 return sal_True; 661 } 662 663 inline sal_Bool SaxWriterHelper::endElement(const rtl::OUString& rName) throw( SAXException ) 664 { 665 FinishStartElement(); 666 mp_Sequence[nCurrentPos] = '<'; 667 nCurrentPos++; 668 if (nCurrentPos == SEQUENCESIZE) 669 nCurrentPos = writeSequence(); 670 mp_Sequence[nCurrentPos] = '/'; 671 nCurrentPos++; 672 if (nCurrentPos == SEQUENCESIZE) 673 nCurrentPos = writeSequence(); 674 675 sal_Bool bRet(writeString( rName, sal_False, sal_False)); 676 677 mp_Sequence[nCurrentPos] = '>'; 678 nCurrentPos++; 679 if (nCurrentPos == SEQUENCESIZE) 680 nCurrentPos = writeSequence(); 681 682 return bRet; 683 } 684 685 inline void SaxWriterHelper::endDocument() throw( SAXException ) 686 { 687 if (nCurrentPos > 0) 688 { 689 m_Sequence.realloc(nCurrentPos); 690 nCurrentPos = writeSequence(); 691 //m_Sequence.realloc(SEQUENCESIZE); 692 } 693 } 694 695 inline void SaxWriterHelper::clearBuffer() throw( SAXException ) 696 { 697 FinishStartElement(); 698 if (nCurrentPos > 0) 699 { 700 m_Sequence.realloc(nCurrentPos); 701 nCurrentPos = writeSequence(); 702 m_Sequence.realloc(SEQUENCESIZE); 703 // Be sure to update the array pointer after the reallocation. 704 mp_Sequence = m_Sequence.getArray(); 705 } 706 } 707 708 inline sal_Bool SaxWriterHelper::processingInstruction(const rtl::OUString& rTarget, const rtl::OUString& rData) throw( SAXException ) 709 { 710 FinishStartElement(); 711 mp_Sequence[nCurrentPos] = '<'; 712 nCurrentPos++; 713 if (nCurrentPos == SEQUENCESIZE) 714 nCurrentPos = writeSequence(); 715 mp_Sequence[nCurrentPos] = '?'; 716 nCurrentPos++; 717 if (nCurrentPos == SEQUENCESIZE) 718 nCurrentPos = writeSequence(); 719 720 sal_Bool bRet(writeString( rTarget, sal_False, sal_False )); 721 722 mp_Sequence[nCurrentPos] = ' '; 723 nCurrentPos++; 724 if (nCurrentPos == SEQUENCESIZE) 725 nCurrentPos = writeSequence(); 726 727 if (!writeString( rData, sal_False, sal_False )) 728 bRet = sal_False; 729 730 mp_Sequence[nCurrentPos] = '?'; 731 nCurrentPos++; 732 if (nCurrentPos == SEQUENCESIZE) 733 nCurrentPos = writeSequence(); 734 mp_Sequence[nCurrentPos] = '>'; 735 nCurrentPos++; 736 if (nCurrentPos == SEQUENCESIZE) 737 nCurrentPos = writeSequence(); 738 739 return bRet; 740 } 741 742 inline void SaxWriterHelper::startCDATA() throw( SAXException ) 743 { 744 FinishStartElement(); 745 if ((nCurrentPos + 9) <= SEQUENCESIZE) 746 { 747 memcpy( &(mp_Sequence[nCurrentPos]), "<![CDATA[" , 9 ); 748 nCurrentPos += 9; 749 } 750 else 751 AddBytes(mp_Sequence, nCurrentPos, (sal_Int8*)"<![CDATA[" , 9); 752 if (nCurrentPos == SEQUENCESIZE) 753 nCurrentPos = writeSequence(); 754 } 755 756 inline void SaxWriterHelper::endCDATA() throw( SAXException ) 757 { 758 FinishStartElement(); 759 if ((nCurrentPos + 3) <= SEQUENCESIZE) 760 { 761 memcpy( &(mp_Sequence[nCurrentPos]), "]]>" , 3 ); 762 nCurrentPos += 3; 763 } 764 else 765 AddBytes(mp_Sequence, nCurrentPos, (sal_Int8*)"]]>" , 3); 766 if (nCurrentPos == SEQUENCESIZE) 767 nCurrentPos = writeSequence(); 768 } 769 770 inline sal_Bool SaxWriterHelper::comment(const rtl::OUString& rComment) throw( SAXException ) 771 { 772 FinishStartElement(); 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 mp_Sequence[nCurrentPos] = '-'; 786 nCurrentPos++; 787 if (nCurrentPos == SEQUENCESIZE) 788 nCurrentPos = writeSequence(); 789 790 sal_Bool bRet(writeString( rComment, sal_False, sal_False)); 791 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 mp_Sequence[nCurrentPos] = '>'; 801 nCurrentPos++; 802 if (nCurrentPos == SEQUENCESIZE) 803 nCurrentPos = writeSequence(); 804 805 return bRet; 806 } 807 808 inline sal_Int32 calcXMLByteLength( const sal_Unicode *pStr, sal_Int32 nStrLen, 809 sal_Bool bDoNormalization, 810 sal_Bool bNormalizeWhitespace ) 811 { 812 sal_Int32 nOutputLength = 0; 813 sal_uInt32 nSurrogate = 0; 814 815 for( sal_Int32 i = 0 ; i < nStrLen ; i++ ) 816 { 817 sal_uInt16 c = pStr[i]; 818 if( !IsInvalidChar(c) && (c >= 0x0001) && (c <= 0x007F) ) 819 { 820 if( bDoNormalization ) 821 { 822 switch( c ) 823 { 824 case '&': // resemble to & 825 nOutputLength +=5; 826 break; 827 case '<': // < 828 case '>': // > 829 nOutputLength +=4; 830 break; 831 case 39: // 39 == ''', ' 832 case '"': // " 833 case 13: // 
 834 nOutputLength += 6; 835 break; 836 837 case 10: // 
 838 case 9: // 	 839 if( bNormalizeWhitespace ) 840 { 841 nOutputLength += 6; // 842 } 843 else 844 { 845 nOutputLength ++; 846 } 847 break; 848 default: 849 nOutputLength ++; 850 } 851 } 852 else 853 { 854 nOutputLength ++; 855 } 856 } 857 else if( c >= 0xd800 && c < 0xdc00 ) 858 { 859 // save surrogate 860 nSurrogate = ( ( c & 0x03ff ) + 0x0040 ); 861 } 862 else if( c >= 0xdc00 && c < 0xe000 ) 863 { 864 // 2. surrogate: write as UTF-8 (if range is OK 865 nSurrogate = ( nSurrogate << 10 ) | ( c & 0x03ff ); 866 if( nSurrogate >= 0x00010000 && nSurrogate <= 0x0010FFFF ) 867 nOutputLength += 4; 868 nSurrogate = 0; 869 } 870 else if( c > 0x07FF ) 871 { 872 nOutputLength += 3; 873 } 874 else 875 { 876 nOutputLength += 2; 877 } 878 879 // surrogate processing 880 if( ( nSurrogate != 0 ) && !( c >= 0xd800 && c < 0xdc00 ) ) 881 nSurrogate = 0; 882 } 883 884 return nOutputLength; 885 } 886 887 /** returns position of first ascii 10 within the string, -1 when no 10 in string. 888 */ 889 static inline sal_Int32 getFirstLineBreak( const OUString & str ) throw () 890 { 891 const sal_Unicode *pSource = str.getStr(); 892 sal_Int32 nLen = str.getLength(); 893 894 for( int n = 0; n < nLen ; n ++ ) 895 { 896 if( LINEFEED == pSource[n] ) { 897 return n; 898 } 899 } 900 return -1; 901 } 902 903 /** returns position of last ascii 10 within sequence, -1 when no 10 in string. 904 */ 905 static inline sal_Int32 getLastLineBreak( const Sequence<sal_Int8> & seq) throw () 906 { 907 const sal_Int8 *pSource = seq.getConstArray(); 908 sal_Int32 nLen = seq.getLength(); 909 910 for( int n = nLen-1; n >= 0 ; n -- ) 911 { 912 if( LINEFEED == pSource[n] ) { 913 return n; 914 } 915 } 916 return -1; 917 } 918 919 920 class SAXWriter : 921 public WeakImplHelper3< 922 XActiveDataSource, 923 XExtendedDocumentHandler, 924 XServiceInfo > 925 { 926 public: 927 SAXWriter( ) : 928 m_seqStartElement(), 929 mp_SaxWriterHelper( NULL ), 930 m_bForceLineBreak(sal_False), 931 m_bAllowLineBreak(sal_False) 932 {} 933 ~SAXWriter() 934 { 935 delete mp_SaxWriterHelper; 936 } 937 938 public: // XActiveDataSource 939 virtual void SAL_CALL setOutputStream(const Reference< XOutputStream > & aStream) 940 throw (RuntimeException) 941 { 942 // temporary: set same stream again to clear buffer 943 if ( m_out == aStream && mp_SaxWriterHelper && m_bDocStarted ) 944 mp_SaxWriterHelper->clearBuffer(); 945 else 946 { 947 948 m_out = aStream; 949 delete mp_SaxWriterHelper; 950 mp_SaxWriterHelper = new SaxWriterHelper(m_out); 951 m_bDocStarted = sal_False; 952 m_nLevel = 0; 953 m_bIsCDATA = sal_False; 954 955 } 956 } 957 virtual Reference< XOutputStream > SAL_CALL getOutputStream(void) 958 throw(RuntimeException) 959 { return m_out; } 960 961 public: // XDocumentHandler 962 virtual void SAL_CALL startDocument(void) 963 throw(SAXException, RuntimeException); 964 965 virtual void SAL_CALL endDocument(void) 966 throw(SAXException, RuntimeException); 967 968 virtual void SAL_CALL startElement(const OUString& aName, 969 const Reference< XAttributeList > & xAttribs) 970 throw (SAXException, RuntimeException); 971 972 virtual void SAL_CALL endElement(const OUString& aName) 973 throw(SAXException, RuntimeException); 974 975 virtual void SAL_CALL characters(const OUString& aChars) 976 throw(SAXException, RuntimeException); 977 978 virtual void SAL_CALL ignorableWhitespace(const OUString& aWhitespaces) 979 throw(SAXException, RuntimeException); 980 virtual void SAL_CALL processingInstruction(const OUString& aTarget, 981 const OUString& aData) 982 throw(SAXException, RuntimeException); 983 virtual void SAL_CALL setDocumentLocator(const Reference< XLocator > & xLocator) 984 throw(SAXException, RuntimeException); 985 986 public: // XExtendedDocumentHandler 987 virtual void SAL_CALL startCDATA(void) throw(SAXException, RuntimeException); 988 virtual void SAL_CALL endCDATA(void) throw(RuntimeException); 989 virtual void SAL_CALL comment(const OUString& sComment) 990 throw(SAXException, RuntimeException); 991 virtual void SAL_CALL unknown(const OUString& sString) 992 throw(SAXException, RuntimeException); 993 virtual void SAL_CALL allowLineBreak(void) 994 throw(SAXException,RuntimeException); 995 996 public: // XServiceInfo 997 OUString SAL_CALL getImplementationName() throw(); 998 Sequence< OUString > SAL_CALL getSupportedServiceNames(void) throw(); 999 sal_Bool SAL_CALL supportsService(const OUString& ServiceName) throw(); 1000 1001 private: 1002 1003 void writeSequence( const Sequence<sal_Int8> & seq ); 1004 sal_Int32 getIndentPrefixLength( sal_Int32 nFirstLineBreakOccurence ) throw(); 1005 1006 Reference< XOutputStream > m_out; 1007 Sequence < sal_Int8 > m_seqStartElement; 1008 SaxWriterHelper* mp_SaxWriterHelper; 1009 1010 // Status information 1011 sal_Bool m_bDocStarted : 1; 1012 sal_Bool m_bIsCDATA : 1; 1013 sal_Bool m_bForceLineBreak : 1; 1014 sal_Bool m_bAllowLineBreak : 1; 1015 sal_Int32 m_nLevel; 1016 }; 1017 1018 1019 //-------------------------------------- 1020 // the extern interface 1021 //--------------------------------------- 1022 Reference < XInterface > SAL_CALL SaxWriter_CreateInstance( 1023 const Reference < XMultiServiceFactory > & ) 1024 throw (Exception) 1025 { 1026 SAXWriter *p = new SAXWriter; 1027 return Reference< XInterface > ( SAL_STATIC_CAST(OWeakObject *, p ) ); 1028 } 1029 1030 OUString SaxWriter_getServiceName() throw() 1031 { 1032 return OUString::createFromAscii( "com.sun.star.xml.sax.Writer" ); 1033 } 1034 1035 OUString SaxWriter_getImplementationName() throw() 1036 { 1037 return OUString::createFromAscii( "com.sun.star.extensions.xml.sax.Writer" ); 1038 } 1039 1040 Sequence< OUString > SaxWriter_getSupportedServiceNames(void) throw() 1041 { 1042 Sequence<OUString> aRet(1); 1043 aRet.getArray()[0] = SaxWriter_getServiceName(); 1044 return aRet; 1045 } 1046 1047 1048 sal_Int32 SAXWriter::getIndentPrefixLength( sal_Int32 nFirstLineBreakOccurence ) throw() 1049 { 1050 sal_Int32 nLength =-1; 1051 if (mp_SaxWriterHelper) 1052 { 1053 if ( m_bForceLineBreak || 1054 (m_bAllowLineBreak && 1055 ((nFirstLineBreakOccurence + mp_SaxWriterHelper->GetLastColumnCount()) > MAXCOLUMNCOUNT)) ) 1056 nLength = m_nLevel; 1057 } 1058 m_bForceLineBreak = sal_False; 1059 m_bAllowLineBreak = sal_False; 1060 return nLength; 1061 } 1062 1063 static inline sal_Bool isFirstCharWhitespace( const sal_Unicode *p ) throw() 1064 { 1065 return *p == ' '; 1066 } 1067 1068 1069 // XServiceInfo 1070 OUString SAXWriter::getImplementationName() throw() 1071 { 1072 return SaxWriter_getImplementationName(); 1073 } 1074 1075 // XServiceInfo 1076 sal_Bool SAXWriter::supportsService(const OUString& ServiceName) throw() 1077 { 1078 Sequence< OUString > aSNL = getSupportedServiceNames(); 1079 const OUString * pArray = aSNL.getConstArray(); 1080 1081 for( sal_Int32 i = 0; i < aSNL.getLength(); i++ ) 1082 if( pArray[i] == ServiceName ) 1083 return sal_True; 1084 1085 return sal_False; 1086 } 1087 1088 // XServiceInfo 1089 Sequence< OUString > SAXWriter::getSupportedServiceNames(void) throw () 1090 { 1091 Sequence<OUString> seq(1); 1092 seq.getArray()[0] = SaxWriter_getServiceName(); 1093 return seq; 1094 } 1095 1096 1097 1098 void SAXWriter::startDocument() throw(SAXException, RuntimeException ) 1099 { 1100 if( m_bDocStarted || ! m_out.is() || !mp_SaxWriterHelper ) { 1101 throw SAXException(); 1102 } 1103 m_bDocStarted = sal_True; 1104 mp_SaxWriterHelper->startDocument(); 1105 } 1106 1107 1108 void SAXWriter::endDocument(void) throw(SAXException, RuntimeException) 1109 { 1110 if( ! m_bDocStarted ) 1111 { 1112 throw SAXException( 1113 OUString::createFromAscii( "endDocument called before startDocument" ), 1114 Reference< XInterface >() , Any() ); 1115 } 1116 if( m_nLevel ) { 1117 throw SAXException( 1118 OUString::createFromAscii( "unexpected end of document" ), 1119 Reference< XInterface >() , Any() ); 1120 } 1121 mp_SaxWriterHelper->endDocument(); 1122 try 1123 { 1124 m_out->closeOutput(); 1125 } 1126 catch( IOException & e ) 1127 { 1128 Any a; 1129 a <<= e; 1130 throw SAXException( 1131 OUString::createFromAscii( "IO exception during closing the IO Stream" ), 1132 Reference< XInterface > (), 1133 a ); 1134 } 1135 } 1136 1137 1138 void SAXWriter::startElement(const OUString& aName, const Reference< XAttributeList >& xAttribs) 1139 throw(SAXException, RuntimeException) 1140 { 1141 if( ! m_bDocStarted ) 1142 { 1143 SAXException except; 1144 except.Message = OUString( RTL_CONSTASCII_USTRINGPARAM( "startElement called before startDocument" )); 1145 throw except; 1146 } 1147 if( m_bIsCDATA ) 1148 { 1149 SAXException except; 1150 except.Message = OUString( RTL_CONSTASCII_USTRINGPARAM( "startElement call not allowed with CDATA sections" )); 1151 throw except; 1152 } 1153 1154 sal_Int32 nLength(0); 1155 if (m_bAllowLineBreak) 1156 { 1157 sal_Int32 nAttribCount = xAttribs.is() ? xAttribs->getLength() : 0; 1158 1159 nLength ++; // "<" 1160 nLength += calcXMLByteLength( aName.getStr() , aName.getLength(), 1161 sal_False, sal_False ); // the tag name 1162 1163 sal_Int16 n; 1164 for( n = 0 ; n < static_cast<sal_Int16>(nAttribCount) ; n ++ ) { 1165 nLength ++; // " " 1166 OUString tmp = xAttribs->getNameByIndex( n ); 1167 1168 nLength += calcXMLByteLength( tmp.getStr() , tmp.getLength() , sal_False, sal_False ); 1169 1170 nLength += 2; // =" 1171 1172 tmp = xAttribs->getValueByIndex( n ); 1173 1174 nLength += calcXMLByteLength( tmp.getStr(), tmp.getLength(), sal_True, sal_True ); 1175 1176 nLength += 1; // " 1177 } 1178 1179 nLength ++; // '>' 1180 } 1181 1182 // Is there a new indentation necesarry ? 1183 sal_Int32 nPrefix(getIndentPrefixLength( nLength )); 1184 1185 // write into sequence 1186 if( nPrefix >= 0 ) 1187 mp_SaxWriterHelper->insertIndentation( nPrefix ); 1188 1189 SaxInvalidCharacterError eRet(mp_SaxWriterHelper->startElement(aName, xAttribs)); 1190 1191 m_nLevel++; 1192 1193 if (eRet == SAX_WARNING) 1194 { 1195 SAXInvalidCharacterException except; 1196 except.Message = OUString( RTL_CONSTASCII_USTRINGPARAM( "Invalid charcter during XML-Export in a attribute value" ) ); 1197 throw except; 1198 } 1199 else if (eRet == SAX_ERROR) 1200 { 1201 SAXException except; 1202 except.Message = OUString( RTL_CONSTASCII_USTRINGPARAM( "Invalid charcter during XML-Export" ) ); 1203 throw except; 1204 } 1205 } 1206 1207 void SAXWriter::endElement(const OUString& aName) throw (SAXException, RuntimeException) 1208 { 1209 if( ! m_bDocStarted ) { 1210 throw SAXException (); 1211 } 1212 m_nLevel --; 1213 1214 if( m_nLevel < 0 ) { 1215 throw SAXException(); 1216 } 1217 sal_Bool bRet(sal_True); 1218 1219 if( mp_SaxWriterHelper->FinishEmptyElement() ) 1220 m_bForceLineBreak = sal_False; 1221 else 1222 { 1223 // only ascii chars allowed 1224 sal_Int32 nLength(0); 1225 if (m_bAllowLineBreak) 1226 nLength = 3 + calcXMLByteLength( aName.getStr(), aName.getLength(), sal_False, sal_False ); 1227 sal_Int32 nPrefix = getIndentPrefixLength( nLength ); 1228 1229 if( nPrefix >= 0 ) 1230 mp_SaxWriterHelper->insertIndentation( nPrefix ); 1231 1232 bRet = mp_SaxWriterHelper->endElement(aName); 1233 } 1234 1235 if (!bRet) 1236 { 1237 SAXException except; 1238 except.Message = OUString( RTL_CONSTASCII_USTRINGPARAM( "Invalid charcter during XML-Export" ) ); 1239 throw except; 1240 } 1241 } 1242 1243 void SAXWriter::characters(const OUString& aChars) throw(SAXException, RuntimeException) 1244 { 1245 if( ! m_bDocStarted ) 1246 { 1247 SAXException except; 1248 except.Message = OUString( RTL_CONSTASCII_USTRINGPARAM( "characters method called before startDocument" ) ); 1249 throw except; 1250 } 1251 1252 sal_Bool bThrowException(sal_False); 1253 if( aChars.getLength() ) 1254 { 1255 if( m_bIsCDATA ) 1256 bThrowException = !mp_SaxWriterHelper->writeString( aChars, sal_False, sal_False ); 1257 else 1258 { 1259 // Note : nFirstLineBreakOccurence is not exact, because we don't know, how 1260 // many 2 and 3 byte chars are inbetween. However this whole stuff 1261 // is eitherway for pretty printing only, so it does not need to be exact. 1262 sal_Int32 nLength(0); 1263 sal_Int32 nIndentPrefix(-1); 1264 if (m_bAllowLineBreak) 1265 { 1266 sal_Int32 nFirstLineBreakOccurence = getFirstLineBreak( aChars ); 1267 1268 nLength = calcXMLByteLength( aChars.getStr(), aChars.getLength(), 1269 ! m_bIsCDATA , sal_False ); 1270 nIndentPrefix = getIndentPrefixLength( 1271 nFirstLineBreakOccurence >= 0 ? nFirstLineBreakOccurence : nLength ); 1272 } 1273 else 1274 nIndentPrefix = getIndentPrefixLength(nLength); 1275 1276 // insert indentation 1277 if( nIndentPrefix >= 0 ) 1278 { 1279 if( isFirstCharWhitespace( aChars.getStr() ) ) 1280 mp_SaxWriterHelper->insertIndentation( nIndentPrefix - 1 ); 1281 else 1282 mp_SaxWriterHelper->insertIndentation( nIndentPrefix ); 1283 } 1284 bThrowException = !mp_SaxWriterHelper->writeString(aChars, sal_True , sal_False); 1285 } 1286 } 1287 if (bThrowException) 1288 { 1289 SAXInvalidCharacterException except; 1290 except.Message = OUString( RTL_CONSTASCII_USTRINGPARAM( "Invalid charcter during XML-Export" ) ); 1291 throw except; 1292 } 1293 } 1294 1295 1296 void SAXWriter::ignorableWhitespace(const OUString&) throw(SAXException, RuntimeException) 1297 { 1298 if( ! m_bDocStarted ) 1299 { 1300 throw SAXException (); 1301 } 1302 1303 m_bForceLineBreak = sal_True; 1304 } 1305 1306 void SAXWriter::processingInstruction(const OUString& aTarget, const OUString& aData) 1307 throw (SAXException, RuntimeException) 1308 { 1309 if( ! m_bDocStarted || m_bIsCDATA ) 1310 { 1311 throw SAXException(); 1312 } 1313 1314 sal_Int32 nLength(0); 1315 if (m_bAllowLineBreak) 1316 { 1317 nLength = 2; // "<?" 1318 nLength += calcXMLByteLength( aTarget.getStr(), aTarget.getLength(), sal_False, sal_False ); 1319 1320 nLength += 1; // " " 1321 1322 nLength += calcXMLByteLength( aData.getStr(), aData.getLength(), sal_False, sal_False ); 1323 1324 nLength += 2; // "?>" 1325 } 1326 1327 sal_Int32 nPrefix = getIndentPrefixLength( nLength ); 1328 1329 if( nPrefix >= 0 ) 1330 mp_SaxWriterHelper->insertIndentation( nPrefix ); 1331 1332 if (!mp_SaxWriterHelper->processingInstruction(aTarget, aData)) 1333 { 1334 SAXException except; 1335 except.Message = OUString( RTL_CONSTASCII_USTRINGPARAM( "Invalid charcter during XML-Export" ) ); 1336 throw except; 1337 } 1338 } 1339 1340 1341 void SAXWriter::setDocumentLocator(const Reference< XLocator >&) 1342 throw (SAXException, RuntimeException) 1343 { 1344 1345 } 1346 1347 void SAXWriter::startCDATA(void) throw(SAXException, RuntimeException) 1348 { 1349 if( ! m_bDocStarted || m_bIsCDATA) 1350 { 1351 throw SAXException (); 1352 } 1353 1354 sal_Int32 nLength = 9; 1355 sal_Int32 nPrefix = getIndentPrefixLength( nLength ); 1356 if( nPrefix >= 0 ) 1357 mp_SaxWriterHelper->insertIndentation( nPrefix ); 1358 1359 mp_SaxWriterHelper->startCDATA(); 1360 1361 m_bIsCDATA = sal_True; 1362 } 1363 1364 void SAXWriter::endCDATA(void) throw (RuntimeException) 1365 { 1366 if( ! m_bDocStarted | ! m_bIsCDATA) 1367 { 1368 SAXException except; 1369 except.Message = OUString( RTL_CONSTASCII_USTRINGPARAM( "endCDATA was called without startCDATA" ) ); 1370 throw except; 1371 } 1372 1373 sal_Int32 nLength = 3; 1374 sal_Int32 nPrefix = getIndentPrefixLength( nLength ); 1375 if( nPrefix >= 0 ) 1376 mp_SaxWriterHelper->insertIndentation( nPrefix ); 1377 1378 mp_SaxWriterHelper->endCDATA(); 1379 1380 m_bIsCDATA = sal_False; 1381 } 1382 1383 1384 void SAXWriter::comment(const OUString& sComment) throw(SAXException, RuntimeException) 1385 { 1386 if( ! m_bDocStarted || m_bIsCDATA ) 1387 { 1388 throw SAXException(); 1389 } 1390 1391 sal_Int32 nLength(0); 1392 if (m_bAllowLineBreak) 1393 { 1394 nLength = 4; // "<!--" 1395 nLength += calcXMLByteLength( sComment.getStr(), sComment.getLength(), sal_False, sal_False); 1396 1397 nLength += 3; 1398 } 1399 1400 sal_Int32 nPrefix = getIndentPrefixLength( nLength ); 1401 if( nPrefix >= 0 ) 1402 mp_SaxWriterHelper->insertIndentation( nPrefix ); 1403 1404 if (!mp_SaxWriterHelper->comment(sComment)) 1405 { 1406 SAXException except; 1407 except.Message = OUString( RTL_CONSTASCII_USTRINGPARAM( "Invalid charcter during XML-Export" ) ); 1408 throw except; 1409 } 1410 } 1411 1412 1413 void SAXWriter::allowLineBreak( ) throw ( SAXException , RuntimeException) 1414 { 1415 if( ! m_bDocStarted || m_bAllowLineBreak ) { 1416 throw SAXException(); 1417 } 1418 1419 m_bAllowLineBreak = sal_True; 1420 } 1421 1422 void SAXWriter::unknown(const OUString& sString) throw (SAXException, RuntimeException) 1423 { 1424 1425 if( ! m_bDocStarted ) 1426 { 1427 throw SAXException (); 1428 } 1429 if( m_bIsCDATA ) 1430 { 1431 throw SAXException(); 1432 } 1433 1434 if( sString.matchAsciiL( "<?xml", 5 ) ) 1435 return; 1436 1437 sal_Int32 nLength(0); 1438 if (m_bAllowLineBreak) 1439 nLength = calcXMLByteLength( sString.getStr(), sString.getLength(), sal_False, sal_False ); 1440 1441 sal_Int32 nPrefix = getIndentPrefixLength( nLength ); 1442 if( nPrefix >= 0 ) 1443 mp_SaxWriterHelper->insertIndentation( nPrefix ); 1444 1445 if (!mp_SaxWriterHelper->writeString( sString, sal_False, sal_False)) 1446 { 1447 SAXException except; 1448 except.Message = OUString( RTL_CONSTASCII_USTRINGPARAM( "Invalid charcter during XML-Export" ) ); 1449 throw except; 1450 } 1451 } 1452 1453 } 1454 1455