1 /*
2 ** Copyright 2007 Double Precision, Inc.
3 ** See COPYING for distribution information.
4 */
5 
6 /*
7 */
8 
9 #include	"cgi.h"
10 #include	<stdio.h>
11 #include	<string.h>
12 #include	<stdlib.h>
13 #include	<ctype.h>
14 
do_cgi_select(const char * name,const char * optvalues,const char * optlabels,const char * default_value,size_t list_size,const char * flags,void (* output_func)(const char *,size_t,void *),void * output_arg)15 static void do_cgi_select(const char *name,
16 			  const char *optvalues,
17 			  const char *optlabels,
18 			  const char *default_value,
19 			  size_t list_size,
20 			  const char *flags,
21 
22 			  void (*output_func)(const char *, size_t, void *),
23 			  void *output_arg)
24 {
25 	(*output_func)("<select name='", 0, output_arg);
26 	(*output_func)(name, 0, output_arg);
27 	(*output_func)("'", 0, output_arg);
28 
29 	if (strchr(flags, 'm'))
30 		(*output_func)(" multiple='multiple'", 0, output_arg);
31 	if (strchr(flags, 'd'))
32 		(*output_func)(" disabled='disabled'", 0, output_arg);
33 
34 	(*output_func)("'>", 0, output_arg);
35 
36 	if (!optvalues)
37 		optvalues="";
38 
39 	while (*optlabels)
40 	{
41 		const char *label_start=optlabels;
42 		const char *value_start=optvalues;
43 
44 		while (*optlabels)
45 		{
46 			if (*optlabels == '\n')
47 				break;
48 			++optlabels;
49 		}
50 
51 		while (*optvalues)
52 		{
53 			if (*optvalues == '\n')
54 				break;
55 			++optvalues;
56 		}
57 
58 		(*output_func)("<option", 0, output_arg);
59 
60 		if (*value_start)
61 		{
62 			if (default_value &&
63 			    optvalues - value_start == strlen(default_value) &&
64 			    strncmp(value_start, default_value,
65 				    optvalues-value_start) == 0)
66 			{
67 				(*output_func)(" selected='selected'", 0,
68 					       output_arg);
69 			}
70 
71 			(*output_func)(" value='", 0, output_arg);
72 			(*output_func)(value_start, optvalues-value_start,
73 				       output_arg);
74 			(*output_func)("'", 0, output_arg);
75 		}
76 		(*output_func)(">", 0, output_arg);
77 		(*output_func)(label_start, optlabels-label_start, output_arg);
78 		(*output_func)("</option>", 0, output_arg);
79 		if (*optlabels)
80 			++optlabels;
81 		if (*optvalues)
82 			++optvalues;
83 	}
84 
85 	(*output_func)("</select>", 0, output_arg);
86 }
87 
cnt_bytes(const char * str,size_t cnt,void * arg)88 static void cnt_bytes(const char *str, size_t cnt, void *arg)
89 {
90 	if (!cnt)
91 		cnt=strlen(str);
92 
93 	*(size_t *)arg += cnt;
94 }
95 
save_bytes(const char * str,size_t cnt,void * arg)96 static void save_bytes(const char *str, size_t cnt, void *arg)
97 {
98 	char **p=(char **)arg;
99 
100 	if (!cnt)
101 		cnt=strlen(str);
102 
103 	memcpy(*p, str, cnt);
104 	*p += cnt;
105 }
106 
cgi_select(const char * name,const char * optvalues,const char * optlabels,const char * default_value,size_t list_size,const char * flags)107 char *cgi_select(const char *name,
108 		 const char *optvalues,
109 		 const char *optlabels,
110 		 const char *default_value,
111 		 size_t list_size,
112 		 const char *flags)
113 {
114 	size_t cnt=1;
115 	char *buf;
116 	char *ptr;
117 
118 	if (!flags)
119 		flags="";
120 
121 	do_cgi_select(name, optvalues, optlabels, default_value,
122 		      list_size, flags, cnt_bytes, &cnt);
123 
124 	buf=malloc(cnt);
125 
126 	if (!buf)
127 		return NULL;
128 
129 	ptr=buf;
130 	do_cgi_select(name, optvalues, optlabels, default_value,
131 		      list_size, flags, save_bytes, &ptr);
132 	*ptr=0;
133 	return buf;
134 }
135