#!/usr/bin/env sh

### Script: w3maction
##
## 環境変数を元に処理を実行する。
##
## Metadata:
##
##   id - 3fd0e58d-392e-4100-b04d-c34b41b797c8
##   author - <qq542vev at https://purl.org/meta/me/>
##   version - 2.3.2
##   date - 2022-12-10
##   since - 2019-07-15
##   copyright - Copyright (C) 2019-2022 qq542vev. Some rights reserved.
##   license - <CC-BY at https://creativecommons.org/licenses/by/4.0/>
##   package - w3mplus
##
## See Also:
##
##   * <Project homepage at https://github.com/qq542vev/w3mplus>
##   * <Bug report at https://github.com/qq542vev/w3mplus/issues>
##
## Help Output:
##
## ------ Text ------
## Usage:
##   w3maction [OPTION]... ACTION VARIABLE_NAME
##
## Options:
##   -d,     --data-type raw | base64 | urlencode 
##                               変数のエンコードタイプを指定する
##   -h,     --help              このヘルプを表示して終了する
##   -v,     --version           バージョン情報を表示して終了する
##
## ACTION:
##   exec-shell 
##             VARIABLE_NAME を基に EXEC_SHELL を実行する
##   goto      VARIABLE_NAME にアクセスする
##   read-shell 
##             VARIABLE_NAME を基に READ_SHELL を実行する
##   setenv    VARIABLE_NAME を別の変数に代入する
##   yank      VARIABLE_NAME の値のヤンクを行う
##
## Exit Status:
##     0 - successful termination
##    64 - command line usage error
##    65 - data format error
##    66 - cannot open input
##    67 - addressee unknown
##    68 - host name unknown
##    69 - service unavailable
##    70 - internal software error
##    71 - system error (e.g., can't fork)
##    72 - critical OS file missing
##    73 - can't create (user) output file
##    74 - input/output error
##    75 - temp failure; user is invited to retry
##    76 - remote error in protocol
##    77 - permission denied
##    78 - configuration error
##   129 - received SIGHUP
##   130 - received SIGINT
##   131 - received SIGQUIT
##   143 - received SIGTERM
## ------------------

readonly 'VERSION=w3maction 2.3.2'

. 'initialize.sh'
. 'option_error.sh'
. 'regex_match.sh'
. 'append_array_posix.sh'

# @getoptions
parser_definition() {
	setup REST plus:true abbr:true error:option_error no:0 help:usage \
		-- 'Usage:' "  ${2##*/} [OPTION]... ACTION VARIABLE_NAME" \
		'' 'Options:'

	param data    -d --data-type init:='raw' pattern:'raw | base64 | urlencode' var:'raw | base64 | urlencode' -- '変数のエンコードタイプを指定する'
	disp  :usage  -h --help    -- 'このヘルプを表示して終了する'
	disp  VERSION -v --version -- 'バージョン情報を表示して終了する'

	msg -- '' 'ACTION:'

	cmd exec-shell -- 'VARIABLE_NAME を基に EXEC_SHELL を実行する'
	cmd goto       -- 'VARIABLE_NAME にアクセスする'
	cmd read-shell -- 'VARIABLE_NAME を基に READ_SHELL を実行する'
	cmd setenv     -- 'VARIABLE_NAME を別の変数に代入する'
	cmd yank       -- 'VARIABLE_NAME の値のヤンクを行う'

	msg -- '' 'Exit Status:' \
		'    0 - successful termination' \
		'   64 - command line usage error' \
		'   65 - data format error' \
		'   66 - cannot open input' \
		'   67 - addressee unknown' \
		'   68 - host name unknown' \
		'   69 - service unavailable' \
		'   70 - internal software error' \
		"   71 - system error (e.g., can't fork)" \
		'   72 - critical OS file missing' \
		"   73 - can't create (user) output file" \
		'   74 - input/output error' \
		'   75 - temp failure; user is invited to retry' \
		'   76 - remote error in protocol' \
		'   77 - permission denied' \
		'   78 - configuration error' \
		'  129 - received SIGHUP' \
		'  130 - received SIGINT' \
		'  131 - received SIGQUIT' \
		'  143 - received SIGTERM'
}

