xref: /trunk/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