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