diff --git a/main.c b/main.c index 42fc6eb..8e155a6 100644 --- a/main.c +++ b/main.c @@ -2,6 +2,7 @@ #include #include +#include #include #include #include @@ -33,6 +34,43 @@ void display_file(const char *); void status(const int, const char *); void status_redirect(const int, const char *); void drop_privileges(const char *, const char *); +int uridecode(char *); + +int +uridecode(char *uri) +{ + int n = 0; + char c = '\0'; + long l = 0; + char *pos = NULL; + + if ((pos = strchr(uri, '%')) == NULL) { + return n; + } + while ((pos = strchr(pos, '%')) != NULL) { + if (strlen(pos) < 3) { + return n; + } + + char hex[3] = {'\0'}; + for (size_t i=0; i < 2; i++) { + hex[i] = tolower(pos[i+1]); + } + errno = 0; + l = strtol(hex, 0, 16); + if (errno == ERANGE && (l == LONG_MAX || l == LONG_MIN)) { + /* conversion failed */ + continue; + } + c = (char)l; + pos[0] = c; + /* rewind of two char to remove %hex */ + memmove(pos+1 , pos + 3, strlen(pos+3) + 1); /* +1 for \0*/ + n++; + pos++; /* avoid infinite loop */ + } + return n; +} void drop_privileges(const char *user, const char *path) @@ -483,7 +521,7 @@ main(int argc, char **argv) cgi(cgipath); } else { - //TODO: percent decoding here + uridecode(uri); /* open file and send it to stdout */ display_file(uri); } diff --git a/tests/test.sh b/tests/test.sh index bd50983..13f2ee8 100644 --- a/tests/test.sh +++ b/tests/test.sh @@ -95,6 +95,10 @@ if ! [ $OUT = "c7e352d6aae4ee7e7604548f7874fb9d" ] ; then echo "error" ; exit 1 OUT=$(printf "gemini://perso.pw/cgi-bin/test.cgi\r\n" | ../vger -v -d var/gemini/ -c perso.pw/cgi-bin | tee /dev/stderr | MD5) if ! [ $OUT = "666e48200f90018b5e96c2cf974882dc" ] ; then echo "error" ; exit 1 ; fi +# percent-decoding +OUT=$(printf "%s\r\n" "gemini://host.name/percent%25-encode%3f.gmi" | ../vger -d var/gemini/ | tee /dev/stderr | MD5) +if ! [ $OUT = "83d59cca9ed7040145ac6df1992f5daf" ] ; then echo "error" ; exit 1 ; fi + # must fail only on OpenBSD ! # try to escape from unveil if [ -f /bsd ] diff --git a/tests/var/gemini/percent%-encode?.gmi b/tests/var/gemini/percent%-encode?.gmi new file mode 100644 index 0000000..4331a1f --- /dev/null +++ b/tests/var/gemini/percent%-encode?.gmi @@ -0,0 +1,2 @@ +solene, here is a % for you +and a λ of course :)