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