commit ead63f21453971163c9235d9b7ea4ea866f81055
parent 90fff06c0d5d196c7d021595858ac06094e364f3
Author: Giygas <mvk@girlpoison.org>
Date: Tue, 4 Jun 2024 01:46:36 +0200
Source profile, command line options, bugfixes...
Diffstat:
M | README | | | 104 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------------- |
M | mime.types | | | 3 | --- |
M | t4t | | | 26 | +++++++++++--------------- |
M | t4t-receive | | | 94 | +++++++++++++++++++++++++++++++++++++++++++------------------------------------ |
4 files changed, 136 insertions(+), 91 deletions(-)
diff --git a/README b/README
@@ -5,11 +5,11 @@ It consists of two scripts: t4t, and t4t-receive.
t4t uploads files to T4T_HOST over ssh, which prompts t4t-receive to write the received data
to the specified file. This is accomplished through setting up your authorized_keys in a certain way;
-see 'SETUP' below.
+see 'SIMPLE SETUP' below.
Usage - t4t
------------
-t4t [-u user] [-h host] [-N] [files...]
+t4t [-u user] [-h host] [files...]
DESCRIPTION
Pipes the given files to user@host through ssh. If no files are specified,
@@ -24,44 +24,88 @@ OPTIONS
T4T_USER.
-h host
Specify which host to connect to over ssh. This overrides T4T_HOST.
- -N
- Do not retain file names when uploading. This will prompt t4t to
- generate one for you.
Usage - t4t-receive
--------------------
-t4t-receive [-D] [-l limit] name
+SYNOPSIS
+ t4t-receive [-B blacklist] [-d dir] [-l limit] [-M | -m mimefile] [-r root]
+ [-S | -s profile] [-t tmp] [-u url] [name]
DESCRIPTION
- Writes file data from stdin to name in T4T_ROOT ($HOME/www by default).
- If name does not have an extension, t4t-receive will attempt to identify
- the data and pick an appropriate extension.
+ Writes file data from stdin to root/name (~/www by default).
+
+ Name is inferred through SSH_ORIGINAL_COMMAND. If this variable is unset,
+ t4t-receive will use the command line option. If no name has been specified
+ on the command line, it will generate a random name automatically.
+
+ If a file with the given name exists, t4t-receive appends random characters
+ to the given name until it is unique.
After a successful write, t4t-receive prints a URL to the uploaded file,
- constructed with the help of T4T_URL.
+ constructed with the help of url.
+
+ If -S is not set, t4t-receive sources the shell profile (~/.profile
+ by default) for relevant variables. All shell variables are overridden by
+ their command line option counterparts (see below)
OPTIONS
- -D
- If the name does not have a file extension, do not attempt to guess
- one.
+ -B blacklist
+ Defines a space-delimited list of extensions to be stripped from name.
+ Its corresponding shell variable is T4T_BLACKLIST.
+
+ -d dir
+ Write to subdirectory dir in root. Its corresponding shell variable
+ is T4T_DIR.
+
-l limit
- Specifies the maximum file size for the incoming data. limit may
+ Defines the maximum file size for the incoming data. limit may
optionally be followed by a unit multiplier, much like dd. e.g.
- KB, MB, GB, TB
-
-SETUP
- Uncomment and define the variables at the start of the script. T4T_ROOT is
- described above. T4T_URL defines the URL displayed in the output.
-
- T4T_MIMETYPES specifies which file to look for extensions in. It defaults
- to '/etc/mime.types', but it is recommended to set it to the saner
- mime.types provided with t4t.
-
- Create an account and home directory for the user account that clients
- will connect to. It is recommended to choose 't4t' as the name. Ensure
- that this user is able to accept incoming ssh connections, and set up the
- .ssh/authorized_keys file like so:
- command="$HOME/t4t-receive" ssh-rsa ...public key for user 1...
- command="$HOME/t4t-receive -l 20M" ssh-rsa ...public key for user 2...
+ KB, MB, GB, TB. Negative numbers correspond to unlimited file size.
+ Its corresponding shell variable is T4T_LIMIT. The default is '-1'.
+
+ -M
+ Do not attempt to guess an appropriate extension based on the file's
+ MIME type.
+
+ -m
+ Defines the file to consult for extensions. Its corresponding shell
+ variable is T4T_MIME. The default is '/usr/share/t4t/mime.types'.
+ Using '/etc/mime.types' may result in nonsensical extensions.
+
+ -r root
+ Defines the root directory to write to. Its corresponding shell
+ variable is T4T_ROOT.
+
+ -S
+ Do not source profile for environment variables.
+
+ -s profile
+ Defines the file to source for environment variables.
+
+ -t tmp
+ Defines the directory to store intermediary files in. Its corresponding
+ shell variable is T4T_TMP. The default is '/tmp'.
+
+ -u url
+ Defines the url to display in the output. Its corresponding shell
+ variable is T4T_URL.
+
+SIMPLE SETUP
+ Create a user account and home directory that clients will connect to.
+ It is recommended to choose 't4t' as the name. Ensure that this user is able
+ to accept incoming ssh connections.
+
+ Define the default variables in .profile. T4T_ROOT and T4T_URL are required.
+ It is recommended to change T4T_MIME to the correct path depending on your
+ distribution and installation.
+
+ Create a line for each authorised user in your .ssh/authorized_keys file like so:
+ command="t4t-receive -l -1 -B ''" ssh-rsa ...public key for owner
+ command="t4t-receive -l 100M -d aaron" ssh-rsa ...public key for aaron
+ command="t4t-receive -d bill" ssh-rsa ...public key for bill
+ command="t4t-receive -d cynthia" ssh-rsa ...public key for cynthia
...etc
+ Users may now leverage the t4t script described above, or upload directly
+ over ssh:
+ ssh -T t4t@[host] [name] <FILE
diff --git a/mime.types b/mime.types
@@ -25,9 +25,6 @@ image/png png
image/x-xbitmap xbm
image/x-xpixmap xpm
image/x-xwindowdump xwd
-text/html html
-text/html htm
-text/javascript js
text/plain txt
text/xml dtd
text/xml xml
diff --git a/t4t b/t4t
@@ -2,20 +2,14 @@
PROGNAME="$(basename $0)"
err() { echo "$PROGNAME: $*" >&2; }
-usage() { err "usage: $PROGNAME [-u user] [-h host] [-N] [files...]"; }
+usage() { err "usage: $PROGNAME [-u user] [-h host] [files...]"; }
randstring() { tr -dc 'A-Za-z0-9_\-' </dev/urandom | head -c "${1-8}"; }
-KEEPNAMES=1
-while getopts "u:h:N" OPT; do
+while getopts "u:h:" OPT; do
case ${OPT} in
- u)
- T4T_USER="${OPTARG}";;
- h)
- T4T_HOST="${OPTARG}";;
- N)
- unset KEEPNAMES;;
- *)
- usage; exit 1;;
+ u) T4T_USER="${OPTARG}";;
+ h) T4T_HOST="${OPTARG}";;
+ *) usage; exit 1;;
esac
done
shift $((OPTIND-1))
@@ -23,9 +17,11 @@ shift $((OPTIND-1))
[ "$T4T_HOST" ] || { err "set T4T_HOST or pass -h"; exit 1; }
for F in "${@:--}"; do
- if [ "$F" != "-" ] && [ ! -e "$F" ]; then err "no such file '$F'"; continue; fi
- if [ ! "$KEEPNAMES" ] || [ "$F" == "-" ]; then NAME="$(randstring)"
- else NAME="$(basename "$F")"; fi
+ unset NAME
+ if [ "$F" != "-" ]; then
+ [ ! -e "$F" ] && { err "no such file '$F'"; continue; }
+ NAME="$(basename "$F")";
+ fi
- cat "$F" | ssh "${T4T_USER-t4t}@$T4T_HOST" "$NAME"
+ cat "$F" | ssh -T "${T4T_USER-t4t}@$T4T_HOST" "$NAME"
done
diff --git a/t4t-receive b/t4t-receive
@@ -1,56 +1,64 @@
#!/bin/bash
-# Set these variables to your liking.
-#T4T_ROOT="$HOME/www"
-#T4T_URL="https://t4t.fun"
-#T4T_MIMETYPES="$HOME/mime.types"
-
PROGNAME="$(basename $0)"
-err() { echo "$PROGNAME: $*" >&2; }
-usage() { err "usage: $PROGNAME [-D] [-l limit] name"; }
+panic() { echo "$PROGNAME: $*" >&2; exit 1; }
+usage() { panic "usage: $PROGNAME [-B blacklist] [-d dir] [-l limit] [-M | -m mimefile]"\
+ "[-r root] [-S | -s profile] [-t tmp] [-u url] name"; }
randstring() { tr -dc 'A-Za-z0-9_\-' </dev/urandom | head -c ${1-8}; }
+clean() { [ -e "$TMPFILE" ] && rm "$TMPFILE"; }
+trap 'clean; exit' INT TERM EXIT QUIT HUP
-[ "$T4T_ROOT" ] && [ -d "$T4T_ROOT" ] || { err "T4T_ROOT not set or directory doesn't exist"; exit 1; }
-[ "$T4T_URL" ] || { err "T4T_URL not set."; exit 1; }
-
-MIMEDETECT=1;
-while getopts "Dl:" OPT; do
+OPTS=("BLACKLIST DETECT DIR LIMIT MIME PROFILE ROOT TMP URL")
+unset $OPTS
+DETECT=1; SOURCE=1
+while getopts "B:d:l:Mm:r:Ss:t:u:" OPT; do
case ${OPT} in
- D)
- unset MIMEDETECT;;
- l)
- T4T_LIMIT="${OPTARG}";;
- *)
- usage; exit 1;;
+ B) BLACKLIST="${OPTARG}";;
+ d) DIR="${OPTARG}";;
+ l) LIMIT="${OPTARG}";;
+ M) DETECT=0;;
+ m) MIME="${OPTARG}";;
+ r) ROOT="${OPTARG}";;
+ S) SOURCE=0;;
+ s) PROFILE="${OPTARG}";;
+ t) TMP="${OPTARG}";;
+ u) URL="${OPTARG}";;
+ *) usage;;
esac
-done
-shift $((OPTIND-1))
+done; shift $((OPTIND-1))
+
+[ $SOURCE -ne 0 ] && { source "${PROFILE-"$HOME/.profile"}" || exit 1; }
+for V in $OPTS; do eval "$(printf 'T4T_%s=${%s-"$T4T_%s"}\n' "$V" "$V" "$V")"; done
+
+[ "$T4T_ROOT" ] || panic "T4T_ROOT not set.";
+[ -d "$T4T_ROOT" ] || panic "T4T_ROOT: '$T4T_DIR' no such directory"
+[ "$T4T_DIR" ] && [ ! -d "$T4T_ROOT/$T4T_DIR" ] && panic "T4T_DIR: '$T4T_ROOT/$T4T_DIR' no such directory"
+TARGETDIR="$T4T_ROOT${T4T_DIR:+"/$T4T_DIR"}"
+[ "$T4T_URL" ] || panic "T4T_URL not set."
+[ "${T4T_MIME:="/usr/share/t4t/mime.types"}" ] && [ ! -f "$T4T_MIME" ] && panic "T4T_MIME: no such file '$T4T_MIME'"
+[ -d "${T4T_TMP:=/tmp}" ] || panic "T4T_TMP: '$T4T_TMP' no such directory"
+T4T_BLACKLIST=("$T4T_BLACKLIST")
-NAME="$(tr -dc 'A-Za-z0-9_\-.' <<<"$SSH_ORIGINAL_COMMAND")"
-[ "$NAME" ] || { err "no name specified"; exit 1; }
-[ "$NAME" == "." ] || [ "$NAME" == ".." ] && err "illegal file name" && exit 1
+NAME="$(tr -dc 'A-Za-z0-9_\-.' <<<"${SSH_ORIGINAL_COMMAND:-"$*"}")"
+[ "$NAME" ] || NAME="$(randstring 4)"
EXT="$(grep -Eo '\.[a-zA-Z0-9]+$' <<<"$NAME")"
+BNAME="$(basename ${EXT:+-s$EXT} "$NAME")"
-while test -e "$T4T_ROOT/$NAME"; do
- SNAME="$(basename ${EXT:+-s$EXT} "$NAME")"
- NAME="$SNAME$(randstring 1)$EXT"
-done
-FILE="$T4T_ROOT/$NAME"
-
-head -c ${T4T_LIMIT-10M} > "$FILE"
-[ -e "$FILE" ] || { err "could not write file '$NAME'"; exit 1; }
-if [ $(du "$FILE" | cut -f1) -eq 0 ]; then
- rm "$FILE"
- err "empty file discarded"
- exit 1
-fi
+for E in $T4T_BLACKLIST; do [ "$EXT" == "$E" ] && unset EXT; done
+
+TMPFILE="$T4T_TMP/t4t-$(randstring 8)"
+head -c ${T4T_LIMIT:--1} > "$TMPFILE"
+[ -e "$TMPFILE" ] || panic "could not write temporary file"
+[ $(du "$TMPFILE" | cut -f1) -eq 0 ] && { panic "empty file discarded"; }
-if [ "$MIMEDETECT" ] && [ ! "$EXT" ]; then
- MIME="$(file -b --mime-type "$FILE")"
- EXT=".$(cat "${T4T_MIMETYPES-/etc/mime.types}" | awk -v m="$MIME" '$1==m{print $NF}')"
- [ ! "$EXT" ] && EXT=".txt"
- mv "$FILE" "$FILE$EXT" || exit 1;
- NAME="$(basename "$FILE")$EXT"
+if [ $DETECT -ne 0 ] && [ ! "$EXT" ]; then
+ TYPE="$(file -b --mime-type "$TMPFILE")"
+ EXT=".$(cat "$T4T_MIME" | awk -v t="$TYPE" '$1==t{print $NF; exit}')"
+ [ "$EXT" == "." ] && EXT=".txt"
fi
-echo "$T4T_URL/$NAME"
+# security note: test -e $TARGETDIR/. and $TARGETDIR/.. always eval to true
+while test -e "$TARGETDIR/$BNAME$EXT"; do BNAME="$BNAME$(randstring 1)"; done
+mv "$TMPFILE" "$TARGETDIR/$BNAME$EXT"
+
+echo "$T4T_URL/${T4T_DIR:+"$T4T_DIR/"}$BNAME$EXT"