--- libaitwww/src/tools.c 2012/07/31 23:11:47 1.2.6.4 +++ libaitwww/src/tools.c 2013/05/30 09:25:35 1.5 @@ -3,7 +3,7 @@ * by Michael Pounov * * $Author: misho $ -* $Id: tools.c,v 1.2.6.4 2012/07/31 23:11:47 misho Exp $ +* $Id: tools.c,v 1.5 2013/05/30 09:25:35 misho Exp $ * ************************************************************************** The ELWIX and AITNET software is distributed under the following @@ -12,7 +12,7 @@ terms: All of the documentation and software included in the ELWIX and AITNET Releases is copyrighted by ELWIX - Sofia/Bulgaria -Copyright 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 +Copyright 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 by Michael Pounov . All rights reserved. Redistribution and use in source and binary forms, with or without @@ -103,7 +103,7 @@ www_cmptype(const char *ct, const char *type) * * @str = query string * @delim = delimiter - * return: NULL error or AV pair, must be io_free() after use! + * return: NULL error or AV pair, must be e_free() after use! */ ait_val_t * www_getpair(char ** __restrict str, const char *delim) @@ -114,9 +114,9 @@ www_getpair(char ** __restrict str, const char *delim) assert(str && *str && delim); - s = io_allocVar(); + s = ait_allocVar(); if (!s) { - www_SetErr(io_GetErrno(), "%s", io_GetError()); + www_SetErr(elwix_GetErrno(), "%s", elwix_GetError()); return NULL; } @@ -137,7 +137,7 @@ www_getpair(char ** __restrict str, const char *delim) * @str = string * return: digit */ -inline char +char www_x2c(const char *str) { register char digit; @@ -157,7 +157,7 @@ www_x2c(const char *str) * @str = string * return: none */ -inline void +void www_unescape(char * __restrict str) { register int i, j; @@ -177,4 +177,81 @@ www_unescape(char * __restrict str) } str[i] = 0; +} + +/* + * www_undot() - Undotted and clean WWW query filename + * + * @pname = query filename + * return: =NULL error or !=NULL allocated valid filename, after use you must call ait_freeVar() + */ +ait_val_t * +www_undot(const char * __restrict pname) +{ + char *s, *s2, *fname; + int l; + ait_val_t *v; + + if (!pname) + return NULL; + /* check for valid query filename */ + if (*pname != '/') + return NULL; + + v = ait_allocVar(); + if (!v) { + www_SetErr(elwix_GetErrno(), "%s", elwix_GetError()); + return NULL; + } else { + AIT_SET_STR(v, pname + 1); + fname = AIT_GET_STR(v); + } + + /* 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(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(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 = fname + l - 3), "/..")) { + for (s2 = s - 1; s2 >= fname && *s2 != '/'; --s2); + if (s2 < fname) + break; + *s2 = 0; + } + + /* if filename is empry add current dir */ + if (!*fname) { + AIT_FREE_VAL(v); + AIT_SET_STR(v, "./"); + fname = AIT_GET_STR(v); + } + + /* check for valid filename */ + if (*fname == '/' || (fname[0] == '.' && fname[1] == '.' && + (!fname[2] || fname[2] == '/'))) { + ait_freeVar(&v); + return NULL; + } + + return v; }