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