Compare commits
3 Commits
e0b6e8d577
...
3db6bfeb30
Author | SHA1 | Date |
---|---|---|
Case Duckworth | 3db6bfeb30 | |
Case Duckworth | cccc29e31a | |
Case Duckworth | d1029c2573 |
|
@ -93,14 +93,14 @@ bollux() {
|
||||||
bollux_args() {
|
bollux_args() {
|
||||||
while getopts :hvq OPT; do
|
while getopts :hvq OPT; do
|
||||||
case "$OPT" in
|
case "$OPT" in
|
||||||
(h)
|
h)
|
||||||
bollux_usage
|
bollux_usage
|
||||||
exit
|
exit
|
||||||
;;
|
;;
|
||||||
(v) BOLLUX_LOGLEVEL=DEBUG ;;
|
v) BOLLUX_LOGLEVEL=DEBUG ;;
|
||||||
(q) BOLLUX_LOGLEVEL=QUIET ;;
|
q) BOLLUX_LOGLEVEL=QUIET ;;
|
||||||
(:) die 1 "Option -$OPTARG requires an argument" ;;
|
:) die 1 "Option -$OPTARG requires an argument" ;;
|
||||||
(*) die 1 "Unknown option: -$OPTARG" ;;
|
*) die 1 "Unknown option: -$OPTARG" ;;
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
shift $((OPTIND - 1))
|
shift $((OPTIND - 1))
|
||||||
|
@ -142,16 +142,16 @@ bollux_config() {
|
||||||
: "${BOLLUX_TIMEOUT:=30}" # connection timeout
|
: "${BOLLUX_TIMEOUT:=30}" # connection timeout
|
||||||
: "${BOLLUX_MAXREDIR:=5}" # max redirects
|
: "${BOLLUX_MAXREDIR:=5}" # max redirects
|
||||||
: "${BOLLUX_PROTO:=gemini}" # default protocol
|
: "${BOLLUX_PROTO:=gemini}" # default protocol
|
||||||
: "${BOLLUX_GEMINI_PORT:=1965}" # default port for gemini
|
: "${BOLLUX_GEMINI_PORT:=1965}" # default port for gemini
|
||||||
: "${BOLLUX_GOPHER_PORT:=70}" # default port for gopher
|
: "${BOLLUX_GOPHER_PORT:=70}" # default port for gopher
|
||||||
: "${BOLLUX_URL:=}" # start url
|
: "${BOLLUX_URL:=}" # start url
|
||||||
: "${BOLLUX_BYEMSG:=See You Space Cowboy ...}" # bye message
|
: "${BOLLUX_BYEMSG:=See You Space Cowboy ...}" # bye message
|
||||||
## lesskeys
|
## lesskeys
|
||||||
: "${KEY_OPEN:=o}" # prompt for a link to open
|
: "${KEY_OPEN:=o}" # prompt for a link to open
|
||||||
: "${KEY_GOTO:=g}" # prompt for a page to 'goto'
|
: "${KEY_GOTO:=g}" # prompt for a page to 'goto'
|
||||||
: "${KEY_GOTO_FROM:=G}" # goto a page with current prefilled
|
: "${KEY_GOTO_FROM:=G}" # goto a page with current prefilled
|
||||||
: "${KEY_BACK:='['}" # go back in the history
|
: "${KEY_BACK:=[}" # go back in the history
|
||||||
: "${KEY_FORWARD:=']'}" # go forward in the history
|
: "${KEY_FORWARD:=]}" # go forward in the history
|
||||||
: "${KEY_REFRESH:=r}" # refresh the page
|
: "${KEY_REFRESH:=r}" # refresh the page
|
||||||
: "${KEY_CYCLE_PRE:=p}" # cycle T_PRE_DISPLAY
|
: "${KEY_CYCLE_PRE:=p}" # cycle T_PRE_DISPLAY
|
||||||
: "${BOLLUX_CUSTOM_LESSKEY:=$BOLLUX_CONF_DIR/bollux.lesskey}"
|
: "${BOLLUX_CUSTOM_LESSKEY:=$BOLLUX_CONF_DIR/bollux.lesskey}"
|
||||||
|
@ -252,24 +252,24 @@ run() { # run COMMAND...
|
||||||
log() { # log LEVEL MESSAGE...
|
log() { # log LEVEL MESSAGE...
|
||||||
# 'QUIET' means don't log anything.
|
# 'QUIET' means don't log anything.
|
||||||
[[ "$BOLLUX_LOGLEVEL" == QUIET ]] && return
|
[[ "$BOLLUX_LOGLEVEL" == QUIET ]] && return
|
||||||
local fmt # ANSI escape code
|
local fmt # ANSI escape code
|
||||||
|
|
||||||
case "$1" in
|
case "$1" in
|
||||||
([dD]*) # Debug level -- only print if bollux -v.
|
[dD]*) # Debug level -- only print if bollux -v.
|
||||||
[[ "$BOLLUX_LOGLEVEL" == DEBUG ]] || return
|
[[ "$BOLLUX_LOGLEVEL" == DEBUG ]] || return
|
||||||
fmt=34 # Blue
|
fmt=34 # Blue
|
||||||
;;
|
;;
|
||||||
([eE]*) # Error level -- always print.
|
[eE]*) # Error level -- always print.
|
||||||
fmt=31 # Red
|
fmt=31 # Red
|
||||||
;;
|
;;
|
||||||
(*) # Diagnostic level -- print unless QUIET.
|
*) # Diagnostic level -- print unless QUIET.
|
||||||
fmt=1 # Bold
|
fmt=1 # Bold
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
shift
|
shift
|
||||||
|
|
||||||
printf >&2 '\e[%sm%s:%-16s:\e[0m %s\n' \
|
printf >&2 '\e[%sm%s:%-16s:\e[0m %s\n' \
|
||||||
"$fmt" "$PRGN" "${FUNCNAME[${LOG_FUNC:-1}]}" "$*"
|
"$fmt" "$PRGN" "${FUNCNAME[${LOG_FUNC:-1}]}" "$*"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Exit with an error and a message describing it.
|
# Exit with an error and a message describing it.
|
||||||
|
@ -298,10 +298,10 @@ list_cycle() { # list_cycle LIST<string> DELIM
|
||||||
# T_PRE_DISPLAY, which is user-configurable. I wanted it to be as easy
|
# T_PRE_DISPLAY, which is user-configurable. I wanted it to be as easy
|
||||||
# to configure for users who might not immediately know the bash array
|
# to configure for users who might not immediately know the bash array
|
||||||
# syntax, but can figure out 'variable=value' without much thought.
|
# syntax, but can figure out 'variable=value' without much thought.
|
||||||
local list="${!1}" # Pass the list by name, not value
|
local list="${!1}" # Pass the list by name, not value
|
||||||
local delim="$2" # The delimiter of the string
|
local delim="$2" # The delimiter of the string
|
||||||
local first="${list%%${delim}*}" # The first element
|
local first="${list%%${delim}*}" # The first element
|
||||||
local rest="${list#*${delim}}" # The rest of the elements
|
local rest="${list#*${delim}}" # The rest of the elements
|
||||||
# -v prints to the variable specified.
|
# -v prints to the variable specified.
|
||||||
printf -v "$1" '%s%s%s' "${rest}" "${delim}" "${first}"
|
printf -v "$1" '%s%s%s' "${rest}" "${delim}" "${first}"
|
||||||
}
|
}
|
||||||
|
@ -325,7 +325,7 @@ prompt() { # prompt [-u] PROMPT [READ_ARGS...]
|
||||||
read_cmd+=(-i "$BOLLUX_URL")
|
read_cmd+=(-i "$BOLLUX_URL")
|
||||||
shift
|
shift
|
||||||
fi
|
fi
|
||||||
local prompt="$1" # How to prompt the user
|
local prompt="$1" # How to prompt the user
|
||||||
shift
|
shift
|
||||||
read_cmd+=(-p "$prompt> ")
|
read_cmd+=(-p "$prompt> ")
|
||||||
"${read_cmd[@]}" </dev/tty "$@"
|
"${read_cmd[@]}" </dev/tty "$@"
|
||||||
|
@ -423,11 +423,11 @@ usplit() { # usplit URL_ARRAY<name> URL
|
||||||
# below performs a reverse lookup on the name to get the actual data.
|
# below performs a reverse lookup on the name to get the actual data.
|
||||||
# shellcheck disable=2034
|
# shellcheck disable=2034
|
||||||
local entire_url="${BASH_REMATCH[0]}" \
|
local entire_url="${BASH_REMATCH[0]}" \
|
||||||
scheme="${BASH_REMATCH[2]}" \
|
scheme="${BASH_REMATCH[2]}" \
|
||||||
authority="${BASH_REMATCH[4]}" \
|
authority="${BASH_REMATCH[4]}" \
|
||||||
path="${BASH_REMATCH[5]}" \
|
path="${BASH_REMATCH[5]}" \
|
||||||
query="${BASH_REMATCH[7]}" \
|
query="${BASH_REMATCH[7]}" \
|
||||||
fragment="${BASH_REMATCH[9]}"
|
fragment="${BASH_REMATCH[9]}"
|
||||||
|
|
||||||
# Iterate through the 5 components of a URL and assign them to elements
|
# Iterate through the 5 components of a URL and assign them to elements
|
||||||
# of URL_ARRAY, as follows:
|
# of URL_ARRAY, as follows:
|
||||||
|
@ -516,10 +516,10 @@ ucblank() { # ucblank COMPONENT<name>
|
||||||
# `ucset' sets one component of a URL array and setting the 0th element to the
|
# `ucset' sets one component of a URL array and setting the 0th element to the
|
||||||
# new full URL. Use it instead of directly setting the array element with U[x],
|
# new full URL. Use it instead of directly setting the array element with U[x],
|
||||||
# because U[0] will fall out of sync with the rest of the contents.
|
# because U[0] will fall out of sync with the rest of the contents.
|
||||||
ucset() { # ucset URL_ARRAY_INDEX<name> NEW_VALUE
|
ucset() { # ucset URL_ARRAY_INDEX<name> NEW_VALUE
|
||||||
local url_array_component="$1" # Of form 'URL_ARRAY[INDEX]'
|
local url_array_component="$1" # Of form 'URL_ARRAY[INDEX]'
|
||||||
local value="$2"
|
local value="$2"
|
||||||
|
|
||||||
# Assign $value to $url_array_component.
|
# Assign $value to $url_array_component.
|
||||||
#
|
#
|
||||||
# Wrapped in an 'eval' for the extra layer of indirection.
|
# Wrapped in an 'eval' for the extra layer of indirection.
|
||||||
|
@ -538,8 +538,8 @@ uencode() { # uencode URL
|
||||||
for ((i = 0; i < ${#1}; i++)); do
|
for ((i = 0; i < ${#1}; i++)); do
|
||||||
: "${1:i:1}"
|
: "${1:i:1}"
|
||||||
case "$_" in
|
case "$_" in
|
||||||
([a-zA-Z0-9.~_-]) printf '%s' "$_" ;;
|
[a-zA-Z0-9.~_-]) printf '%s' "$_" ;;
|
||||||
(*) printf '%%%02X' "'$_" ;;
|
*) printf '%%%02X' "'$_" ;;
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
printf '\n'
|
printf '\n'
|
||||||
|
@ -704,7 +704,6 @@ gemini_request() { # gemini_request URL
|
||||||
port="$BOLLUX_GEMINI_PORT"
|
port="$BOLLUX_GEMINI_PORT"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
# Build the SSL command to request the resource.
|
# Build the SSL command to request the resource.
|
||||||
#
|
#
|
||||||
# This is the beating heart of bollux, the command that does all the
|
# This is the beating heart of bollux, the command that does all the
|
||||||
|
@ -716,12 +715,12 @@ gemini_request() { # gemini_request URL
|
||||||
# manual [9] it says not to use it, but who reads the manual,
|
# manual [9] it says not to use it, but who reads the manual,
|
||||||
# anyway?
|
# anyway?
|
||||||
openssl s_client
|
openssl s_client
|
||||||
-crlf # Automatically add CR+LF to line
|
-crlf # Automatically add CR+LF to line
|
||||||
-quiet # Don't print all the cert stuff
|
-quiet # Don't print all the cert stuff
|
||||||
# -ign_eof # `-quiet' implies `-ign_eof'
|
# -ign_eof # `-quiet' implies `-ign_eof'
|
||||||
-connect "${url[2]}:$port" # The server and port to connect
|
-connect "${url[2]}:$port" # The server and port to connect
|
||||||
-servername "${url[2]}" # SNI: Server Name Identification
|
-servername "${url[2]}" # SNI: Server Name Identification
|
||||||
-no_ssl3 -no_tls1 -no_tls1_1 # disable old TLS/SSL versions
|
-no_ssl3 -no_tls1 -no_tls1_1 # disable old TLS/SSL versions
|
||||||
)
|
)
|
||||||
|
|
||||||
# Actually request the resource.
|
# Actually request the resource.
|
||||||
|
@ -733,9 +732,9 @@ gemini_request() { # gemini_request URL
|
||||||
|
|
||||||
# Handle the gemini response - see [3] Section 3.
|
# Handle the gemini response - see [3] Section 3.
|
||||||
gemini_response() { # gemini_response URL
|
gemini_response() { # gemini_response URL
|
||||||
local code meta # received on the first line of the response
|
local code meta # received on the first line of the response
|
||||||
local title # determined by a clunky heuristic, see read loop: (2*)
|
local title # determined by a clunky heuristic, see read loop: (2*)
|
||||||
local url="$1" # the currently-visited URL.
|
local url="$1" # the currently-visited URL.
|
||||||
|
|
||||||
# Read the first line.
|
# Read the first line.
|
||||||
#
|
#
|
||||||
|
@ -751,7 +750,7 @@ gemini_response() { # gemini_response URL
|
||||||
# `download', below), but I'm not sure how to remedy that issue either.
|
# `download', below), but I'm not sure how to remedy that issue either.
|
||||||
# It requires more research.
|
# It requires more research.
|
||||||
while read -t "$BOLLUX_TIMEOUT" -r code meta ||
|
while read -t "$BOLLUX_TIMEOUT" -r code meta ||
|
||||||
{ (($? > 128)) && die 99 "Timeout."; }; do
|
{ (($? > 128)) && die 99 "Timeout."; }; do
|
||||||
break
|
break
|
||||||
done
|
done
|
||||||
log d "[$code] $meta"
|
log d "[$code] $meta"
|
||||||
|
@ -763,20 +762,20 @@ gemini_response() { # gemini_response URL
|
||||||
# - I branch on the first digit of the status code, instead of both, to
|
# - I branch on the first digit of the status code, instead of both, to
|
||||||
# minimize the amount of duplicated code I need to write.
|
# minimize the amount of duplicated code I need to write.
|
||||||
case "$code" in
|
case "$code" in
|
||||||
(1*) # INPUT
|
1*) # INPUT
|
||||||
# Gemini allows GET-style requests, and the INPUT family of
|
# Gemini allows GET-style requests, and the INPUT family of
|
||||||
# response codes facilitate them. `10' is for standard input,
|
# response codes facilitate them. `10' is for standard input,
|
||||||
# and `11' is for sensitive information, like passwords.
|
# and `11' is for sensitive information, like passwords.
|
||||||
REDIRECTS=0
|
REDIRECTS=0
|
||||||
BOLLUX_URL="$url"
|
BOLLUX_URL="$url"
|
||||||
case "$code" in
|
case "$code" in
|
||||||
(10) run prompt "$meta" ;;
|
10) run prompt "$meta" ;;
|
||||||
(11) run prompt "$meta" -s ;; # sensitive input
|
11) run prompt "$meta" -s ;; # sensitive input
|
||||||
esac
|
esac
|
||||||
run history_append "$url" "${title:-}"
|
run history_append "$url" "${title:-}"
|
||||||
run blastoff "?$(uencode "$REPLY")"
|
run blastoff "?$(uencode "$REPLY")"
|
||||||
;;
|
;;
|
||||||
(2*) # OK
|
2*) # OK
|
||||||
# The `20' family of requests is like HTTP's `200' family: it
|
# The `20' family of requests is like HTTP's `200' family: it
|
||||||
# means that the request worked and the server is sending the
|
# means that the request worked and the server is sending the
|
||||||
# requested content.
|
# requested content.
|
||||||
|
@ -811,7 +810,7 @@ gemini_response() { # gemini_response URL
|
||||||
passthru
|
passthru
|
||||||
} | run display "$meta" "${title:-}"
|
} | run display "$meta" "${title:-}"
|
||||||
;;
|
;;
|
||||||
(3*) # REDIRECT
|
3*) # REDIRECT
|
||||||
# Redirects are a fundamental part of any hypertext framework,
|
# Redirects are a fundamental part of any hypertext framework,
|
||||||
# and if I remember correctly, one of the main reasons
|
# and if I remember correctly, one of the main reasons
|
||||||
# solderpunk and others began thinking about gemini (the others
|
# solderpunk and others began thinking about gemini (the others
|
||||||
|
@ -838,51 +837,51 @@ gemini_response() { # gemini_response URL
|
||||||
# will also be an option, however.
|
# will also be an option, however.
|
||||||
run blastoff "$meta" # TODO: confirm redirect
|
run blastoff "$meta" # TODO: confirm redirect
|
||||||
;;
|
;;
|
||||||
(4*) # TEMPORARY ERROR
|
4*) # TEMPORARY ERROR
|
||||||
# Since the 4* codes ([3] Appendix 1) are all server issues,
|
# Since the 4* codes ([3] Appendix 1) are all server issues,
|
||||||
# bollux can treat them all basically the same. This is an area
|
# bollux can treat them all basically the same. This is an area
|
||||||
# that could use some expansion.
|
# that could use some expansion.
|
||||||
local desc="Temporary error"
|
local desc="Temporary error"
|
||||||
case "$code" in
|
case "$code" in
|
||||||
(41) desc+=" (server unavailable)" ;;
|
41) desc+=" (server unavailable)" ;;
|
||||||
(42) desc+=" (CGI error)" ;;
|
42) desc+=" (CGI error)" ;;
|
||||||
(43) desc+=" (proxy error)" ;;
|
43) desc+=" (proxy error)" ;;
|
||||||
(44) desc+=" (slow down)" ;; # could be particularly improved
|
44) desc+=" (slow down)" ;; # could be particularly improved
|
||||||
esac
|
esac
|
||||||
REDIRECTS=0
|
REDIRECTS=0
|
||||||
die "$((100 + code))" "$desc [$code]: $meta"
|
die "$((100 + code))" "$desc [$code]: $meta"
|
||||||
;;
|
;;
|
||||||
(5*) # PERMANENT ERROR
|
5*) # PERMANENT ERROR
|
||||||
# The situation with the 5* codes is basically similar to the 4*
|
# The situation with the 5* codes is basically similar to the 4*
|
||||||
# codes. It could maybe use more thought as to what behavior to
|
# codes. It could maybe use more thought as to what behavior to
|
||||||
# implement. Maybe adding the (bad) requests to history,
|
# implement. Maybe adding the (bad) requests to history,
|
||||||
# subject to configuration?
|
# subject to configuration?
|
||||||
local desc="Permanent failure"
|
local desc="Permanent failure"
|
||||||
case "$code" in
|
case "$code" in
|
||||||
(51) desc+=" (not found)" ;;
|
51) desc+=" (not found)" ;;
|
||||||
(52) desc+=" (gone)" ;;
|
52) desc+=" (gone)" ;;
|
||||||
(53) desc+=" (proxy request refused)" ;;
|
53) desc+=" (proxy request refused)" ;;
|
||||||
# For some reason, codes 54--58 inclusive aren't used.
|
# For some reason, codes 54--58 inclusive aren't used.
|
||||||
(59) desc+=" (bad request)" ;;
|
59) desc+=" (bad request)" ;;
|
||||||
esac
|
esac
|
||||||
REDIRECTS=0
|
REDIRECTS=0
|
||||||
die "$((100 + code))" "$desc [$code]: $meta"
|
die "$((100 + code))" "$desc [$code]: $meta"
|
||||||
;;
|
;;
|
||||||
(6*) # CERTIFICATE ERROR (TODO)
|
6*) # CERTIFICATE ERROR (TODO)
|
||||||
# Dealing with certificates is honestly the most important
|
# Dealing with certificates is honestly the most important
|
||||||
# feature missing from bollux to get it to 1.0. Right now,
|
# feature missing from bollux to get it to 1.0. Right now,
|
||||||
# bollux deals with 6* status codes identically to 4* and 5*
|
# bollux deals with 6* status codes identically to 4* and 5*
|
||||||
# codes. This is not ideal, in the slightest.
|
# codes. This is not ideal, in the slightest.
|
||||||
local desc="Client certificate required"
|
local desc="Client certificate required"
|
||||||
case "$code" in
|
case "$code" in
|
||||||
(61) desc+=" (certificate not authorized)" ;;
|
61) desc+=" (certificate not authorized)" ;;
|
||||||
(62) desc+=" (certificate not valid)" ;;
|
62) desc+=" (certificate not valid)" ;;
|
||||||
esac
|
esac
|
||||||
REDIRECTS=0
|
REDIRECTS=0
|
||||||
log d "Not implemented: Client certificates"
|
log d "Not implemented: Client certificates"
|
||||||
die "$((100 + code))" "[$code] $meta"
|
die "$((100 + code))" "[$code] $meta"
|
||||||
;;
|
;;
|
||||||
(*) # UNKNOWN
|
*) # UNKNOWN
|
||||||
# Just in case we get a weird, un-spec-compliant status code.
|
# Just in case we get a weird, un-spec-compliant status code.
|
||||||
[[ -z "${code-}" ]] && die 100 "Empty response code."
|
[[ -z "${code-}" ]] && die 100 "Empty response code."
|
||||||
die "$((100 + code))" "Unknown response code: $code."
|
die "$((100 + code))" "Unknown response code: $code."
|
||||||
|
@ -916,9 +915,9 @@ gopher_request() { # gopher_request URL
|
||||||
# [7] Section 2.1
|
# [7] Section 2.1
|
||||||
[[ "$url" =~ gopher://([^/?#:]*)(:([0-9]+))?(/((.))?(/?.*))?$ ]]
|
[[ "$url" =~ gopher://([^/?#:]*)(:([0-9]+))?(/((.))?(/?.*))?$ ]]
|
||||||
local server="${BASH_REMATCH[1]}" \
|
local server="${BASH_REMATCH[1]}" \
|
||||||
port="${BASH_REMATCH[3]:-$BOLLUX_GOPHER_PORT}" \
|
port="${BASH_REMATCH[3]:-$BOLLUX_GOPHER_PORT}" \
|
||||||
type="${BASH_REMATCH[6]:-1}" \
|
type="${BASH_REMATCH[6]:-1}" \
|
||||||
path="${BASH_REMATCH[7]}"
|
path="${BASH_REMATCH[7]}"
|
||||||
log d "URL='$url' SERVER='$server' TYPE='$type' PATH='$path'"
|
log d "URL='$url' SERVER='$server' TYPE='$type' PATH='$path'"
|
||||||
|
|
||||||
# Bash has this really neat feature where it can open a TCP socket
|
# Bash has this really neat feature where it can open a TCP socket
|
||||||
|
@ -952,25 +951,25 @@ gopher_response() { # gopher_response URL
|
||||||
# text-ish, it only concerns itself with those in this case statement.
|
# text-ish, it only concerns itself with those in this case statement.
|
||||||
# All the others are simply downloaded.
|
# All the others are simply downloaded.
|
||||||
case "$type" in
|
case "$type" in
|
||||||
(0) # Item is a file
|
0) # Item is a file
|
||||||
# Since gopher doesn't send MIME-type information in-band, we
|
# Since gopher doesn't send MIME-type information in-band, we
|
||||||
# just assume it's text/plain, and try to convert it later to
|
# just assume it's text/plain, and try to convert it later to
|
||||||
# UTF-8 with `iconv'.
|
# UTF-8 with `iconv'.
|
||||||
run display text/plain
|
run display text/plain
|
||||||
;;
|
;;
|
||||||
(1) # Item is a directory [gophermap]
|
1) # Item is a directory [gophermap]
|
||||||
# Since I've already written all the code to typeset gemini
|
# Since I've already written all the code to typeset gemini
|
||||||
# well, it's easy to convert a gophermap to text/gemini and
|
# well, it's easy to convert a gophermap to text/gemini and
|
||||||
# display it than to write a whole new gophermap typesetter.
|
# display it than to write a whole new gophermap typesetter.
|
||||||
run gopher_convert | run display text/gemini
|
run gopher_convert | run display text/gemini
|
||||||
;;
|
;;
|
||||||
(3) # Error
|
3) # Error
|
||||||
# I don't know all the gopher error cases, and the spec is
|
# I don't know all the gopher error cases, and the spec is
|
||||||
# pretty quiet on them. So bollux just signals failure and
|
# pretty quiet on them. So bollux just signals failure and
|
||||||
# bails.
|
# bails.
|
||||||
die 203 "GOPHER: failed"
|
die 203 "GOPHER: failed"
|
||||||
;;
|
;;
|
||||||
(7) # Item is an Index-Search server
|
7) # Item is an Index-Search server
|
||||||
# Gopher search queries are separated from their resources by a
|
# Gopher search queries are separated from their resources by a
|
||||||
# TAB. It's wild.
|
# TAB. It's wild.
|
||||||
if [[ "$url" =~ $'\t' ]]; then
|
if [[ "$url" =~ $'\t' ]]; then
|
||||||
|
@ -980,7 +979,7 @@ gopher_response() { # gopher_response URL
|
||||||
run blastoff "$url $REPLY"
|
run blastoff "$url $REPLY"
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
(*) # Anything else
|
*) # Anything else
|
||||||
# The list at [6] Section 3.8 includes the following (noted where it
|
# The list at [6] Section 3.8 includes the following (noted where it
|
||||||
# might be good to differently handle them in the future):
|
# might be good to differently handle them in the future):
|
||||||
#
|
#
|
||||||
|
@ -1030,19 +1029,19 @@ gopher_convert() {
|
||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
case "$type" in
|
case "$type" in
|
||||||
(.) # end of file
|
.) # end of file
|
||||||
printf '.\n'
|
printf '.\n'
|
||||||
break
|
break
|
||||||
;;
|
;;
|
||||||
(i) # label
|
i) # label
|
||||||
case "$label" in
|
case "$label" in
|
||||||
('#'* | '*'[[:space:]]*)
|
'#'* | '*'[[:space:]]*)
|
||||||
if $pre; then
|
if $pre; then
|
||||||
printf '%s\n' '```'
|
printf '%s\n' '```'
|
||||||
pre=false
|
pre=false
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
(*)
|
*)
|
||||||
if ! $pre; then
|
if ! $pre; then
|
||||||
printf '%s\n' '```'
|
printf '%s\n' '```'
|
||||||
pre=true
|
pre=true
|
||||||
|
@ -1051,28 +1050,28 @@ gopher_convert() {
|
||||||
esac
|
esac
|
||||||
printf '%s\n' "$label"
|
printf '%s\n' "$label"
|
||||||
;;
|
;;
|
||||||
(h) # html link
|
h) # html link
|
||||||
if $pre; then
|
if $pre; then
|
||||||
printf '%s\n' '```'
|
printf '%s\n' '```'
|
||||||
pre=false
|
pre=false
|
||||||
fi
|
fi
|
||||||
printf '=> %s %s\n' "${path:4}" "$label"
|
printf '=> %s %s\n' "${path:4}" "$label"
|
||||||
;;
|
;;
|
||||||
(T) # telnet link
|
T) # telnet link
|
||||||
if $pre; then
|
if $pre; then
|
||||||
printf '%s\n' '```'
|
printf '%s\n' '```'
|
||||||
pre=false
|
pre=false
|
||||||
fi
|
fi
|
||||||
printf '=> telnet://%s:%s/%s%s %s\n' \
|
printf '=> telnet://%s:%s/%s%s %s\n' \
|
||||||
"$server" "$port" "$type" "$path" "$label"
|
"$server" "$port" "$type" "$path" "$label"
|
||||||
;;
|
;;
|
||||||
(*) # other type
|
*) # other type
|
||||||
if $pre; then
|
if $pre; then
|
||||||
printf '%s\n' '```'
|
printf '%s\n' '```'
|
||||||
pre=false
|
pre=false
|
||||||
fi
|
fi
|
||||||
printf '=> gopher://%s:%s/%s%s %s\n' \
|
printf '=> gopher://%s:%s/%s%s %s\n' \
|
||||||
"$server" "$port" "$type" "$path" "$label"
|
"$server" "$port" "$type" "$path" "$label"
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
|
@ -1109,7 +1108,7 @@ display() { # display METADATA [TITLE]
|
||||||
for ((i = 1; i <= "${#hdr[@]}"; i++)); do
|
for ((i = 1; i <= "${#hdr[@]}"; i++)); do
|
||||||
h="${hdr[$i]}"
|
h="${hdr[$i]}"
|
||||||
case "$h" in
|
case "$h" in
|
||||||
(*charset=*) charset="${h#*=}" ;;
|
*charset=*) charset="${h#*=}" ;;
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
|
|
||||||
|
@ -1119,7 +1118,7 @@ display() { # display METADATA [TITLE]
|
||||||
log debug "mime='$mime'; charset='$charset'"
|
log debug "mime='$mime'; charset='$charset'"
|
||||||
|
|
||||||
case "$mime" in
|
case "$mime" in
|
||||||
(text/*)
|
text/*)
|
||||||
set_title "$title${title:+ - }bollux"
|
set_title "$title${title:+ - }bollux"
|
||||||
# Build the `less' command
|
# Build the `less' command
|
||||||
less_cmd=(less)
|
less_cmd=(less)
|
||||||
|
@ -1163,7 +1162,7 @@ display() { # display METADATA [TITLE]
|
||||||
run "${less_cmd[@]}" && bollux_quit
|
run "${less_cmd[@]}" && bollux_quit
|
||||||
} || run handle_keypress "$?"
|
} || run handle_keypress "$?"
|
||||||
;;
|
;;
|
||||||
(*) run download "$BOLLUX_URL" ;;
|
*) run download "$BOLLUX_URL" ;;
|
||||||
esac
|
esac
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1173,8 +1172,8 @@ less_prompt_escape() { # less_prompt_escape STRING
|
||||||
for ((i = 0; i < ${#1}; i++)); do
|
for ((i = 0; i < ${#1}; i++)); do
|
||||||
: "${1:i:1}"
|
: "${1:i:1}"
|
||||||
case "$_" in
|
case "$_" in
|
||||||
([\?:\.%\\]) printf '\%s' "$_" ;;
|
[\?:\.%\\]) printf '\%s' "$_" ;;
|
||||||
(*) printf '%s' "$_" ;;
|
*) printf '%s' "$_" ;;
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
printf '\n'
|
printf '\n'
|
||||||
|
@ -1232,7 +1231,7 @@ typeset_gemini() {
|
||||||
|
|
||||||
while IFS= read -r; do
|
while IFS= read -r; do
|
||||||
case "$REPLY" in
|
case "$REPLY" in
|
||||||
('```'*)
|
'```'*)
|
||||||
PRE_LINE_FORCE=false
|
PRE_LINE_FORCE=false
|
||||||
if $pre; then
|
if $pre; then
|
||||||
pre=false
|
pre=false
|
||||||
|
@ -1240,28 +1239,28 @@ typeset_gemini() {
|
||||||
pre=true
|
pre=true
|
||||||
fi
|
fi
|
||||||
case "${T_PRE_DISPLAY%%,*}" in
|
case "${T_PRE_DISPLAY%%,*}" in
|
||||||
(pre)
|
pre)
|
||||||
:
|
:
|
||||||
;;
|
;;
|
||||||
(alt | both)
|
alt | both)
|
||||||
$pre && PRE_LINE_FORCE=true \
|
$pre && PRE_LINE_FORCE=true \
|
||||||
gemini_pre "${REPLY#\`\`\`}"
|
gemini_pre "${REPLY#\`\`\`}"
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
continue
|
continue
|
||||||
;;
|
;;
|
||||||
('=>'*)
|
'=>'*)
|
||||||
: $((ln += 1))
|
: $((ln += 1))
|
||||||
gemini_link "$REPLY" $pre "$ln"
|
gemini_link "$REPLY" $pre "$ln"
|
||||||
;;
|
;;
|
||||||
('#'*) gemini_header "$REPLY" $pre ;;
|
'#'*) gemini_header "$REPLY" $pre ;;
|
||||||
('*'[[:space:]]*)
|
'*'[[:space:]]*)
|
||||||
gemini_list "$REPLY" $pre
|
gemini_list "$REPLY" $pre
|
||||||
;;
|
;;
|
||||||
('>'*)
|
'>'*)
|
||||||
gemini_quote "$REPLY" $pre
|
gemini_quote "$REPLY" $pre
|
||||||
;;
|
;;
|
||||||
(*) gemini_text "$REPLY" $pre ;;
|
*) gemini_text "$REPLY" $pre ;;
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
@ -1282,13 +1281,13 @@ gemini_link() {
|
||||||
printf "\e[${C_SIGIL}m%${S_MARGIN}s ${C_RESET}" "$s"
|
printf "\e[${C_SIGIL}m%${S_MARGIN}s ${C_RESET}" "$s"
|
||||||
printf "\e[${C_LINK_NUMBER}m[%d]${C_RESET} " "$ln"
|
printf "\e[${C_LINK_NUMBER}m[%d]${C_RESET} " "$ln"
|
||||||
fold_line -n -B "\e[${C_LINK_TITLE}m" -A "${C_RESET}" \
|
fold_line -n -B "\e[${C_LINK_TITLE}m" -A "${C_RESET}" \
|
||||||
-l "$((${#ln} + 3))" -m "${T_MARGIN}" \
|
-l "$((${#ln} + 3))" -m "${T_MARGIN}" \
|
||||||
"$WIDTH" "$(trim_string "$t")"
|
"$WIDTH" "$(trim_string "$t")"
|
||||||
fold_line -B " \e[${C_LINK_URL}m" \
|
fold_line -B " \e[${C_LINK_URL}m" \
|
||||||
-A "${C_RESET}" \
|
-A "${C_RESET}" \
|
||||||
-l "$((${#ln} + 3 + ${#t}))" \
|
-l "$((${#ln} + 3 + ${#t}))" \
|
||||||
-m "$((T_MARGIN + ${#ln} + 2))" \
|
-m "$((T_MARGIN + ${#ln} + 2))" \
|
||||||
"$WIDTH" "$a"
|
"$WIDTH" "$a"
|
||||||
else
|
else
|
||||||
gemini_pre "$1"
|
gemini_pre "$1"
|
||||||
fi
|
fi
|
||||||
|
@ -1306,7 +1305,7 @@ gemini_header() {
|
||||||
|
|
||||||
printf "\e[${C_SIGIL}m%${S_MARGIN}s ${C_RESET}" "$s"
|
printf "\e[${C_SIGIL}m%${S_MARGIN}s ${C_RESET}" "$s"
|
||||||
fold_line -B "\e[${hdrfmt}m" -A "${C_RESET}" -m "${T_MARGIN}" \
|
fold_line -B "\e[${hdrfmt}m" -A "${C_RESET}" -m "${T_MARGIN}" \
|
||||||
"$WIDTH" "$t"
|
"$WIDTH" "$t"
|
||||||
else
|
else
|
||||||
gemini_pre "$1"
|
gemini_pre "$1"
|
||||||
fi
|
fi
|
||||||
|
@ -1321,7 +1320,7 @@ gemini_list() {
|
||||||
|
|
||||||
printf "\e[${C_SIGIL}m%${S_MARGIN}s ${C_RESET}" "$s"
|
printf "\e[${C_SIGIL}m%${S_MARGIN}s ${C_RESET}" "$s"
|
||||||
fold_line -B "\e[${C_LIST}m" -A "${C_RESET}" -m "$T_MARGIN" \
|
fold_line -B "\e[${C_LIST}m" -A "${C_RESET}" -m "$T_MARGIN" \
|
||||||
"$WIDTH" "$t"
|
"$WIDTH" "$t"
|
||||||
else
|
else
|
||||||
gemini_pre "$1"
|
gemini_pre "$1"
|
||||||
fi
|
fi
|
||||||
|
@ -1336,7 +1335,7 @@ gemini_quote() {
|
||||||
|
|
||||||
printf "\e[${C_SIGIL}m%${S_MARGIN}s ${C_RESET}" "$s"
|
printf "\e[${C_SIGIL}m%${S_MARGIN}s ${C_RESET}" "$s"
|
||||||
fold_line -B "\e[${C_QUOTE}m" -A "${C_RESET}" -m "$T_MARGIN" \
|
fold_line -B "\e[${C_QUOTE}m" -A "${C_RESET}" -m "$T_MARGIN" \
|
||||||
"$WIDTH" "$t"
|
"$WIDTH" "$t"
|
||||||
else
|
else
|
||||||
gemini_pre "$1"
|
gemini_pre "$1"
|
||||||
fi
|
fi
|
||||||
|
@ -1346,7 +1345,7 @@ gemini_text() {
|
||||||
if ! ${2-false}; then
|
if ! ${2-false}; then
|
||||||
printf "%${S_MARGIN}s " ' '
|
printf "%${S_MARGIN}s " ' '
|
||||||
fold_line -m "$T_MARGIN" \
|
fold_line -m "$T_MARGIN" \
|
||||||
"$WIDTH" "$1"
|
"$WIDTH" "$1"
|
||||||
else
|
else
|
||||||
gemini_pre "$1"
|
gemini_pre "$1"
|
||||||
fi
|
fi
|
||||||
|
@ -1370,25 +1369,25 @@ fold_line() { # fold_line [OPTIONS...] WIDTH TEXT
|
||||||
OPTIND=0
|
OPTIND=0
|
||||||
while getopts nm:f:l:B:A: OPT; do
|
while getopts nm:f:l:B:A: OPT; do
|
||||||
case "$OPT" in
|
case "$OPT" in
|
||||||
(n) # -n = no trailing newline
|
n) # -n = no trailing newline
|
||||||
newline=false
|
newline=false
|
||||||
;;
|
;;
|
||||||
(m) # -m MARGIN = margin for all lines
|
m) # -m MARGIN = margin for all lines
|
||||||
margin_all="$OPTARG"
|
margin_all="$OPTARG"
|
||||||
;;
|
;;
|
||||||
(f) # -f MARGIN = margin for first line
|
f) # -f MARGIN = margin for first line
|
||||||
margin_first="$OPTARG"
|
margin_first="$OPTARG"
|
||||||
;;
|
;;
|
||||||
(l) # -l LENGTH = length of line before starting fold
|
l) # -l LENGTH = length of line before starting fold
|
||||||
ll="$OPTARG"
|
ll="$OPTARG"
|
||||||
;;
|
;;
|
||||||
(B) # -B BEFORE = text to insert before each line
|
B) # -B BEFORE = text to insert before each line
|
||||||
before="$OPTARG"
|
before="$OPTARG"
|
||||||
;;
|
;;
|
||||||
(A) # -A AFTER = text to insert after each line
|
A) # -A AFTER = text to insert after each line
|
||||||
after="$OPTARG"
|
after="$OPTARG"
|
||||||
;;
|
;;
|
||||||
(*) return 1 ;;
|
*) return 1 ;;
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
shift "$((OPTIND - 1))"
|
shift "$((OPTIND - 1))"
|
||||||
|
@ -1426,37 +1425,37 @@ fold_line() { # fold_line [OPTIONS...] WIDTH TEXT
|
||||||
# use the exit code from less (see mklesskey) to do things
|
# use the exit code from less (see mklesskey) to do things
|
||||||
handle_keypress() { # handle_keypress CODE
|
handle_keypress() { # handle_keypress CODE
|
||||||
case "$1" in
|
case "$1" in
|
||||||
(48) # o - open a link -- show a menu of links on the page
|
48) # o - open a link -- show a menu of links on the page
|
||||||
run select_url "$BOLLUX_PAGESRC"
|
run select_url "$BOLLUX_PAGESRC"
|
||||||
;;
|
;;
|
||||||
(49) # g - goto a url -- input a new url
|
49) # g - goto a url -- input a new url
|
||||||
prompt GO
|
prompt GO
|
||||||
run blastoff -u "$REPLY"
|
run blastoff -u "$REPLY"
|
||||||
;;
|
;;
|
||||||
(50) # [ - back in the history
|
50) # [ - back in the history
|
||||||
run history_back || {
|
run history_back || {
|
||||||
sleep 0.5
|
sleep 0.5
|
||||||
run blastoff "$BOLLUX_URL"
|
run blastoff "$BOLLUX_URL"
|
||||||
}
|
}
|
||||||
;;
|
;;
|
||||||
(51) # ] - forward in the history
|
51) # ] - forward in the history
|
||||||
run history_forward || {
|
run history_forward || {
|
||||||
sleep 0.5
|
sleep 0.5
|
||||||
run blastoff "$BOLLUX_URL"
|
run blastoff "$BOLLUX_URL"
|
||||||
}
|
}
|
||||||
;;
|
;;
|
||||||
(52) # r - re-request the current resource
|
52) # r - re-request the current resource
|
||||||
run blastoff "$BOLLUX_URL"
|
run blastoff "$BOLLUX_URL"
|
||||||
;;
|
;;
|
||||||
(53) # G - goto a url (pre-filled with current)
|
53) # G - goto a url (pre-filled with current)
|
||||||
run prompt -u GO
|
run prompt -u GO
|
||||||
run blastoff -u "$REPLY"
|
run blastoff -u "$REPLY"
|
||||||
;;
|
;;
|
||||||
(54) # ` - change alt-text visibility and refresh
|
54) # ` - change alt-text visibility and refresh
|
||||||
run list_cycle T_PRE_DISPLAY ,
|
run list_cycle T_PRE_DISPLAY ,
|
||||||
run blastoff "$BOLLUX_URL"
|
run blastoff "$BOLLUX_URL"
|
||||||
;;
|
;;
|
||||||
(55) # 55-57 -- still available for binding
|
55) # 55-57 -- still available for binding
|
||||||
die "$?" "less(1) error"
|
die "$?" "less(1) error"
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
@ -1473,8 +1472,8 @@ select_url() { # select_url FILE
|
||||||
PS3="OPEN> "
|
PS3="OPEN> "
|
||||||
select u in "${MAPFILE[@]}"; do
|
select u in "${MAPFILE[@]}"; do
|
||||||
case "$REPLY" in
|
case "$REPLY" in
|
||||||
(q) bollux_quit ;;
|
q) bollux_quit ;;
|
||||||
([^0-9]*) run blastoff -u "$REPLY" && break ;;
|
[^0-9]*) run blastoff -u "$REPLY" && break ;;
|
||||||
esac
|
esac
|
||||||
run blastoff "${u%%[[:space:]]*}" && break
|
run blastoff "${u%%[[:space:]]*}" && break
|
||||||
done </dev/tty
|
done </dev/tty
|
||||||
|
@ -1543,12 +1542,12 @@ history_append() { # history_append URL TITLE
|
||||||
|
|
||||||
# Print the URL and its title (if given) to $BOLLUX_HISTFILE.
|
# Print the URL and its title (if given) to $BOLLUX_HISTFILE.
|
||||||
local fmt=''
|
local fmt=''
|
||||||
fmt+='%(%FT%T)T\t' # %(_)T calls directly to 'strftime'.
|
fmt+='%(%FT%T)T\t' # %(_)T calls directly to 'strftime'.
|
||||||
if (( $# == 2 )); then
|
if (($# == 2)); then
|
||||||
fmt+='%s\t' # $url
|
fmt+='%s\t' # $url
|
||||||
fmt+='%s\n' # $title
|
fmt+='%s\n' # $title
|
||||||
else
|
else
|
||||||
fmt+='%s%s\n' # printf needs a field for every argument.
|
fmt+='%s%s\n' # printf needs a field for every argument.
|
||||||
fi
|
fi
|
||||||
run printf -- "$fmt" -1 "$url" "$title" >>"$BOLLUX_HISTFILE"
|
run printf -- "$fmt" -1 "$url" "$title" >>"$BOLLUX_HISTFILE"
|
||||||
|
|
||||||
|
@ -1567,26 +1566,26 @@ history_back() {
|
||||||
# one with each call to `history_append'. If we subtract 1, we'll just
|
# one with each call to `history_append'. If we subtract 1, we'll just
|
||||||
# be at the end of the array again, reloading the page.
|
# be at the end of the array again, reloading the page.
|
||||||
((HN -= 2))
|
((HN -= 2))
|
||||||
|
|
||||||
if ((HN < 0)); then
|
if ((HN < 0)); then
|
||||||
HN=0
|
HN=0
|
||||||
log e "Beginning of history."
|
log e "Beginning of history."
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
run blastoff "${HISTORY[$HN]}"
|
run blastoff "${HISTORY[$HN]}"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Move forward in session history.
|
# Move forward in session history.
|
||||||
history_forward() {
|
history_forward() {
|
||||||
log d "HN=$HN"
|
log d "HN=$HN"
|
||||||
|
|
||||||
if ((HN >= ${#HISTORY[@]})); then
|
if ((HN >= ${#HISTORY[@]})); then
|
||||||
HN="${#HISTORY[@]}"
|
HN="${#HISTORY[@]}"
|
||||||
log e "End of history."
|
log e "End of history."
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
run blastoff "${HISTORY[$HN]}"
|
run blastoff "${HISTORY[$HN]}"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1646,8 +1645,8 @@ blastoff() { # blastoff [-u] URL
|
||||||
run "${url[1]}_response" "$url"
|
run "${url[1]}_response" "$url"
|
||||||
else
|
else
|
||||||
log d \
|
log d \
|
||||||
"No response handler for '${url[1]}';" \
|
"No response handler for '${url[1]}';" \
|
||||||
" passing thru"
|
" passing thru"
|
||||||
passthru
|
passthru
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue