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