#!/bin/sh

# Set environment
MOD_CP_NAME=captive_portal
MOD_CP_CHAIN_IN=$MOD_CP_NAME-in
MOD_CP_CHAIN_FWU=$MOD_CP_NAME-fwu
MOD_CP_CHAIN_FWD=$MOD_CP_NAME-fwd
MOD_CP_CHAIN_PRE=$MOD_CP_NAME-pre
MOD_CP_CHAIN_UT_RX1=$MOD_CP_NAME-rx-wlan0
MOD_CP_CHAIN_UT_TX1=$MOD_CP_NAME-tx-wlan0
MOD_CP_CHAIN_UT_RX2=$MOD_CP_NAME-rx-wlan02
MOD_CP_CHAIN_UT_TX2=$MOD_CP_NAME-tx-wlan02
MOD_CP_CHAIN_UT_RX3=$MOD_CP_NAME-rx-eth0
MOD_CP_CHAIN_UT_TX3=$MOD_CP_NAME-tx-eth0
MOD_CP_CHAIN_UB=$MOD_CP_NAME-ub
MOD_CP_CHAIN_UB_PRE=$MOD_CP_CHAIN_UB-pre
MOD_CP_DB_DIR=/var/$MOD_CP_NAME
MOD_CP_TMP_DIR=/var/$MOD_CP_NAME/tmp
MOD_CP_BAN_DIR=$MOD_CP_DB_DIR/ban
MOD_CP_RESTRICTED_DIR=$MOD_CP_DB_DIR/restricted
MOD_CP_IP_DIR=$MOD_CP_DB_DIR/ip
MOD_CP_STATS_DIR=$MOD_CP_DB_DIR/stats
MOD_CP_LOG_DIR=$MOD_CP_DB_DIR/log
MOD_CP_USERS_LOG_FILE=$MOD_CP_LOG_DIR/users.log
MOD_CP_LIB_DIR=/opt/$MOD_CP_NAME/usr/libexec
MOD_CP_SALT_DIR=$MOD_CP_DB_DIR/salt
MOD_CP_SHARE_DIR=/opt/$MOD_CP_NAME/usr/share
MOD_CP_WWW_DIR=/opt/$MOD_CP_NAME/var/www
MOD_CP_CRONTAB=/var/scripts/crontab

# Read configuration
MOD_CP_CONF_FILE=/opt/$MOD_CP_NAME/etc/settings
[ -f $MOD_CP_CONF_FILE ] || cp /opt/$MOD_CP_NAME/etc/defaults $MOD_CP_CONF_FILE
. $MOD_CP_CONF_FILE
. /etc/rc.d/init.d/ip

# Can be set up to 3 public interfaces
get_public_iface_info()
{
  for IDX in 1 2 3; do
    PUBLIC_IF=`echo $MOD_CP_PUBLIC_IF | awk -v var="$IDX"  -F ':' '{print $var}'`
    [ ! -n "$PUBLIC_IF" ] && break
    if [ "$PUBLIC_IF" = "wlan0" ] || [ "$PUBLIC_IF" = "wlan02" ]; then
     [ -f /etc/settings.wifi_ap ] || exit 3
      . /etc/settings.wifi_ap
      if [ "$PUBLIC_IF" = "wlan0" ]; then
        if [ -n "$WIFI_AP_IPADDR" ]; then
          export PUBLIC_IF1_NAME="wlan0"
          export PUBLIC_IF1_IP=$WIFI_AP_IPADDR
          export PUBLIC_IF1_NETWORK=`ip_calc_network $WIFI_AP_IPADDR $WIFI_AP_NETMASK`
          export PUBLIC_IF1_NETMASK=$WIFI_AP_NETMASK
          export PUBLIC_IF1_SSID=$WIFI_AP_SSID
          export PUBLIC_IF1_MAC=`ifconfig $PUBLIC_IF | awk '/HWaddr/ { print $5 }'`
        fi
      else
        if [ -n "$WIFI_AP2_IPADDR" ]; then
          export PUBLIC_IF2_NAME="wlan02"
          export PUBLIC_IF2_IP=$WIFI_AP2_IPADDR
          export PUBLIC_IF2_NETWORK=`ip_calc_network $WIFI_AP2_IPADDR $WIFI_AP2_NETMASK`
          export PUBLIC_IF2_NETMASK=$WIFI_AP2_NETMASK
          export PUBLIC_IF2_SSID=$WIFI_AP2_SSID
          export PUBLIC_IF2_MAC=`ifconfig $PUBLIC_IF | awk '/HWaddr/ { print $5 }'`
        fi
      fi
    elif [ "$PUBLIC_IF" = "eth0" ]; then
      [ -f /etc/settings.eth ] || exit 3
      . /etc/settings.eth
      if [ -n "$ETH_IPADDR" ]; then
        export PUBLIC_IF3_NAME="eth0"
        export PUBLIC_IF3_IP=$ETH_IPADDR
        export PUBLIC_IF3_NETWORK=`ip_calc_network $ETH_IPADDR $ETH_NETMASK`
        export PUBLIC_IF3_NETMASK=$ETH_NETMASK
        export PUBLIC_IF3_SSID=''
        export PUBLIC_IF3_MAC=`ifconfig $PUBLIC_IF | awk '/HWaddr/ { print $5 }'`
      fi
    fi
  done
}
WAN_IF=`ip -4 route | awk '/default via / { print $5 }'`
# ipv6 is not currently supported by captive portal
# WAN6_IF=`ip -6 route | awk '/default via / { print $5 }'`

