1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 2; tab-width: 2 -*- */
2 /* gdome-xml-domimpl.c
3  *
4  * Copyright (C) 1999 Raph Levien <raph@acm.org>
5  * Copyright (C) 2000 Mathieu Lacage <mathieu@gnu.org>
6  * Copyright (C) 2000 Anders Carlsson <andersca@gnu.org>
7  * Copyright (C) 2001 Paolo Casarini <paolo@casarini.org>
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22  */
23 
24 #include <string.h>
25 #include <glib.h>
26 #include <libxml/tree.h>
27 #include <libxml/parser.h>
28 #include <libxml/parserInternals.h>
29 #include <libxml/hash.h>
30 #include <libxml/entities.h>
31 #include "gdome.h"
32 #include "gdome-treegc.h"
33 #include "gdome-xml-node.h"
34 #include "gdome-xml-document.h"
35 #include "gdome-xml-documentt.h"
36 #include "gdome-xml-util.h"
37 #include "gdome-xml-xmlutil.h"
38 #include "gdome-xml-domimpl.h"
39 
40 Gdome_xml_DOMImplementation *gdome_xml_DOMImplementation = NULL;
41 
42 /* vtable for the DOMImplementation */
43 const GdomeDOMImplementationVtab gdome_xml_di_vtab = {
44 	gdome_xml_di_ref,
45 	gdome_xml_di_unref,
46 	gdome_xml_di_query_interface,
47 	gdome_xml_di_hasFeature,
48 	gdome_xml_di_createDocumentType,
49 	gdome_xml_di_createDocument,
50 	gdome_xml_di_freeDoc,
51 	gdome_xml_di_createDocFromURI,
52 	gdome_xml_di_createDocFromMemory,
53 	gdome_xml_di_createDocFromURIWithEntitiesTable,
54 	gdome_xml_di_createDocFromMemoryWithEntitiesTable,
55 	gdome_xml_di_saveDocToFile,
56   gdome_xml_di_saveDocToMemory,
57   gdome_xml_di_saveDocToFileEnc,
58   gdome_xml_di_saveDocToMemoryEnc,
59 	gdome_xml_di_enableEvent,
60 	gdome_xml_di_disableEvent,
61 	gdome_xml_di_eventIsEnabled
62 };
63 
64 /**
65  * gdome_xml_di_mkref:
66  *
67  * Constructor of the DOMImplementation interface.
68  * Returns: the reference to the DOMImplementation structure.
69  */
70 GdomeDOMImplementation *
gdome_xml_di_mkref(void)71 gdome_xml_di_mkref (void) {
72 	if (gdome_xml_DOMImplementation == NULL) {
73 		gdome_xml_DOMImplementation = g_new (Gdome_xml_DOMImplementation, 1);
74 		memset(gdome_xml_DOMImplementation, 0, sizeof(Gdome_xml_DOMImplementation));
75 		gdome_xml_DOMImplementation->refcnt = 1;
76 		gdome_xml_DOMImplementation->vtab = &gdome_xml_di_vtab;
77 	} else
78 		gdome_xml_DOMImplementation->refcnt++;
79 
80 	return (GdomeDOMImplementation *)gdome_xml_DOMImplementation;
81 }
82 
83 /**
84  * gdome_xml_di_ref:
85  * @self:  DOMImplementation Object ref
86  * @exc:  Exception Object ref
87  *
88  * Increase the reference count of the DOMImplementation structure.
89  */
90 void
gdome_xml_di_ref(GdomeDOMImplementation * self,GdomeException * exc)91 gdome_xml_di_ref (GdomeDOMImplementation *self,
92                   GdomeException *exc) {
93 	Gdome_xml_DOMImplementation *priv = (Gdome_xml_DOMImplementation *)self;
94 
95 	g_return_if_fail (self != NULL);
96 	g_return_if_fail (exc != NULL);
97 	g_assert(self == (GdomeDOMImplementation *)gdome_xml_DOMImplementation);
98 
99 	priv->refcnt++;
100 }
101 
102 /**
103  * gdome_xml_di_unref:
104  * @self:  DOMImplementation Object ref
105  * @exc:  Exception Object ref
106  *
107  * Decrease the reference count of the DOMImplementation. Free the structure
108  * if DOMImplementation will have zero reference.
109  */
110 void
gdome_xml_di_unref(GdomeDOMImplementation * self,GdomeException * exc)111 gdome_xml_di_unref (GdomeDOMImplementation *self,
112                     GdomeException *exc) {
113 	Gdome_xml_DOMImplementation *priv = (Gdome_xml_DOMImplementation *)self;
114 
115 	g_return_if_fail (self != NULL);
116 	g_return_if_fail (exc != NULL);
117 	g_assert(self == (GdomeDOMImplementation *)gdome_xml_DOMImplementation);
118 
119 	g_assert (priv->refcnt > 0);
120 	priv->refcnt--;
121 
122 	if (priv->refcnt == 0) {
123 		g_free (self);
124 		gdome_xml_DOMImplementation = NULL;
125 	}
126 }
127 
128 /**
129  * gdome_xml_di_query_interface:
130  * @self:  DOMImplementation Object ref
131  * @interface:  interface needed
132  * @exc:  Exception Object ref
133  *
134  * Returns: a reference to this object that implements the @interface needed,
135  *          or %NULL if the @interface is not supported by this Object.
136  */
137 gpointer
gdome_xml_di_query_interface(GdomeDOMImplementation * self,const char * interface,GdomeException * exc)138 gdome_xml_di_query_interface (GdomeDOMImplementation *self, const char *interface, GdomeException *exc)
139 {
140 	Gdome_xml_DOMImplementation *priv = (Gdome_xml_DOMImplementation *)self;
141 
142 	g_return_val_if_fail (priv != NULL, NULL);
143 	g_return_val_if_fail (interface != NULL, NULL);
144 	g_return_val_if_fail (exc != NULL, NULL);
145 	g_assert(self == (GdomeDOMImplementation *)gdome_xml_DOMImplementation);
146 
147 	if (!strcmp (interface, "DOMImplementation")) {
148 		priv->refcnt++;
149 		return self;
150 	}
151 	else
152 		return NULL;
153 }
154 
155 /**
156  * gdome_xml_di_hasFeature:
157  * @self:  The DOMImplementation Object ref
158  * @feature:  The name of the feature to test (case-insensitive).
159  * @version:  This is the version number of the feature to test. In Level 2,
160  *            version 1, this is the string "2.0". If the version is not
161  *            specified, supporting any version of the feature will cause the
162  *            method to return %TRUE.
163  * @exc:  Exception Object ref
164  *
165  * Tests whether the DOM implementation implements a specific feature.
166  * Returns: %TRUE if the feature is supported, %FALSE otherwise.
167  */
168 GdomeBoolean
gdome_xml_di_hasFeature(GdomeDOMImplementation * self,GdomeDOMString * feature,GdomeDOMString * version,GdomeException * exc)169 gdome_xml_di_hasFeature (GdomeDOMImplementation *self,
170                          GdomeDOMString *feature,
171                          GdomeDOMString *version,
172                          GdomeException *exc)
173 {
174 	g_return_val_if_fail (self != NULL, FALSE);
175 	g_return_val_if_fail (feature != NULL, FALSE);
176 	g_return_val_if_fail (exc != NULL, FALSE);
177 	g_assert(self == (GdomeDOMImplementation *)gdome_xml_DOMImplementation);
178 
179 	if (version == NULL)
180 		return TRUE;
181 
182 	if (strcmp (version->str, "1.0") && strcmp (version->str,"2.0"))
183 		return FALSE;
184 
185 	if (!g_strcasecmp(feature->str, "Core") ||
186 			!g_strcasecmp(feature->str, "XML") ||
187 			!g_strcasecmp(feature->str, "Events") ||
188 			!g_strcasecmp(feature->str, "MutationEVents"))
189 		return TRUE;
190 
191 	return FALSE;
192 }
193 
194 /**
195  * gdome_xml_di_createDocumentType:
196  * @self:  The DOMImplementation Object ref
197  * @qualifiedName:  The qualified name of the document type to be created
198  * @publicID:  The external subset public identifier
199  * @systemID:  The external subset system identifier
200  * @exc:  The Exception Object ref
201  *
202  * Creates an empty DocumentType node. Entity declarations and notations are
203  * not made available. Entity reference expansions and default attribute
204  * additions do not occur. It is expected that a future version of the DOM will
205  * provide a way for populating a DocumentType.
206  *
207  * %GDOME_NAMESPACE_ERR: Raised if the qualifiedName is malformed.
208  * Returns: A new DocumentType node.
209  */
210 GdomeDocumentType *
gdome_xml_di_createDocumentType(GdomeDOMImplementation * self,GdomeDOMString * qualifiedName,GdomeDOMString * publicId,GdomeDOMString * systemId,GdomeException * exc)211 gdome_xml_di_createDocumentType (GdomeDOMImplementation *self,
212 																 GdomeDOMString *qualifiedName,
213 																 GdomeDOMString *publicId,
214 																 GdomeDOMString *systemId,
215 																 GdomeException *exc) {
216 	gchar **strs, *localName = NULL;
217 	xmlDtd *n;
218 	xmlChar *pch1 = NULL, *pch2 = NULL;
219 
220 	g_return_val_if_fail (self != NULL, NULL);
221 	g_return_val_if_fail (qualifiedName != NULL, NULL);
222 	if (publicId != NULL)
223 		pch1 = publicId->str;
224 	if (systemId != NULL)
225 		pch2 = systemId->str;
226 	g_return_val_if_fail (exc != NULL, NULL);
227 	g_assert(self == (GdomeDOMImplementation *)gdome_xml_DOMImplementation);
228 
229 	/* test malformed qualifiedName */
230 	strs = g_strsplit((gchar *)qualifiedName->str, ":", 0);
231 	if (strs[0] && strs[1] && strs[2]) {
232 		*exc = GDOME_NAMESPACE_ERR;
233 	} else if (strs[0] && strs[1] && !strs[2]) {
234 		localName = g_strdup(strs[1]);
235 	}
236 	g_strfreev(strs);
237 
238 	if (!*exc) {
239 		/* create the new DTD node */
240 		if (localName != NULL) {
241 			n = xmlCreateIntSubset (NULL, (xmlChar *)localName, pch1, pch2);
242 			g_free(localName);
243 		} else
244 			n = xmlCreateIntSubset (NULL, (xmlChar *)qualifiedName->str, pch1, pch2);
245 
246 		/* FOR THE FUTURE: What about prefix?
247 		 DOM2 specs about DocumentType interface says: "...the effect of namespaces
248 		 and the various XML schema efforts on DTD representation are not clearly
249 		 understood as of this writing." */
250 
251 		return (GdomeDocumentType *)gdome_xml_dt_mkref (n);
252 	} else {
253 		if (localName != NULL)
254 			g_free(localName);
255 		return NULL;
256 	}
257 }
258 
259 /**
260  * gdome_xml_di_createDocument:
261  * @self:  DOMImplementation Object ref
262  * @namespaceURI:  The namespace URI of the document element to create
263  * @qualifiedName:  The qualified name of the document element to be created
264  * @doctype:  The type of document to be created or NULL
265  * @exc:  Exception Object ref
266  *
267  * Creates an XML Document object of the specified type with its document
268  * element.
269  *
270  * %GDOME_NAMESPACE_ERR: Raised if the @qualifiedName is malformed, if the
271  * @qualifiedName has a prefix and the @namespaceURI is %NULL, or if the
272  * @qualifiedName has a prefix that is "xml" and the @namespaceURI is different
273  * from "http://www.w3.org/XML/1998/namespace"
274  * %GDOME_WRONG_DOCUMENT_ERR: Raised if @doctype has already been used with a
275  * different document.
276  * Returns: a new Document node.
277  */
278 GdomeDocument *
gdome_xml_di_createDocument(GdomeDOMImplementation * self,GdomeDOMString * namespaceURI,GdomeDOMString * qualifiedName,GdomeDocumentType * doctype,GdomeException * exc)279 gdome_xml_di_createDocument (GdomeDOMImplementation *self,
280 														 GdomeDOMString *namespaceURI,
281 														 GdomeDOMString *qualifiedName,
282 														 GdomeDocumentType *doctype,
283 														 GdomeException *exc) {
284 	GdomeDocument *ret = NULL;
285 	GdomeElement *docElem;
286 	GdomeNode *result = NULL;
287 
288 	g_return_val_if_fail (self != NULL, NULL);
289 	g_return_val_if_fail (qualifiedName != NULL, NULL);
290 	if (doctype != NULL) {
291 		g_return_val_if_fail (GDOME_XML_IS_DT(doctype), NULL);
292 		if (gdome_xmlGetOwner((xmlNode *)((Gdome_xml_DocumentType *)doctype)->n) != NULL) {
293 			*exc = GDOME_WRONG_DOCUMENT_ERR;
294 			return NULL;
295 		}
296 	}
297 	g_return_val_if_fail (exc != NULL, NULL);
298 	g_assert(self == (GdomeDOMImplementation *)gdome_xml_DOMImplementation);
299 
300 	ret = (GdomeDocument *)gdome_xml_n_mkref ((xmlNode *)xmlNewDoc ("1.0"));
301   g_assert (ret != NULL);
302 
303 	/* Add the doctype */
304 	if (doctype != NULL) {
305 		xmlDtd *n = xmlCreateIntSubset (((Gdome_xml_Document *)ret)->n,
306 																		((Gdome_xml_DocumentType *)doctype)->n->name,
307 																		((Gdome_xml_DocumentType *)doctype)->n->ExternalID,
308 																		((Gdome_xml_DocumentType *)doctype)->n->SystemID);
309 		xmlFreeDtd (((Gdome_xml_DocumentType *)doctype)->n);
310 		((Gdome_xml_DocumentType *)doctype)->n = n;
311 		gdome_treegc_addNode ((GdomeNode *)doctype);
312 	}
313 
314 	docElem = gdome_xml_doc_createElementNS (ret, namespaceURI, qualifiedName, exc);
315 	if (!*exc) {
316 		result = gdome_xml_n_appendChild((GdomeNode *)ret, (GdomeNode *)docElem, exc);
317     g_assert (result != NULL);
318 		gdome_xml_n_unref (result, exc);
319 		gdome_xml_n_unref ((GdomeNode *)docElem, exc);
320 
321     return ret;
322 	} else {
323 		gdome_xml_doc_unref ((GdomeNode *)ret, exc);
324 		return NULL;
325 	}
326 }
327 
328 /**
329  * gdome_xml_di_freeDoc:
330  * @self:  DOMImplementation Object ref
331  * @doc:  The Document Object ref to be freed
332  * @exc:  Exception Object ref
333  *
334  * DEPRECATED!
335  * Free all objects and structures associated to the Document specified.
336  */
337 void
gdome_xml_di_freeDoc(GdomeDOMImplementation * self,GdomeDocument * doc,GdomeException * exc)338 gdome_xml_di_freeDoc (GdomeDOMImplementation *self,
339 											GdomeDocument *doc,
340 											GdomeException *exc) {
341 	Gdome_xml_Document *priv_doc = (Gdome_xml_Document *)doc;
342 
343 	g_return_if_fail (self != NULL);
344 	g_return_if_fail (doc != NULL);
345 	g_return_if_fail (exc != NULL);
346 	g_assert(self == (GdomeDOMImplementation *)gdome_xml_DOMImplementation);
347 
348 	xmlFreeDoc (priv_doc->n);
349 }
350 
351 /**
352  * gdome_xml_di_createDocFromURI:
353  * @self:  DOMImplementation Object ref
354  * @uri:  the uri of XML file to load
355  * @mode:  specifies if the document is to be parsed, validated or recovered
356  *         and if the entity substitution has to be done.
357  * @exc:  Exception Object ref
358  *
359  * Loads a XML Document from a URI and build a DOM tree. If @mode is
360  * %GDOME_LOAD_PARSING the document must be well formed, if @mode is
361  * %GDOME_LOAD_VALIDATING the document must valid and if @mode is
362  * %GDOME_LOAD_RECOVERING a tree is built anyway.
363  * If the %GDOME_LOAD_SUBSTITUTE_ENTITIES flag is added, entity substitution is
364  * performed (es. @mode = %GDOME_LOAD_PARSING | %GDOME_LOAD_SUBSTITUTE_ENTITIES
365  * ).
366  * If the %GDOME_LOAD_COMPLETE_ATTR flag is set, the tree is populated
367  * with default attributes from the DTD.
368  * Returns: The Document Object of the created tree or %NULL if an error occur.
369  */
370 GdomeDocument *
gdome_xml_di_createDocFromURI(GdomeDOMImplementation * self,const char * uri,unsigned int mode,GdomeException * exc)371 gdome_xml_di_createDocFromURI (GdomeDOMImplementation *self,
372 															 const char *uri,
373 															 unsigned int  mode,
374 															 GdomeException *exc) {
375 	int oldvalue =  xmlDoValidityCheckingDefaultValue;
376 	GdomeDocument *ret = NULL;
377 	int prevSubstValue;
378 
379 	g_return_val_if_fail (self != NULL, NULL);
380 	g_return_val_if_fail (uri != NULL, NULL);
381 	g_return_val_if_fail (exc != NULL, NULL);
382 	g_assert(self == (GdomeDOMImplementation *)gdome_xml_DOMImplementation);
383 
384 	if (mode & GDOME_LOAD_SUBSTITUTE_ENTITIES)
385 		prevSubstValue = xmlSubstituteEntitiesDefault (1);
386 	else
387 		prevSubstValue = xmlSubstituteEntitiesDefault (0);
388 
389 	if (mode & GDOME_LOAD_COMPLETE_ATTRS)
390 		xmlLoadExtDtdDefaultValue |= XML_COMPLETE_ATTRS;
391 
392 	switch (mode & (GDOME_LOAD_PARSING |
393 									GDOME_LOAD_VALIDATING |
394 									GDOME_LOAD_RECOVERING)) {
395 	case GDOME_LOAD_PARSING:
396 		xmlDoValidityCheckingDefaultValue = 0;
397 		ret = (GdomeDocument *)gdome_xml_n_mkref ((xmlNode *)xmlParseFile (uri));
398 		break;
399 	case GDOME_LOAD_VALIDATING:
400 		xmlDoValidityCheckingDefaultValue = 1;
401 		ret = (GdomeDocument *)gdome_xml_n_mkref ((xmlNode *)xmlParseFile (uri));
402 		break;
403 	case GDOME_LOAD_RECOVERING:
404 		xmlDoValidityCheckingDefaultValue = 0;
405 		ret = (GdomeDocument *)gdome_xml_n_mkref ((xmlNode *)xmlRecoverFile (uri));
406 		break;
407 	}
408 
409 	xmlSubstituteEntitiesDefault (prevSubstValue);
410 	xmlDoValidityCheckingDefaultValue = oldvalue;
411 	return ret;
412 }
413 
414 /**
415  * gdome_xml_di_createDocFromMemory:
416  * @self:  DOMImplementation Object ref
417  * @buffer:  a pointer to char array that holds the XML document
418  * @mode:  specifies if the document is to be parsed, validated or recovered
419  *         and if the entity substitution has to be done.
420  * @exc:  Exception Object ref
421  *
422  * Loads a XML Document from a memory buffer and build a DOM tree. If @mode is
423  * %GDOME_LOAD_PARSING the document must be well formed, if @mode is
424  * %GDOME_LOAD_VALIDATING the document must valid and if @mode is
425  * %GDOME_LOAD_RECOVERING a tree is built anyway.
426  * If the %GDOME_LOAD_SUBSTITUTE_ENTITIES flag is added, entity substitution is
427  * performed (es. @mode = %GDOME_LOAD_PARSING | %GDOME_LOAD_SUBSTITUTE_ENTITIES
428  * ).
429  * If the %GDOME_LOAD_COMPLETE_ATTR flag is set, the tree is populated
430  * with default attributes from the DTD.
431  * Returns: The Document Object of the created tree or %NULL if an error occur.
432  */
433 GdomeDocument *
gdome_xml_di_createDocFromMemory(GdomeDOMImplementation * self,char * buffer,unsigned int mode,GdomeException * exc)434 gdome_xml_di_createDocFromMemory (GdomeDOMImplementation *self,
435 																	char *buffer,
436 																	unsigned int mode,
437 																	GdomeException *exc) {
438 	int oldvalue =  xmlDoValidityCheckingDefaultValue;
439 	GdomeDocument *ret = NULL;
440 	int size;
441 	int prevSubstValue;
442 
443 	g_return_val_if_fail (self != NULL, NULL);
444 	g_return_val_if_fail (buffer != NULL, NULL);
445 	g_return_val_if_fail (exc != NULL, NULL);
446 	g_assert(self == (GdomeDOMImplementation *)gdome_xml_DOMImplementation);
447 
448 	size = strlen (buffer);
449 
450 	if (mode & GDOME_LOAD_SUBSTITUTE_ENTITIES)
451 		prevSubstValue = xmlSubstituteEntitiesDefault (1);
452 	else
453 		prevSubstValue = xmlSubstituteEntitiesDefault (0);
454 
455 	if (mode & GDOME_LOAD_COMPLETE_ATTRS)
456 		xmlLoadExtDtdDefaultValue |= XML_COMPLETE_ATTRS;
457 
458 	switch (mode & (GDOME_LOAD_PARSING |
459 									GDOME_LOAD_VALIDATING |
460 									GDOME_LOAD_RECOVERING)) {
461 	case GDOME_LOAD_PARSING:
462 		xmlDoValidityCheckingDefaultValue = 0;
463 		ret = (GdomeDocument *)gdome_xml_n_mkref ((xmlNode *)xmlParseMemory (buffer, size));
464 		break;
465 	case GDOME_LOAD_VALIDATING:
466 		xmlDoValidityCheckingDefaultValue = 1;
467 		ret = (GdomeDocument *)gdome_xml_n_mkref ((xmlNode *)xmlParseMemory (buffer, size));
468 		break;
469 	case GDOME_LOAD_RECOVERING:
470 		xmlDoValidityCheckingDefaultValue = 0;
471 		ret = (GdomeDocument *)gdome_xml_n_mkref ((xmlNode *)xmlRecoverMemory (buffer, size));
472 		break;
473 	}
474 
475 	xmlSubstituteEntitiesDefault (prevSubstValue);
476 	xmlDoValidityCheckingDefaultValue = oldvalue;
477 	return ret;
478 }
479 
480 /* Helper variables and function for WithEntityTable APIs*/
481 static getEntitySAXFunc default_entity_resolver;
482 static xmlHashTable *pfwet_entities;
483 
484 static xmlEntity *
pfwet_entity_resolver(void * ctxt,const xmlChar * name)485 pfwet_entity_resolver(void* ctxt, const xmlChar *name) {
486 	xmlEntity *entity = NULL;
487 
488 	if (default_entity_resolver != NULL)
489 		entity = default_entity_resolver(ctxt, name);
490 	if (entity == NULL)
491 		entity = (xmlEntity *)xmlHashLookup(pfwet_entities, name);
492 	if (entity == NULL)
493 		fprintf (stderr, "Entity %s not found!\n", name);
494 
495 	return entity;
496 }
497 
498 /**
499  * gdome_xml_di_createDocFromURIWithEntitiesTable:
500  * @self:  DOMImplementation Object ref
501  * @uri:  the uri of XML file to load
502  * @entityTable:  array of #GdomeEntitiesTableEntry that define name, value,
503  *                publicID ans systemID of entities used but not declared
504  *                in DTD. The array must be NULL terminated.
505  * @mode:  specifies if the document is to be parsed, validated or recovered
506  *         and if the entity substitution has to be done.
507  * @exc:  Exception Object ref
508  *
509  * Loads a XML Document using also entity declaration specified in @entityTable
510  * from a URI and build a DOM tree. If @mode is %GDOME_LOAD_PARSING the
511  * document must be well formed, if @mode is %GDOME_LOAD_VALIDATING the
512  * document must valid and if @mode is %GDOME_LOAD_RECOVERING a tree is built
513  * anyway.
514  * If the %GDOME_LOAD_SUBSTITUTE_ENTITIES flag is added, entity substitution is
515  * performed (es. @mode = %GDOME_LOAD_PARSING | %GDOME_LOAD_SUBSTITUTE_ENTITIES
516  * ).
517  * If the %GDOME_LOAD_COMPLETE_ATTR flag is set, the tree is populated
518  * with default attributes from the DTD.
519  * Returns: The Document Object of the created tree or %NULL if an error occur.
520  */
521 GdomeDocument *
gdome_xml_di_createDocFromURIWithEntitiesTable(GdomeDOMImplementation * self,const char * uri,const GdomeEntitiesTableEntry entityTable[],unsigned int mode,GdomeException * exc)522 gdome_xml_di_createDocFromURIWithEntitiesTable (GdomeDOMImplementation *self,
523                                                 const char *uri,
524                                                 const GdomeEntitiesTableEntry entityTable[],
525                                                 unsigned int mode,
526                                                 GdomeException *exc) {
527 	int oldvalue =  xmlDoValidityCheckingDefaultValue;
528 	xmlParserCtxt *ctxt;
529 	xmlDoc *doc;
530 	int i, recovery = 0;
531 	int prevSubstValue;
532 
533 	g_return_val_if_fail (self != NULL, NULL);
534 	g_return_val_if_fail (uri != NULL, NULL);
535 	g_return_val_if_fail (entityTable != NULL, NULL);
536 	g_return_val_if_fail (exc != NULL, NULL);
537 	g_assert(self == (GdomeDOMImplementation *)gdome_xml_DOMImplementation);
538 
539 	if (mode & GDOME_LOAD_SUBSTITUTE_ENTITIES)
540 		prevSubstValue = xmlSubstituteEntitiesDefault (1);
541 	else
542 		prevSubstValue = xmlSubstituteEntitiesDefault (0);
543 
544 	if (mode & GDOME_LOAD_COMPLETE_ATTRS)
545 		xmlLoadExtDtdDefaultValue |= XML_COMPLETE_ATTRS;
546 
547 	switch (mode & (GDOME_LOAD_PARSING |
548 									GDOME_LOAD_VALIDATING |
549 									GDOME_LOAD_RECOVERING)) {
550 	case GDOME_LOAD_PARSING:
551 		xmlDoValidityCheckingDefaultValue = 0;
552 		recovery = 0;
553 		break;
554 	case GDOME_LOAD_VALIDATING:
555 		xmlDoValidityCheckingDefaultValue = 1;
556 		recovery = 0;
557 		break;
558 	case GDOME_LOAD_RECOVERING:
559 		xmlDoValidityCheckingDefaultValue = 0;
560 		recovery = 1;
561 		break;
562 	}
563 
564 	/* Create the Parser Context and Set the sax getEntity function */
565 	ctxt = xmlCreateFileParserCtxt(uri);
566 	if (ctxt == NULL)
567 		return NULL;
568 	g_assert (ctxt->sax != NULL);
569   default_entity_resolver = ctxt->sax->getEntity;
570 	ctxt->sax->getEntity = pfwet_entity_resolver;
571 
572 	/* Create the hash Table of entities from entityTable */
573 	if ((doc = xmlNewDoc ("1.0")) == NULL)
574 		return NULL;
575 	if (xmlCreateIntSubset(doc, NULL, NULL, NULL) == NULL)
576 		return NULL;
577 	for (i=0; entityTable[i].name != NULL; i++) {
578 		xmlAddDocEntity (doc, entityTable[i].name, XML_INTERNAL_GENERAL_ENTITY,
579 										 entityTable[i].publicID, entityTable[i].systemID, entityTable[i].value);
580 	}
581 	pfwet_entities = doc->intSubset->entities;
582 
583 	/* Parse the XML document */
584 	xmlParseDocument(ctxt);
585 	xmlFreeDoc (doc);
586 	if ((ctxt->wellFormed) || recovery)
587 		doc = ctxt->myDoc;
588 	else {
589 		doc = NULL;
590 		xmlFreeDoc(ctxt->myDoc);
591 		ctxt->myDoc = NULL;
592 	}
593 	xmlFreeParserCtxt(ctxt);
594 
595 	xmlSubstituteEntitiesDefault (prevSubstValue);
596 	xmlDoValidityCheckingDefaultValue = oldvalue;
597 	return (GdomeDocument *)gdome_xml_n_mkref ((xmlNode *)doc);
598 }
599 
600 /**
601  * gdome_xml_di_createDocFromMemoryWithEntitiesTable:
602  * @self:  DOMImplementation Object ref
603  * @buffer:  a pointer to char array that holds the XML document
604  * @entityTable:  array of #GdomeEntitiesTableEntry that define name, value,
605  *                publicID ans systemID of entities used but not declared
606  *                in DTD. The array must be NULL terminated.
607  * @mode:  specifies if the document is to be parsed, validated or recovered
608  *         and if the entity substitution has to be done.
609  * @exc:  Exception Object ref
610  *
611  * Loads a XML Document using also entity declaration specified in @entityTable
612  * from a memory buffer and build a DOM tree. If @mode is %GDOME_LOAD_PARSING
613  * the document must be well formed, if @mode is %GDOME_LOAD_VALIDATING the
614  * document must valid and if @mode is %GDOME_LOAD_RECOVERING a tree is built
615  * anyway.
616  * If the %GDOME_LOAD_SUBSTITUTE_ENTITIES flag is added, entity substitution is
617  * performed (es. @mode = %GDOME_LOAD_PARSING | %GDOME_LOAD_SUBSTITUTE_ENTITIES
618  * ).
619  * If the %GDOME_LOAD_COMPLETE_ATTR flag is set, the tree is populated
620  * with default attributes from the DTD.
621  * Returns: The Document Object of the created tree or %NULL if an error occur.
622  */
623 GdomeDocument *
gdome_xml_di_createDocFromMemoryWithEntitiesTable(GdomeDOMImplementation * self,char * buffer,const GdomeEntitiesTableEntry entityTable[],unsigned int mode,GdomeException * exc)624 gdome_xml_di_createDocFromMemoryWithEntitiesTable (GdomeDOMImplementation *self,
625 																									 char *buffer,
626 																									 const GdomeEntitiesTableEntry entityTable[],
627 																									 unsigned int mode,
628 																									 GdomeException *exc) {
629 	int oldvalue =  xmlDoValidityCheckingDefaultValue;
630 	xmlParserCtxt *ctxt;
631 	xmlDoc *doc;
632 	int i, recovery = 0, size;
633 	int prevSubstValue;
634 
635 	g_return_val_if_fail (self != NULL, NULL);
636 	g_return_val_if_fail (buffer != NULL, NULL);
637 	g_return_val_if_fail (entityTable != NULL, NULL);
638 	g_return_val_if_fail (exc != NULL, NULL);
639 	g_assert(self == (GdomeDOMImplementation *)gdome_xml_DOMImplementation);
640 
641 	size = strlen (buffer);
642 
643 	if (mode & GDOME_LOAD_SUBSTITUTE_ENTITIES)
644 		prevSubstValue = xmlSubstituteEntitiesDefault (1);
645 	else
646 		prevSubstValue = xmlSubstituteEntitiesDefault (0);
647 
648 	if (mode & GDOME_LOAD_COMPLETE_ATTRS)
649 		xmlLoadExtDtdDefaultValue |= XML_COMPLETE_ATTRS;
650 
651 	switch (mode & (GDOME_LOAD_PARSING |
652 									GDOME_LOAD_VALIDATING |
653 									GDOME_LOAD_RECOVERING)) {
654 	case GDOME_LOAD_PARSING:
655 		xmlDoValidityCheckingDefaultValue = 0;
656 		recovery = 0;
657 		break;
658 	case GDOME_LOAD_VALIDATING:
659 		xmlDoValidityCheckingDefaultValue = 1;
660 		recovery = 0;
661 		break;
662 	case GDOME_LOAD_RECOVERING:
663 		xmlDoValidityCheckingDefaultValue = 0;
664 		recovery = 1;
665 		break;
666 	}
667 
668 	/* Create the Parser Context and Set the sax getEntity function */
669 	ctxt = xmlCreateMemoryParserCtxt(buffer, size);
670 	if (ctxt == NULL)
671 		return NULL;
672 	g_assert (ctxt->sax != NULL);
673   default_entity_resolver = ctxt->sax->getEntity;
674 	ctxt->sax->getEntity = pfwet_entity_resolver;
675 
676 	/* Create the hash Table of entities from entityTable */
677 	if ((doc = xmlNewDoc ("1.0")) == NULL)
678 		return NULL;
679 	if (xmlCreateIntSubset(doc, NULL, NULL, NULL) == NULL)
680 		return NULL;
681 	for (i=0; entityTable[i].name != NULL; i++) {
682 		xmlAddDocEntity (doc, entityTable[i].name, XML_INTERNAL_GENERAL_ENTITY,
683 										 entityTable[i].publicID, entityTable[i].systemID, entityTable[i].value);
684 	}
685 	pfwet_entities = doc->intSubset->entities;
686 
687 	/* Parse the XML document */
688 	xmlParseDocument(ctxt);
689 	xmlFreeDoc (doc);
690 	if ((ctxt->wellFormed) || recovery)
691 		doc = ctxt->myDoc;
692 	else {
693 		doc = NULL;
694 		xmlFreeDoc(ctxt->myDoc);
695 		ctxt->myDoc = NULL;
696 	}
697 	xmlFreeParserCtxt(ctxt);
698 
699 	xmlSubstituteEntitiesDefault (prevSubstValue);
700 	xmlDoValidityCheckingDefaultValue = oldvalue;
701 	return (GdomeDocument *)gdome_xml_n_mkref ((xmlNode *)doc);
702 }
703 
704 /**
705  * gdome_xml_di_saveDocToFile:
706  * @self:  DOMImplementation Object ref
707  * @doc:  the Document of which the tree is wanted to be saved
708  * @filename:  the XML filename to save
709  * @mode:  the indentation mode wanted
710  * @exc:  Exception Object ref
711  *
712  * Save the DOM tree of the Document specified to file.
713  * Returns: %FALSE in case of failure, %TRUE otherwise.
714  */
715 GdomeBoolean
gdome_xml_di_saveDocToFile(GdomeDOMImplementation * self,GdomeDocument * doc,const char * filename,GdomeSavingCode mode,GdomeException * exc)716 gdome_xml_di_saveDocToFile (GdomeDOMImplementation *self, GdomeDocument *doc,
717                             const char *filename, GdomeSavingCode mode,
718                             GdomeException *exc)
719 {
720 	Gdome_xml_Document *priv_doc = (Gdome_xml_Document *)doc;
721 
722 	g_return_val_if_fail (self != NULL, FALSE);
723 	g_return_val_if_fail (doc != NULL, FALSE);
724 	g_return_val_if_fail (filename != NULL, FALSE);
725 	g_return_val_if_fail (exc != NULL, FALSE);
726 	g_assert(self == (GdomeDOMImplementation *)gdome_xml_DOMImplementation);
727 
728 	return (xmlSaveFormatFile (filename, priv_doc->n, mode) != -1);
729 }
730 
731 /**
732  * gdome_xml_di_saveDocToFileEnc:
733  * @self:  DOMImplementation Object ref
734  * @doc:  the Document of which the tree is wanted to be saved
735  * @filename:  the XML filename to save
736  * @encoding:  character encoding to use when generating XML text
737  * @mode:  the indentation mode wanted
738  * @exc:  Exception Object ref
739  *
740  * Save the DOM tree of the Document specified to file with the specified
741  * Character encoding.
742  * Returns: %FALSE in case of failure, %TRUE otherwise.
743  */
744 GdomeBoolean
gdome_xml_di_saveDocToFileEnc(GdomeDOMImplementation * self,GdomeDocument * doc,const char * filename,const char * encoding,GdomeSavingCode mode,GdomeException * exc)745 gdome_xml_di_saveDocToFileEnc (GdomeDOMImplementation *self, GdomeDocument *doc,
746                                const char *filename, const char *encoding,
747                                GdomeSavingCode mode, GdomeException *exc)
748 {
749 	Gdome_xml_Document *priv_doc = (Gdome_xml_Document *)doc;
750 
751 	g_return_val_if_fail (self != NULL, FALSE);
752 	g_return_val_if_fail (doc != NULL, FALSE);
753 	g_return_val_if_fail (filename != NULL, FALSE);
754 	g_return_val_if_fail (exc != NULL, FALSE);
755 	g_assert(self == (GdomeDOMImplementation *)gdome_xml_DOMImplementation);
756 
757 	return (xmlSaveFormatFileEnc (filename, priv_doc->n, encoding, mode) != -1);
758 }
759 
760 /**
761  * gdome_xml_di_saveDocToMemory:
762  * @self:  DOMImplementation Object ref
763  * @doc:  the Document of which the tree is wanted to be saved
764  * @mem:  the memory pointer where the saved document is returned
765  * @mode:  the indentation mode wanted
766  * @exc:  Exception Object ref
767  *
768  * Save the DOM tree of the Document specified to a new allocated memory and
769  * return it in the @mem pointer.
770  * Returns: %FALSE in case of failure, %TRUE otherwise.
771  */
772 GdomeBoolean
gdome_xml_di_saveDocToMemory(GdomeDOMImplementation * self,GdomeDocument * doc,char ** mem,GdomeSavingCode mode,GdomeException * exc)773 gdome_xml_di_saveDocToMemory (GdomeDOMImplementation *self, GdomeDocument *doc,
774 															char **mem, GdomeSavingCode mode,
775 															GdomeException *exc)
776 {
777 	Gdome_xml_Document *priv_doc = (Gdome_xml_Document *)doc;
778 	int size = 0;
779 
780 	g_return_val_if_fail (self != NULL, FALSE);
781 	g_return_val_if_fail (doc != NULL, FALSE);
782 	g_return_val_if_fail (mem != NULL, FALSE);
783 	g_return_val_if_fail (exc != NULL, FALSE);
784 	g_assert(self == (GdomeDOMImplementation *)gdome_xml_DOMImplementation);
785 
786 	xmlDocDumpFormatMemory(priv_doc->n, (xmlChar **)mem, &size, mode);
787 	if ((mem == NULL) && (size > 0))
788 		return FALSE;
789 	else
790 		return TRUE;
791 }
792 
793 /**
794  * gdome_xml_di_saveDocToMemoryEnc:
795  * @self:  DOMImplementation Object ref
796  * @doc:  the Document of which the tree is wanted to be saved
797  * @mem:  the memory pointer where the saved document is returned
798  * @encoding:  character encoding to use when generating XML text
799  * @mode:  the indentation mode wanted
800  * @exc:  Exception Object ref
801  *
802  * Save the DOM tree of the Document specified using the specified character
803  * encoding standard to a new allocated memory and return it in the @mem
804  * pointer.
805  * Returns: %FALSE in case of failure, %TRUE otherwise.
806  */
807 GdomeBoolean
gdome_xml_di_saveDocToMemoryEnc(GdomeDOMImplementation * self,GdomeDocument * doc,char ** mem,const char * encoding,GdomeSavingCode mode,GdomeException * exc)808 gdome_xml_di_saveDocToMemoryEnc (GdomeDOMImplementation *self, GdomeDocument *doc,
809                                  char **mem, const char *encoding,
810                                  GdomeSavingCode mode, GdomeException *exc)
811 {
812 	Gdome_xml_Document *priv_doc = (Gdome_xml_Document *)doc;
813 	int size = 0;
814 
815 	g_return_val_if_fail (self != NULL, FALSE);
816 	g_return_val_if_fail (doc != NULL, FALSE);
817 	g_return_val_if_fail (mem != NULL, FALSE);
818 	g_return_val_if_fail (encoding != NULL, FALSE);
819 	g_return_val_if_fail (exc != NULL, FALSE);
820 	g_assert(self == (GdomeDOMImplementation *)gdome_xml_DOMImplementation);
821 
822 	xmlDocDumpFormatMemoryEnc(priv_doc->n, (xmlChar **)mem, &size, encoding, mode);
823 	if ((mem == NULL) && (size > 0))
824 		return FALSE;
825 	else
826 		return TRUE;
827 }
828 
829 /**
830  * gdome_xml_di_enableEvent:
831  * @self:  DOMImplementation Object ref
832  * @doc:  the Document on which we want to enable events
833  * @name:  the name of the event type to enable
834  * @exc:  Exception Object ref
835  *
836  * Enables the propagation of the event type specified.
837  */
838 void
gdome_xml_di_enableEvent(GdomeDOMImplementation * self,GdomeDocument * doc,const char * name,GdomeException * exc)839 gdome_xml_di_enableEvent (GdomeDOMImplementation *self, GdomeDocument *doc,
840 													const char *name,
841 													GdomeException *exc)
842 {
843 	g_return_if_fail (self != NULL);
844 	g_return_if_fail (doc != NULL);
845 	g_return_if_fail (name != NULL);
846 
847 	gdome_xml_doc_enableEventByName(doc, name);
848 }
849 
850 /**
851  * gdome_xml_di_disableEvent:
852  * @self:  DOMImplementation Object ref
853  * @doc:  the Document on which we want to disable events
854  * @name:  the name of the event type to disable
855  * @exc:  Exception Object ref
856  *
857  * Disables the propagation of the event type specified.
858  */
859 void
gdome_xml_di_disableEvent(GdomeDOMImplementation * self,GdomeDocument * doc,const char * name,GdomeException * exc)860 gdome_xml_di_disableEvent (GdomeDOMImplementation *self, GdomeDocument *doc,
861 													 const char *name,
862 													 GdomeException *exc)
863 {
864 	g_return_if_fail (self != NULL);
865 	g_return_if_fail (doc != NULL);
866 	g_return_if_fail (name != NULL);
867 
868 	gdome_xml_doc_disableEventByName(doc, name);
869 }
870 
871 /**
872  * gdome_xml_di_eventIsEnabled:
873  * @self:  DOMImplementation Object ref
874  * @doc:  the Document on which we want to make the check
875  * @name:  the name of the event type to check
876  * @exc:  Exception Object ref
877  *
878  * Checks if the specified event type is enabled.
879  * Returns: %TRUE if the event type specified is enabled, %FALSE otherwise.
880  */
881 GdomeBoolean
gdome_xml_di_eventIsEnabled(GdomeDOMImplementation * self,GdomeDocument * doc,const char * name,GdomeException * exc)882 gdome_xml_di_eventIsEnabled (GdomeDOMImplementation *self, GdomeDocument *doc,
883 														 const char *name,
884 														 GdomeException *exc)
885 {
886 	g_return_val_if_fail (self != NULL, FALSE);
887 	g_return_val_if_fail (doc != NULL, FALSE);
888 	g_return_val_if_fail (name != NULL, FALSE);
889 
890 	return gdome_xml_doc_eventEnabledByName(doc, name);
891 }
892