diff options
author | bptato <nincsnevem662@gmail.com> | 2024-10-12 17:14:01 +0200 |
---|---|---|
committer | bptato <nincsnevem662@gmail.com> | 2024-10-12 17:19:44 +0200 |
commit | c4a75720959a968004fec1996d6870d0874c953d (patch) | |
tree | 428407444b6aa0199060629047f5393f3b590218 /adapter | |
parent | 828716e78b5b1a9fea93c2839d89e189c1fcb252 (diff) | |
download | chawan-c4a75720959a968004fec1996d6870d0874c953d.tar.gz |
Add `nc' tool & adjust finger/spartan to use it
Simple netcat clone, useful for portable scripts. Especially because some netcats will close the connection as soon as I close stdin... this one only quits when either stdout or the socket refuses new data. Also, it uses our standard TCP connection routine, meaning it respects ALL_PROXY. (i.e. now spartan works with socks5 too)
Diffstat (limited to 'adapter')
-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 |
4 files changed, 82 insertions, 57 deletions
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() |