-
Notifications
You must be signed in to change notification settings - Fork 159
Expand file tree
/
Copy pathencode-password.sh
More file actions
executable file
·57 lines (47 loc) · 1.95 KB
/
encode-password.sh
File metadata and controls
executable file
·57 lines (47 loc) · 1.95 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#!/usr/bin/env bash
# encode-password.sh — percent-encode a database password for safe use in a DSN URL.
#
# Encodes all characters except RFC 3986 unreserved characters (A-Z a-z 0-9 - _ . ~).
# UTF-8 passwords are handled correctly: multi-byte characters are encoded byte-by-byte.
#
# Usage:
# scripts/encode-password.sh 'my$ecret#pass'
# echo 'my$ecret#pass' | scripts/encode-password.sh
#
# Capture for use in another command:
# PASS=$(scripts/encode-password.sh 'my$ecret#pass')
# dbdiff diff --server1-url="postgres://user:${PASS}@host:5432/db" ...
#
# If dbdiff is already installed, prefer the built-in command instead:
# PASS=$(dbdiff url:encode 'my$ecret#pass')
set -euo pipefail
# ── Read input ────────────────────────────────────────────────────────────────
raw="${1:-}"
if [[ -z "$raw" && ! -t 0 ]]; then
# No argument — try stdin (supports: echo 'pass' | encode-password.sh)
IFS= read -r raw || true
fi
if [[ -z "${raw:-}" ]]; then
printf 'Usage: %s <password>\n echo <password> | %s\n' \
"$(basename "$0")" "$(basename "$0")" >&2
exit 1
fi
# ── Encode ────────────────────────────────────────────────────────────────────
#
# Force LC_ALL=C so bash treats the string as a byte array.
# This makes ${raw:i:1} return one byte at a time, which is exactly what we
# want for percent-encoding: each byte of a multi-byte UTF-8 character gets
# its own %HH escape (e.g. 'ä' = 0xC3 0xA4 → '%C3%A4').
LC_ALL=C
encoded=""
len="${#raw}"
for (( i = 0; i < len; i++ )); do
c="${raw:i:1}"
if [[ "$c" =~ ^[A-Za-z0-9._~-]$ ]]; then
encoded+="$c"
else
printf -v hex '%02X' "'$c"
encoded+="%${hex}"
fi
done
printf '%s\n' "$encoded"