diff options
-rw-r--r-- | Makefile | 17 | ||||
-rwxr-xr-x | adapter/protocol/cha-finger | 45 | ||||
-rwxr-xr-x | adapter/protocol/finger | 29 | ||||
-rwxr-xr-x | adapter/protocol/spartan | 15 | ||||
-rw-r--r-- | adapter/tools/nc.nim | 50 | ||||
-rw-r--r-- | bonus/Makefile | 28 | ||||
-rw-r--r-- | doc/protocols.md | 14 | ||||
-rw-r--r-- | res/urimethodmap | 2 |
8 files changed, 114 insertions, 86 deletions
diff --git a/Makefile b/Makefile index 85dc38c5..587d0ba6 100644 --- a/Makefile +++ b/Makefile @@ -48,13 +48,13 @@ endif all: $(OUTDIR_BIN)/cha $(OUTDIR_BIN)/mancha $(OUTDIR_CGI_BIN)/http \ $(OUTDIR_CGI_BIN)/gemini $(OUTDIR_LIBEXEC)/gmi2html \ $(OUTDIR_CGI_BIN)/gopher $(OUTDIR_LIBEXEC)/gopher2html \ - $(OUTDIR_CGI_BIN)/cha-finger $(OUTDIR_CGI_BIN)/about \ + $(OUTDIR_CGI_BIN)/finger $(OUTDIR_CGI_BIN)/about \ $(OUTDIR_CGI_BIN)/file $(OUTDIR_CGI_BIN)/ftp $(OUTDIR_CGI_BIN)/sftp \ $(OUTDIR_LIBEXEC)/dirlist2html \ $(OUTDIR_CGI_BIN)/man $(OUTDIR_CGI_BIN)/spartan \ $(OUTDIR_CGI_BIN)/stbi $(OUTDIR_CGI_BIN)/jebp $(OUTDIR_CGI_BIN)/canvas \ $(OUTDIR_CGI_BIN)/sixel $(OUTDIR_CGI_BIN)/resize \ - $(OUTDIR_LIBEXEC)/urldec $(OUTDIR_LIBEXEC)/urlenc \ + $(OUTDIR_LIBEXEC)/urldec $(OUTDIR_LIBEXEC)/urlenc $(OUTDIR_LIBEXEC)/nc \ $(OUTDIR_LIBEXEC)/md2html $(OUTDIR_LIBEXEC)/ansi2html ln -sf "$(OUTDIR)/$(TARGET)/bin/cha" cha @@ -170,10 +170,10 @@ manpages = $(manpages1) $(manpages5) .PHONY: manpage manpage: $(manpages:%=doc/%) -protocols = http about file ftp sftp gopher gemini cha-finger man spartan stbi \ +protocols = http about file ftp sftp gopher gemini finger man spartan stbi \ jebp sixel canvas resize converters = gopher2html md2html ansi2html gmi2html dirlist2html -tools = urlenc +tools = urlenc nc .PHONY: install install: @@ -201,12 +201,15 @@ uninstall: rm -f "$(DESTDIR)$(PREFIX)/bin/mancha" # intentionally not quoted for f in $(protocols); do rm -f $(LIBEXECDIR_CHAWAN)/cgi-bin/$$f; done -# note: png has been removed in favor of stbi. +# notes: +# * png has been removed in favor of stbi +# * data has been moved back into the main binary +# * gmifetch has been replaced by gemini +# * cha-finger has been renamed to finger rm -f $(LIBEXECDIR_CHAWAN)/cgi-bin/png -# note: data has been moved back into the main binary. rm -f $(LIBEXECDIR_CHAWAN)/cgi-bin/data -# note: gmifetch has been replaced by gemini rm -f $(LIBEXECDIR_CHAWAN)/cgi-bin/gmifetch + rm -f $(LIBEXECDIR_CHAWAN)/cgi-bin/cha-finger rmdir $(LIBEXECDIR_CHAWAN)/cgi-bin || true for f in $(converters) $(tools); do rm -f $(LIBEXECDIR_CHAWAN)/$$f; done # urldec is just a symlink to urlenc diff --git a/adapter/protocol/cha-finger b/adapter/protocol/cha-finger deleted file mode 100755 index 42472e21..00000000 --- a/adapter/protocol/cha-finger +++ /dev/null @@ -1,45 +0,0 @@ -#!/bin/sh -# Finger protocol adapter for Chawan. Requires curl. -# (It does *not* work without the environment variables MAPPED_URI_*, so no -# w3m support.) -# -# Usage: put this script in your cgi-bin folder, then add the following line to -# your urimethodmap: -# -# finger: /cgi-bin/cha-finger -# -# Note: the Chawan default configuration already does this, so normally you -# don't need to do anything to use the finger protocol. - -# Check for errors. -die() { - echo "Cha-Control: ConnectionError $1 $2" - exit 1 -} - -type curl >/dev/null || \ - die 1 "curl must be installed on your computer to use finger" - -PORT="${MAPPED_URI_PORT:-79}" -test "$PORT" = 79 || die 3 "invalid port; only port 79 is supported" - -# Parse the URL. Roughly based on Lynx finger URL parsing, but less -# sophisticated. -if test -n "$MAPPED_URI_USERNAME" -then USER="$MAPPED_URI_USERNAME" -else case "$MAPPED_URI_PATH" in - /w*) USER="/w ${MAPPED_URI_PATH#/w}" ;; - *) USER="${MAPPED_URI_PATH#/}" ;; - esac -fi -URL="telnet://$MAPPED_URI_HOST:$PORT" - -# Headers. -printf 'Content-Type: text/plain\n' -# Newline; from here on we are sending the content body. -printf '\n' -# Finger request, the output of which goes to stdout. -printf '%s\r\n' "$USER" | if test -n "$ALL_PROXY" -then curl -x "$ALL_PROXY" -- "$URL" -else curl -- "$URL" -fi 2>/dev/null diff --git a/adapter/protocol/finger b/adapter/protocol/finger new file mode 100755 index 00000000..4404c8a6 --- /dev/null +++ b/adapter/protocol/finger @@ -0,0 +1,29 @@ +#!/bin/sh +# Finger protocol adapter for Chawan. + +die() { + echo "Cha-Control: ConnectionError $1 $2" + exit 1 +} + +PORT=${MAPPED_URI_PORT:-79} +test "$PORT" = 79 || die InvalidURL "wrong port, only port 79 is supported" + +# Parse the URL. Roughly based on Lynx finger URL parsing, but less +# sophisticated. +USER=$MAPPED_URI_USERNAME +if test -z "$USER" +then case "$MAPPED_URI_PATH" in + /w/*) USER="/w ${MAPPED_URI_PATH#/w/}" ;; + *) USER=${MAPPED_URI_PATH#/} ;; + esac +fi + +# Headers. +printf 'Content-Type: text/plain\n' + +# Newline; from here on we are sending the content body. +printf '\n' + +# Finger request, the output of which goes to stdout. +printf '%s\r\n' "$USER" | "$CHA_LIBEXEC_DIR"/nc "$MAPPED_URI_HOST" "$PORT" diff --git a/adapter/protocol/spartan b/adapter/protocol/spartan index ac0f590e..2f232fb1 100755 --- a/adapter/protocol/spartan +++ b/adapter/protocol/spartan @@ -1,22 +1,13 @@ #!/bin/sh # Adapter for the spartan protocol. See: spartan://mozz.us -# Requires netcat (nc). -# -# Usage: add the following line to your urimethodmap: -# -# spartan: /cgi-bin/spartan.cgi -if ! type nc >/dev/null 2>/dev/null -then printf 'Cha-Control: ConnectionError 1 nc not found\n' - exit 1 -fi MAPPED_URI_PORT=${MAPPED_URI_PORT:=300} # default port is 300 MAPPED_URI_PATH=${MAPPED_URI_PATH:=/} # needs / for root if test "$REQUEST_METHOD" != POST && test "$MAPPED_URI_QUERY" = "input" then printf "Content-Type: text/html <!DOCTYPE html> -<form method=POST action=\"$MAPPED_URI_PATH\"> +<form method=POST action='\"$MAPPED_URI_PATH\"'> Input text to upload: <p> <textarea name=q></textarea> @@ -30,7 +21,7 @@ CONTENT_LENGTH=${CONTENT_LENGTH:=0} # if missing, set to 0 { printf '%s %d\n' "$MAPPED_URI_HOST $MAPPED_URI_PATH" "$CONTENT_LENGTH" tail -c+3 # skip q= -} | nc "$MAPPED_URI_HOST" "$MAPPED_URI_PORT" 2>/dev/null | { +} | "$CHA_LIBEXEC_DIR"/nc "$MAPPED_URI_HOST" "$MAPPED_URI_PORT" | { IFS= read -r line case $line in '2 '*) ctype=${line#2 } @@ -42,6 +33,6 @@ CONTENT_LENGTH=${CONTENT_LENGTH:=0} # if missing, set to 0 '3 '*) printf "Status: 301\nLocation: %s\n" "${line#3 }" ;; '4 '*) printf "Status: 403\n\n%s" "${line#4 }" ;; '5 '*) printf "Status: 500\n\n%s" "${line#5 }" ;; - *) printf "Cha-Control: ConnectionError 1 malformed response\n" + *) printf "Cha-Control: ConnectionError InvalidResponse\n" esac } diff --git a/adapter/tools/nc.nim b/adapter/tools/nc.nim new file mode 100644 index 00000000..c9e3735b --- /dev/null +++ b/adapter/tools/nc.nim @@ -0,0 +1,50 @@ +# Minimal, TCP-only nc clone. Intended for use in shell scripts in +# simple protocols (e.g. finger, spartan). +# +# This program respects ALL_PROXY (if set). +import std/os +import std/posix + +import ../protocol/lcgi +import io/poll + +proc usage() {.noreturn.} = + stderr.write("Usage: " & paramStr(0) & " [host] [port]\n") + quit(1) + +proc main() = + if paramCount() != 2: + usage() + let os = newPosixStream(STDOUT_FILENO) + let ips = newPosixStream(STDIN_FILENO) + let ps = os.connectSocket(paramStr(1), paramStr(2)) + var pollData = PollData() + pollData.register(STDIN_FILENO, POLLIN) + pollData.register(ps.fd, POLLIN) + var buf {.noinit.}: array[4096, uint8] + var i = 0 # unregister counter + while i < 2: + pollData.poll(-1) + for event in pollData.events: + assert (event.revents and POLLOUT) == 0 + if (event.revents and POLLIN) != 0: + if event.fd == STDIN_FILENO: + let n = ips.recvData(buf) + if n == 0: + pollData.unregister(ips.fd) + inc i + continue + ps.sendDataLoop(buf.toOpenArray(0, n - 1)) + else: + assert event.fd == ps.fd + let n = ps.recvData(buf) + if n == 0: + pollData.unregister(ips.fd) + inc i + continue + os.sendDataLoop(buf.toOpenArray(0, n - 1)) + if (event.revents and POLLERR) != 0 or (event.revents and POLLHUP) != 0: + pollData.unregister(event.fd) + inc i + +main() diff --git a/bonus/Makefile b/bonus/Makefile index 6365e7c0..cab38f89 100644 --- a/bonus/Makefile +++ b/bonus/Makefile @@ -9,6 +9,19 @@ bindir = $(DESTDIR)$(prefix)/bin none: @echo "Run make install-{file} to install a script." +.PHONY: install-git.cgi +install-git.cgi: git.cgi + mkdir -p $(CHA_CGI_DIR) + cp git.cgi $(CHA_CGI_DIR) + ./addurimethod git git.cgi +#TODO this will almost never work unless the user is root... + ln -s $(CHA_CGI_DIR)/git.cgi $(bindir)/gitcha + +.PHONY: install-filei.cgi +install-filei.cgi: filei.cgi + mkdir -p $(CHA_CGI_DIR) + cp filei.cgi $(CHA_CGI_DIR) + stbir2_url=https://raw.githubusercontent.com/nothings/stb/master/stb_image_resize2.h stbir2/stb_image_resize2.h: @@ -24,30 +37,19 @@ install-stbir2: stbir2/stbir2.nim stbir2/stb_image_resize2.h stbir2/stb_image_re mkdir -p $(CHA_CGI_DIR) nim c -d:release -d:lto -o:$(CHA_CGI_DIR)/resize stbir2/stbir2.nim -.PHONY: install-git.cgi -install-git.cgi: git.cgi - mkdir -p $(CHA_CGI_DIR) - cp git.cgi $(CHA_CGI_DIR) - ./addurimethod git git.cgi -#TODO this will almost never work unless the user is root... - ln -s $(CHA_CGI_DIR)/git.cgi $(bindir)/gitcha - -.PHONY: install-filei.cgi -install-filei.cgi: filei.cgi - mkdir -p $(CHA_CGI_DIR) - cp filei.cgi $(CHA_CGI_DIR) - .PHONY: install-libfetch.c install-libfetch-http.c: $(CHA_CGI_DIR)/libfetch-http $(CC) -Wall -O2 -g -std=c89 $< -lfetch -o $@ ./addurimethod http libfetch-http ./addurimethod https libfetch-http +.PHONY: install-magnet.cgi install-magnet.cgi: magnet.cgi mkdir -p $(CHA_CGI_DIR) cp magnet.cgi $(CHA_CGI_DIR) ./addurimethod magnet magnet.cgi +.PHONY: install-trans.cgi install-trans.cgi: trans.cgi mkdir -p $(CHA_CGI_DIR) cp trans.cgi $(CHA_CGI_DIR) diff --git a/doc/protocols.md b/doc/protocols.md index 9fa07f06..dbf271bf 100644 --- a/doc/protocols.md +++ b/doc/protocols.md @@ -94,19 +94,17 @@ HTML. ## Finger -Finger is supported through the `adapter/protocol/cha-finger` shell script. -It is implemented as a shell script because of the protocol's simplicity. -cha-finger uses the `curl` program's telnet:// protocol to make requests. -As such, it will not work if `curl` is not installed. +Finger is supported through the `finger` shell script. It is implemented +as a shell script because of the protocol's simplicity. -Aspiring protocol adapter writers are encouraged to study cha-finger for -a simple example of how a custom protocol handler could be written. +For portability, `finger` uses Chawan's `nc` tool (a very limited netcat +clone) to make requests. ## Spartan Spartan is a protocol similar to Gemini, but without TLS. It is supported -through the `adapter/protocol/spartan` shell script, which uses `nc` to make -requests. +through the `spartan` shell script, and like Finger, it uses Chawan's `nc` to +make requests. Spartan has the very strange property of extending gemtext with a protocol-specific line type. This is sort of supported through a sed filter diff --git a/res/urimethodmap b/res/urimethodmap index 5f0a2b28..bdeb5b20 100644 --- a/res/urimethodmap +++ b/res/urimethodmap @@ -2,7 +2,7 @@ http: cgi-bin:http https: cgi-bin:http -finger: cgi-bin:cha-finger +finger: cgi-bin:finger gemini: cgi-bin:gemini about: cgi-bin:about file: cgi-bin:file |