iAdd new REST calling convention. - geomyidae - A small C-based gopherd. Err bitreich.org 70 hgit clone git://bitreich.org/geomyidae/ git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65d7roiv6bfj7d652fid.onion/geomyidae/ URL:git://bitreich.org/geomyidae/ git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65d7roiv6bfj7d652fid.onion/geomyidae/ bitreich.org 70 1Log /scm/geomyidae/log.gph bitreich.org 70 1Files /scm/geomyidae/files.gph bitreich.org 70 1Refs /scm/geomyidae/refs.gph bitreich.org 70 1Tags /scm/geomyidae/tag bitreich.org 70 1README /scm/geomyidae/file/README.gph bitreich.org 70 1LICENSE /scm/geomyidae/file/LICENSE.gph bitreich.org 70 i--- Err bitreich.org 70 1commit 418068d8e58c69ef9abf183ac02e942bf5912883 /scm/geomyidae/commit/418068d8e58c69ef9abf183ac02e942bf5912883.gph bitreich.org 70 1parent 248e0a1c429fa0ce1f35103765e84175a9c7571e /scm/geomyidae/commit/248e0a1c429fa0ce1f35103765e84175a9c7571e.gph bitreich.org 70 hAuthor: Christoph Lohmann <20h@r-36.net> URL:mailto:20h@r-36.net bitreich.org 70 iDate: Sat, 2 Apr 2022 22:47:11 +0200 Err bitreich.org 70 i Err bitreich.org 70 iAdd new REST calling convention. Err bitreich.org 70 i Err bitreich.org 70 iDiffstat: Err bitreich.org 70 i M CGI.md | 19 +++++++++++++++++++ Err bitreich.org 70 i A cgi-examples/rest.dcgi | 23 +++++++++++++++++++++++ Err bitreich.org 70 i M geomyidae.8 | 5 ++++- Err bitreich.org 70 i M main.c | 101 ++++++++++++++++++++++++------- Err bitreich.org 70 i Err bitreich.org 70 i4 files changed, 125 insertions(+), 23 deletions(-) Err bitreich.org 70 i--- Err bitreich.org 70 1diff --git a/CGI.md b/CGI.md /scm/geomyidae/file/CGI.md.gph bitreich.org 70 i@@ -59,6 +59,25 @@ If both ways of input are combined, the variables are set as following: Err bitreich.org 70 i -> $host = server host Err bitreich.org 70 i -> $port = server port Err bitreich.org 70 i Err bitreich.org 70 i+## REST CALLING CONVENTION Err bitreich.org 70 i+ Err bitreich.org 70 i+There is a special mode in geomyidae to imitate REST calling abilities. Err bitreich.org 70 i+ Err bitreich.org 70 i+When a user requests some non-existing path, geomyidae will start from Err bitreich.org 70 i+the base and go up the path directories, until it reaches the first not Err bitreich.org 70 i+existing directory. Err bitreich.org 70 i+ Err bitreich.org 70 i+ C: /base/some/dir/that/does/not/exist?some-arguments searchterm Err bitreich.org 70 i+ -> /base exists Err bitreich.org 70 i+ -> /some exists Err bitreich.org 70 i+ -> /dir does not exist Err bitreich.org 70 i+ -> search for index.cgi or index.dcgi in /base/some Err bitreich.org 70 i+ -> if not found, display directory content Err bitreich.org 70 i+ -> if found, call index.cgi or index.dcgi as follows: Err bitreich.org 70 i+ -> $search = »searchterm« Err bitreich.org 70 i+ -> $arguments = »/dir/that/does/not/exist?some-arguments« Err bitreich.org 70 i+ -> $host = server host Err bitreich.org 70 i+ -> $port = server port Err bitreich.org 70 i Err bitreich.org 70 i ## STANDARD CGI Err bitreich.org 70 i Err bitreich.org 70 1diff --git a/cgi-examples/rest.dcgi b/cgi-examples/rest.dcgi /scm/geomyidae/file/cgi-examples/rest.dcgi.gph bitreich.org 70 i@@ -0,0 +1,23 @@ Err bitreich.org 70 i+#!/bin/sh Err bitreich.org 70 i+# Err bitreich.org 70 i+# Simple gopher REST interpretation. Err bitreich.org 70 i+# Err bitreich.org 70 i+ Err bitreich.org 70 i+if [ -n "$2" ]; Err bitreich.org 70 i+then Err bitreich.org 70 i+ case "$2" in Err bitreich.org 70 i+ /articles*) Err bitreich.org 70 i+ printf "Article 1\n"; Err bitreich.org 70 i+ printf "Article 2\n"; Err bitreich.org 70 i+ ;; Err bitreich.org 70 i+ /read*) Err bitreich.org 70 i+ printf "Read me!\n"; Err bitreich.org 70 i+ ;; Err bitreich.org 70 i+ /write*) Err bitreich.org 70 i+ printf "Write me!\n"; Err bitreich.org 70 i+ ;; Err bitreich.org 70 i+ *) Err bitreich.org 70 i+ ;; Err bitreich.org 70 i+ esac Err bitreich.org 70 i+fi Err bitreich.org 70 i+ Err bitreich.org 70 1diff --git a/geomyidae.8 b/geomyidae.8 /scm/geomyidae/file/geomyidae.8.gph bitreich.org 70 i@@ -347,7 +347,7 @@ Both .cgi and .dcgi scripts have the same argument call structure (as seen by ge Err bitreich.org 70 i where Err bitreich.org 70 i .Pp Err bitreich.org 70 i .D1 search = query string (type 7) or Qo Qc (type 0) Err bitreich.org 70 i-.D1 arguments = string after Qo ? Qc in the path or Qo Qc Err bitreich.org 70 i+.D1 arguments = string after Qo ? Qc in the path, the remaining path or Qo Qc Err bitreich.org 70 i .D1 host = server's hostname ("localhost" by default) Err bitreich.org 70 i .D1 port = server's port ("70" by default) Err bitreich.org 70 i .Pp Err bitreich.org 70 i@@ -355,6 +355,9 @@ All terms are tab-separated (per gopher protocol) which can cause some Err bitreich.org 70 i surprises depending on how a script is written. See the CGI file (included Err bitreich.org 70 i in the geomyidae source archive) for further elaboration. Err bitreich.org 70 i .Pp Err bitreich.org 70 i+For a special REST path case for the arguments, see the CGI file for the Err bitreich.org 70 i+description. Err bitreich.org 70 i+.Pp Err bitreich.org 70 i QUIRK: The original gopher client tried to be too intelligent. It is using Err bitreich.org 70 i gopher+ when you request some resource. When "search" is just the value "+", Err bitreich.org 70 i "!", "$" or empty, geomyidae will display a gopher+ redirect instead of invoking the Err bitreich.org 70 1diff --git a/main.c b/main.c /scm/geomyidae/file/main.c.gph bitreich.org 70 i@@ -65,6 +65,8 @@ char *nocgierr = "3Sorry, execution of the token '%s' was requested, but this " Err bitreich.org 70 i "\tlocalhost\t70\r\n"; Err bitreich.org 70 i char *notfounderr = "3Sorry, but the requested token '%s' could not be found.\tErr" Err bitreich.org 70 i "\tlocalhost\t70\r\n"; Err bitreich.org 70 i+char *toolongerr = "3Sorry, but the requested token '%s' is a too long path.\tErr" Err bitreich.org 70 i+ "\tlocalhost\t70\r\n"; Err bitreich.org 70 i char *htredir = "\n" Err bitreich.org 70 i "\n" Err bitreich.org 70 i@@ -133,13 +135,16 @@ handlerequest(int sock, char *req, int rlen, char *base, char *ohost, Err bitreich.org 70 i int istls) Err bitreich.org 70 i { Err bitreich.org 70 i struct stat dir; Err bitreich.org 70 i- char recvc[1025], recvb[1025], path[1025], *args = NULL, *sear, *c; Err bitreich.org 70 i+ char recvc[1025], recvb[1025], path[1025], args[1025], argsc[1025], Err bitreich.org 70 i+ *sear, *c, *sep, *pathp, *recvbp; Err bitreich.org 70 i int len = 0, fd, i, maxrecv; Err bitreich.org 70 i filetype *type; Err bitreich.org 70 i Err bitreich.org 70 i memset(&dir, 0, sizeof(dir)); Err bitreich.org 70 i memset(recvb, 0, sizeof(recvb)); Err bitreich.org 70 i memset(recvc, 0, sizeof(recvc)); Err bitreich.org 70 i+ memset(args, 0, sizeof(args)); Err bitreich.org 70 i+ memset(argsc, 0, sizeof(argsc)); Err bitreich.org 70 i Err bitreich.org 70 i maxrecv = sizeof(recvb) - 1; Err bitreich.org 70 i if (rlen > maxrecv || rlen < 0) Err bitreich.org 70 i@@ -204,9 +209,11 @@ handlerequest(int sock, char *req, int rlen, char *base, char *ohost, Err bitreich.org 70 i * selectors. Err bitreich.org 70 i */ Err bitreich.org 70 i Err bitreich.org 70 i- args = strchr(recvb, '?'); Err bitreich.org 70 i- if (args != NULL) Err bitreich.org 70 i- *args++ = '\0'; Err bitreich.org 70 i+ c = strchr(recvb, '?'); Err bitreich.org 70 i+ if (c != NULL) { Err bitreich.org 70 i+ *c++ = '\0'; Err bitreich.org 70 i+ snprintf(args, sizeof(args), "%s", c); Err bitreich.org 70 i+ } Err bitreich.org 70 i Err bitreich.org 70 i if (recvb[0] == '\0') { Err bitreich.org 70 i recvb[0] = '/'; Err bitreich.org 70 i@@ -222,31 +229,81 @@ handlerequest(int sock, char *req, int rlen, char *base, char *ohost, Err bitreich.org 70 i return; Err bitreich.org 70 i } Err bitreich.org 70 i Err bitreich.org 70 i- snprintf(path, sizeof(path), "%s%s", base, recvb); Err bitreich.org 70 i+ if (snprintf(path, sizeof(path), "%s%s", base, recvb) > sizeof(path)) { Err bitreich.org 70 i+ if (loglvl & ERRORS) { Err bitreich.org 70 i+ logentry(clienth, clientp, recvc, Err bitreich.org 70 i+ "path truncation occurred"); Err bitreich.org 70 i+ } Err bitreich.org 70 i+ dprintf(sock, toolongerr, recvc); Err bitreich.org 70 i+ return; Err bitreich.org 70 i+ } Err bitreich.org 70 i Err bitreich.org 70 i fd = -1; Err bitreich.org 70 i- if (stat(path, &dir) != -1 && S_ISDIR(dir.st_mode)) { Err bitreich.org 70 i- for (i = 0; i < sizeof(indexf)/sizeof(indexf[0]); i++) { Err bitreich.org 70 i- if (strlen(path) + strlen(indexf[i]) >= sizeof(path)) { Err bitreich.org 70 i+ /* Err bitreich.org 70 i+ * If path could not be found, do: Err bitreich.org 70 i+ * 1.) Traverse from base directory one dir by dir. Err bitreich.org 70 i+ * 2.) If one path element, separated by "/", is not found, stop. Err bitreich.org 70 i+ * 3.) Prepare new args string: Err bitreich.org 70 i+ * Err bitreich.org 70 i+ * $args = $rest_of_path + "?" + $args Err bitreich.org 70 i+ */ Err bitreich.org 70 i+ if (stat(path, &dir) == -1) { Err bitreich.org 70 i+ memmove(argsc, args, strlen(args)); Err bitreich.org 70 i+ snprintf(path, sizeof(path), "%s", base); Err bitreich.org 70 i+ recvbp = recvb + 1; Err bitreich.org 70 i+ while (recvbp != NULL) { Err bitreich.org 70 i+ sep = strsep(&recvbp, "/"); Err bitreich.org 70 i+ snprintf(path+strlen(path), sizeof(path)-strlen(path), Err bitreich.org 70 i+ "/%s", sep); Err bitreich.org 70 i+ if (stat(path, &dir) == -1) { Err bitreich.org 70 i+ c = strrchr(path, '/'); Err bitreich.org 70 i+ if (c != NULL) { Err bitreich.org 70 i+ *c++ = '\0'; Err bitreich.org 70 i+ snprintf(args, sizeof(args), Err bitreich.org 70 i+ "/%s%s%s%s%s", Err bitreich.org 70 i+ c, Err bitreich.org 70 i+ (recvbp != NULL)? "/" : "", Err bitreich.org 70 i+ (recvbp != NULL)? recvbp : "", Err bitreich.org 70 i+ (argsc[0] != '\0')? "?" : "", Err bitreich.org 70 i+ (argsc[0] != '\0')? argsc : "" Err bitreich.org 70 i+ ); Err bitreich.org 70 i+ } Err bitreich.org 70 i+ /* path fallthrough */ Err bitreich.org 70 i+ break; Err bitreich.org 70 i+ } Err bitreich.org 70 i+ } Err bitreich.org 70 i+ } Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (stat(path, &dir) != -1) { Err bitreich.org 70 i+ if (S_ISDIR(dir.st_mode)) { Err bitreich.org 70 i+ for (i = 0; i < sizeof(indexf)/sizeof(indexf[0]); Err bitreich.org 70 i+ i++) { Err bitreich.org 70 i+ if (strlen(path) + strlen(indexf[i]) Err bitreich.org 70 i+ >= sizeof(path)) { Err bitreich.org 70 i+ if (loglvl & ERRORS) { Err bitreich.org 70 i+ logentry(clienth, clientp, Err bitreich.org 70 i+ recvc, Err bitreich.org 70 i+ "path truncation occurred"); Err bitreich.org 70 i+ } Err bitreich.org 70 i+ return; Err bitreich.org 70 i+ } Err bitreich.org 70 i+ strncat(path, indexf[i], Err bitreich.org 70 i+ sizeof(path)-strlen(path)-1); Err bitreich.org 70 i+ fd = open(path, O_RDONLY); Err bitreich.org 70 i+ if (fd >= 0) Err bitreich.org 70 i+ break; Err bitreich.org 70 i+ path[strlen(path)-strlen(indexf[i])] = '\0'; Err bitreich.org 70 i+ } Err bitreich.org 70 i+ } else { Err bitreich.org 70 i+ fd = open(path, O_RDONLY); Err bitreich.org 70 i+ if (fd < 0) { Err bitreich.org 70 i+ dprintf(sock, notfounderr, recvc); Err bitreich.org 70 i if (loglvl & ERRORS) { Err bitreich.org 70 i logentry(clienth, clientp, recvc, Err bitreich.org 70 i- "path truncation occurred"); Err bitreich.org 70 i+ strerror(errno)); Err bitreich.org 70 i } Err bitreich.org 70 i return; Err bitreich.org 70 i } Err bitreich.org 70 i- strncat(path, indexf[i], sizeof(path) - strlen(path) - 1); Err bitreich.org 70 i- fd = open(path, O_RDONLY); Err bitreich.org 70 i- if (fd >= 0) Err bitreich.org 70 i- break; Err bitreich.org 70 i- path[strlen(path)-strlen(indexf[i])] = '\0'; Err bitreich.org 70 i- } Err bitreich.org 70 i- } else { Err bitreich.org 70 i- fd = open(path, O_RDONLY); Err bitreich.org 70 i- if (fd < 0) { Err bitreich.org 70 i- dprintf(sock, notfounderr, recvc); Err bitreich.org 70 i- if (loglvl & ERRORS) Err bitreich.org 70 i- logentry(clienth, clientp, recvc, strerror(errno)); Err bitreich.org 70 i- return; Err bitreich.org 70 i } Err bitreich.org 70 i } Err bitreich.org 70 i Err bitreich.org 70 .