Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 :
21 : #include <rtl/ustring.hxx>
22 :
23 : #include "saxhelper.hxx"
24 : #include "libxml/parserInternals.h"
25 :
26 : #ifndef XMLSEC_NO_XSLT
27 : #include "libxslt/xslt.h"
28 : #endif
29 :
30 : namespace cssu = com::sun::star::uno;
31 : namespace cssxs = com::sun::star::xml::sax;
32 : namespace cssxcsax = com::sun::star::xml::csax;
33 :
34 : /**
35 : * The return value is NULL terminated. The application has the responsibilty to
36 : * deallocte the return value.
37 : */
38 1 : xmlChar* ous_to_xmlstr( const OUString& oustr )
39 : {
40 1 : OString ostr = OUStringToOString( oustr , RTL_TEXTENCODING_UTF8 ) ;
41 1 : return xmlStrndup( reinterpret_cast<xmlChar const *>(ostr.getStr()), ( int )ostr.getLength() ) ;
42 : }
43 :
44 : /**
45 : * The return value is NULL terminated. The application has the responsibilty to
46 : * deallocte the return value.
47 : */
48 0 : xmlChar* ous_to_nxmlstr( const OUString& oustr, int& length )
49 : {
50 0 : OString ostr = OUStringToOString( oustr , RTL_TEXTENCODING_UTF8 ) ;
51 0 : length = ostr.getLength();
52 :
53 0 : return xmlStrndup( reinterpret_cast<xmlChar const *>(ostr.getStr()), length ) ;
54 : }
55 :
56 : /**
57 : * The return value and the referenced value must be NULL terminated.
58 : * The application has the responsibilty to deallocte the return value.
59 : */
60 1 : const xmlChar** attrlist_to_nxmlstr( const cssu::Sequence< cssxcsax::XMLAttribute >& aAttributes )
61 : {
62 1 : xmlChar* attname = NULL ;
63 1 : xmlChar* attvalue = NULL ;
64 1 : const xmlChar** attrs = NULL ;
65 :
66 1 : sal_Int32 nLength = aAttributes.getLength();
67 :
68 1 : if( nLength != 0 )
69 : {
70 0 : attrs = static_cast<const xmlChar**>(xmlMalloc( ( nLength * 2 + 2 ) * sizeof( xmlChar* ) ));
71 : }
72 : else
73 : {
74 1 : return NULL ;
75 : }
76 :
77 0 : for( int i = 0 , j = 0 ; j < nLength ; ++j )
78 : {
79 0 : attname = ous_to_xmlstr( aAttributes[j].sName ) ;
80 0 : attvalue = ous_to_xmlstr( aAttributes[j].sValue ) ;
81 :
82 0 : if( attname != NULL && attvalue != NULL )
83 : {
84 0 : attrs[i++] = attname ;
85 0 : attrs[i++] = attvalue ;
86 0 : attrs[i] = NULL ;
87 0 : attrs[i+1] = NULL ;
88 : }
89 : else
90 : {
91 0 : if( attname != NULL )
92 0 : xmlFree( attname ) ;
93 0 : if( attvalue != NULL )
94 0 : xmlFree( attvalue ) ;
95 : }
96 : }
97 :
98 0 : return attrs ;
99 : }
100 :
101 : /**
102 : * Constructor
103 : *
104 : * In this constructor, a libxml sax parser context is initialized. a libxml
105 : * default sax handler is initialized with the context.
106 : */
107 1 : SAXHelper::SAXHelper( )
108 : : m_pParserCtxt( NULL ),
109 1 : m_pSaxHandler( NULL )
110 : {
111 1 : xmlInitParser() ;
112 1 : LIBXML_TEST_VERSION ;
113 :
114 : /*
115 : * compile error:
116 : * xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS ;
117 : */
118 1 : xmlSubstituteEntitiesDefault( 1 ) ;
119 :
120 : #ifndef XMLSEC_NO_XSLT
121 : xmlIndentTreeOutput = 1 ;
122 : #endif /* XMLSEC_NO_XSLT */
123 :
124 1 : m_pParserCtxt = xmlNewParserCtxt() ;
125 :
126 1 : if( m_pParserCtxt == NULL )
127 : {
128 : #ifndef XMLSEC_NO_XSLT
129 : xsltCleanupGlobals() ;
130 : #endif
131 : // see issue i74334, we cannot call xmlCleanupParser when libxml is still used
132 : // in other parts of the office.
133 : // xmlCleanupParser() ;
134 0 : throw cssu::RuntimeException() ;
135 : }
136 : else
137 : {
138 1 : xmlSAXVersion(m_pParserCtxt->sax, 1);
139 :
140 1 : if( m_pParserCtxt->inputTab[0] != NULL )
141 : {
142 1 : m_pParserCtxt->inputTab[0] = NULL ;
143 : }
144 :
145 1 : if( m_pParserCtxt->sax == NULL )
146 : {
147 0 : xmlFreeParserCtxt( m_pParserCtxt ) ;
148 :
149 : #ifndef XMLSEC_NO_XSLT
150 : xsltCleanupGlobals() ;
151 : #endif
152 : // see issue i74334, we cannot call xmlCleanupParser when libxml is still used
153 : // in other parts of the office.
154 : // xmlCleanupParser() ;
155 0 : m_pParserCtxt = NULL ;
156 0 : throw cssu::RuntimeException() ;
157 : }
158 : else
159 : {
160 1 : m_pSaxHandler = m_pParserCtxt->sax ;
161 :
162 : //Adjust the context
163 1 : m_pParserCtxt->recovery = 1 ;
164 : }
165 : }
166 1 : }
167 :
168 : /**
169 : * Destructor
170 : *
171 : * In this destructor, a libxml sax parser context is desturcted. The XML tree
172 : * in the context is not deallocated because the tree is bind with a document
173 : * model by the setTargetDocument method, which delegate the target document to
174 : * destruct the xml tree.
175 : */
176 1 : SAXHelper::~SAXHelper() {
177 1 : if( m_pParserCtxt != NULL )
178 : {
179 : /*
180 : * In the situation that no object refer the Document, this destructor
181 : * must deallocate the Document memory
182 : */
183 1 : if( m_pSaxHandler == m_pParserCtxt->sax )
184 : {
185 1 : m_pSaxHandler = NULL ;
186 : }
187 :
188 1 : xmlFreeParserCtxt( m_pParserCtxt ) ;
189 1 : m_pParserCtxt = NULL ;
190 : }
191 :
192 1 : if( m_pSaxHandler != NULL )
193 : {
194 0 : xmlFree( m_pSaxHandler ) ;
195 0 : m_pSaxHandler = NULL ;
196 : }
197 : // see issue i74334, we cannot call xmlCleanupParser when libxml is still used
198 : // in other parts of the office.
199 : // xmlCleanupParser() ;
200 1 : }
201 :
202 :
203 0 : void SAXHelper::setCurrentNode(const xmlNodePtr pNode)
204 : {
205 : /*
206 : * This is really a black trick.
207 : * When the current node is replaced, the nodeTab
208 : * stack's top has to been replaced with the same
209 : * node, in order to make compatibility.
210 : */
211 0 : m_pParserCtxt->nodeTab[m_pParserCtxt->nodeNr - 1]
212 : = m_pParserCtxt->node
213 0 : = pNode;
214 0 : }
215 :
216 :
217 : /**
218 : * XDocumentHandler -- start an xml document
219 : */
220 1 : void SAXHelper::startDocument()
221 : throw( cssxs::SAXException , cssu::RuntimeException )
222 : {
223 1 : if( m_pParserCtxt == NULL)
224 : {
225 0 : throw cssu::RuntimeException() ;
226 : }
227 : /*
228 : * Adjust inputTab
229 : */
230 1 : xmlParserInputPtr pInput = xmlNewInputStream( m_pParserCtxt ) ;
231 :
232 1 : if( m_pParserCtxt->inputTab != NULL && m_pParserCtxt->inputMax != 0 )
233 : {
234 1 : m_pParserCtxt->inputTab[0] = pInput ;
235 1 : m_pParserCtxt->input = pInput ;
236 : }
237 :
238 1 : m_pSaxHandler->startDocument( m_pParserCtxt ) ;
239 :
240 1 : if( m_pParserCtxt->myDoc == NULL )
241 : {
242 0 : throw cssu::RuntimeException() ;
243 : }
244 1 : }
245 :
246 : /**
247 : * XDocumentHandler -- end an xml document
248 : */
249 1 : void SAXHelper::endDocument()
250 : throw( cssxs::SAXException , cssu::RuntimeException )
251 : {
252 1 : m_pSaxHandler->endDocument( m_pParserCtxt ) ;
253 1 : }
254 :
255 : /**
256 : * XDocumentHandler -- start an xml element
257 : */
258 1 : void SAXHelper::startElement(
259 : const OUString& aName,
260 : const cssu::Sequence< cssxcsax::XMLAttribute >& aAttributes )
261 : throw( cssxs::SAXException , cssu::RuntimeException )
262 : {
263 1 : const xmlChar* fullName = NULL ;
264 1 : const xmlChar** attrs = NULL ;
265 :
266 1 : fullName = ous_to_xmlstr( aName ) ;
267 1 : attrs = attrlist_to_nxmlstr( aAttributes ) ;
268 :
269 1 : if( fullName != NULL || attrs != NULL )
270 : {
271 1 : m_pSaxHandler->startElement( m_pParserCtxt , fullName , attrs ) ;
272 : }
273 :
274 1 : if( fullName != NULL )
275 : {
276 1 : xmlFree( const_cast<xmlChar*>(fullName) ) ;
277 1 : fullName = NULL ;
278 : }
279 :
280 1 : if( attrs != NULL )
281 : {
282 0 : for( int i = 0 ; attrs[i] != NULL ; ++i )
283 : {
284 0 : xmlFree( const_cast<xmlChar*>(attrs[i]) ) ;
285 0 : attrs[i] = NULL ;
286 : }
287 :
288 0 : xmlFree( static_cast<void*>(attrs) ) ;
289 0 : attrs = NULL ;
290 : }
291 1 : }
292 :
293 : /**
294 : * XDocumentHandler -- end an xml element
295 : */
296 0 : void SAXHelper::endElement( const OUString& aName )
297 : throw( cssxs::SAXException , cssu::RuntimeException )
298 : {
299 0 : xmlChar* fullname = NULL ;
300 :
301 0 : fullname = ous_to_xmlstr( aName ) ;
302 0 : m_pSaxHandler->endElement( m_pParserCtxt , fullname ) ;
303 :
304 0 : if( fullname != NULL )
305 : {
306 0 : xmlFree( fullname ) ;
307 0 : fullname = NULL ;
308 : }
309 0 : }
310 :
311 : /**
312 : * XDocumentHandler -- an xml element or cdata characters
313 : */
314 0 : void SAXHelper::characters( const OUString& aChars )
315 : throw( cssxs::SAXException , cssu::RuntimeException )
316 : {
317 0 : const xmlChar* chars = NULL ;
318 0 : int length = 0 ;
319 :
320 0 : chars = ous_to_nxmlstr( aChars, length ) ;
321 0 : m_pSaxHandler->characters( m_pParserCtxt , chars , length ) ;
322 :
323 0 : if( chars != NULL )
324 : {
325 0 : xmlFree( const_cast<xmlChar*>(chars) ) ;
326 : }
327 0 : }
328 :
329 : /**
330 : * XDocumentHandler -- ignorable xml white space
331 : */
332 0 : void SAXHelper::ignorableWhitespace( const OUString& aWhitespaces )
333 : throw( cssxs::SAXException , cssu::RuntimeException )
334 : {
335 0 : const xmlChar* chars = NULL ;
336 0 : int length = 0 ;
337 :
338 0 : chars = ous_to_nxmlstr( aWhitespaces, length ) ;
339 0 : m_pSaxHandler->ignorableWhitespace( m_pParserCtxt , chars , length ) ;
340 :
341 0 : if( chars != NULL )
342 : {
343 0 : xmlFree( const_cast<xmlChar*>(chars) ) ;
344 : }
345 0 : }
346 :
347 : /**
348 : * XDocumentHandler -- preaorocessing instruction
349 : */
350 0 : void SAXHelper::processingInstruction(
351 : const OUString& aTarget,
352 : const OUString& aData )
353 : throw( cssxs::SAXException , cssu::RuntimeException )
354 : {
355 0 : xmlChar* target = NULL ;
356 0 : xmlChar* data = NULL ;
357 :
358 0 : target = ous_to_xmlstr( aTarget ) ;
359 0 : data = ous_to_xmlstr( aData ) ;
360 :
361 0 : m_pSaxHandler->processingInstruction( m_pParserCtxt , target , data ) ;
362 :
363 0 : if( target != NULL )
364 : {
365 0 : xmlFree( target ) ;
366 0 : target = NULL ;
367 : }
368 :
369 0 : if( data != NULL )
370 : {
371 0 : xmlFree( data ) ;
372 0 : data = NULL ;
373 : }
374 0 : }
375 :
376 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|