13 parse_command(const char *cmdline
)
15 const char *p
= cmdline
, *s
;
16 char **argv
= NULL
, *out
;
21 while (isspace(*cmdline
))
24 for (p
= cmdline
, s
= p
, esc
= false; p
; p
++) {
28 else if (*p
== '\\' && p
[1] != 0) {
31 else if (isspace(*p
) || *p
== 0) {
34 arglen
+= sizeof(char *) + (p
- s
) + 1;
47 argv
= calloc(1, arglen
+ sizeof(char *));
52 out
= (char *)argv
+ sizeof(char *) * (argnum
+ 1);
55 for (p
= cmdline
, s
= p
, esc
= false, argnum
= 0; p
; p
++) {
60 else if (*p
== '\\' && p
[1] != 0) {
63 else if (isspace(*p
) || *p
== 0) {
86 postdecode_fields(char *postbuf
, ssize_t len
, char **fields
, int n_fields
)
89 int i
, field
, found
= 0;
91 for (p
= postbuf
, i
= 0; i
<= len
; i
++)
93 if (postbuf
[i
] == '=')
97 for (field
= 0; field
< (n_fields
* 2); field
+= 2)
99 if (!strcmp(p
, fields
[field
]))
101 fields
[field
+ 1] = postbuf
+ i
+ 1;
106 else if (postbuf
[i
] == '&' || postbuf
[i
] == '\0')
110 if (found
>= n_fields
)
117 for (field
= 0; field
< (n_fields
* 2); field
+= 2)
119 if (!urldecode(fields
[field
+ 1]))
130 postdecode(char **fields
, int n_fields
)
134 ssize_t len
= 0, rlen
= 0, content_length
= 0;
136 var
= getenv("CONTENT_TYPE");
138 if (!var
|| strncmp(var
, "application/x-www-form-urlencoded", 33))
141 var
= getenv("CONTENT_LENGTH");
146 content_length
= strtol(var
, &p
, 10);
148 if (p
== var
|| content_length
<= 0 || content_length
>= POST_LIMIT
)
151 postbuf
= calloc(1, content_length
+ 1);
156 for (len
= 0; len
< content_length
; )
158 rlen
= read(0, postbuf
+ len
, content_length
- len
);
166 if (len
< content_length
)
172 return postdecode_fields(postbuf
, len
, fields
, n_fields
);
176 datadup(const void *in
, size_t len
)
178 char *out
= malloc(len
+ 1);
183 memcpy(out
, in
, len
);
191 canonicalize_path(const char *path
, size_t len
)
193 char *canonpath
, *cp
;
196 if (path
== NULL
|| *path
== '\0')
199 canonpath
= datadup(path
, len
);
201 if (canonpath
== NULL
)
205 for (cp
= canonpath
, p
= path
, e
= path
+ len
; p
< e
; ) {
209 /* skip repeating / */
210 if ((p
+ 1 < e
) && (p
[1] == '/')) {
216 if ((p
+ 1 < e
) && (p
[1] == '.')) {
218 if ((p
+ 2 >= e
) || (p
[2] == '/')) {
223 /* collapse /x/../ */
224 if ((p
+ 2 < e
) && (p
[2] == '.') && ((p
+ 3 >= e
) || (p
[3] == '/'))) {
225 while ((cp
> canonpath
) && (*--cp
!= '/'))
237 /* remove trailing slash if not root / */
238 if ((cp
> canonpath
+ 1) && (cp
[-1] == '/'))
240 else if (cp
== canonpath
)
257 (((x) <= '9') ? ((x) - '0') : \
258 (((x) <= 'F') ? ((x) - 'A' + 10) : \
261 for (c
= p
= buf
; *p
; c
++)
265 if (!isxdigit(*(p
+ 1)) || !isxdigit(*(p
+ 2)))
268 *c
= (char)(16 * hex(*(p
+ 1)) + hex(*(p
+ 2)));