#!/bin/sh -euf
# -*- mode: Shell-script; tab-width: 8; fill-column: 70; -*-
# $Id: phpfunc,v 0.0.1 2006/01/26 03:06:53 legion Exp $ 

phpver="${PHP_VERSION:?}"
if [ -z "${phpver##4*}" ]; then
	# Backward compatibility
	readonly PHP_BIN="/usr/bin/php-${PHP_VERSION:?}"
else
	readonly PHP_BIN="/usr/bin/phpinfo-${PHP_VERSION:?}"
fi
unset phpver

readonly PHP_INI="/etc/php/$PHP_VERSION/${PHP_SAPI:?}/php.ini"

readonly php_on='On'
readonly php_off='Off'
readonly php_enable='enabled'
readonly php_disable='disabled'

php_error() {
    printf %s\\n "${0##*/}: Error: $*"
}

php_fatal() {
    php_error "$*"
    exit 1
}

[ -x "$PHP_BIN" ] || php_fatal "Cannot execute: $PHP_BIN"
[ -r "$PHP_INI" ] || php_fatal "No such file or directory: $PHP_INI"

php_modes=
php_rule() {
    [ "$#" -ge 3 ] || php_fatal "more arguments required: MODE DIRECTIVE VALUE [ INTRERNAL_VALUE ]"
    php_modes="$php_modes$1	$2	$3"
  
    local ivalue=""
    [ "$#" -ne 4 ] || ivalue="$4"
    php_modes="$php_modes	$ivalue
"
}

php_show_modes() {
  printf %s "$php_modes" |cut -f1 |uniq |tr \\n \ #
  printf \\n
}

php_info() {
    local d v i
    IFS="	"
    while read d v i; do
	printf %s\\t "$d"
	[ -z "$i" ] &&
	    printf %s "$v" ||
	    printf %s "$i"
	printf \\n
    done
}

php_config() {
    $PHP_BIN -c "$PHP_INI" -i |
	sed -n \
		-e '0,/^PHP Core[[:space:]]*$/d' \
		-e '/^Directive => Local Value => Master Value/d' \
		-e '/^[[:space:]]*$/d' \
		-e '/^Environment[[:space:]]*$/Q' \
		-e 's#no value##g' \
		-e 's# => enabled# => enabled#i' \
		-e 's# => active# => enabled#i' \
		-e 's# => #\t#gp' |
	cut -f1,2
}

php_check() {
    [ "$#" -eq 1 ] || { php_error "more arguments required"; return 1; }
    local sys modes args out

    modes="$(printf %s\\n "$php_modes" |egrep "^$1[[:space:]]" |cut -f2- |php_info)"
    [ -n "$modes" ] || return 1
    
    args="$(printf %s "$modes" |cut -f1 |xargs -ri printf "-e '^%s[[:space:]]' " \{\})"
    sys="$(php_config |eval grep -G $args)"
    unset args

    out="$(printf %s\\n%s\\n "$sys" "$modes" |sort |uniq -u |cut -f1 |sort -u)"
    unset sys modes
  
    [ -z "$out" ] || return 1
}

php_type() {
    local v
    while read v; do
	[ -n "$v" ] || continue
	[ -z "${v#$php_off}" -o -z "${v#$php_on}" ] &&
	    printf %s "$v" && continue
	printf %g "$v" >/dev/null 2>&1 &&
	    printf %s "$v" && continue
	printf %s "$v" | grep -qs 'E_' &&
	    printf %s "$v" && continue
	printf '"%s"' "$v"
    done
}

php_setmode() {
    [ "$#" -eq 1 ] || { php_error "more arguments required"; return 1; }
    local sys modes args out val

    modes="$(printf %s\\n "$php_modes" |egrep "^$1[[:space:]]" |cut -f2,3)"
    [ -n "$modes" ] || return 1

    args="$(printf %s "$modes" |cut -f1 |xargs -ri printf "-e '^%s[[:space:]]' " \{\})"
    sys="$(php_config |eval grep -G $args)"
    unset args

    out="$(printf %s\\n%s\\n "$sys" "$modes" |sort |uniq -u |cut -f1 |sort -u)"
    unset sys
  
    [ -n "$out" ] || return 0

    printf %s\\n "$out" |
    while read d; do
	val="$(printf %s\\n "$modes" |grep "^$d[[:space:]]" |cut -f2 |php_type)"
	if grep -qs "^[[:space:]]*$d[[:space:]]*=" "$PHP_INI"; then
	    if [ -z "$val" ]; then
		subst "/^[[:space:]]*$d[[:space:]]*=.*$/d" "$PHP_INI"
		continue
	    fi
    	    subst "
/^[[:space:]]*$d[[:space:]]*=.*$/{s|^[[:space:]]*$d[[:space:]]*=.*$||
c \
$d = $val
}" "$PHP_INI"
	else
	    [ -z "$val" ] || printf '%s = %s\n' "$d" "$val" >> "$PHP_INI"
	fi
    done
}

php_help() {
    [ "$#" -eq 1 ] || { php_error "more arguments required"; return 1; }
    local d v
    printf '%s: %s\n' "$1" "Following directives shuild be changed/added at \`$1' security mode."
    IFS="	"
    printf %s\\n "$php_modes" |egrep "^$1[[:space:]]" |cut  -f2,3 |
    while read d v; do
	v="$(printf %s\\n "$v" |php_type)"
	[ -n "$v" ] || v="\"\""
	printf '\t%s = %s\n' "$d" "$v"
    done
    printf \\n
}
