Introduction
Introduction Statistics Contact Development Disclaimer Help
Add new REST calling convention. - geomyidae - A small C-based gopherd.
git clone git://bitreich.org/geomyidae/ git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfri…
Log
Files
Refs
Tags
README
LICENSE
---
commit 418068d8e58c69ef9abf183ac02e942bf5912883
parent 248e0a1c429fa0ce1f35103765e84175a9c7571e
Author: Christoph Lohmann <[email protected]>
Date: Sat, 2 Apr 2022 22:47:11 +0200
Add new REST calling convention.
Diffstat:
M CGI.md | 19 +++++++++++++++++++
A cgi-examples/rest.dcgi | 23 +++++++++++++++++++++++
M geomyidae.8 | 5 ++++-
M main.c | 101 ++++++++++++++++++++++++-----…
4 files changed, 125 insertions(+), 23 deletions(-)
---
diff --git a/CGI.md b/CGI.md
@@ -59,6 +59,25 @@ If both ways of input are combined, the variables are set as…
-> $host = server host
-> $port = server port
+## REST CALLING CONVENTION
+
+There is a special mode in geomyidae to imitate REST calling abilities.
+
+When a user requests some non-existing path, geomyidae will start from
+the base and go up the path directories, until it reaches the first not
+existing directory.
+
+ C: /base/some/dir/that/does/not/exist?some-arguments searchterm
+ -> /base exists
+ -> /some exists
+ -> /dir does not exist
+ -> search for index.cgi or index.dcgi in /base/some
+ -> if not found, display directory content
+ -> if found, call index.cgi or index.dcgi as follows:
+ -> $search = »searchterm«
+ -> $arguments = »/dir/that/does/not/exist?some-arguments«
+ -> $host = server host
+ -> $port = server port
## STANDARD CGI
diff --git a/cgi-examples/rest.dcgi b/cgi-examples/rest.dcgi
@@ -0,0 +1,23 @@
+#!/bin/sh
+#
+# Simple gopher REST interpretation.
+#
+
+if [ -n "$2" ];
+then
+ case "$2" in
+ /articles*)
+ printf "Article 1\n";
+ printf "Article 2\n";
+ ;;
+ /read*)
+ printf "Read me!\n";
+ ;;
+ /write*)
+ printf "Write me!\n";
+ ;;
+ *)
+ ;;
+ esac
+fi
+
diff --git a/geomyidae.8 b/geomyidae.8
@@ -347,7 +347,7 @@ Both .cgi and .dcgi scripts have the same argument call str…
where
.Pp
.D1 search = query string (type 7) or Qo Qc (type 0)
-.D1 arguments = string after Qo ? Qc in the path or Qo Qc
+.D1 arguments = string after Qo ? Qc in the path, the remaining path or Qo Qc
.D1 host = server's hostname ("localhost" by default)
.D1 port = server's port ("70" by default)
.Pp
@@ -355,6 +355,9 @@ All terms are tab-separated (per gopher protocol) which can…
surprises depending on how a script is written. See the CGI file (included
in the geomyidae source archive) for further elaboration.
.Pp
+For a special REST path case for the arguments, see the CGI file for the
+description.
+.Pp
QUIRK: The original gopher client tried to be too intelligent. It is using
gopher+ when you request some resource. When "search" is just the value "+",
"!", "$" or empty, geomyidae will display a gopher+ redirect instead of invoki…
diff --git a/main.c b/main.c
@@ -65,6 +65,8 @@ char *nocgierr = "3Sorry, execution of the token '%s' was req…
"\tlocalhost\t70\r\n";
char *notfounderr = "3Sorry, but the requested token '%s' could not be found.\…
"\tlocalhost\t70\r\n";
+char *toolongerr = "3Sorry, but the requested token '%s' is a too long path.\t…
+ "\tlocalhost\t70\r\n";
char *htredir = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
"<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//E…
" \"DTD/xhtml-transitional.dtd\">\n"
@@ -133,13 +135,16 @@ handlerequest(int sock, char *req, int rlen, char *base, …
int istls)
{
struct stat dir;
- char recvc[1025], recvb[1025], path[1025], *args = NULL, *sear, *c;
+ char recvc[1025], recvb[1025], path[1025], args[1025], argsc[1025],
+ *sear, *c, *sep, *pathp, *recvbp;
int len = 0, fd, i, maxrecv;
filetype *type;
memset(&dir, 0, sizeof(dir));
memset(recvb, 0, sizeof(recvb));
memset(recvc, 0, sizeof(recvc));
+ memset(args, 0, sizeof(args));
+ memset(argsc, 0, sizeof(argsc));
maxrecv = sizeof(recvb) - 1;
if (rlen > maxrecv || rlen < 0)
@@ -204,9 +209,11 @@ handlerequest(int sock, char *req, int rlen, char *base, c…
* selectors.
*/
- args = strchr(recvb, '?');
- if (args != NULL)
- *args++ = '\0';
+ c = strchr(recvb, '?');
+ if (c != NULL) {
+ *c++ = '\0';
+ snprintf(args, sizeof(args), "%s", c);
+ }
if (recvb[0] == '\0') {
recvb[0] = '/';
@@ -222,31 +229,81 @@ handlerequest(int sock, char *req, int rlen, char *base, …
return;
}
- snprintf(path, sizeof(path), "%s%s", base, recvb);
+ if (snprintf(path, sizeof(path), "%s%s", base, recvb) > sizeof(path)) {
+ if (loglvl & ERRORS) {
+ logentry(clienth, clientp, recvc,
+ "path truncation occurred");
+ }
+ dprintf(sock, toolongerr, recvc);
+ return;
+ }
fd = -1;
- if (stat(path, &dir) != -1 && S_ISDIR(dir.st_mode)) {
- for (i = 0; i < sizeof(indexf)/sizeof(indexf[0]); i++) {
- if (strlen(path) + strlen(indexf[i]) >= sizeof(path)) {
+ /*
+ * If path could not be found, do:
+ * 1.) Traverse from base directory one dir by dir.
+ * 2.) If one path element, separated by "/", is not found, stop.
+ * 3.) Prepare new args string:
+ *
+ * $args = $rest_of_path + "?" + $args
+ */
+ if (stat(path, &dir) == -1) {
+ memmove(argsc, args, strlen(args));
+ snprintf(path, sizeof(path), "%s", base);
+ recvbp = recvb + 1;
+ while (recvbp != NULL) {
+ sep = strsep(&recvbp, "/");
+ snprintf(path+strlen(path), sizeof(path)-strlen(path),
+ "/%s", sep);
+ if (stat(path, &dir) == -1) {
+ c = strrchr(path, '/');
+ if (c != NULL) {
+ *c++ = '\0';
+ snprintf(args, sizeof(args),
+ "/%s%s%s%s%s",
+ c,
+ (recvbp != NULL)? "/" : "",
+ (recvbp != NULL)? recvbp : "",
+ (argsc[0] != '\0')? "?" : "",
+ (argsc[0] != '\0')? argsc : ""
+ );
+ }
+ /* path fallthrough */
+ break;
+ }
+ }
+ }
+
+ if (stat(path, &dir) != -1) {
+ if (S_ISDIR(dir.st_mode)) {
+ for (i = 0; i < sizeof(indexf)/sizeof(indexf[0]);
+ i++) {
+ if (strlen(path) + strlen(indexf[i])
+ >= sizeof(path)) {
+ if (loglvl & ERRORS) {
+ logentry(clienth, clientp,
+ recvc,
+ "path truncation occur…
+ }
+ return;
+ }
+ strncat(path, indexf[i],
+ sizeof(path)-strlen(path)-1);
+ fd = open(path, O_RDONLY);
+ if (fd >= 0)
+ break;
+ path[strlen(path)-strlen(indexf[i])] = '\0';
+ }
+ } else {
+ fd = open(path, O_RDONLY);
+ if (fd < 0) {
+ dprintf(sock, notfounderr, recvc);
if (loglvl & ERRORS) {
logentry(clienth, clientp, recvc,
- "path truncation occurred");
+ strerror(errno));
}
return;
}
- strncat(path, indexf[i], sizeof(path) - strlen(path) -…
- fd = open(path, O_RDONLY);
- if (fd >= 0)
- break;
- path[strlen(path)-strlen(indexf[i])] = '\0';
- }
- } else {
- fd = open(path, O_RDONLY);
- if (fd < 0) {
- dprintf(sock, notfounderr, recvc);
- if (loglvl & ERRORS)
- logentry(clienth, clientp, recvc, strerror(err…
- return;
}
}
You are viewing proxied material from bitreich.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.