--- libaitwww/src/tools.c 2012/07/31 11:56:16 1.2.6.1 +++ libaitwww/src/tools.c 2012/08/06 11:08:08 1.3.2.1 @@ -3,7 +3,7 @@ * by Michael Pounov * * $Author: misho $ -* $Id: tools.c,v 1.2.6.1 2012/07/31 11:56:16 misho Exp $ +* $Id: tools.c,v 1.3.2.1 2012/08/06 11:08:08 misho Exp $ * ************************************************************************** The ELWIX and AITNET software is distributed under the following @@ -60,12 +60,12 @@ www_cmp(const char *ct, const char *s) assert(ct && s); - while (isspace(*ct)) + while (isspace((int) *ct)) ct++; if (!(sc = strchr(ct, ';'))) sc = strchr(ct, '\x0'); - while (isspace(*(sc - 1))) + while (isspace((int) *(sc - 1))) sc--; if (strlen(s) != sc - ct) @@ -87,7 +87,7 @@ www_cmptype(const char *ct, const char *type) assert(ct && type); - while (isspace(*ct)) + while (isspace((int) *ct)) ct++; if (!(sl = strchr(ct, '/'))) @@ -103,30 +103,31 @@ www_cmptype(const char *ct, const char *type) * * @str = query string * @delim = delimiter - * return: NULL error or AV pair, must be free() after use! + * return: NULL error or AV pair, must be io_free() after use! */ -char * +ait_val_t * www_getpair(char ** __restrict str, const char *delim) { - char *tr, *s = NULL; + char *tr; int cx; + ait_val_t *s; assert(str && *str && delim); + s = io_allocVar(); + if (!s) { + www_SetErr(io_GetErrno(), "%s", io_GetError()); + return NULL; + } + cx = strcspn(*str, delim); tr = *str + cx; + if (*tr) + *tr++ = 0; - s = malloc(cx + 1); - if (!s) { - LOGERR; - return NULL; - } else - strlcpy(s, *str, cx + 1); + AIT_SET_STR(s, *str); *str = tr; - if (**str) - (*str)++; - return s; } @@ -161,7 +162,8 @@ www_unescape(char * __restrict str) { register int i, j; - assert(str); + if (!str) + return; for (i = j = 0; str[j]; i++, j++) { str[i] = str[j]; @@ -175,4 +177,52 @@ www_unescape(char * __restrict str) } str[i] = 0; +} + +/* + * www_undot() - Undotted and clean WWW query filename + * + * @fname = query filename + * return: none + */ +void +www_undot(const char * __restrict fname) +{ + char *s, *s2; + int l; + + if (!fname) + return; + + /* collapse / sequences */ + if ((s = strstr(fname, "//"))) { + s2 = s + 1; + for (s2 = ++s; *s2 == '/'; s2++); + memmove(s, s2, strlen(s2) + 1); + } + + /* escaped ./ and /./ sequences */ + while (!strncmp(fname, "./", 2)) + memmove((void*) fname, fname + 2, strlen(fname + 1)); + while ((s = strstr(fname, "/./"))) + memmove(s, s + 2, strlen(s + 1)); + + /* alternate between removing leading ../ and removing xxx/../ */ + while (42) { + while (!strncmp(fname, "../", 3)) + memmove((void*) fname, fname + 3, strlen(fname + 2)); + if (!(s = strstr(fname, "/../"))) + break; + for (s2 = s - 1; s2 >= fname && *s2 != '/'; --s2); + memmove(s2 + 1, s + 4, strlen(s + 3)); + } + + /* elide any /.. at the end */ + while ((l = strlen(fname)) > 3 && + !strcmp((s = (char*) fname + l - 3), "/..")) { + for (s2 = s - 1; s2 >= fname && *s2 != '/'; --s2); + if (s2 < fname) + break; + *s2 = 0; + } }