1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <string.h>
4 #include <ctype.h>
5 #include <errno.h>
7 #include "utils_params.h"
9 struct parameter_s
10 {
11 char *key;
12 char *value;
13 };
14 typedef struct parameter_s parameter_t;
16 static parameter_t *parameters = NULL;
17 static size_t parameters_num = 0;
18 static _Bool parameters_init = 0;
20 static int parameter_add (const char *key, const char *value) /* {{{ */
21 {
22 parameter_t *ptr;
24 if (value == NULL)
25 return (EINVAL);
27 ptr = realloc (parameters, sizeof (*parameters) * (parameters_num + 1));
28 if (ptr == NULL)
29 return (ENOMEM);
30 parameters = ptr;
32 ptr = parameters + parameters_num;
33 if (key == NULL)
34 {
35 ptr->key = NULL;
36 }
37 else
38 {
39 ptr->key = strdup (key);
40 if (ptr->key == NULL)
41 return (ENOMEM);
42 }
44 ptr->value = strdup (value);
45 if (ptr->value == NULL)
46 {
47 free (ptr->key);
48 return (ENOMEM);
49 }
51 parameters_num++;
52 return (0);
53 } /* }}} int parameter_add */
55 static char *parameter_lookup (const char *key) /* {{{ */
56 {
57 size_t i;
59 for (i = 0; i < parameters_num; i++)
60 {
61 if ((key == NULL) && (parameters[i].key == NULL))
62 return (parameters[i].value);
63 else if ((key != NULL) && (parameters[i].key != NULL)
64 && (strcmp (key, parameters[i].key) == 0))
65 return (parameters[i].value);
66 }
68 return (NULL);
69 } /* }}} char *parameter_lookup */
71 static char *uri_unescape (char *string) /* {{{ */
72 {
73 char *in;
74 char *out;
76 if (string == NULL)
77 return (NULL);
79 in = string;
80 out = string;
82 while (*in != 0)
83 {
84 if (*in == '+')
85 {
86 *out = ' ';
87 }
88 else if ((in[0] == '%')
89 && isxdigit ((int) in[1]) && isxdigit ((int) in[2]))
90 {
91 char tmpstr[3];
92 char *endptr;
93 long value;
95 tmpstr[0] = in[1];
96 tmpstr[1] = in[2];
97 tmpstr[2] = 0;
99 errno = 0;
100 endptr = NULL;
101 value = strtol (tmpstr, &endptr, /* base = */ 16);
102 if ((endptr == tmpstr) || (errno != 0))
103 {
104 *out = '?';
105 }
106 else
107 {
108 *out = (char) value;
109 }
111 in += 2;
112 }
113 else
114 {
115 *out = *in;
116 }
118 in++;
119 out++;
120 } /* while (*in != 0) */
122 *out = 0;
123 return (string);
124 } /* }}} char *uri_unescape */
126 static int parse_keyval (char *keyval) /* {{{ */
127 {
128 char *key;
129 char *val;
131 val = strchr (keyval, '=');
132 if (val == NULL)
133 {
134 key = NULL;
135 val = keyval;
136 }
137 else
138 {
139 key = keyval;
140 *val = 0;
141 val++;
142 }
144 parameter_add (uri_unescape (key), uri_unescape (val));
146 return (0);
147 } /* }}} int parse_keyval */
149 static int parse_query_string (char *query_string) /* {{{ */
150 {
151 char *dummy;
152 char *keyval;
154 if (query_string == NULL)
155 return (EINVAL);
157 dummy = query_string;
158 while ((keyval = strtok (dummy, ";&")) != NULL)
159 {
160 dummy = NULL;
161 parse_keyval (keyval);
162 }
164 return (0);
165 } /* }}} int parse_query_string */
167 int param_init (void) /* {{{ */
168 {
169 const char *query_string;
170 char *copy;
171 int status;
173 if (parameters_init)
174 return (0);
176 query_string = getenv ("QUERY_STRING");
177 if (query_string == NULL)
178 return (ENOENT);
180 copy = strdup (query_string);
181 if (copy == NULL)
182 return (ENOMEM);
184 status = parse_query_string (copy);
185 free (copy);
187 parameters_init = 1;
189 return (status);
190 } /* }}} int param_init */
192 void param_finish (void) /* {{{ */
193 {
194 size_t i;
196 if (!parameters_init)
197 return;
199 for (i = 0; i < parameters_num; i++)
200 {
201 free (parameters[i].key);
202 free (parameters[i].value);
203 }
204 free (parameters);
206 parameters = NULL;
207 parameters_num = 0;
208 parameters_init = 0;
209 } /* }}} void param_finish */
211 const char *param (const char *key) /* {{{ */
212 {
213 param_init ();
215 return (parameter_lookup (key));
216 } /* }}} const char *param */
218 int uri_escape (char *dst, const char *src, size_t size) /* {{{ */
219 {
220 size_t in;
221 size_t out;
223 in = 0;
224 out = 0;
225 while (42)
226 {
227 if (src[in] == 0)
228 {
229 dst[out] = 0;
230 return (0);
231 }
232 else if ((src[in] < 32)
233 || (src[in] == '&')
234 || (src[in] == ';')
235 || (src[in] >= 128))
236 {
237 char esc[4];
239 if ((size - out) < 4)
240 break;
242 snprintf (esc, sizeof (esc), "%%%02x", (unsigned int) src[in]);
243 dst[out] = esc[0];
244 dst[out+1] = esc[1];
245 dst[out+2] = esc[2];
247 out += 3;
248 in++;
249 }
250 else
251 {
252 dst[out] = src[in];
253 out++;
254 in++;
255 }
256 } /* while (42) */
257 } /* }}} int uri_escape */
259 /* vim: set sw=2 sts=2 et fdm=marker : */