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 */
ous_to_xmlstr(const rtl::OUString & oustr)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 */
ous_to_nxmlstr(const rtl::OUString & oustr,int & length)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 */
xmlchar_to_ous(const xmlChar * pChar,int length)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 */
xmlstr_to_ous(const xmlChar * pStr)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 */
attrlist_to_nxmlstr(const cssu::Sequence<cssxcsax::XMLAttribute> & aAttributes)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 */
SAXHelper()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 */
~SAXHelper()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
getCurrentNode()244 xmlNodePtr SAXHelper::getCurrentNode()
245 {
246 return m_pParserCtxt->node;
247 }
248
setCurrentNode(const xmlNodePtr pNode)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
getDocument()262 xmlDocPtr SAXHelper::getDocument()
263 {
264 return m_pParserCtxt->myDoc;
265 }
266
267 /**
268 * XDocumentHandler -- start an xml document
269 */
startDocument(void)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 */
endDocument(void)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 */
startElement(const rtl::OUString & aName,const cssu::Sequence<cssxcsax::XMLAttribute> & aAttributes)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 */
endElement(const rtl::OUString & aName)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 */
characters(const rtl::OUString & aChars)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 */
ignorableWhitespace(const rtl::OUString & aWhitespaces)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 */
processingInstruction(const rtl::OUString & aTarget,const rtl::OUString & aData)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 */
setDocumentLocator(const cssu::Reference<cssxs::XLocator> &)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