slcl-upload/slcl-upload

144 lines
2.1 KiB
Bash
Executable File

#! /bin/bash
# Use of bash is required because "upload_dir" is recursive and
# thus needs local variables.
set -eu
usage()
{
printf "$0 <srcdir> <dstdir> <url>\n"
}
escape_url()
{
perl -MURI::Escape -e \
'print uri_escape shift, , q{^A-Za-z0-9\-._~/:}' -- "$1"
}
if [ $# != 3 ]
then
usage >&2
exit 1
fi
src="$1"
dir="$2"
url="$3"
echo Username: >&2
IFS= read -r user
if printf '%s' "$user" | grep -qe '[[:space:]]'
then
echo Username cannot contain whitespaces >&2
exit 1
fi
ttycfg=$(stty -g)
trap "stty $ttycfg" INT QUIT TERM EXIT
stty -echo
echo Password: >&2
IFS= read -r pwd
stty echo
# Force newline
echo
cookie="$(mktemp)"
cleanup()
{
rm -f $cookie
}
slcl_mkdir()
{
if ! curl --head \
--fail-with-body \
--no-progress-meter \
-s \
-b "$cookie" \
-o /dev/null \
"$(escape_url "$url/user$2/$1/")"
then
curl -X POST \
--fail-with-body \
-b "$cookie" \
--data-urlencode "name=$1" --data-urlencode "dir=$2/" \
"$url/mkdir"
fi
}
trap cleanup EXIT
curl -X POST \
--fail-with-body \
-c "$cookie" \
--data-urlencode "username=$user" --data-urlencode "password=$pwd" \
"$url/login"
level=0
upload_dir()
{
local src="$1"
local dir="$2"
local n=$(cd "$1" && ls -A | wc -l)
local i=1
test $n -eq 0 && return
level=$(($level + 1))
while read f
do
for l in $(seq $level)
do
printf "-"
done
printf " [%d/%d] %s -> %s " "$i" "$n" "$f" "$dir$src/"
if test -d "$src/$f"
then
printf "[entering directory]\n"
slcl_mkdir "$f" "$dir$src"
upload_dir "$src/$f" "$dir"
elif ! test -f "$src/$f"
then
printf "[not a file]\n"
elif curl --head \
--fail-with-body \
--no-progress-meter \
-s \
-b "$cookie" \
-o /dev/null \
"$(escape_url "$url/user$dir$src/$f")"
then
printf "[skipping]\n"
else
while ! curl -X POST \
--fail-with-body \
-b "$cookie" \
-F dir="$dir$src/" \
-F "file=@$src/$f;filename=$(basename -- "$f")" \
"$(escape_url "$url/upload")"
do
printf "[retrying]"
sleep 5
done
printf "[done]\n"
fi
i=$(($i + 1))
done <<-EOF
$(cd "$1" && ls -A)
EOF
level=$(($level - 1))
}
slcl_mkdir "$src" "$dir"
upload_dir "$src" "$dir"