aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatěj Cepl <mcepl@cepl.eu>2023-08-10 11:58:52 +0200
committerMatěj Cepl <mcepl@cepl.eu>2023-08-11 11:59:11 +0200
commita17fee5ee64a6b6cb294a9f166d7995832b0abe4 (patch)
tree6eec57939aafe2e298b5d9dace927ce038dfdca1
parentdc5b5bf4362d0d829fe02bbda1ea627097331b53 (diff)
downloadpinentry-rofi-a17fee5ee64a6b6cb294a9f166d7995832b0abe4.tar.gz
fix: add tested new implementation of URL encode/decode.
-rw-r--r--.gitignore1
-rwxr-xr-xpinentry-rofi.sh52
-rw-r--r--tests/foundational.bats73
3 files changed, 88 insertions, 38 deletions
diff --git a/.gitignore b/.gitignore
index 2a0a755..77c1213 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,3 +3,4 @@
# SPDX-License-Identifier: CC0-1.0
pinentry-rofi.log
+.bats/
diff --git a/pinentry-rofi.sh b/pinentry-rofi.sh
index 57e6022..7f01b2e 100755
--- a/pinentry-rofi.sh
+++ b/pinentry-rofi.sh
@@ -54,24 +54,32 @@ split_line() {
echo "${out_arr[@]}"
}
-# Originally from https://www.baeldung.com/linux/decoding-encoded-urls
-rfc3986-decode() {
- strg="${*}"
- printf '%s' "${strg%%[%+]*}"
- j="${strg#"${strg%%[%+]*}"}"
- strg="${j#?}"
- case "${j}" in "%"* )
- printf '%b' "\\0$(printf '%o' "0x${strg%"${strg#??}"}")"
- strg="${strg#??}"
- ;; "+"* ) printf ' '
- ;; * ) return
- esac
- if [ -n "${strg}" ] ; then rfc3986-decode "${strg}"; fi
+# Originally from https://github.com/sfinktah/bash/blob/master/rawurlencode.inc.sh
+# There is also more explanation and documentation there
+rawurlencode() {
+ local string="${1}"
+ local strlen=${#string}
+ local encoded=""
+ local pos c o
+
+ for (( pos=0 ; pos<strlen ; pos++ )); do
+ c=${string:$pos:1}
+ case "$c" in
+ [-_.~a-zA-Z0-9] ) o="${c}" ;;
+ * ) printf -v o '%%%02x' "'$c"
+ esac
+ encoded+="${o}"
+ done
+ printf "%s" "${encoded}" # You can either set a return variable (FASTER)
}
-# This is something too clever, doesn’t work in the script
-# from https://stackoverflow.com/a/70560850/164233
-# rfc3986decode() { : "${*//+/ }"; echo -e "${_//%/\\x}"; }
+rawurldecode() {
+ # This is perhaps a risky gambit, but since all escape characters must be
+ # encoded, we can replace %NN with \xNN and pass the lot to printf -b, which
+ # will decode hex for us
+
+ printf '%b' "${1//%/\\x}"
+}
rofi_cmd="rofi -dmenu -input /dev/null -password"
INSIDE_BATS=${INSIDE_BATS:-0}
@@ -156,7 +164,9 @@ while : ; do
#SETDESC Please enter the passphrase for the ssh key%0A ke:yf:in:ge:rp:ri:nt
IFS=" " line_arr=($(split_line "$line"))
log_debug "line_arr: ${line_arr[*]}"
- win_mesg="$(rfc3986-decode "${line_arr[*]}")"
+ temp_str="$(rawurldecode "${line_arr[*]}")"
+ log_debug "temp_str: ${temp_str}"
+ win_mesg="$(rawurlencode "${temp_str}")"
assuan_send "OK"
elif [[ "$line" =~ ^SETPROMPT ]] ; then
#SETPROMPT Passphrase:
@@ -164,6 +174,14 @@ while : ; do
log_debug "line_arr: ${line_arr[*]}"
win_prompt="${line_arr[0]}"
assuan_send "OK"
+ elif [[ "$line" =~ ^SETTITLE ]] ; then
+ IFS=" " line_arr=($(split_line "$line"))
+ log_debug "line_arr: ${line_arr[*]}"
+ log_debug "line_arr: ${line_arr[*]}"
+ temp_str="$(rawurldecode "${line_arr[*]}")"
+ log_debug "temp_str: ${temp_str}"
+ win_title="$(rawurlencode "${temp_str}")"
+ assuan_send "OK"
elif [[ "$line" =~ ^GETPIN ]] ; then
passw=None
sys_env="$(systemctl --user show-environment | tr -s " \t\n" " ")"
diff --git a/tests/foundational.bats b/tests/foundational.bats
index 29b8881..2d53b10 100644
--- a/tests/foundational.bats
+++ b/tests/foundational.bats
@@ -1,42 +1,73 @@
#!/usr/bin/env bats
setup() {
- export INSIDE_BATS=1
- DIR="$( cd "$(dirname "$BATS_TEST_FILENAME" )" >/dev/null 2>&1 && pwd )"
- source "$(readlink -f "${DIR}/../pinentry-rofi.sh")"
+ export INSIDE_BATS=1
+ DIR="$( cd "$(dirname "$BATS_TEST_FILENAME" )" >/dev/null 2>&1 && pwd )"
+ # shellcheck source=pinentry-rofi.sh
+ source "$(readlink -f "${DIR}/../pinentry-rofi.sh")"
+
+ mapfile -d '' instr <<- EOF
+ Please enter the passphrase to unlock the OpenPGP secret key:
+ "Matěj Cepl <mcepl@cepl.eu>"
+ 4096-bit RSA key, ID 77D15A36BD4211B2,
+ created 2016-04-27 (main key ID 79205802880BC9D8).
+ EOF
}
log_debug() {
- echo "$@" >> /dev/stderr
+ echo "$@" >> /dev/stderr
}
@test "split line" {
- line_arr=($(split_line "GETINFO version"))
- [ "${line_arr[0]}" = "version" ]
+ line_arr=($(split_line "GETINFO version"))
+ [ "${line_arr[0]}" = "version" ]
}
@test "split line rmfirst" {
- line_arr=($(split_line "GETINFO version" 0))
- [ "${line_arr[0]}" = "version" ]
+ line_arr=($(split_line "GETINFO version" 0))
+ [ "${line_arr[0]}" = "version" ]
}
@test "split line no-rmfirst" {
- IFS=" " line_arr=($(split_line "GETINFO version" 1))
- [[ "$(declare -p line_arr)" == 'declare -'[aA]* ]]
- [[ "${line_arr[0]}" == "GETINFO" ]]
- [[ ${#line_arr[@]} -eq 2 ]]
- [[ "${line_arr[1]}" == "version" ]]
+ IFS=" " line_arr=($(split_line "GETINFO version" 1))
+ [[ "$(declare -p line_arr)" == 'declare -'[aA]* ]]
+ [[ "${line_arr[0]}" == "GETINFO" ]]
+ [[ ${#line_arr[@]} -eq 2 ]]
+ [[ "${line_arr[1]}" == "version" ]]
}
-@test "decode RFC-3986 encoded string" {
- local instr="Please enter the passphrase to unlock the OpenPGP secret key:%0A%22Matěj Cepl <mcepl@cepl.eu>%22%0A4096-bit RSA key, ID 77D15A36BD4211B2,%0Acreated 2016-04-27 (main key ID 79205802880BC9D8).%0A"
- local expected="Please enter the passphrase to unlock the OpenPGP secret key:\n\
+@test "decode example RFC-3986 encoded string" {
+ local instr="Please enter the passphrase to unlock the OpenPGP secret key:%0A%22Matěj Cepl <mcepl@cepl.eu>%22%0A4096-bit RSA key, ID 77D15A36BD4211B2,%0Acreated 2016-04-27 (main key ID 79205802880BC9D8).%0A"
+ local expected="Please enter the passphrase to unlock the OpenPGP secret key:\n\
\"Matěj Cepl <mcepl@cepl.eu>\"\n\
4096-bit RSA key, ID 77D15A36BD4211B2,\n\
created 2016-04-27 (main key ID 79205802880BC9D8)."
- log_debug "expected: ${expected}"
- log_debug "instr: ${instr}"
- observed=$(rfc3986-decode "${instr}")
- log_debug "observed: ${observed}"
- [[ "$observed" == "$expected" ]] || diff -u <(echo -e "$observed") <(echo -e "$expected")
+ log_debug "expected: ${expected}"
+ log_debug "instr: ${instr}"
+ observed=$(rawurldecode "${instr}")
+ log_debug "observed: ${observed}"
+ [[ "$observed" == "$expected" ]] || diff -u <(echo -e "$observed") <(echo -e "$expected")
+}
+
+@test "encode into RFC-3986 encoded string" {
+ local expected
+
+ expected="Please%20enter%20the%20passphrase%20to%20unlock%20the%20OpenPGP%20secret%20key%3a%0a%22Matěj%20Cepl%20%3cmcepl%40cepl.eu%3e%22%0a4096-bit%20RSA%20key%2c%20ID%2077D15A36BD4211B2%2c%0acreated%202016-04-27%20%28main%20key%20ID%2079205802880BC9D8%29.%0a"
+ log_debug "expected: ${expected}"
+ log_debug "instr: ${instr}"
+ observed=$(rawurlencode "${instr}")
+ log_debug "observed: ${observed}"
+ [[ "$observed" == "$expected" ]] || diff -u <(echo -e "$observed") <(echo -e "$expected")
+}
+
+@test "encode/decode forth and back with RFC-3986 encoded string" {
+ local workstr observed
+
+ log_debug "instr: ${instr}"
+ workstr=$(rawurlencode "${instr}")
+ log_debug "workstr: ${workstr}"
+ observed="$(rawurldecode "${workstr}")"
+ log_debug "observed: ${observed}"
+ # There is some mockery with trailing newlines
+ [[ "$observed" == "$instr" ]] || diff -u <(echo "$observed") <(printf "%s" "$instr")
}