Browse Source

fix cgi support for PATH_INFO

looks for files immediately after the cgidir, and anything after that file
if there are '/'s becomes PATH_INFO.

also adds a function strip_trailing_slash which may be useful in other parts too.
pull/3/head
aabacchus 7 months ago
parent
commit
aa1affb6c2
Signed by untrusted user: phoebos
GPG Key ID: B02F7D053AC351D3
  1. 47
      main.c
  2. 4
      tests/test.sh

47
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);

4
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

Loading…
Cancel
Save