• source navigation  • diff markup  • identifier search  • freetext search  • 

Sources/cgi-io/util.c

  1 #include <ctype.h>
  2 #include <stddef.h>
  3 #include <stdbool.h>
  4 #include <stdlib.h>
  5 #include <string.h>
  6 #include <unistd.h>
  7 
  8 #include <stdio.h>
  9 
 10 #include "util.h"
 11 
 12 char **
 13 parse_command(const char *cmdline)
 14 {
 15         const char *p = cmdline, *s;
 16         char **argv = NULL, *out;
 17         size_t arglen = 0;
 18         int argnum = 0;
 19         bool esc;
 20 
 21         while (isspace(*cmdline))
 22                 cmdline++;
 23 
 24         for (p = cmdline, s = p, esc = false; p; p++) {
 25                 if (esc) {
 26                         esc = false;
 27                 }
 28                 else if (*p == '\\' && p[1] != 0) {
 29                         esc = true;
 30                 }
 31                 else if (isspace(*p) || *p == 0) {
 32                         if (p > s) {
 33                                 argnum += 1;
 34                                 arglen += sizeof(char *) + (p - s) + 1;
 35                         }
 36 
 37                         s = p + 1;
 38                 }
 39 
 40                 if (*p == 0)
 41                         break;
 42         }
 43 
 44         if (arglen == 0)
 45                 return NULL;
 46 
 47         argv = calloc(1, arglen + sizeof(char *));
 48 
 49         if (!argv)
 50                 return NULL;
 51 
 52         out = (char *)argv + sizeof(char *) * (argnum + 1);
 53         argv[0] = out;
 54 
 55         for (p = cmdline, s = p, esc = false, argnum = 0; p; p++) {
 56                 if (esc) {
 57                         esc = false;
 58                         *out++ = *p;
 59                 }
 60                 else if (*p == '\\' && p[1] != 0) {
 61                         esc = true;
 62                 }
 63                 else if (isspace(*p) || *p == 0) {
 64                         if (p > s) {
 65                                 *out++ = ' ';
 66                                 argv[++argnum] = out;
 67                         }
 68 
 69                         s = p + 1;
 70                 }
 71                 else {
 72                         *out++ = *p;
 73                 }
 74 
 75                 if (*p == 0)
 76                         break;
 77         }
 78 
 79         argv[argnum] = NULL;
 80         out[-1] = 0;
 81 
 82         return argv;
 83 }
 84 
 85 char *
 86 postdecode_fields(char *postbuf, ssize_t len, char **fields, int n_fields)
 87 {
 88         char *p;
 89         int i, field, found = 0;
 90 
 91         for (p = postbuf, i = 0; i < len; i++)
 92         {
 93                 if (postbuf[i] == '=')
 94                 {
 95                         postbuf[i] = 0;
 96 
 97                         for (field = 0; field < (n_fields * 2); field += 2)
 98                         {
 99                                 if (!strcmp(p, fields[field]))
100                                 {
101                                         fields[field + 1] = postbuf + i + 1;
102                                         found++;
103                                 }
104                         }
105                 }
106                 else if (postbuf[i] == '&' || postbuf[i] == '\0')
107                 {
108                         postbuf[i] = 0;
109 
110                         if (found >= n_fields)
111                                 break;
112 
113                         p = postbuf + i + 1;
114                 }
115         }
116 
117         for (field = 0; field < (n_fields * 2); field += 2)
118         {
119                 if (!urldecode(fields[field + 1]))
120                 {
121                         free(postbuf);
122                         return NULL;
123                 }
124         }
125 
126         return postbuf;
127 }
128 
129 char *
130 postdecode(char **fields, int n_fields)
131 {
132         const char *var;
133         char *p, *postbuf;
134         ssize_t len = 0, rlen = 0, content_length = 0;
135 
136         var = getenv("CONTENT_TYPE");
137 
138         if (!var || strncmp(var, "application/x-www-form-urlencoded", 33))
139                 return NULL;
140 
141         var = getenv("CONTENT_LENGTH");
142 
143         if (!var)
144                 return NULL;
145 
146         content_length = strtol(var, &p, 10);
147 
148         if (p == var || content_length <= 0 || content_length >= POST_LIMIT)
149                 return NULL;
150 
151         postbuf = calloc(1, content_length + 1);
152 
153         if (postbuf == NULL)
154                 return NULL;
155 
156         for (len = 0; len < content_length; )
157         {
158                 rlen = read(0, postbuf + len, content_length - len);
159 
160                 if (rlen <= 0)
161                         break;
162 
163                 len += rlen;
164         }
165 
166         if (len < content_length)
167         {
168                 free(postbuf);
169                 return NULL;
170         }
171 
172         return postdecode_fields(postbuf, len, fields, n_fields);
173 }
174 
175 char *
176 datadup(const void *in, size_t len)
177 {
178         char *out = malloc(len + 1);
179 
180         if (!out)
181                 return NULL;
182 
183         memcpy(out, in, len);
184 
185         *(out + len) = 0;
186 
187         return out;
188 }
189 
190 char *
191 canonicalize_path(const char *path, size_t len)
192 {
193         char *canonpath, *cp;
194         const char *p, *e;
195 
196         if (path == NULL || *path == '\0')
197                 return NULL;
198 
199         canonpath = datadup(path, len);
200 
201         if (canonpath == NULL)
202                 return NULL;
203 
204         /* normalize */
205         for (cp = canonpath, p = path, e = path + len; p < e; ) {
206                 if (*p != '/')
207                         goto next;
208 
209                 /* skip repeating / */
210                 if ((p + 1 < e) && (p[1] == '/')) {
211                         p++;
212                         continue;
213                 }
214 
215                 /* /./ or /../ */
216                 if ((p + 1 < e) && (p[1] == '.')) {
217                         /* skip /./ */
218                         if ((p + 2 >= e) || (p[2] == '/')) {
219                                 p += 2;
220                                 continue;
221                         }
222 
223                         /* collapse /x/../ */
224                         if ((p + 2 < e) && (p[2] == '.') && ((p + 3 >= e) || (p[3] == '/'))) {
225                                 while ((cp > canonpath) && (*--cp != '/'))
226                                         ;
227 
228                                 p += 3;
229                                 continue;
230                         }
231                 }
232 
233 next:
234                 *cp++ = *p++;
235         }
236 
237         /* remove trailing slash if not root / */
238         if ((cp > canonpath + 1) && (cp[-1] == '/'))
239                 cp--;
240         else if (cp == canonpath)
241                 *cp++ = '/';
242 
243         *cp = '\0';
244 
245         return canonpath;
246 }
247 
248 bool
249 urldecode(char *buf)
250 {
251         char *c, *p;
252 
253         if (!buf || !*buf)
254                 return true;
255 
256 #define hex(x) \
257         (((x) <= '9') ? ((x) - '') : \
258                 (((x) <= 'F') ? ((x) - 'A' + 10) : \
259                         ((x) - 'a' + 10)))
260 
261         for (c = p = buf; *p; c++)
262         {
263                 if (*p == '%')
264                 {
265                         if (!isxdigit(*(p + 1)) || !isxdigit(*(p + 2)))
266                                 return false;
267 
268                         *c = (char)(16 * hex(*(p + 1)) + hex(*(p + 2)));
269 
270                         p += 3;
271                 }
272                 else if (*p == '+')
273                 {
274                         *c = ' ';
275                         p++;
276                 }
277                 else
278                 {
279                         *c = *p++;
280                 }
281         }
282 
283         *c = 0;
284 
285         return true;
286 }
287 

This page was automatically generated by LXR 0.3.1.  •  OpenWrt