acme.sh/acme.sh

6874 lines
183 KiB
Bash
Raw Permalink Normal View History

#!/usr/bin/env sh
2016-04-25 20:01:37 +08:00
2019-04-29 22:11:25 +08:00
VER=2.8.2
2016-04-13 20:37:18 +08:00
2016-04-14 21:44:26 +08:00
PROJECT_NAME="acme.sh"
2016-04-13 20:37:18 +08:00
2016-04-14 21:44:26 +08:00
PROJECT_ENTRY="acme.sh"
PROJECT="https://github.com/Neilpang/$PROJECT_NAME"
2016-03-08 20:44:12 +08:00
DEFAULT_INSTALL_HOME="$HOME/.$PROJECT_NAME"
_WINDOWS_SCHEDULER_NAME="$PROJECT_NAME.cron"
_SCRIPT_="$0"
_SUB_FOLDER_NOTIFY="notify"
_SUB_FOLDER_DNSAPI="dnsapi"
_SUB_FOLDER_DEPLOY="deploy"
_SUB_FOLDERS="$_SUB_FOLDER_DNSAPI $_SUB_FOLDER_DEPLOY $_SUB_FOLDER_NOTIFY"
2018-01-06 12:45:24 +08:00
LETSENCRYPT_CA_V1="https://acme-v01.api.letsencrypt.org/directory"
LETSENCRYPT_STAGING_CA_V1="https://acme-staging.api.letsencrypt.org/directory"
LETSENCRYPT_CA_V2="https://acme-v02.api.letsencrypt.org/directory"
LETSENCRYPT_STAGING_CA_V2="https://acme-staging-v02.api.letsencrypt.org/directory"
2019-03-12 21:16:15 +08:00
DEFAULT_CA=$LETSENCRYPT_CA_V2
DEFAULT_STAGING_CA=$LETSENCRYPT_STAGING_CA_V2
2016-11-13 21:47:58 +08:00
DEFAULT_USER_AGENT="$PROJECT_NAME/$VER ($PROJECT)"
DEFAULT_ACCOUNT_EMAIL=""
2016-03-19 22:04:03 +08:00
DEFAULT_ACCOUNT_KEY_LENGTH=2048
DEFAULT_DOMAIN_KEY_LENGTH=2048
DEFAULT_OPENSSL_BIN="openssl"
2018-01-06 12:45:24 +08:00
_OLD_CA_HOST="https://acme-v01.api.letsencrypt.org"
2017-06-17 17:15:37 +08:00
_OLD_STAGE_CA_HOST="https://acme-staging.api.letsencrypt.org"
2016-03-08 20:44:12 +08:00
VTYPE_HTTP="http-01"
VTYPE_DNS="dns-01"
VTYPE_ALPN="tls-alpn-01"
LOCAL_ANY_ADDRESS="0.0.0.0"
DEFAULT_RENEW=60
2016-06-26 10:09:51 +08:00
DEFAULT_DNS_SLEEP=120
2016-09-23 22:35:13 +08:00
NO_VALUE="no"
W_DNS="dns"
W_ALPN="alpn"
2018-02-12 21:49:22 +08:00
DNS_ALIAS_PREFIX="="
2016-03-08 20:44:12 +08:00
2017-02-06 20:42:54 +08:00
MODE_STATELESS="stateless"
STATE_VERIFIED="verified_ok"
2017-02-13 23:29:37 +08:00
NGINX="nginx:"
NGINX_START="#ACME_NGINX_START"
NGINX_END="#ACME_NGINX_END"
2017-02-13 23:29:37 +08:00
2016-03-17 21:18:09 +08:00
BEGIN_CSR="-----BEGIN CERTIFICATE REQUEST-----"
END_CSR="-----END CERTIFICATE REQUEST-----"
BEGIN_CERT="-----BEGIN CERTIFICATE-----"
END_CERT="-----END CERTIFICATE-----"
CONTENT_TYPE_JSON="application/jose+json"
2016-06-18 11:29:28 +08:00
RENEW_SKIP=2
B64CONF_START="__ACME_BASE64__START_"
B64CONF_END="__ACME_BASE64__END_"
ECC_SEP="_"
ECC_SUFFIX="${ECC_SEP}ecc"
2016-09-25 21:58:59 +08:00
LOG_LEVEL_1=1
LOG_LEVEL_2=2
LOG_LEVEL_3=3
DEFAULT_LOG_LEVEL="$LOG_LEVEL_1"
2017-02-19 12:13:18 +08:00
DEBUG_LEVEL_1=1
DEBUG_LEVEL_2=2
DEBUG_LEVEL_3=3
DEBUG_LEVEL_DEFAULT=$DEBUG_LEVEL_1
DEBUG_LEVEL_NONE=0
2017-02-19 13:24:00 +08:00
HIDDEN_VALUE="[hidden](please add '--output-insecure' to see this value)"
2017-02-11 21:15:36 +08:00
SYSLOG_ERROR="user.error"
2017-02-19 12:13:18 +08:00
SYSLOG_INFO="user.info"
2017-02-11 21:15:36 +08:00
SYSLOG_DEBUG="user.debug"
2017-02-19 12:13:18 +08:00
#error
2017-02-19 12:42:37 +08:00
SYSLOG_LEVEL_ERROR=3
2017-02-19 12:13:18 +08:00
#info
2017-02-19 12:42:37 +08:00
SYSLOG_LEVEL_INFO=6
2017-02-19 12:13:18 +08:00
#debug
2017-02-19 12:42:37 +08:00
SYSLOG_LEVEL_DEBUG=7
2017-02-19 12:13:18 +08:00
#debug2
2017-02-19 12:42:37 +08:00
SYSLOG_LEVEL_DEBUG_2=8
2017-02-19 12:13:18 +08:00
#debug3
2017-02-19 12:42:37 +08:00
SYSLOG_LEVEL_DEBUG_3=9
2017-02-19 12:13:18 +08:00
2017-02-19 12:42:37 +08:00
SYSLOG_LEVEL_DEFAULT=$SYSLOG_LEVEL_ERROR
2017-02-19 12:13:18 +08:00
#none
SYSLOG_LEVEL_NONE=0
NOTIFY_LEVEL_DISABLE=0
NOTIFY_LEVEL_ERROR=1
NOTIFY_LEVEL_RENEW=2
NOTIFY_LEVEL_SKIP=3
NOTIFY_LEVEL_DEFAULT=$NOTIFY_LEVEL_RENEW
NOTIFY_MODE_BULK=0
NOTIFY_MODE_CERT=1
NOTIFY_MODE_DEFAULT=$NOTIFY_MODE_BULK
2016-09-25 21:58:59 +08:00
_DEBUG_WIKI="https://github.com/Neilpang/acme.sh/wiki/How-to-debug-acme.sh"
2016-03-08 20:44:12 +08:00
_PREPARE_LINK="https://github.com/Neilpang/acme.sh/wiki/Install-preparations"
2017-02-06 20:42:54 +08:00
_STATELESS_WIKI="https://github.com/Neilpang/acme.sh/wiki/Stateless-Mode"
2018-02-10 10:45:29 +08:00
_DNS_ALIAS_WIKI="https://github.com/Neilpang/acme.sh/wiki/DNS-alias-mode"
_DNS_MANUAL_WIKI="https://github.com/Neilpang/acme.sh/wiki/dns-manual-mode"
_NOTIFY_WIKI="https://github.com/Neilpang/acme.sh/wiki/notify"
2017-08-22 20:27:13 +08:00
_DNS_MANUAL_ERR="The dns manual mode can not renew automatically, you must issue it again manually. You'd better use the other modes instead."
_DNS_MANUAL_WARN="It seems that you are using dns manual mode. please take care: $_DNS_MANUAL_ERR"
_DNS_MANUAL_ERROR="It seems that you are using dns manual mode. Read this link first: $_DNS_MANUAL_WIKI"
2016-09-06 19:37:41 +08:00
__INTERACTIVE=""
2016-11-09 19:30:39 +08:00
if [ -t 1 ]; then
2016-09-06 19:37:41 +08:00
__INTERACTIVE="1"
fi
2016-04-17 17:33:08 +08:00
__green() {
if [ "${__INTERACTIVE}${ACME_NO_COLOR:-0}" = "10" -o "${ACME_FORCE_COLOR}" = "1" ]; then
printf '\033[1;31;32m%b\033[0m' "$1"
return
2016-09-02 20:55:11 +08:00
fi
printf -- "%b" "$1"
}
__red() {
if [ "${__INTERACTIVE}${ACME_NO_COLOR:-0}" = "10" -o "${ACME_FORCE_COLOR}" = "1" ]; then
printf '\033[1;31;40m%b\033[0m' "$1"
return
2016-09-02 20:55:11 +08:00
fi
printf -- "%b" "$1"
}
2016-04-17 17:33:08 +08:00
2016-09-25 21:58:59 +08:00
_printargs() {
2018-03-14 09:52:58 +01:00
_exitstatus="$?"
if [ -z "$NO_TIMESTAMP" ] || [ "$NO_TIMESTAMP" = "0" ]; then
printf -- "%s" "[$(date)] "
fi
2016-11-09 19:30:39 +08:00
if [ -z "$2" ]; then
printf -- "%s" "$1"
else
printf -- "%s" "$1='$2'"
fi
2016-09-25 21:58:59 +08:00
printf "\n"
# return the saved exit status
return "$_exitstatus"
}
2016-11-04 22:03:41 +08:00
_dlg_versions() {
echo "Diagnosis versions: "
2017-02-25 19:08:00 +08:00
echo "openssl:$ACME_OPENSSL_BIN"
2017-03-30 21:16:25 +08:00
if _exists "${ACME_OPENSSL_BIN:-openssl}"; then
${ACME_OPENSSL_BIN:-openssl} version 2>&1
2016-11-04 22:03:41 +08:00
else
2017-02-25 19:08:00 +08:00
echo "$ACME_OPENSSL_BIN doesn't exists."
2016-11-04 22:03:41 +08:00
fi
2016-11-09 19:30:39 +08:00
2016-11-04 22:03:41 +08:00
echo "apache:"
2016-11-09 19:30:39 +08:00
if [ "$_APACHECTL" ] && _exists "$_APACHECTL"; then
2017-03-03 22:03:19 +08:00
$_APACHECTL -V 2>&1
2016-11-04 22:03:41 +08:00
else
echo "apache doesn't exists."
fi
2016-11-09 19:30:39 +08:00
2017-06-15 21:44:10 +08:00
echo "nginx:"
if _exists "nginx"; then
nginx -V 2>&1
else
echo "nginx doesn't exists."
fi
echo "socat:"
if _exists "socat"; then
socat -h 2>&1
2016-11-04 22:03:41 +08:00
else
_debug "socat doesn't exists."
2016-11-04 22:03:41 +08:00
fi
}
2017-02-11 21:15:36 +08:00
#class
_syslog() {
2018-03-14 09:52:58 +01:00
_exitstatus="$?"
2017-02-19 12:13:18 +08:00
if [ "${SYS_LOG:-$SYSLOG_LEVEL_NONE}" = "$SYSLOG_LEVEL_NONE" ]; then
2017-02-11 21:15:36 +08:00
return
fi
_logclass="$1"
shift
if [ -z "$__logger_i" ]; then
if _contains "$(logger --help 2>&1)" "-i"; then
__logger_i="logger -i"
else
__logger_i="logger"
fi
fi
$__logger_i -t "$PROJECT_NAME" -p "$_logclass" "$(_printargs "$@")" >/dev/null 2>&1
2018-03-14 09:52:58 +01:00
return "$_exitstatus"
2017-02-11 21:15:36 +08:00
}
2016-09-25 21:58:59 +08:00
_log() {
[ -z "$LOG_FILE" ] && return
2016-11-09 20:45:57 +08:00
_printargs "$@" >>"$LOG_FILE"
2016-09-25 21:58:59 +08:00
}
_info() {
2017-02-19 12:13:18 +08:00
_log "$@"
2017-02-19 12:42:37 +08:00
if [ "${SYS_LOG:-$SYSLOG_LEVEL_NONE}" -ge "$SYSLOG_LEVEL_INFO" ]; then
2017-02-19 12:13:18 +08:00
_syslog "$SYSLOG_INFO" "$@"
fi
2016-09-25 21:58:59 +08:00
_printargs "$@"
2016-03-08 20:44:12 +08:00
}
_err() {
2017-02-19 12:13:18 +08:00
_syslog "$SYSLOG_ERROR" "$@"
_log "$@"
if [ -z "$NO_TIMESTAMP" ] || [ "$NO_TIMESTAMP" = "0" ]; then
printf -- "%s" "[$(date)] " >&2
fi
2016-11-09 19:30:39 +08:00
if [ -z "$2" ]; then
2016-09-28 13:13:08 +08:00
__red "$1" >&2
else
__red "$1='$2'" >&2
fi
2016-09-27 21:27:43 +08:00
printf "\n" >&2
2016-03-08 20:44:12 +08:00
return 1
}
_usage() {
2016-11-09 19:30:39 +08:00
__red "$@" >&2
2016-09-28 13:13:08 +08:00
printf "\n" >&2
}
_debug() {
2017-02-19 12:13:18 +08:00
if [ "${LOG_LEVEL:-$DEFAULT_LOG_LEVEL}" -ge "$LOG_LEVEL_1" ]; then
_log "$@"
2016-09-25 21:58:59 +08:00
fi
2017-02-19 12:42:37 +08:00
if [ "${SYS_LOG:-$SYSLOG_LEVEL_NONE}" -ge "$SYSLOG_LEVEL_DEBUG" ]; then
2017-02-19 12:13:18 +08:00
_syslog "$SYSLOG_DEBUG" "$@"
fi
if [ "${DEBUG:-$DEBUG_LEVEL_NONE}" -ge "$DEBUG_LEVEL_1" ]; then
_printargs "$@" >&2
fi
}
2017-02-19 13:24:00 +08:00
#output the sensitive messages
_secure_debug() {
if [ "${LOG_LEVEL:-$DEFAULT_LOG_LEVEL}" -ge "$LOG_LEVEL_1" ]; then
if [ "$OUTPUT_INSECURE" = "1" ]; then
_log "$@"
else
_log "$1" "$HIDDEN_VALUE"
fi
fi
if [ "${SYS_LOG:-$SYSLOG_LEVEL_NONE}" -ge "$SYSLOG_LEVEL_DEBUG" ]; then
_syslog "$SYSLOG_DEBUG" "$1" "$HIDDEN_VALUE"
fi
if [ "${DEBUG:-$DEBUG_LEVEL_NONE}" -ge "$DEBUG_LEVEL_1" ]; then
if [ "$OUTPUT_INSECURE" = "1" ]; then
_printargs "$@" >&2
else
_printargs "$1" "$HIDDEN_VALUE" >&2
fi
fi
}
_debug2() {
2017-02-19 12:13:18 +08:00
if [ "${LOG_LEVEL:-$DEFAULT_LOG_LEVEL}" -ge "$LOG_LEVEL_2" ]; then
_log "$@"
2016-09-25 21:58:59 +08:00
fi
2017-02-19 12:42:37 +08:00
if [ "${SYS_LOG:-$SYSLOG_LEVEL_NONE}" -ge "$SYSLOG_LEVEL_DEBUG_2" ]; then
2017-02-19 12:13:18 +08:00
_syslog "$SYSLOG_DEBUG" "$@"
fi
if [ "${DEBUG:-$DEBUG_LEVEL_NONE}" -ge "$DEBUG_LEVEL_2" ]; then
2017-02-11 21:15:36 +08:00
_printargs "$@" >&2
fi
}
2017-02-19 13:24:00 +08:00
_secure_debug2() {
if [ "${LOG_LEVEL:-$DEFAULT_LOG_LEVEL}" -ge "$LOG_LEVEL_2" ]; then
if [ "$OUTPUT_INSECURE" = "1" ]; then
_log "$@"
else
_log "$1" "$HIDDEN_VALUE"
fi
fi
if [ "${SYS_LOG:-$SYSLOG_LEVEL_NONE}" -ge "$SYSLOG_LEVEL_DEBUG_2" ]; then
_syslog "$SYSLOG_DEBUG" "$1" "$HIDDEN_VALUE"
fi
if [ "${DEBUG:-$DEBUG_LEVEL_NONE}" -ge "$DEBUG_LEVEL_2" ]; then
if [ "$OUTPUT_INSECURE" = "1" ]; then
_printargs "$@" >&2
else
_printargs "$1" "$HIDDEN_VALUE" >&2
fi
fi
}
_debug3() {
2017-02-19 12:13:18 +08:00
if [ "${LOG_LEVEL:-$DEFAULT_LOG_LEVEL}" -ge "$LOG_LEVEL_3" ]; then
_log "$@"
fi
2017-02-19 12:42:37 +08:00
if [ "${SYS_LOG:-$SYSLOG_LEVEL_NONE}" -ge "$SYSLOG_LEVEL_DEBUG_3" ]; then
2017-02-19 12:13:18 +08:00
_syslog "$SYSLOG_DEBUG" "$@"
2016-09-25 21:58:59 +08:00
fi
2017-02-19 12:13:18 +08:00
if [ "${DEBUG:-$DEBUG_LEVEL_NONE}" -ge "$DEBUG_LEVEL_3" ]; then
2017-02-11 21:15:36 +08:00
_printargs "$@" >&2
fi
}
2017-02-19 13:24:00 +08:00
_secure_debug3() {
if [ "${LOG_LEVEL:-$DEFAULT_LOG_LEVEL}" -ge "$LOG_LEVEL_3" ]; then
if [ "$OUTPUT_INSECURE" = "1" ]; then
_log "$@"
else
_log "$1" "$HIDDEN_VALUE"
fi
fi
if [ "${SYS_LOG:-$SYSLOG_LEVEL_NONE}" -ge "$SYSLOG_LEVEL_DEBUG_3" ]; then
_syslog "$SYSLOG_DEBUG" "$1" "$HIDDEN_VALUE"
fi
if [ "${DEBUG:-$DEBUG_LEVEL_NONE}" -ge "$DEBUG_LEVEL_3" ]; then
if [ "$OUTPUT_INSECURE" = "1" ]; then
_printargs "$@" >&2
else
_printargs "$1" "$HIDDEN_VALUE" >&2
fi
fi
}
2017-03-08 21:51:25 +08:00
_upper_case() {
# shellcheck disable=SC2018,SC2019
tr 'a-z' 'A-Z'
}
_lower_case() {
# shellcheck disable=SC2018,SC2019
tr 'A-Z' 'a-z'
}
2016-11-09 19:30:39 +08:00
_startswith() {
2016-04-16 21:52:24 +08:00
_str="$1"
_sub="$2"
2016-05-13 21:14:00 +08:00
echo "$_str" | grep "^$_sub" >/dev/null 2>&1
2016-04-16 21:52:24 +08:00
}
2016-11-09 19:30:39 +08:00
_endswith() {
_str="$1"
_sub="$2"
echo "$_str" | grep -- "$_sub\$" >/dev/null 2>&1
}
2016-11-09 19:30:39 +08:00
_contains() {
2016-04-16 21:52:24 +08:00
_str="$1"
_sub="$2"
echo "$_str" | grep -- "$_sub" >/dev/null 2>&1
2016-04-16 21:52:24 +08:00
}
_hasfield() {
_str="$1"
_field="$2"
_sep="$3"
2016-11-09 19:30:39 +08:00
if [ -z "$_field" ]; then
_usage "Usage: str field [sep]"
return 1
fi
2016-11-09 19:30:39 +08:00
if [ -z "$_sep" ]; then
_sep=","
fi
2016-11-09 19:30:39 +08:00
for f in $(echo "$_str" | tr "$_sep" ' '); do
2016-11-09 19:30:39 +08:00
if [ "$f" = "$_field" ]; then
_debug2 "'$_str' contains '$_field'"
return 0 #contains ok
fi
done
_debug2 "'$_str' does not contain '$_field'"
2017-04-17 19:08:34 +08:00
return 1 #not contains
}
# str index [sep]
2016-11-09 19:30:39 +08:00
_getfield() {
_str="$1"
_findex="$2"
_sep="$3"
2016-11-09 19:30:39 +08:00
if [ -z "$_findex" ]; then
_usage "Usage: str field [sep]"
return 1
fi
2016-11-09 19:30:39 +08:00
if [ -z "$_sep" ]; then
_sep=","
fi
2016-11-09 22:28:12 +08:00
_ffi="$_findex"
2016-11-09 19:30:39 +08:00
while [ "$_ffi" -gt "0" ]; do
2016-11-09 22:28:12 +08:00
_fv="$(echo "$_str" | cut -d "$_sep" -f "$_ffi")"
2016-11-09 19:30:39 +08:00
if [ "$_fv" ]; then
printf -- "%s" "$_fv"
return 0
fi
2016-11-09 20:45:57 +08:00
_ffi="$(_math "$_ffi" - 1)"
done
2016-11-09 19:30:39 +08:00
printf -- "%s" "$_str"
}
2016-11-09 19:30:39 +08:00
_exists() {
cmd="$1"
2016-11-09 19:30:39 +08:00
if [ -z "$cmd" ]; then
_usage "Usage: _exists cmd"
return 1
fi
2016-11-17 13:17:29 +08:00
if eval type type >/dev/null 2>&1; then
eval type "$cmd" >/dev/null 2>&1
elif command >/dev/null 2>&1; then
2016-05-13 21:14:00 +08:00
command -v "$cmd" >/dev/null 2>&1
2016-11-17 13:20:20 +08:00
else
2016-11-11 21:13:33 +08:00
which "$cmd" >/dev/null 2>&1
2016-04-16 19:38:11 +08:00
fi
ret="$?"
_debug3 "$cmd exists=$ret"
return $ret
}
2016-04-17 17:33:08 +08:00
#a + b
2016-11-09 19:30:39 +08:00
_math() {
2016-11-12 10:58:20 +08:00
_m_opts="$@"
printf "%s" "$(($_m_opts))"
2016-04-17 17:33:08 +08:00
}
_h_char_2_dec() {
_ch=$1
case "${_ch}" in
2016-11-09 19:30:39 +08:00
a | A)
2016-05-13 21:14:00 +08:00
printf "10"
2016-11-09 19:30:39 +08:00
;;
b | B)
2016-05-13 21:14:00 +08:00
printf "11"
2016-11-09 19:30:39 +08:00
;;
c | C)
2016-05-13 21:14:00 +08:00
printf "12"
2016-11-09 19:30:39 +08:00
;;
d | D)
2016-05-13 21:14:00 +08:00
printf "13"
2016-11-09 19:30:39 +08:00
;;
e | E)
2016-05-13 21:14:00 +08:00
printf "14"
2016-11-09 19:30:39 +08:00
;;
f | F)
2016-05-13 21:14:00 +08:00
printf "15"
2016-11-09 19:30:39 +08:00
;;
2016-04-17 17:33:08 +08:00
*)
2016-05-13 21:14:00 +08:00
printf "%s" "$_ch"
2016-11-09 19:30:39 +08:00
;;
2016-05-13 21:14:00 +08:00
esac
2016-04-17 17:33:08 +08:00
}
2016-08-14 22:37:21 +08:00
_URGLY_PRINTF=""
2016-11-09 19:30:39 +08:00
if [ "$(printf '\x41')" != 'A' ]; then
2016-08-14 22:37:21 +08:00
_URGLY_PRINTF=1
fi
_ESCAPE_XARGS=""
2017-06-23 18:11:11 +08:00
if _exists xargs && [ "$(printf %s '\\x41' | xargs printf)" = 'A' ]; then
_ESCAPE_XARGS=1
fi
2016-03-08 20:44:12 +08:00
_h2b() {
if _exists xxd && xxd -r -p 2>/dev/null; then
2017-05-17 13:16:53 +08:00
return
fi
2016-03-08 20:44:12 +08:00
hex=$(cat)
2017-05-20 11:02:48 +08:00
ic=""
jc=""
2017-05-17 13:16:53 +08:00
_debug2 _URGLY_PRINTF "$_URGLY_PRINTF"
if [ -z "$_URGLY_PRINTF" ]; then
if [ "$_ESCAPE_XARGS" ] && _exists xargs; then
2017-05-20 11:02:48 +08:00
_debug2 "xargs"
echo "$hex" | _upper_case | sed 's/\([0-9A-F]\{2\}\)/\\\\\\x\1/g' | xargs printf
2017-05-20 11:02:48 +08:00
else
for h in $(echo "$hex" | _upper_case | sed 's/\([0-9A-F]\{2\}\)/ \1/g'); do
2017-05-20 11:02:48 +08:00
if [ -z "$h" ]; then
break
fi
printf "\x$h%s"
done
fi
2017-05-17 13:16:53 +08:00
else
for c in $(echo "$hex" | _upper_case | sed 's/\([0-9A-F]\)/ \1/g'); do
2017-05-20 11:02:48 +08:00
if [ -z "$ic" ]; then
ic=$c
continue
2016-04-17 17:33:08 +08:00
fi
2017-05-20 11:02:48 +08:00
jc=$c
2016-05-13 21:14:00 +08:00
ic="$(_h_char_2_dec "$ic")"
jc="$(_h_char_2_dec "$jc")"
2016-11-11 22:00:15 +08:00
printf '\'"$(printf "%o" "$(_math "$ic" \* 16 + $jc)")""%s"
2017-05-20 11:02:48 +08:00
ic=""
jc=""
2017-05-17 13:16:53 +08:00
done
fi
2016-11-11 21:13:33 +08:00
2016-03-08 20:44:12 +08:00
}
2017-01-30 12:07:50 +08:00
_is_solaris() {
_contains "${__OS__:=$(uname -a)}" "solaris" || _contains "${__OS__:=$(uname -a)}" "SunOS"
}
2017-02-05 13:16:51 +08:00
#_ascii_hex str
#this can only process ascii chars, should only be used when od command is missing as a backup way.
_ascii_hex() {
_debug2 "Using _ascii_hex"
_str="$1"
_str_len=${#_str}
_h_i=1
while [ "$_h_i" -le "$_str_len" ]; do
_str_c="$(printf "%s" "$_str" | cut -c "$_h_i")"
printf " %02x" "'$_str_c"
_h_i="$(_math "$_h_i" + 1)"
done
}
2017-01-30 12:07:50 +08:00
#stdin output hexstr splited by one space
#input:"abc"
#output: " 61 62 63"
_hex_dump() {
if _exists od; then
od -A n -v -t x1 | tr -s " " | sed 's/ $//' | tr -d "\r\t\n"
elif _exists hexdump; then
_debug3 "using hexdump"
hexdump -v -e '/1 ""' -e '/1 " %02x" ""'
elif _exists xxd; then
_debug3 "using xxd"
xxd -ps -c 20 -i | sed "s/ 0x/ /g" | tr -d ",\n" | tr -s " "
else
_debug3 "using _ascii_hex"
2017-02-05 13:16:51 +08:00
str=$(cat)
_ascii_hex "$str"
fi
2017-01-30 12:07:50 +08:00
}
#url encode, no-preserved chars
#A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
#41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f 50 51 52 53 54 55 56 57 58 59 5a
#a b c d e f g h i j k l m n o p q r s t u v w x y z
#61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f 70 71 72 73 74 75 76 77 78 79 7a
#0 1 2 3 4 5 6 7 8 9 - _ . ~
#30 31 32 33 34 35 36 37 38 39 2d 5f 2e 7e
#stdin stdout
_url_encode() {
_hex_str=$(_hex_dump)
_debug3 "_url_encode"
_debug3 "_hex_str" "$_hex_str"
for _hex_code in $_hex_str; do
#upper case
case "${_hex_code}" in
2017-01-30 12:25:56 +08:00
"41")
printf "%s" "A"
;;
"42")
printf "%s" "B"
;;
"43")
printf "%s" "C"
;;
"44")
printf "%s" "D"
;;
"45")
printf "%s" "E"
;;
"46")
printf "%s" "F"
;;
"47")
printf "%s" "G"
;;
"48")
printf "%s" "H"
;;
"49")
printf "%s" "I"
;;
"4a")
printf "%s" "J"
;;
"4b")
printf "%s" "K"
;;
"4c")
printf "%s" "L"
;;
"4d")
printf "%s" "M"
;;
"4e")
printf "%s" "N"
;;
"4f")
printf "%s" "O"
;;
"50")
printf "%s" "P"
;;
"51")
printf "%s" "Q"
;;
"52")
printf "%s" "R"
;;
"53")
printf "%s" "S"
;;
"54")
printf "%s" "T"
;;
"55")
printf "%s" "U"
;;
"56")
printf "%s" "V"
;;
"57")
printf "%s" "W"
;;
"58")
printf "%s" "X"
;;
"59")
printf "%s" "Y"
;;
"5a")
printf "%s" "Z"
;;
#lower case
"61")
printf "%s" "a"
;;
"62")
printf "%s" "b"
;;
"63")
printf "%s" "c"
;;
"64")
printf "%s" "d"
;;
"65")
printf "%s" "e"
;;
"66")
printf "%s" "f"
;;
"67")
printf "%s" "g"
;;
"68")
printf "%s" "h"
;;
"69")
printf "%s" "i"
;;
"6a")
printf "%s" "j"
;;
"6b")
printf "%s" "k"
;;
"6c")
printf "%s" "l"
;;
"6d")
printf "%s" "m"
;;
"6e")
printf "%s" "n"
;;
"6f")
printf "%s" "o"
;;
"70")
printf "%s" "p"
;;
"71")
printf "%s" "q"
;;
"72")
printf "%s" "r"
;;
"73")
printf "%s" "s"
;;
"74")
printf "%s" "t"
;;
"75")
printf "%s" "u"
;;
"76")
printf "%s" "v"
;;
"77")
printf "%s" "w"
;;