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