1: /* $Id: minixml.c,v 1.1.1.1 2023/09/27 11:25:11 misho Exp $ */
2: /* vim: tabstop=4 shiftwidth=4 noexpandtab
3: * minixml.c : the minimum size a xml parser can be ! */
4: /* Project : miniupnp
5: * webpage: http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
6: * Author : Thomas Bernard
7:
8: Copyright (c) 2005-2017, Thomas BERNARD
9: All rights reserved.
10:
11: Redistribution and use in source and binary forms, with or without
12: modification, are permitted provided that the following conditions are met:
13:
14: * Redistributions of source code must retain the above copyright notice,
15: this list of conditions and the following disclaimer.
16: * Redistributions in binary form must reproduce the above copyright notice,
17: this list of conditions and the following disclaimer in the documentation
18: and/or other materials provided with the distribution.
19: * The name of the author may not be used to endorse or promote products
20: derived from this software without specific prior written permission.
21:
22: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23: AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24: IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25: ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
26: LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27: CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28: SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29: INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30: CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31: ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32: POSSIBILITY OF SUCH DAMAGE.
33: */
34: #include <string.h>
35: #include "minixml.h"
36:
37: /* parseatt : used to parse the argument list
38: * return 0 (false) in case of success and -1 (true) if the end
39: * of the xmlbuffer is reached. */
40: static int parseatt(struct xmlparser * p)
41: {
42: const char * attname;
43: int attnamelen;
44: const char * attvalue;
45: int attvaluelen;
46: while(p->xml < p->xmlend)
47: {
48: if(*p->xml=='/' || *p->xml=='>')
49: return 0;
50: if( !IS_WHITE_SPACE(*p->xml) )
51: {
52: char sep;
53: attname = p->xml;
54: attnamelen = 0;
55: while(*p->xml!='=' && !IS_WHITE_SPACE(*p->xml) )
56: {
57: attnamelen++; p->xml++;
58: if(p->xml >= p->xmlend)
59: return -1;
60: }
61: while(*(p->xml++) != '=')
62: {
63: if(p->xml >= p->xmlend)
64: return -1;
65: }
66: while(IS_WHITE_SPACE(*p->xml))
67: {
68: p->xml++;
69: if(p->xml >= p->xmlend)
70: return -1;
71: }
72: sep = *p->xml;
73: if(sep=='\'' || sep=='\"')
74: {
75: p->xml++;
76: if(p->xml >= p->xmlend)
77: return -1;
78: attvalue = p->xml;
79: attvaluelen = 0;
80: while(*p->xml != sep)
81: {
82: attvaluelen++; p->xml++;
83: if(p->xml >= p->xmlend)
84: return -1;
85: }
86: }
87: else
88: {
89: attvalue = p->xml;
90: attvaluelen = 0;
91: while( !IS_WHITE_SPACE(*p->xml)
92: && *p->xml != '>' && *p->xml != '/')
93: {
94: attvaluelen++; p->xml++;
95: if(p->xml >= p->xmlend)
96: return -1;
97: }
98: }
99: /*printf("%.*s='%.*s'\n",
100: attnamelen, attname, attvaluelen, attvalue);*/
101: if(p->attfunc)
102: p->attfunc(p->data, attname, attnamelen, attvalue, attvaluelen);
103: }
104: p->xml++;
105: }
106: return -1;
107: }
108:
109: /* parseelt parse the xml stream and
110: * call the callback functions when needed... */
111: static void parseelt(struct xmlparser * p)
112: {
113: int i;
114: const char * elementname;
115: while(p->xml < (p->xmlend - 1))
116: {
117: if((p->xml + 4) <= p->xmlend && (0 == memcmp(p->xml, "<!--", 4)))
118: {
119: p->xml += 3;
120: /* ignore comments */
121: do
122: {
123: p->xml++;
124: if ((p->xml + 3) >= p->xmlend)
125: return;
126: }
127: while(memcmp(p->xml, "-->", 3) != 0);
128: p->xml += 3;
129: }
130: else if((p->xml)[0]=='<' && (p->xml)[1]!='?')
131: {
132: i = 0; elementname = ++p->xml;
133: while( !IS_WHITE_SPACE(*p->xml)
134: && (*p->xml!='>') && (*p->xml!='/')
135: )
136: {
137: i++; p->xml++;
138: if (p->xml >= p->xmlend)
139: return;
140: /* to ignore namespace : */
141: if(*p->xml==':')
142: {
143: i = 0;
144: elementname = ++p->xml;
145: }
146: }
147: if(i>0)
148: {
149: if(p->starteltfunc)
150: p->starteltfunc(p->data, elementname, i);
151: if(parseatt(p))
152: return;
153: if(*p->xml!='/')
154: {
155: const char * data;
156: i = 0; data = ++p->xml;
157: if (p->xml >= p->xmlend)
158: return;
159: while( IS_WHITE_SPACE(*p->xml) )
160: {
161: i++; p->xml++;
162: if (p->xml >= p->xmlend)
163: return;
164: }
165: /* CDATA are at least 9 + 3 characters long : <![CDATA[ ]]> */
166: if((p->xmlend >= (p->xml + (9 + 3))) && (memcmp(p->xml, "<![CDATA[", 9) == 0))
167: {
168: /* CDATA handling */
169: p->xml += 9;
170: data = p->xml;
171: i = 0;
172: while(memcmp(p->xml, "]]>", 3) != 0)
173: {
174: i++; p->xml++;
175: if ((p->xml + 3) >= p->xmlend)
176: return;
177: }
178: if(i>0 && p->datafunc)
179: p->datafunc(p->data, data, i);
180: while(*p->xml!='<')
181: {
182: p->xml++;
183: if (p->xml >= p->xmlend)
184: return;
185: }
186: }
187: else
188: {
189: while(*p->xml!='<')
190: {
191: i++; p->xml++;
192: if ((p->xml + 1) >= p->xmlend)
193: return;
194: }
195: if(i>0 && p->datafunc && *(p->xml + 1) == '/')
196: p->datafunc(p->data, data, i);
197: }
198: }
199: }
200: else if(*p->xml == '/')
201: {
202: i = 0; elementname = ++p->xml;
203: if (p->xml >= p->xmlend)
204: return;
205: while((*p->xml != '>'))
206: {
207: i++; p->xml++;
208: if (p->xml >= p->xmlend)
209: return;
210: }
211: if(p->endeltfunc)
212: p->endeltfunc(p->data, elementname, i);
213: p->xml++;
214: }
215: }
216: else
217: {
218: p->xml++;
219: }
220: }
221: }
222:
223: /* the parser must be initialized before calling this function */
224: void parsexml(struct xmlparser * parser)
225: {
226: parser->xml = parser->xmlstart;
227: parser->xmlend = parser->xmlstart + parser->xmlsize;
228: parseelt(parser);
229: }
230:
231:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>