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