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 0 : xmlChar* ous_to_xmlstr( const OUString& oustr )
39 : {
40 0 : OString ostr = OUStringToOString( oustr , RTL_TEXTENCODING_UTF8 ) ;
41 0 : return xmlStrndup( ( xmlChar* )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( ( xmlChar* )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 0 : const xmlChar** attrlist_to_nxmlstr( const cssu::Sequence< cssxcsax::XMLAttribute >& aAttributes )
61 : {
62 0 : xmlChar* attname = NULL ;
63 0 : xmlChar* attvalue = NULL ;
64 0 : const xmlChar** attrs = NULL ;
65 :
66 0 : sal_Int32 nLength = aAttributes.getLength();
67 :
68 0 : if( nLength != 0 )
69 : {
70 0 : attrs = ( const xmlChar** )xmlMalloc( ( nLength * 2 + 2 ) * sizeof( xmlChar* ) ) ;
71 : }
72 : else
73 : {
74 0 : 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 0 : SAXHelper::SAXHelper( )
108 : : m_pParserCtxt( NULL ),
109 0 : m_pSaxHandler( NULL )
110 : {
111 0 : xmlInitParser() ;
112 0 : LIBXML_TEST_VERSION ;
113 :
114 : /*
115 : * compile error:
116 : * xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS ;
117 : */
118 0 : xmlSubstituteEntitiesDefault( 1 ) ;
119 :
120 : #ifndef XMLSEC_NO_XSLT
121 : xmlIndentTreeOutput = 1 ;
122 : #endif /* XMLSEC_NO_XSLT */
123 :
124 0 : m_pParserCtxt = xmlNewParserCtxt() ;
125 :
126 0 : 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 0 : xmlSAXVersion(m_pParserCtxt->sax, 1);
139 :
140 0 : if( m_pParserCtxt->inputTab[0] != NULL )
141 : {
142 0 : m_pParserCtxt->inputTab[0] = NULL ;
143 : }
144 :
145 0 : 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 0 : m_pSaxHandler = m_pParserCtxt->sax ;
161 :
162 : //Adjust the context
163 0 : m_pParserCtxt->recovery = 1 ;
164 : }
165 : }
166 0 : }
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 0 : SAXHelper::~SAXHelper() {
177 0 : 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 0 : if( m_pSaxHandler == m_pParserCtxt->sax )
184 : {
185 0 : m_pSaxHandler = NULL ;
186 : }
187 :
188 0 : xmlFreeParserCtxt( m_pParserCtxt ) ;
189 0 : m_pParserCtxt = NULL ;
190 : }
191 :
192 0 : 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 0 : }
201 :
202 0 : xmlNodePtr SAXHelper::getCurrentNode()
203 : {
204 0 : return m_pParserCtxt->node;
205 : }
206 :
207 0 : void SAXHelper::setCurrentNode(const xmlNodePtr pNode)
208 : {
209 : /*
210 : * This is really a black trick.
211 : * When the current node is replaced, the nodeTab
212 : * stack's top has to been replaced with the same
213 : * node, in order to make compatibility.
214 : */
215 0 : m_pParserCtxt->nodeTab[m_pParserCtxt->nodeNr - 1]
216 : = m_pParserCtxt->node
217 0 : = pNode;
218 0 : }
219 :
220 0 : xmlDocPtr SAXHelper::getDocument()
221 : {
222 0 : return m_pParserCtxt->myDoc;
223 : }
224 :
225 : /**
226 : * XDocumentHandler -- start an xml document
227 : */
228 0 : void SAXHelper::startDocument( void )
229 : throw( cssxs::SAXException , cssu::RuntimeException )
230 : {
231 0 : if( m_pParserCtxt == NULL)
232 : {
233 0 : throw cssu::RuntimeException() ;
234 : }
235 : /*
236 : * Adjust inputTab
237 : */
238 0 : xmlParserInputPtr pInput = xmlNewInputStream( m_pParserCtxt ) ;
239 :
240 0 : if( m_pParserCtxt->inputTab != NULL && m_pParserCtxt->inputMax != 0 )
241 : {
242 0 : m_pParserCtxt->inputTab[0] = pInput ;
243 0 : m_pParserCtxt->input = pInput ;
244 : }
245 :
246 0 : m_pSaxHandler->startDocument( m_pParserCtxt ) ;
247 :
248 0 : if( m_pParserCtxt->myDoc == NULL )
249 : {
250 0 : throw cssu::RuntimeException() ;
251 : }
252 0 : }
253 :
254 : /**
255 : * XDocumentHandler -- end an xml document
256 : */
257 0 : void SAXHelper::endDocument( void )
258 : throw( cssxs::SAXException , cssu::RuntimeException )
259 : {
260 0 : m_pSaxHandler->endDocument( m_pParserCtxt ) ;
261 0 : }
262 :
263 : /**
264 : * XDocumentHandler -- start an xml element
265 : */
266 0 : void SAXHelper::startElement(
267 : const OUString& aName,
268 : const cssu::Sequence< cssxcsax::XMLAttribute >& aAttributes )
269 : throw( cssxs::SAXException , cssu::RuntimeException )
270 : {
271 0 : const xmlChar* fullName = NULL ;
272 0 : const xmlChar** attrs = NULL ;
273 :
274 0 : fullName = ous_to_xmlstr( aName ) ;
275 0 : attrs = attrlist_to_nxmlstr( aAttributes ) ;
276 :
277 0 : if( fullName != NULL || attrs != NULL )
278 : {
279 0 : m_pSaxHandler->startElement( m_pParserCtxt , fullName , attrs ) ;
280 : }
281 :
282 0 : if( fullName != NULL )
283 : {
284 0 : xmlFree( ( xmlChar* )fullName ) ;
285 0 : fullName = NULL ;
286 : }
287 :
288 0 : if( attrs != NULL )
289 : {
290 0 : for( int i = 0 ; attrs[i] != NULL ; ++i )
291 : {
292 0 : xmlFree( ( xmlChar* )attrs[i] ) ;
293 0 : attrs[i] = NULL ;
294 : }
295 :
296 0 : xmlFree( ( void* ) attrs ) ;
297 0 : attrs = NULL ;
298 : }
299 0 : }
300 :
301 : /**
302 : * XDocumentHandler -- end an xml element
303 : */
304 0 : void SAXHelper::endElement( const OUString& aName )
305 : throw( cssxs::SAXException , cssu::RuntimeException )
306 : {
307 0 : xmlChar* fullname = NULL ;
308 :
309 0 : fullname = ous_to_xmlstr( aName ) ;
310 0 : m_pSaxHandler->endElement( m_pParserCtxt , fullname ) ;
311 :
312 0 : if( fullname != NULL )
313 : {
314 0 : xmlFree( ( xmlChar* )fullname ) ;
315 0 : fullname = NULL ;
316 : }
317 0 : }
318 :
319 : /**
320 : * XDocumentHandler -- an xml element or cdata characters
321 : */
322 0 : void SAXHelper::characters( const OUString& aChars )
323 : throw( cssxs::SAXException , cssu::RuntimeException )
324 : {
325 0 : const xmlChar* chars = NULL ;
326 0 : int length = 0 ;
327 :
328 0 : chars = ous_to_nxmlstr( aChars, length ) ;
329 0 : m_pSaxHandler->characters( m_pParserCtxt , chars , length ) ;
330 :
331 0 : if( chars != NULL )
332 : {
333 0 : xmlFree( ( xmlChar* )chars ) ;
334 : }
335 0 : }
336 :
337 : /**
338 : * XDocumentHandler -- ignorable xml white space
339 : */
340 0 : void SAXHelper::ignorableWhitespace( const OUString& aWhitespaces )
341 : throw( cssxs::SAXException , cssu::RuntimeException )
342 : {
343 0 : const xmlChar* chars = NULL ;
344 0 : int length = 0 ;
345 :
346 0 : chars = ous_to_nxmlstr( aWhitespaces, length ) ;
347 0 : m_pSaxHandler->ignorableWhitespace( m_pParserCtxt , chars , length ) ;
348 :
349 0 : if( chars != NULL )
350 : {
351 0 : xmlFree( ( xmlChar* )chars ) ;
352 : }
353 0 : }
354 :
355 : /**
356 : * XDocumentHandler -- preaorocessing instruction
357 : */
358 0 : void SAXHelper::processingInstruction(
359 : const OUString& aTarget,
360 : const OUString& aData )
361 : throw( cssxs::SAXException , cssu::RuntimeException )
362 : {
363 0 : xmlChar* target = NULL ;
364 0 : xmlChar* data = NULL ;
365 :
366 0 : target = ous_to_xmlstr( aTarget ) ;
367 0 : data = ous_to_xmlstr( aData ) ;
368 :
369 0 : m_pSaxHandler->processingInstruction( m_pParserCtxt , target , data ) ;
370 :
371 0 : if( target != NULL )
372 : {
373 0 : xmlFree( ( xmlChar* )target ) ;
374 0 : target = NULL ;
375 : }
376 :
377 0 : if( data != NULL )
378 : {
379 0 : xmlFree( ( xmlChar* )data ) ;
380 0 : data = NULL ;
381 : }
382 0 : }
383 :
384 : /**
385 : * XDocumentHandler -- set document locator
386 : * In this case, locator is useless.
387 : */
388 0 : void SAXHelper::setDocumentLocator(
389 : const cssu::Reference< cssxs::XLocator > &)
390 : throw( cssxs::SAXException , cssu::RuntimeException )
391 : {
392 0 : }
393 :
394 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|