WEB_PORT_WP=8899
WEB_PORT_BP=8898

# Get public iface
# Input       : $1 = client's address
# Output      : Name of interface
# Description : Get name of public iface where the IP belongs
get_public_iface()
{
  IP=$1
  for IDX in 1 2 3; do
    eval NETWORK_IDX='$'PUBLIC_IF${IDX}_NETWORK
    eval NETMASK_IDX='$'PUBLIC_IF${IDX}_NETMASK
    NETWORK=`sipcalc $IP $NETMASK_IDX | awk -F '[-/]' '/Subnet/ || /Network address/ {print $2}'`
    if [ -n "$NETWORK_IDX" ] && [ "$NETWORK" = " $NETWORK_IDX" ]; then
      eval echo '$'PUBLIC_IF${IDX}_NAME
    fi
  done
}
# Get public iface IP address
# Input       : $1 = client's IP address
# Output      : IP address of public interface
# Description : Get IP address of public iface where the IP belongs
get_public_ip()
{
  IP=$1
  for IDX in 1 2 3; do
    eval NETWORK_IDX='$'PUBLIC_IF${IDX}_NETWORK
    eval NETMASK_IDX='$'PUBLIC_IF${IDX}_NETMASK
    NETWORK=`sipcalc $IP $NETMASK_IDX | awk -F '[-/]' '/Subnet/ || /Network address/ {print $2}'`
    if [ -n "$NETWORK_IDX" ] && [ "$NETWORK" = " $NETWORK_IDX" ]; then
      eval echo '$'PUBLIC_IF${IDX}_IP
    fi
  done
}
# Get public iface MAC address
# Input       : $1 = client's IP address
# Output      : MAC address of public interface
# Description : Get MAC address of public iface where the IP belongs
get_public_mac()
{
  IP=$1
  for IDX in 1 2 3; do
    eval NETWORK_IDX='$'PUBLIC_IF${IDX}_NETWORK
    eval NETMASK_IDX='$'PUBLIC_IF${IDX}_NETMASK
    NETWORK=`sipcalc $IP $NETMASK_IDX | awk -F '[-/]' '/Subnet/ || /Network address/ {print $2}'`
    if [ -n "$NETWORK_IDX" ] && [ "$NETWORK" = " $NETWORK_IDX" ]; then
      eval echo '$'PUBLIC_IF${IDX}_MAC
    fi
  done
}
# Get MAC
# Input       : $1 =  IP address
# Output      : MAC address
# Description : Search MAC address inside ARP table
ip2mac()
{
  arp -an | awk 'BEGIN { mac = "00:00:00:00:00:00" } $2 ~ IP { mac = $4 } END { print mac }' IP=$1
}

# Encode URL
# Input       : $1 = URL to encode
# Output      : encoded URL
# Description : replace ':', '/', '?' and '&' by escape sequence %XX
url_encode()
{
  echo "$1" | sed -e 's/:/%3A/g' -e 's/\//%2F/g' -e 's/\?/%3F/g' -e 's/&/%26/g'
}

# Decode URL
# Input       : $1 = URL to encode
# Output      : encoded URL
# Description : replace escape sequence %XX by ':', '/', '?' or '&'
url_decode()
{
  echo "$1" | sed -e 's/%3A/:/g' -e 's/%2F/\//g' -e 's/%3F/\?/g' -e 's/%26/\&/g'
}

# Get property value by name from query record
# Input       : $1 = query record
#             : $2 = property name
# Output      : property value
# Description : search and get property value from query record
#               in form "name1=value1&name2=value2&..."
query_value_get()
{
  [ -n "$2" ] || return
  echo "$1" | grep -q "$2" 2>/dev/null || return
  echo "$1" | sed -e "s/.*$2=//" -e 's/&.*//'
}

# Set property value by name in query record
# Input       : $1 = query record
#             : $2 = property name
#             : $3 = new value
# Output      : modified query record
# Description : set new property value in query record
#               in form "name1=value1&name2=value2&..."
query_value_set()
{
  if [ $# -ne 3 ]; then
    echo $1
    return
  fi
  if [ -z "$2" ]; then
    echo $1
    return
  fi
  if [ -z "$3" ]; then
    echo $1
    return
  fi
  echo "$1" | grep -q "$2" 2>/dev/null
  if [ $? -ne 0 ]; then
    echo $1
    return
  fi
  echo "$1" | sed -e "s/\(.*$2=\)[^&$]*\(.*\)/\1$3\2/"
}

# Get existing page name
# Input       : $1 = base page name
#             : $2 = document root
# Output      : existing page name
# Description : search page in all possible directories with all possible extensions
page_name_get()
{
  DIRS="sd html captive_portal"
  for DIR in $DIRS; do
    EXTS="shtml html"
    for EXT in $EXTS; do
      [ -f "$2/$DIR/$1.$EXT" ] && break 2
    done
  done
  echo "/$DIR/$1.$EXT"
}

# Convert URL to HEX
url_to_hex() {

  echo "$1" |
  awk '{
    for(n = 0; n < 256; n++) {
      ord[sprintf("%c", n)] = n;
    }
    i = split($1, arr, ".");
    for (j = 1; j <= i; j++) {
      printf "%02x ", length(arr[j]);
      for (k = 1; k <= length(arr[j]); k++) {
        nib = substr(arr[j], k, 1);
        printf "%02x ", ord[nib];
      }
    }
  }'
}
