1 /*
2  * Copyright (c)2004 Cat's Eye Technologies.  All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  *   Redistributions of source code must retain the above copyright
9  *   notice, this list of conditions and the following disclaimer.
10  *
11  *   Redistributions in binary form must reproduce the above copyright
12  *   notice, this list of conditions and the following disclaimer in
13  *   the documentation and/or other materials provided with the
14  *   distribution.
15  *
16  *   Neither the name of Cat's Eye Technologies nor the names of its
17  *   contributors may be used to endorse or promote products derived
18  *   from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
25  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
31  * OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33 
34 /*
35  * decode.c
36  * $Id: decode.c,v 1.11 2005/02/07 06:39:59 cpressey Exp $
37  */
38 
39 #include <ctype.h>
40 #include <stdlib.h>
41 
42 #include <libaura/mem.h>
43 #include <libaura/buffer.h>
44 
45 #define	NEEDS_DFUI_STRUCTURE_DEFINITIONS
46 #include "dfui.h"
47 #undef	NEEDS_DFUI_STRUCTURE_DEFINITIONS
48 #include "encoding.h"
49 #include "dump.h"
50 
51 /*** BASIC TYPES ***/
52 
53 /*
54  * This function returns a newly-allocated string.  It is the
55  * caller's responsibility that it be free()'ed.
56  */
57 char *
58 dfui_decode_string(struct aura_buffer *e)
59 {
60 	char *str;
61 	int i = 0;
62 	int len = 0;
63 
64 	while (isdigit(aura_buffer_peek_char(e)) && !aura_buffer_eof(e)) {
65 		len = len * 10 + aura_buffer_scan_char(e) - '0';
66 	}
67 
68 	str = aura_malloc(len + 1, "decoded string");
69 
70 	if (!aura_buffer_expect(e, ":")) return(NULL);
71 	while (len > 0 && !aura_buffer_eof(e)) {
72 		str[i++] = aura_buffer_scan_char(e);
73 		len--;
74 	}
75 
76 	str[i] = '\0';
77 
78 	return(str);
79 }
80 
81 int
82 dfui_decode_int(struct aura_buffer *e)
83 {
84 	int x = 0;
85 
86 	while (isdigit(aura_buffer_peek_char(e)) && !aura_buffer_eof(e)) {
87 		x = x * 10 + aura_buffer_scan_char(e) - '0';
88 	}
89 	if (aura_buffer_expect(e, " ")) {
90 		return(x);
91 	} else {
92 		return(0);
93 	}
94 }
95 
96 int
97 dfui_decode_bool(struct aura_buffer *e)
98 {
99 	char c;
100 
101 	c = aura_buffer_scan_char(e);
102 
103 	if (c == 'Y')
104 		return(1);
105 	else if (c == 'N')
106 		return(0);
107 	else /* XXX ??? error */
108 		return(0);
109 }
110 
111 /*** FORM TYPES ***/
112 
113 struct dfui_info *
114 dfui_decode_info(struct aura_buffer *e)
115 {
116 	char *name, *short_desc, *long_desc;
117 	struct dfui_info *i;
118 
119 	name = dfui_decode_string(e);
120 	short_desc = dfui_decode_string(e);
121 	long_desc = dfui_decode_string(e);
122 
123 	i = dfui_info_new(name, short_desc, long_desc);
124 
125 	free(name);
126 	free(short_desc);
127 	free(long_desc);
128 
129 	return(i);
130 }
131 
132 struct dfui_field *
133 dfui_decode_field(struct aura_buffer *e)
134 {
135 	char *id;
136 	struct dfui_info *i;
137 	struct dfui_field *fi;
138 
139 	id = dfui_decode_string(e);
140 	i = dfui_decode_info(e);
141 
142 	fi = dfui_field_new(id, i);
143 	fi->option_head = dfui_decode_options(e);
144 	fi->property_head = dfui_decode_properties(e);
145 	free(id);
146 
147 	return(fi);
148 }
149 
150 struct dfui_field *
151 dfui_decode_fields(struct aura_buffer *e)
152 {
153 	struct dfui_field *head = NULL, *fi;
154 
155 	if (!aura_buffer_expect(e, "f{")) return(NULL);
156 	while (aura_buffer_peek_char(e) != '}') {
157 		fi = dfui_decode_field(e);
158 		fi->next = head;
159 		head = fi;
160 	}
161 	aura_buffer_expect(e, "}");
162 
163 	return(head);
164 }
165 
166 struct dfui_option *
167 dfui_decode_option(struct aura_buffer *e)
168 {
169 	char *value;
170 
171 	value = dfui_decode_string(e);
172 
173 	return(dfui_option_new(value));
174 }
175 
176 struct dfui_option *
177 dfui_decode_options(struct aura_buffer *e)
178 {
179 	struct dfui_option *head = NULL, *o;
180 
181 	if (!aura_buffer_expect(e, "O{")) return(NULL);
182 	while (aura_buffer_peek_char(e) != '}') {
183 		o = dfui_decode_option(e);
184 		o->next = head;
185 		head = o;
186 	}
187 	aura_buffer_expect(e, "}");
188 
189 	return(head);
190 }
191 
192 struct dfui_action *
193 dfui_decode_action(struct aura_buffer *e)
194 {
195 	char *id;
196 	struct dfui_info *i;
197 	struct dfui_action *a;
198 
199 	id = dfui_decode_string(e);
200 	i = dfui_decode_info(e);
201 	a = dfui_action_new(id, i);
202 	a->property_head = dfui_decode_properties(e);
203 	free(id);
204 
205 	return(a);
206 }
207 
208 struct dfui_action *
209 dfui_decode_actions(struct aura_buffer *e)
210 {
211 	struct dfui_action *head = NULL, *a;
212 
213 	if (!aura_buffer_expect(e, "a{")) return(NULL);
214 	while (aura_buffer_peek_char(e) != '}') {
215 		a = dfui_decode_action(e);
216 		a->next = head;
217 		head = a;
218 	}
219 	aura_buffer_expect(e, "}");
220 
221 	return(head);
222 }
223 
224 struct dfui_celldata *
225 dfui_decode_celldata(struct aura_buffer *e)
226 {
227 	char *field_id;
228 	char *value;
229 	struct dfui_celldata *c;
230 
231 	field_id = dfui_decode_string(e);
232 	value = dfui_decode_string(e);
233 
234 	c = dfui_celldata_new(field_id, value);
235 
236 	free(field_id);
237 	free(value);
238 
239 	return(c);
240 }
241 
242 struct dfui_celldata *
243 dfui_decode_celldatas(struct aura_buffer *e)
244 {
245 	struct dfui_celldata *c, *head = NULL;
246 
247 	if (!aura_buffer_expect(e, "d{")) return(NULL);
248 	while (aura_buffer_peek_char(e) != '}') {
249 		c = dfui_decode_celldata(e);
250 		c->next = head;
251 		head = c;
252 	}
253 	aura_buffer_expect(e, "}");
254 
255 	return(head);
256 }
257 
258 struct dfui_property *
259 dfui_decode_property(struct aura_buffer *e)
260 {
261 	char *name, *value;
262 	struct dfui_property *h;
263 
264 	name = dfui_decode_string(e);
265 	value = dfui_decode_string(e);
266 
267 	h = dfui_property_new(name, value);
268 
269 	free(value);
270 	free(name);
271 
272 	return(h);
273 }
274 
275 struct dfui_property *
276 dfui_decode_properties(struct aura_buffer *e)
277 {
278 	struct dfui_property *h, *head = NULL;
279 
280 	if (!aura_buffer_expect(e, "p{")) return(NULL);
281 	while (aura_buffer_peek_char(e) != '}') {
282 		h = dfui_decode_property(e);
283 		h->next = head;
284 		head = h;
285 	}
286 	aura_buffer_expect(e, "}");
287 
288 	return(head);
289 }
290 
291 struct dfui_dataset *
292 dfui_decode_dataset(struct aura_buffer *e)
293 {
294 	struct dfui_dataset *ds;
295 
296 	ds = dfui_dataset_new();
297 	ds->celldata_head = dfui_decode_celldatas(e);
298 
299 	return(ds);
300 }
301 
302 struct dfui_dataset *
303 dfui_decode_datasets(struct aura_buffer *e)
304 {
305 	struct dfui_dataset *head = NULL, *ds;
306 
307 	if (!aura_buffer_expect(e, "D{")) return(NULL);
308 	while (aura_buffer_peek_char(e) != '}') {
309 		ds = dfui_decode_dataset(e);
310 		ds->next = head;
311 		head = ds;
312 	}
313 	aura_buffer_expect(e, "}");
314 
315 	return(head);
316 }
317 
318 struct dfui_form *
319 dfui_decode_form(struct aura_buffer *e)
320 {
321 	char *id;
322 	struct dfui_info *i;
323 	struct dfui_form *f;
324 
325 	if (!aura_buffer_expect(e, "F{")) return(NULL);
326 
327 	id = dfui_decode_string(e);
328 	i = dfui_decode_info(e);
329 
330 	f = dfui_form_new(id, i);
331 
332 	dfui_form_set_multiple(f, dfui_decode_bool(e));
333 	dfui_form_set_extensible(f, dfui_decode_bool(e));
334 
335 	f->field_head = dfui_decode_fields(e);
336 	f->action_head = dfui_decode_actions(e);
337 	f->dataset_head = dfui_decode_datasets(e);
338 	f->property_head = dfui_decode_properties(e);
339 
340 	aura_buffer_expect(e, "}");
341 	free(id);
342 
343 	return(f);
344 }
345 
346 struct dfui_response *
347 dfui_decode_response(struct aura_buffer *e)
348 {
349 	char *form_id;
350 	char *action_id;
351 	struct dfui_response *r;
352 
353 	if (!aura_buffer_expect(e, "R{")) return(NULL);
354 
355 	form_id = dfui_decode_string(e);
356 	action_id = dfui_decode_string(e);
357 	r = dfui_response_new(form_id, action_id);
358 	r->dataset_head = dfui_decode_datasets(e);
359 	free(form_id);
360 	free(action_id);
361 
362 	aura_buffer_expect(e, "}");
363 
364 	return(r);
365 }
366 
367 struct dfui_progress *
368 dfui_decode_progress(struct aura_buffer *e)
369 {
370 	struct dfui_info *i;
371 	int amount, streaming;
372 	char *msg_line;
373 	struct dfui_progress *pr;
374 
375 	i = dfui_decode_info(e);
376 	amount = dfui_decode_int(e);
377 	streaming = dfui_decode_int(e);
378 	msg_line = dfui_decode_string(e);
379 
380 	pr = dfui_progress_new(i, amount);
381 	dfui_progress_set_streaming(pr, streaming);
382 	dfui_progress_set_msg_line(pr, msg_line);
383 
384 	free(msg_line);
385 
386 	return(pr);
387 }
388