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 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_xmlsecurity.hxx" 30 31 #include <rtl/ustring.hxx> 32 33 #include "saxhelper.hxx" 34 #include "libxml/parserInternals.h" 35 36 #ifndef XMLSEC_NO_XSLT 37 #include "libxslt/xslt.h" 38 #endif 39 40 namespace cssu = com::sun::star::uno; 41 namespace cssxs = com::sun::star::xml::sax; 42 namespace cssxcsax = com::sun::star::xml::csax; 43 44 /** 45 * The return value is NULL terminated. The application has the responsibilty to 46 * deallocte the return value. 47 */ 48 xmlChar* ous_to_xmlstr( const rtl::OUString& oustr ) 49 { 50 rtl::OString ostr = rtl::OUStringToOString( oustr , RTL_TEXTENCODING_UTF8 ) ; 51 return xmlStrndup( ( xmlChar* )ostr.getStr(), ( int )ostr.getLength() ) ; 52 } 53 54 /** 55 * The return value is NULL terminated. The application has the responsibilty to 56 * deallocte the return value. 57 */ 58 xmlChar* ous_to_nxmlstr( const rtl::OUString& oustr, int& length ) 59 { 60 rtl::OString ostr = rtl::OUStringToOString( oustr , RTL_TEXTENCODING_UTF8 ) ; 61 length = ostr.getLength(); 62 63 return xmlStrndup( ( xmlChar* )ostr.getStr(), length ) ; 64 } 65 66 /** 67 * The input parameter isn't necessaryly NULL terminated. 68 */ 69 rtl::OUString xmlchar_to_ous( const xmlChar* pChar, int length ) 70 { 71 if( pChar != NULL ) 72 { 73 return rtl::OUString( ( sal_Char* )pChar , length , RTL_TEXTENCODING_UTF8 ) ; 74 } 75 else 76 { 77 return rtl::OUString() ; 78 } 79 } 80 81 /** 82 * The input parameter is NULL terminated 83 */ 84 rtl::OUString xmlstr_to_ous( const xmlChar* pStr ) 85 { 86 if( pStr != NULL ) 87 { 88 return xmlchar_to_ous( pStr , xmlStrlen( pStr ) ) ; 89 } 90 else 91 { 92 return rtl::OUString() ; 93 } 94 } 95 96 /** 97 * The return value and the referenced value must be NULL terminated. 98 * The application has the responsibilty to deallocte the return value. 99 */ 100 const xmlChar** attrlist_to_nxmlstr( const cssu::Sequence< cssxcsax::XMLAttribute >& aAttributes ) 101 { 102 xmlChar* attname = NULL ; 103 xmlChar* attvalue = NULL ; 104 const xmlChar** attrs = NULL ; 105 rtl::OUString oustr ; 106 107 sal_Int32 nLength = aAttributes.getLength();; 108 109 if( nLength != 0 ) 110 { 111 attrs = ( const xmlChar** )xmlMalloc( ( nLength * 2 + 2 ) * sizeof( xmlChar* ) ) ; 112 } 113 else 114 { 115 return NULL ; 116 } 117 118 for( int i = 0 , j = 0 ; j < nLength ; ++j ) 119 { 120 attname = ous_to_xmlstr( aAttributes[j].sName ) ; 121 attvalue = ous_to_xmlstr( aAttributes[j].sValue ) ; 122 123 if( attname != NULL && attvalue != NULL ) 124 { 125 attrs[i++] = attname ; 126 attrs[i++] = attvalue ; 127 attrs[i] = NULL ; 128 attrs[i+1] = NULL ; 129 } 130 else 131 { 132 if( attname != NULL ) 133 xmlFree( attname ) ; 134 if( attvalue != NULL ) 135 xmlFree( attvalue ) ; 136 } 137 } 138 139 return attrs ; 140 } 141 142 /** 143 * Constructor 144 * 145 * In this constructor, a libxml sax parser context is initialized. a libxml 146 * default sax handler is initialized with the context. 147 */ 148 SAXHelper::SAXHelper( ) 149 : m_pParserCtxt( NULL ), 150 m_pSaxHandler( NULL ) 151 { 152 xmlInitParser() ; 153 LIBXML_TEST_VERSION ; 154 155 /* 156 * compile error: 157 * xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS ; 158 */ 159 xmlSubstituteEntitiesDefault( 1 ) ; 160 161 #ifndef XMLSEC_NO_XSLT 162 xmlIndentTreeOutput = 1 ; 163 #endif /* XMLSEC_NO_XSLT */ 164 165 m_pParserCtxt = xmlNewParserCtxt() ; 166 167 /* 168 * i41748 169 * 170 * mmi : re-initialize the SAX handler to version 1 171 */ 172 173 xmlSAXVersion(m_pParserCtxt->sax, 1); 174 175 /* end */ 176 177 if( m_pParserCtxt->inputTab[0] != NULL ) 178 { 179 m_pParserCtxt->inputTab[0] = NULL ; 180 } 181 182 if( m_pParserCtxt == NULL ) 183 { 184 #ifndef XMLSEC_NO_XSLT 185 xsltCleanupGlobals() ; 186 #endif 187 // see issue i74334, we cannot call xmlCleanupParser when libxml is still used 188 // in other parts of the office. 189 // xmlCleanupParser() ; 190 throw cssu::RuntimeException() ; 191 } 192 else if( m_pParserCtxt->sax == NULL ) 193 { 194 xmlFreeParserCtxt( m_pParserCtxt ) ; 195 196 #ifndef XMLSEC_NO_XSLT 197 xsltCleanupGlobals() ; 198 #endif 199 // see issue i74334, we cannot call xmlCleanupParser when libxml is still used 200 // in other parts of the office. 201 // xmlCleanupParser() ; 202 m_pParserCtxt = NULL ; 203 throw cssu::RuntimeException() ; 204 } 205 else 206 { 207 m_pSaxHandler = m_pParserCtxt->sax ; 208 209 //Adjust the context 210 m_pParserCtxt->recovery = 1 ; 211 } 212 } 213 214 /** 215 * Destructor 216 * 217 * In this destructor, a libxml sax parser context is desturcted. The XML tree 218 * in the context is not deallocated because the tree is bind with a document 219 * model by the setTargetDocument method, which delegate the target document to 220 * destruct the xml tree. 221 */ 222 SAXHelper::~SAXHelper() { 223 if( m_pParserCtxt != NULL ) 224 { 225 /* 226 * In the situation that no object refer the Document, this destructor 227 * must deallocate the Document memory 228 */ 229 if( m_pSaxHandler == m_pParserCtxt->sax ) 230 { 231 m_pSaxHandler = NULL ; 232 } 233 234 xmlFreeParserCtxt( m_pParserCtxt ) ; 235 m_pParserCtxt = NULL ; 236 } 237 238 if( m_pSaxHandler != NULL ) 239 { 240 xmlFree( m_pSaxHandler ) ; 241 m_pSaxHandler = NULL ; 242 } 243 // see issue i74334, we cannot call xmlCleanupParser when libxml is still used 244 // in other parts of the office. 245 // xmlCleanupParser() ; 246 } 247 248 xmlNodePtr SAXHelper::getCurrentNode() 249 { 250 return m_pParserCtxt->node; 251 } 252 253 void SAXHelper::setCurrentNode(const xmlNodePtr pNode) 254 { 255 /* 256 * This is really a black trick. 257 * When the current node is replaced, the nodeTab 258 * stack's top has to been replaced with the same 259 * node, in order to make compatibility. 260 */ 261 m_pParserCtxt->nodeTab[m_pParserCtxt->nodeNr - 1] 262 = m_pParserCtxt->node 263 = pNode; 264 } 265 266 xmlDocPtr SAXHelper::getDocument() 267 { 268 return m_pParserCtxt->myDoc; 269 } 270 271 /** 272 * XDocumentHandler -- start an xml document 273 */ 274 void SAXHelper::startDocument( void ) 275 throw( cssxs::SAXException , cssu::RuntimeException ) 276 { 277 /* 278 * Adjust inputTab 279 */ 280 xmlParserInputPtr pInput = xmlNewInputStream( m_pParserCtxt ) ; 281 282 if( m_pParserCtxt->inputTab != NULL && m_pParserCtxt->inputMax != 0 ) 283 { 284 m_pParserCtxt->inputTab[0] = pInput ; 285 m_pParserCtxt->input = pInput ; 286 } 287 288 m_pSaxHandler->startDocument( m_pParserCtxt ) ; 289 290 if( m_pParserCtxt == NULL || m_pParserCtxt->myDoc == NULL ) 291 { 292 throw cssu::RuntimeException() ; 293 } 294 } 295 296 /** 297 * XDocumentHandler -- end an xml document 298 */ 299 void SAXHelper::endDocument( void ) 300 throw( cssxs::SAXException , cssu::RuntimeException ) 301 { 302 m_pSaxHandler->endDocument( m_pParserCtxt ) ; 303 } 304 305 /** 306 * XDocumentHandler -- start an xml element 307 */ 308 void SAXHelper::startElement( 309 const rtl::OUString& aName, 310 const cssu::Sequence< cssxcsax::XMLAttribute >& aAttributes ) 311 throw( cssxs::SAXException , cssu::RuntimeException ) 312 { 313 const xmlChar* fullName = NULL ; 314 const xmlChar** attrs = NULL ; 315 316 fullName = ous_to_xmlstr( aName ) ; 317 attrs = attrlist_to_nxmlstr( aAttributes ) ; 318 319 if( fullName != NULL || attrs != NULL ) 320 { 321 m_pSaxHandler->startElement( m_pParserCtxt , fullName , attrs ) ; 322 } 323 324 if( fullName != NULL ) 325 { 326 xmlFree( ( xmlChar* )fullName ) ; 327 fullName = NULL ; 328 } 329 330 if( attrs != NULL ) 331 { 332 for( int i = 0 ; attrs[i] != NULL ; ++i ) 333 { 334 xmlFree( ( xmlChar* )attrs[i] ) ; 335 attrs[i] = NULL ; 336 } 337 338 xmlFree( ( void* ) attrs ) ; 339 attrs = NULL ; 340 } 341 } 342 343 /** 344 * XDocumentHandler -- end an xml element 345 */ 346 void SAXHelper::endElement( const rtl::OUString& aName ) 347 throw( cssxs::SAXException , cssu::RuntimeException ) 348 { 349 xmlChar* fullname = NULL ; 350 351 fullname = ous_to_xmlstr( aName ) ; 352 m_pSaxHandler->endElement( m_pParserCtxt , fullname ) ; 353 354 if( fullname != NULL ) 355 { 356 xmlFree( ( xmlChar* )fullname ) ; 357 fullname = NULL ; 358 } 359 } 360 361 /** 362 * XDocumentHandler -- an xml element or cdata characters 363 */ 364 void SAXHelper::characters( const rtl::OUString& aChars ) 365 throw( cssxs::SAXException , cssu::RuntimeException ) 366 { 367 const xmlChar* chars = NULL ; 368 int length = 0 ; 369 370 chars = ous_to_nxmlstr( aChars, length ) ; 371 m_pSaxHandler->characters( m_pParserCtxt , chars , length ) ; 372 373 if( chars != NULL ) 374 { 375 xmlFree( ( xmlChar* )chars ) ; 376 } 377 } 378 379 /** 380 * XDocumentHandler -- ignorable xml white space 381 */ 382 void SAXHelper::ignorableWhitespace( const rtl::OUString& aWhitespaces ) 383 throw( cssxs::SAXException , cssu::RuntimeException ) 384 { 385 const xmlChar* chars = NULL ; 386 int length = 0 ; 387 388 chars = ous_to_nxmlstr( aWhitespaces, length ) ; 389 m_pSaxHandler->ignorableWhitespace( m_pParserCtxt , chars , length ) ; 390 391 if( chars != NULL ) 392 { 393 xmlFree( ( xmlChar* )chars ) ; 394 } 395 } 396 397 /** 398 * XDocumentHandler -- preaorocessing instruction 399 */ 400 void SAXHelper::processingInstruction( 401 const rtl::OUString& aTarget, 402 const rtl::OUString& aData ) 403 throw( cssxs::SAXException , cssu::RuntimeException ) 404 { 405 xmlChar* target = NULL ; 406 xmlChar* data = NULL ; 407 408 target = ous_to_xmlstr( aTarget ) ; 409 data = ous_to_xmlstr( aData ) ; 410 411 m_pSaxHandler->processingInstruction( m_pParserCtxt , target , data ) ; 412 413 if( target != NULL ) 414 { 415 xmlFree( ( xmlChar* )target ) ; 416 target = NULL ; 417 } 418 419 if( data != NULL ) 420 { 421 xmlFree( ( xmlChar* )data ) ; 422 data = NULL ; 423 } 424 } 425 426 /** 427 * XDocumentHandler -- set document locator 428 * In this case, locator is useless. 429 */ 430 void SAXHelper::setDocumentLocator( 431 const cssu::Reference< cssxs::XLocator > &) 432 throw( cssxs::SAXException , cssu::RuntimeException ) 433 { 434 //--Pseudo code if necessary 435 //--m_pSaxLocator is a member defined as xmlSAXHabdlerPtr 436 //--m_pSaxLocatorHdl is a member defined as Sax_Locator 437 438 //if( m_pSaxLocator != NULL ) { 439 // //Deallocate the memory 440 //} 441 //if( m_pSaxLocatorHdl != NULL ) { 442 // //Deallocate the memory 443 //} 444 445 //m_pSaxLocatorHdl = new Sax_Locator( xLocator ) ; 446 //m_pSaxLocator = { m_pSaxLocatorHdl->getPublicId , m_pSaxLocatorHdl->getSystemId , m_pSaxLocatorHdl->getLineNumber , m_pSaxLocatorHdl->getColumnNumber } ; 447 448 //m_pSaxHandler->setDocumentLocator( m_pParserCtxt , m_pSaxLocator ) ; 449 } 450 451