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 rtl::OUString& oustr )
39 : {
40 0 : rtl::OString ostr = rtl::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 rtl::OUString& oustr, int& length )
49 : {
50 0 : rtl::OString ostr = rtl::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 : /*
127 : * i41748
128 : *
129 : * mmi : re-initialize the SAX handler to version 1
130 : */
131 :
132 0 : xmlSAXVersion(m_pParserCtxt->sax, 1);
133 :
134 : /* end */
135 :
136 0 : if( m_pParserCtxt->inputTab[0] != NULL )
137 : {
138 0 : m_pParserCtxt->inputTab[0] = NULL ;
139 : }
140 :
141 0 : if( m_pParserCtxt == NULL )
142 : {
143 : #ifndef XMLSEC_NO_XSLT
144 : xsltCleanupGlobals() ;
145 : #endif
146 : // see issue i74334, we cannot call xmlCleanupParser when libxml is still used
147 : // in other parts of the office.
148 : // xmlCleanupParser() ;
149 0 : throw cssu::RuntimeException() ;
150 : }
151 0 : else if( m_pParserCtxt->sax == NULL )
152 : {
153 0 : xmlFreeParserCtxt( m_pParserCtxt ) ;
154 :
155 : #ifndef XMLSEC_NO_XSLT
156 : xsltCleanupGlobals() ;
157 : #endif
158 : // see issue i74334, we cannot call xmlCleanupParser when libxml is still used
159 : // in other parts of the office.
160 : // xmlCleanupParser() ;
161 0 : m_pParserCtxt = NULL ;
162 0 : throw cssu::RuntimeException() ;
163 : }
164 : else
165 : {
166 0 : m_pSaxHandler = m_pParserCtxt->sax ;
167 :
168 : //Adjust the context
169 0 : m_pParserCtxt->recovery = 1 ;
170 : }
171 0 : }
172 :
173 : /**
174 : * Destructor
175 : *
176 : * In this destructor, a libxml sax parser context is desturcted. The XML tree
177 : * in the context is not deallocated because the tree is bind with a document
178 : * model by the setTargetDocument method, which delegate the target document to
179 : * destruct the xml tree.
180 : */
181 0 : SAXHelper::~SAXHelper() {
182 0 : if( m_pParserCtxt != NULL )
183 : {
184 : /*
185 : * In the situation that no object refer the Document, this destructor
186 : * must deallocate the Document memory
187 : */
188 0 : if( m_pSaxHandler == m_pParserCtxt->sax )
189 : {
190 0 : m_pSaxHandler = NULL ;
191 : }
192 :
193 0 : xmlFreeParserCtxt( m_pParserCtxt ) ;
194 0 : m_pParserCtxt = NULL ;
195 : }
196 :
197 0 : if( m_pSaxHandler != NULL )
198 : {
199 0 : xmlFree( m_pSaxHandler ) ;
200 0 : m_pSaxHandler = NULL ;
201 : }
202 : // see issue i74334, we cannot call xmlCleanupParser when libxml is still used
203 : // in other parts of the office.
204 : // xmlCleanupParser() ;
205 0 : }
206 :
207 0 : xmlNodePtr SAXHelper::getCurrentNode()
208 : {
209 0 : return m_pParserCtxt->node;
210 : }
211 :
212 0 : void SAXHelper::setCurrentNode(const xmlNodePtr pNode)
213 : {
214 : /*
215 : * This is really a black trick.
216 : * When the current node is replaced, the nodeTab
217 : * stack's top has to been replaced with the same
218 : * node, in order to make compatibility.
219 : */
220 0 : m_pParserCtxt->nodeTab[m_pParserCtxt->nodeNr - 1]
221 : = m_pParserCtxt->node
222 0 : = pNode;
223 0 : }
224 :
225 0 : xmlDocPtr SAXHelper::getDocument()
226 : {
227 0 : return m_pParserCtxt->myDoc;
228 : }
229 :
230 : /**
231 : * XDocumentHandler -- start an xml document
232 : */
233 0 : void SAXHelper::startDocument( void )
234 : throw( cssxs::SAXException , cssu::RuntimeException )
235 : {
236 : /*
237 : * Adjust inputTab
238 : */
239 0 : xmlParserInputPtr pInput = xmlNewInputStream( m_pParserCtxt ) ;
240 :
241 0 : if( m_pParserCtxt->inputTab != NULL && m_pParserCtxt->inputMax != 0 )
242 : {
243 0 : m_pParserCtxt->inputTab[0] = pInput ;
244 0 : m_pParserCtxt->input = pInput ;
245 : }
246 :
247 0 : m_pSaxHandler->startDocument( m_pParserCtxt ) ;
248 :
249 0 : if( m_pParserCtxt == NULL || m_pParserCtxt->myDoc == NULL )
250 : {
251 0 : throw cssu::RuntimeException() ;
252 : }
253 0 : }
254 :
255 : /**
256 : * XDocumentHandler -- end an xml document
257 : */
258 0 : void SAXHelper::endDocument( void )
259 : throw( cssxs::SAXException , cssu::RuntimeException )
260 : {
261 0 : m_pSaxHandler->endDocument( m_pParserCtxt ) ;
262 0 : }
263 :
264 : /**
265 : * XDocumentHandler -- start an xml element
266 : */
267 0 : void SAXHelper::startElement(
268 : const rtl::OUString& aName,
269 : const cssu::Sequence< cssxcsax::XMLAttribute >& aAttributes )
270 : throw( cssxs::SAXException , cssu::RuntimeException )
271 : {
272 0 : const xmlChar* fullName = NULL ;
273 0 : const xmlChar** attrs = NULL ;
274 :
275 0 : fullName = ous_to_xmlstr( aName ) ;
276 0 : attrs = attrlist_to_nxmlstr( aAttributes ) ;
277 :
278 0 : if( fullName != NULL || attrs != NULL )
279 : {
280 0 : m_pSaxHandler->startElement( m_pParserCtxt , fullName , attrs ) ;
281 : }
282 :
283 0 : if( fullName != NULL )
284 : {
285 0 : xmlFree( ( xmlChar* )fullName ) ;
286 0 : fullName = NULL ;
287 : }
288 :
289 0 : if( attrs != NULL )
290 : {
291 0 : for( int i = 0 ; attrs[i] != NULL ; ++i )
292 : {
293 0 : xmlFree( ( xmlChar* )attrs[i] ) ;
294 0 : attrs[i] = NULL ;
295 : }
296 :
297 0 : xmlFree( ( void* ) attrs ) ;
298 0 : attrs = NULL ;
299 : }
300 0 : }
301 :
302 : /**
303 : * XDocumentHandler -- end an xml element
304 : */
305 0 : void SAXHelper::endElement( const rtl::OUString& aName )
306 : throw( cssxs::SAXException , cssu::RuntimeException )
307 : {
308 0 : xmlChar* fullname = NULL ;
309 :
310 0 : fullname = ous_to_xmlstr( aName ) ;
311 0 : m_pSaxHandler->endElement( m_pParserCtxt , fullname ) ;
312 :
313 0 : if( fullname != NULL )
314 : {
315 0 : xmlFree( ( xmlChar* )fullname ) ;
316 0 : fullname = NULL ;
317 : }
318 0 : }
319 :
320 : /**
321 : * XDocumentHandler -- an xml element or cdata characters
322 : */
323 0 : void SAXHelper::characters( const rtl::OUString& aChars )
324 : throw( cssxs::SAXException , cssu::RuntimeException )
325 : {
326 0 : const xmlChar* chars = NULL ;
327 0 : int length = 0 ;
328 :
329 0 : chars = ous_to_nxmlstr( aChars, length ) ;
330 0 : m_pSaxHandler->characters( m_pParserCtxt , chars , length ) ;
331 :
332 0 : if( chars != NULL )
333 : {
334 0 : xmlFree( ( xmlChar* )chars ) ;
335 : }
336 0 : }
337 :
338 : /**
339 : * XDocumentHandler -- ignorable xml white space
340 : */
341 0 : void SAXHelper::ignorableWhitespace( const rtl::OUString& aWhitespaces )
342 : throw( cssxs::SAXException , cssu::RuntimeException )
343 : {
344 0 : const xmlChar* chars = NULL ;
345 0 : int length = 0 ;
346 :
347 0 : chars = ous_to_nxmlstr( aWhitespaces, length ) ;
348 0 : m_pSaxHandler->ignorableWhitespace( m_pParserCtxt , chars , length ) ;
349 :
350 0 : if( chars != NULL )
351 : {
352 0 : xmlFree( ( xmlChar* )chars ) ;
353 : }
354 0 : }
355 :
356 : /**
357 : * XDocumentHandler -- preaorocessing instruction
358 : */
359 0 : void SAXHelper::processingInstruction(
360 : const rtl::OUString& aTarget,
361 : const rtl::OUString& aData )
362 : throw( cssxs::SAXException , cssu::RuntimeException )
363 : {
364 0 : xmlChar* target = NULL ;
365 0 : xmlChar* data = NULL ;
366 :
367 0 : target = ous_to_xmlstr( aTarget ) ;
368 0 : data = ous_to_xmlstr( aData ) ;
369 :
370 0 : m_pSaxHandler->processingInstruction( m_pParserCtxt , target , data ) ;
371 :
372 0 : if( target != NULL )
373 : {
374 0 : xmlFree( ( xmlChar* )target ) ;
375 0 : target = NULL ;
376 : }
377 :
378 0 : if( data != NULL )
379 : {
380 0 : xmlFree( ( xmlChar* )data ) ;
381 0 : data = NULL ;
382 : }
383 0 : }
384 :
385 : /**
386 : * XDocumentHandler -- set document locator
387 : * In this case, locator is useless.
388 : */
389 0 : void SAXHelper::setDocumentLocator(
390 : const cssu::Reference< cssxs::XLocator > &)
391 : throw( cssxs::SAXException , cssu::RuntimeException )
392 : {
393 0 : }
394 :
395 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|