diff --git a/main.c b/main.c index 687bc15..ce9c7da 100644 --- a/main.c +++ b/main.c @@ -20,7 +20,7 @@ #include "opts.h" #include "utils.h" -/* lenght of "gemini://" */ +/* length of "gemini://" */ #define GEMINI_PART 9 /* @@ -38,6 +38,7 @@ void echdir (const char *); void status (const int, const char *); void status_redirect(const int, const char *); void status_error(const int, const char *); +void strip_trailing_slash(char *path); int uridecode (char *); @@ -304,6 +305,17 @@ cgi(const char *cgicmd) exit(1); } +void +strip_trailing_slash(char *path) +{ + size_t end = strlen(path); + if (end == 0) + return; + end--; + while (path[end] == '/') + path[end--] = '\0'; +} + int main(int argc, char **argv) { @@ -454,7 +466,25 @@ main(int argc, char **argv) * found, then requested file is actually a directory */ if (strlen(dir) > 0) { - pos = strrchr(dir, '/'); + /* + * if in cgidir, only the first file after cgidir/FILE is to be executed + * the rest is PATH_INFO + */ + /* find the string of cgidir without chroot_dir prefix */ + char tmp [PATH_MAX] = {'\0'}; + char *cgipp; + strip_trailing_slash(chroot_dir); + strip_trailing_slash(cgidir); + estrlcpy(tmp, cgidir + strlen(chroot_dir), sizeof(tmp)); + cgipp = tmp; + if (tmp[0] == '/') + cgipp++; + + if (docgi && strncmp(dir, cgipp, strlen(cgipp)) == 0) { + pos = strchr(dir+strlen(cgipp), '/'); + } else { + pos = strrchr(dir, '/'); + } if (pos != NULL) { estrlcpy(file, pos + 1, sizeof(file)); /* +1 : no leading '/' */ pos[0] = '\0'; @@ -491,15 +521,12 @@ main(int argc, char **argv) if (*query) esetenv("QUERY_STRING", query, 1); - /* look for an extension to find PATH_INFO */ - pos = strrchr(file, '.'); + + /* if we've got here and file contains a '/', it should be interpreted as PATH_INFO */ + pos = strchr(file, '/'); if (pos != NULL) { - /* found a dot */ - pos = strchr(pos, '/'); - if (pos != NULL) { - setenv("PATH_INFO", pos, 1); - pos[0] = '\0'; /* keep only script name */ - } + setenv("PATH_INFO", pos, 1); + pos[0] = '\0'; /* keep only script name */ } esetenv("SCRIPT_NAME", file, 1); esetenv("SERVER_NAME", hostname, 1); diff --git a/tests/test.sh b/tests/test.sh index 3f86c9e..0bdc509 100755 --- a/tests/test.sh +++ b/tests/test.sh @@ -91,6 +91,10 @@ if ! [ $OUT = "fa065a67d1f7c973501d4a9e3ca2ea57" ] ; then echo "error" ; exit 1 OUT=$(printf "gemini://host.name/cgi-bin/nope\r\n" | ../vger -d var/gemini/ -c var/gemini/cgi-bin | tee /dev/stderr | MD5) if ! [ $OUT = "74ba4b36dcebec9ce9dae33033f3378a" ] ; then echo "error" ; exit 1 ; fi +# cgi with PATH_INFO +OUT=$(printf "gemini://host.name/cgi-bin/test.cgi/path/info\r\n" | ../vger -d var/gemini -c var/gemini/cgi-bin | tee /dev/stderr | MD5) +if ! [ $OUT = "ec64da76dc578ffb479fbfb23e3a7a5b" ] ; then echo "error" ; exit 1 ; fi + # virtualhost + cgi OUT=$(printf "gemini://perso.pw/cgi-bin/test.cgi\r\n" | ../vger -v -d var/gemini/ -c var/gemini/perso.pw/cgi-bin | tee /dev/stderr | MD5) if ! [ $OUT = "666e48200f90018b5e96c2cf974882dc" ] ; then echo "error" ; exit 1 ; fi