1 /* domc document object model library in c
2  * Copyright (c) 2001 Michael B. Allen <mballen@erols.com>
3  *
4  * The MIT License
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the "Software"),
8  * to deal in the Software without restriction, including without limitation
9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10  * and/or sell copies of the Software, and to permit persons to whom the
11  * Software is furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included
14  * in all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22  * OTHER DEALINGS IN THE SOFTWARE.
23  */
24 
25 /* expatls.c - DOM_DocumentLS
26  */
27 #include <limits.h>
28 #include <ctype.h>
29 #include <stdio.h>
30 #include "xmlparse.h"
31 #include "stack.h"
32 #include "dom.h"
33 
34 const char *SP = "                                ";
35 #define INDENT(n) ((n) > 8 ? SP : (SP + (32 - (n) * 4)))
36 #define BUF_SIZ 8192
37 
38 void
start_fn(void * userData,const XML_Char * name,const XML_Char ** atts)39 start_fn(void *userData, const XML_Char *name, const XML_Char **atts)
40 {
41 	struct stack *stk = (struct stack *) userData;
42 	DOM_Node *parent, *child;
43 	int i;
44 
45 	if (stk == NULL || name == NULL || atts == NULL) {
46 		DOM_Exception = DOM_NULL_POINTER_ERR;
47 		return;
48 	}
49 
50 	parent = (DOM_Node *) stack_peek(stk);
51 	if (parent == NULL) {
52 		DOM_Exception = DOM_SYSTEM_ERR;
53 		return;
54 	}
55 	child = DOM_Document_createElement(parent->ownerDocument, name);
56 	if (child == NULL) {
57 		return;
58 	}
59 	for (i = 0; atts[i]; i += 2) {
60 		DOM_Element_setAttribute(child, atts[i], atts[i + 1]);
61 		if (DOM_Exception) {
62 			return;
63 		}
64 	}
65 	if (DOM_Node_appendChild(parent, child) == NULL) {
66 		return;
67 	}
68 	if (stack_push(stk, child) == 0) {
69 		DOM_Exception = DOM_SYSTEM_ERR;
70 	}
71 }
72 void
end_fn(void * userData,const XML_Char * name)73 end_fn(void *userData, const XML_Char *name)
74 {
75 	stack_pop((struct stack *)userData);
76 }
77 void
chardata_fn(void * userData,const XML_Char * s,int len)78 chardata_fn(void *userData, const XML_Char *s, int len)
79 {
80 	struct stack *stk = (struct stack *) userData;
81 	DOM_String *str;
82 	DOM_Text *tex;
83 	DOM_Node *parent;
84 
85 	if (stk == NULL || s == NULL || len == 0) {
86 		DOM_Exception = DOM_NULL_POINTER_ERR;
87 		return;
88 	}
89 
90 	parent = (DOM_Node *) stack_peek(stk);
91 	if (parent == NULL) {
92 		DOM_Exception = DOM_SYSTEM_ERR;
93 		return;
94 	}
95 	if ((str = (DOM_String *) malloc(len + 1)) == NULL) {
96 		DOM_Exception = DOM_NO_MEMORY_ERR;
97 		return;
98 	}
99 	memcpy(str, s, len);
100 	str[len] = '\0';
101 	tex = DOM_Document_createTextNode(parent->ownerDocument, str);
102 	free(str);
103 	if (tex == NULL) {
104 		return;
105 	}
106 
107 	DOM_Node_appendChild(parent, tex);
108 	if (DOM_Exception) {
109 		DOM_Document_destroyNode(parent->ownerDocument, tex);
110 	}
111 }
112 void
comment_fn(void * userData,const XML_Char * s)113 comment_fn(void *userData, const XML_Char *s)
114 {
115 	struct stack *stk = (struct stack *) userData;
116 	DOM_Comment *com;
117 	DOM_Node *parent;
118 
119 	parent = (DOM_Node *) stack_peek(stk);
120 	if (parent == NULL) {
121 		DOM_Exception = DOM_SYSTEM_ERR;
122 		return;
123 	}
124 	if ((com = DOM_Document_createComment(parent->ownerDocument, s))) {
125 		DOM_Node_appendChild(parent, com);
126 		if (DOM_Exception) {
127 			DOM_Document_destroyNode(parent->ownerDocument, com);
128 		}
129 	}
130 }
131 void
processing_fn(void * userData,const XML_Char * target,const XML_Char * data)132 processing_fn(void *userData, const XML_Char *target, const XML_Char *data)
133 {
134 	struct stack *stk = (struct stack *) userData;
135 	DOM_ProcessingInstruction *pi;
136 	DOM_Node *parent;
137 
138 	parent = (DOM_Node *) stack_peek(stk);
139 	if (parent == NULL) {
140 		DOM_Exception = DOM_SYSTEM_ERR;
141 		return;
142 	}
143 	if ((pi = DOM_Document_createProcessingInstruction(parent->ownerDocument, target, data))) {
144 		DOM_Node_appendChild(parent, pi);
145 		if (DOM_Exception) {
146 			DOM_Document_destroyNode(parent->ownerDocument, pi);
147 		}
148 	}
149 }
150 int
DOM_DocumentLS_load(DOM_Document * doc,const DOM_String * uri)151 DOM_DocumentLS_load(DOM_Document *doc, const DOM_String *uri)
152 {
153 	FILE *fd;
154 	XML_Parser p;
155 	struct stack *stk;
156 	size_t n;	// was ssize_t (DBL)
157 	void *buf;
158 	int ret, done;
159 
160 	DOM_Exception=DOM_NO_ERR; //line added by DBL
161 
162 	if (doc == NULL || uri == NULL) {
163 		DOM_Exception = DOM_NULL_POINTER_ERR;
164 		return 0;
165 	}
166 
167 	fd = fopen(uri, "r");
168 	if (fd == NULL) {
169 		DOM_Exception = DOM_SYSTEM_ERR;
170 		return 0;
171 	}
172 
173 	p = XML_ParserCreate(NULL);
174 	if (p == NULL) {
175 		DOM_Exception = DOM_XML_PARSER_ERR;
176 		fclose(fd);
177 		return 0;
178 	}
179 
180 	stk = stack_new(INT_MAX);
181 	if (stk == NULL || stack_push(stk, doc) == 0) {
182 		DOM_Exception = DOM_SYSTEM_ERR;
183 		XML_ParserFree(p);
184 		fclose(fd);
185 		stack_del(stk, NULL);
186 		return 0;
187 	}
188 
189 	XML_SetElementHandler(p, start_fn, end_fn);
190 	XML_SetCharacterDataHandler(p, chardata_fn);
191 	XML_SetCommentHandler(p, comment_fn);
192 	XML_SetProcessingInstructionHandler(p , processing_fn);
193 	XML_SetUserData(p, stk);
194 
195 	ret = 1;
196 	for ( ;; ) {
197 		if ((buf = XML_GetBuffer(p, BUF_SIZ)) == NULL) {
198 			DOM_Exception = DOM_NO_MEMORY_ERR;
199 			ret = 0;
200 			break;
201 		}
202 		if ((n = fread(buf, 1, BUF_SIZ, fd)) == 0 && ferror(fd)) {
203 			DOM_Exception = DOM_SYSTEM_ERR;
204 			ret = 0;
205 			break;
206 		}
207 		if (XML_ParseBuffer(p, (int) n, (done = feof(fd))) == 0 || DOM_Exception) {
208 			if (DOM_Exception == 0) {
209 				DOM_Exception = DOM_XML_PARSER_ERR;
210 			}
211 			ret = 0;
212 			break;
213 		}
214 		if (done) {
215 			break;
216 		}
217 	}
218 
219 	stack_del(stk, NULL);
220 	XML_ParserFree(p);
221 	fclose(fd);
222 
223 	return ret;
224 }
225 
226 
227 void
DocumentLS_save(FILE * fd,const DOM_Node * node,int indent)228 DocumentLS_save(FILE *fd, const DOM_Node *node, int indent)
229 {
230 	NodeEntry *e;
231 	DOM_Node *c;
232 
233     if (fd == NULL || node == NULL) {
234 		return;
235     }
236 
237     switch (node->nodeType) {
238         case DOM_ELEMENT_NODE:
239             fprintf(fd, "%s<%s", INDENT(indent), node->nodeName);
240 			for (e = node->attributes->first; e != NULL; e = e->next) {
241 				fprintf(fd, " %s=\"%s\"", e->node->nodeName, e->node->nodeValue);
242 			}
243 			if (DOM_Node_hasChildNodes(node)) {
244 				fprintf(fd, ">\n");
245 				for (c = node->firstChild; c != NULL; c = c->nextSibling) {
246 					DocumentLS_save(fd, c, indent + 1);
247             	}
248             	fprintf(fd, "%s</%s>\n", INDENT(indent), node->nodeName);
249 			} else {
250 				fprintf(fd, "/>\n");
251 			}
252             break;
253         case DOM_ATTRIBUTE_NODE:
254             break;
255         case DOM_TEXT_NODE:
256             fprintf(fd, "%s\n", node->nodeValue);
257             break;
258         case DOM_CDATA_SECTION_NODE:
259             break;
260         case DOM_ENTITY_REFERENCE_NODE:
261             break;
262         case DOM_ENTITY_NODE:
263             break;
264         case DOM_PROCESSING_INSTRUCTION_NODE:
265             break;
266         case DOM_COMMENT_NODE:
267 			fprintf(fd, "%s<!--%s-->\n", INDENT(indent), node->nodeValue);
268             break;
269         case DOM_DOCUMENT_NODE:
270             DocumentLS_save(fd, node->u.Document.documentElement, 0);
271             break;
272         case DOM_DOCUMENT_TYPE_NODE:
273             break;
274         case DOM_DOCUMENT_FRAGMENT_NODE:
275             break;
276         case DOM_NOTATION_NODE:
277             break;
278     }
279 }
280 int
DOM_DocumentLS_save(DOM_Document * doc,const DOM_String * uri,const DOM_Node * node)281 DOM_DocumentLS_save(DOM_Document *doc, const DOM_String *uri, const DOM_Node *node)
282 {
283 	FILE *fd;
284 
285 	if (doc == NULL && node == NULL) {
286 		DOM_Exception = DOM_NULL_POINTER_ERR;
287 		return 0;
288 	}
289 
290 	fd = fopen(uri, "w");
291 	if (fd) {
292 		DocumentLS_save(fd, doc ? doc : node, 0);
293 		fclose(fd);
294 		return 1;
295 	}
296 
297 	return 0;
298 }
299