parser_definition_goto() {
	setup REST plus:true abbr:true error:option_error no:0 help:usage_goto \
		-- 'Usage:' "  ${2##*/} [OPTION]... goto VARIABLE_NAME [SUB_OPTION]... [COMMNAD_ARG].." \
		'' 'Sub options:'

	param :'append_array_posix "option" "${1}" "${OPTARG}"' --a1 --a2 --a3 --a4 --a5 --a6 --a7 --a8 --a9 var:W3M_COMMAND -- 'n個目の URI アクセス後に W3M_COMMAND を実行する'
	param :'append_array_posix "option" "${1}" "${OPTARG}"' --b1 --b2 --b3 --b4 --b5 --b6 --b7 --b8 --b9 var:W3M_COMMAND -- 'n個目の URI アクセス前に W3M_COMMAND を実行する'
	param :'append_array_posix "option" "${1}" "${OPTARG}"' -t --tab var:'current | del-prebuf | newtab | open-newtab' -- 'タブの動作を指定する'
	disp  :usage_goto -h --help -- 'このヘルプを表示して終了する'
}

parser_definition_setenv() {
	setup REST plus:true abbr:true error:option_error no:0 help:usage_setenv \
		-- 'Usage:' "  ${2##*/} [OPTION]... setenv VARIABLE_NAME [SUB_OPTION]..." \
		'' 'Sub options:'

	param encode        -e --encode-type init:='raw' pattern:'raw | base64 | urlencode'
	disp  :usage_setenv -h --help        -- 'このヘルプを表示して終了する'
}
# @end

# @gengetoptions parser -i parser_definition parse "${1}"
# @end

eval "$(getoptions parser_definition parse "${0}")"
parse ${@+"${@}"}
eval "set -- ${REST}"

case "${#}" in '0' | '1')
	printf "%s: 引数が不足しています。\\n" "${0##*/}" >&2
	printf "詳細については '%s' を実行してください。\\n" "${0##*/} --help" >&2

	end_call "${EX_USAGE}"
esac

action="${1}"
variableName="${2}"
shift 2

if ! regex_match "${variableName}" '^[_A-Za-z][_0-9A-Za-z]*$'; then
	printf "%s: '%s' -- VARIABLE_NAME の値が不正です。\\n" "${0##*/}" "${variableName}" >&2
	printf "詳細については '%s' を実行してください。\\n" "${0##*/} --help" >&2

	end_call "${EX_USAGE}"
fi

eval "value=\"\${${variableName}-}\""

case "${data}" in
	'base64')
		value=$(printf '%s' "${value}" | base64 -d; printf '_')
		value="${value%_}"
		;;
	'urlencode')
		value=$(printf '%s' "${value}" | urldecode; printf '_')
		value="${value%_}"
		;;
esac

case "${value}" in '')
	org_lc httpresponse -H 'W3m-control: BACK'
	exit
esac

case "${action}" in
	'exec-shell' | 'read-shell')
		case "${action}" in
			'exec-shell') w3mcmd='EXEC_SHELL';;
			'read-shell') w3mcmd='READ_SHELL';;
		esac

		case "${#}" in '0')
			set -- 'cat'
		esac

		command=$(printf '%s' "${*}" | base64 | tr -d '\n')
		value=$(printf '%s' "${value}" | base64 | tr -d '\n')

		org_lc httpresponse \
			-H 'W3m-control: BACK' \
			-H "W3m-control: ${w3mcmd} printf '%s' '${value}' | base64 -d | eval \"\$(printf '%s' '${command}' | base64 -d)\""
		;;
	'goto')
# @gengetoptions parser -i parser_definition_goto parse_goto "${1}"
# @end

		eval "$(getoptions parser_definition_goto parse_goto "${0}")"
		parse_goto ${@+"${@}"}
		eval "set -- ${REST}"

		case "${#}" in [1-9]*)
			value=$(printf '%s' "${value}" | org_lc sh -c "${*}" 'sh' || :; printf '_')
			value="${value%_}"
		esac

		eval org_lc "w3mredirect ${option-} -- \${value}"
		;;
	'setenv')
# @gengetoptions parser -i parser_definition_setenv parse_setenv "${1}"
# @end

		eval "$(getoptions parser_definition_setenv parse_setenv "${0}")"
		parse_setenv ${@+"${@}"}
		eval "set -- ${REST}"

		case "${encode}" in
			'base64') value=$(printf '%s' "${value}" | base64 | tr -d '\n');;
			'urlencode') value=$(printf '%s' "${value}" | urlencode);;
		esac

		org_lc httpresponse \
			-H 'W3m-control: BACK' \
			-H "W3m-control: SETENV ${1}=${value}"
		;;
	'yank')
		printf '%s' "${value}" | org_lc sh -c -- "${*}" 'sh' || :

		org_lc httpresponse -H 'W3m-control: BACK'
		;;
esac
