oconfig.c: Fix compiler warning.
[collection4.git] / utils_params.c
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <string.h>
4 #include <ctype.h>
5 #include <errno.h>
6
7 #include "utils_params.h"
8
9 struct parameter_s
10 {
11   char *key;
12   char *value;
13 };
14 typedef struct parameter_s parameter_t;
15
16 static parameter_t *parameters = NULL;
17 static size_t parameters_num = 0;
18 static _Bool parameters_init = 0;
19
20 static int parameter_add (const char *key, const char *value) /* {{{ */
21 {
22   parameter_t *ptr;
23
24   if (value == NULL)
25     return (EINVAL);
26
27   ptr = realloc (parameters, sizeof (*parameters) * (parameters_num + 1));
28   if (ptr == NULL)
29     return (ENOMEM);
30   parameters = ptr;
31
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   }
43
44   ptr->value = strdup (value);
45   if (ptr->value == NULL)
46   {
47     free (ptr->key);
48     return (ENOMEM);
49   }
50
51   parameters_num++;
52   return (0);
53 } /* }}} int parameter_add */
54
55 static char *parameter_lookup (const char *key) /* {{{ */
56 {
57   size_t i;
58
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   }
67
68   return (NULL);
69 } /* }}} char *parameter_lookup */
70
71 static char *uri_unescape (char *string) /* {{{ */
72 {
73   char *in;
74   char *out;
75
76   if (string == NULL)
77     return (NULL);
78
79   in = string;
80   out = string;
81
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;
94
95       tmpstr[0] = in[1];
96       tmpstr[1] = in[2];
97       tmpstr[2] = 0;
98
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       }
110
111       in += 2;
112     }
113     else
114     {
115       *out = *in;
116     }
117
118     in++;
119     out++;
120   } /* while (*in != 0) */
121
122   *out = 0;
123   return (string);
124 } /* }}} char *uri_unescape */
125
126 static int parse_keyval (char *keyval) /* {{{ */
127 {
128   char *key;
129   char *val;
130
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   }
143
144   parameter_add (uri_unescape (key), uri_unescape (val));
145
146   return (0);
147 } /* }}} int parse_keyval */
148
149 static int parse_query_string (char *query_string) /* {{{ */
150 {
151   char *dummy;
152   char *keyval;
153
154   if (query_string == NULL)
155     return (EINVAL);
156
157   dummy = query_string;
158   while ((keyval = strtok (dummy, ";&")) != NULL)
159   {
160     dummy = NULL;
161     parse_keyval (keyval);
162   }
163
164   return (0);
165 } /* }}} int parse_query_string */
166
167 int param_init (void) /* {{{ */
168 {
169   const char *query_string;
170   char *copy;
171   int status;
172
173   if (parameters_init)
174     return (0);
175
176   query_string = getenv ("QUERY_STRING");
177   if (query_string == NULL)
178     return (ENOENT);
179
180   copy = strdup (query_string);
181   if (copy == NULL)
182     return (ENOMEM);
183
184   status = parse_query_string (copy);
185   free (copy);
186
187   parameters_init = 1;
188
189   return (status);
190 } /* }}} int param_init */
191
192 void param_finish (void) /* {{{ */
193 {
194   size_t i;
195
196   if (!parameters_init)
197     return;
198
199   for (i = 0; i < parameters_num; i++)
200   {
201     free (parameters[i].key);
202     free (parameters[i].value);
203   }
204   free (parameters);
205
206   parameters = NULL;
207   parameters_num = 0;
208   parameters_init = 0;
209 } /* }}} void param_finish */
210
211 const char *param (const char *key) /* {{{ */
212 {
213   param_init ();
214
215   return (parameter_lookup (key));
216 } /* }}} const char *param */
217
218 int uri_escape (char *dst, const char *src, size_t size) /* {{{ */
219 {
220   size_t in;
221   size_t out;
222
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];
238
239       if ((size - out) < 4)
240         break;
241       
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];
246
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 */
258
259 /* vim: set sw=2 sts=2 et fdm=marker : */