xref: /AOO41X/main/xmlsecurity/source/xmlsec/saxhelper.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
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