#!/bin/bash

###############################################################
#
# Do not edit this file directly
# This file is generated as part of the gabriel installer build
#
###############################################################


ALLOW_SUDO=0
SILENT_INSTALL=0

# Determine if the script was sourced
if [ ! -z ${BASH_SOURCE[0]} ] && [ ${BASH_SOURCE[0]} != ${0} ]; then
  SOURCED=1
  THISAPP=${BASH_SOURCE[0]}
else
  NOTSOURCED=1
  THISAPP=${0}
fi

DARWIN=0
ARM7=0
# Determine if we are on a raspberry pi or osx
if uname -a | grep -q armv7l; then
  ARM7=1
elif uname -a | grep -q Darwin; then
  DARWIN=1
fi

CENTOS=0
if [ -e /etc/redhat-release ]; then
  CENTOS=1
fi

#
# function to see if the user has root privledges
#   if ALLOW_SUDO is set it will re run the script as root
#
function require_root()
{
  if [ $EUID -ne 0 ]; then
    if [ ! -z $ALLOW_SUDO ] && [ $ALLOW_SUDO == 1 ]; then
      echo This requires higher unix privledges than you have, attempting to run as root
      exec sudo $*
    else
      echo This requires higher unix privledges than you have, exiting
      exit
    fi
  fi
}


###################################################
#
# Get the local unix user
#
###################################################

#
# Gets the local user
#
# Input: None
#
# global GABRIEL_LOCAL_USER,GAB_USER_HOME set after running
#   GABRIEL_LOCAL_USER the user to run Gabriel
#   GAB_USER_HOME the home dir of the Gabriel user
#
# returns 0
#
function get_local_user()
{
  if [ ! -z $GAB_USER_HOME ] && [ ! -z $GABRIEL_LOCAL_USER ]; then
    return
  fi

  if [ -e /usr/local/lib/gabriel/user ]; then
    GABRIEL_LOCAL_USER=`cat /usr/local/lib/gabriel/user`
  elif [ -e /lib/systemd/system/gabriel.service ]; then
    GABRIEL_LOCAL_USER=`grep -i User= /lib/systemd/system/gabriel.service | awk -F= '{print $2}'`
  fi

  if [ -z $GABRIEL_LOCAL_USER ]; then
    if [ `(cd /home; ls -1d */.gabriel 2> /dev/null) | awk -F/ '{print $1}' | wc -w` -ge 1 ]; then
      GABRIEL_LOCAL_USER=`(cd /home; ls -1d */.gabriel | head -1) | awk -F/ '{print $1}'`
      USERHOME=/home/$GABRIEL_LOCAL_USER
    elif [ ! -z $SUDO_USER ]; then
      USERHOME=$(eval echo "~${SUDO_USER}/")
      GABRIEL_LOCAL_USER=$SUDO_USER
    elif [ $USER != root ]; then
      USERHOME=$(eval echo "~/")
      GABRIEL_LOCAL_USER=$USER
    fi
    if [ -z $USERHOME ] || [ ! -e $USERHOME/.gabriel ]; then
      #echo $USERHOME/.gabriel not found
      if [ ! -z $OTHER_GABRIEL_USER ]; then
        GABRIEL_LOCAL_USER=$OTHER_GABRIEL_USER
      elif id -u virnetx &> /dev/null; then
        GABRIEL_LOCAL_USER=virnetx
      elif id -u gabriel &> /dev/null; then
        GABRIEL_LOCAL_USER=gabriel
      elif [ $ARM7 -eq 0 ]; then 
        GABRIEL_LOCAL_USER=gabriel
      fi
    fi
  fi
  GAB_USER_HOME=$(eval echo "~${GABRIEL_LOCAL_USER}/")
}

#
# Given a user create the user and group
#
# Input: 
#   GABRIEL_LOCAL_USER the user to run Gabriel
#   GAB_USER_HOME the home dir of the Gabriel user
#
# returns 0
#
function setup_local_user()
{
  require_root
  if ! grep -q -E "^gabriel:" /etc/group > /dev/null; then
    groupadd gabriel
  fi
  get_local_user
  if ! id -u $GABRIEL_LOCAL_USER &> /dev/null; then
    if [ $CENTOS == 1 ]; then
      adduser gabriel -g gabriel --shell /bin/bash
      passwd -l gabriel
    else
      adduser --gecos "" --shell /bin/bash --disabled-password ${GABRIEL_LOCAL_USER} --ingroup gabriel
    fi
    GAB_USER_HOME=$(eval echo "~${GABRIEL_LOCAL_USER}/")
  fi
  mkdir -p $GAB_USER_HOME/.gabriel/
  chown -R $GABRIEL_LOCAL_USER $GAB_USER_HOME/.gabriel/
  if ! id -nG "$GABRIEL_LOCAL_USER" | grep -qw "gabriel"; then
    usermod -aG gabriel $GABRIEL_LOCAL_USER
  fi
  return 0
}


#####################################################
#
# Gabriel key install
#
#####################################################

#
# Add the public gpg key to the keyring so that apt works
#
# Input: Optional - file to put the key into 
#
# returns 0 on success
#
function add_virnetx_key()
{
  KEYRING=
  if [ ! -z $1 ]; then
    KEYRING="--keyring $1"
    #echo $KEYRING
  fi
#  echo | apt-key $KEYRING add - > /dev/null << EOF_KEY_FILE
  if [ $CENTOS == 0 ]; then
    gabrielfile=$(mktemp /tmp/gabriel.service.XXXXXXXXX)
  else
    gabrielfile=/usr/local/lib/gabriel/gabriel_key.pem
    mkdir -p /usr/local/lib/gabriel
    touch $gabrielfile
    chmod 600 $gabrielfile
  fi
echo | tee $gabrielfile > /dev/null << EOF_KEY_FILE
-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v1

mQINBFvtjsQBEADo0Wp1vdDb2tWQ+ni1dTVFcdhizhd6hVlyVtzpVxsyCzwrQsOb
QPeYFeGsyz9t0ZcDWifvusCbOZjnhMEwIe2FpsC0lueugoTmkqhNc3MYHYZ1gL+7
OctjQ3I6Rg6HswidhLr99k5IX88cdZbn9OJz/H7YkHAKMdxcSsJfFRTTFDJfNaVs
2RXVvGRjYbt8mL93pZVmR2XAnSftA1+a5UAK2Hrw0qp32kOgdg0NnhjcEQBulW5H
M/tFMecq9VNzovFLsXBuzh4STt2npUvNknKJBOGD+INbBKDeyRvMtSsyxr3OfM/j
uF4sdQN7YUNQifIOxivkYxhCUJah7DeYjkShlGXc3SB9r8K873bAxHnrMJYS3I3f
FAD3w62YK5y9lxo5GsZzvYz9FVy8/PkxgpVeId4HKkTPSo6YuHgzQE2BwjApHeAF
XvvL7gqvZ2odzPbFvVZoyIao9k+YHpEW3zQ2x++qI9+O1XiWcEweIdXqFw+Sbflv
+cqz6hIZ9TYUuVNHwkxsZKseU4MFArRn4BmQl+mWC2o34msNVjxfEbQgy5GEep+j
gw79zFBGEkmVZFP0uNjxKhgxg34p4cTWYX1pdavuOw72K3MJFVqF64yKCAmmL03V
4pUXTCMzKLjZ6FV6Ki3S2g2yxxAJdVWuqrnk42cuG72VzKvG79JhXI6lkQARAQAB
tBtWaXJuZXRYIDx2aXJuZXR4QGdtYWlsLmNvbT6JAj4EEwECACgFAlvtjsQCGwMF
CRLMAwAGCwkIBwMCBhUIAgkKCwQWAgMBAh4BAheAAAoJEK/p97XXK5b5v4UP/j1k
7IrVUqj9ICQzvt4KMAg+OAKanCbLRGz96hnsOQPYUePznbdZhRMtuU7dF6a8uJ1D
XvWAEBK1h+rgc6th1fZROaz8V7IknQljDlAQASMKh8Q8RMfV9VMP4u124EG8VxiH
ddmw8lvbOENjgHGH+Ic9SWg6OVBS6Vf/QSuD7ANcrA9r0ptxZmTmohA+Ii/oODf9
e8+VbOzaY/oXlVDyL+1Pa9keltj9WIJWgMBuLbJso59270rnk+cTm/KIUYWzxHgq
Z16/z5JrdvJZuJe852jWxbhaOs8nu41w97ONm0YeIIsLfzorpt1AgWgrzwqcOqWu
fX9IjYEyG213Y367pNhubl0TwD1Y5vlirRHLtMRmx+YMCZRaes6+VkFBlly0Ujbk
enqn1CYYsFm5EyrLNtIZHU3/xUR3yM6vNVSiKcd0tzBFhigVSVZUztEiHoTXby+I
O8CbvSqPRU3zU2iDl7lN8HIyWtFRD1xGtLGnewCLs+IZFY8zAdf91oBoLOZUuJEN
qCawPtxutaUcH86m8qrXqXXnTXagJIkdlTKv/5cLcBlpVbOj5Z6lhFEQL4j6Xq9o
ZXKxGa+AyIKKFWDlqHfd6eRcNW9uJj6cOfTaKhgi/Urup5u0ZVmSUxsE0hvh6xRX
FwNFZYC8waUseaLcPUL/DF7FUod6LUajoNtDiZ15uQINBFvtjsQBEACwDfEgdgQe
KZsywgQ3lH357Ogrr0XYSASLMeavYGCi3teU2cxX3Llief9dmQTHwNEnuxJ3h+Yx
l8qirF0BilpR6amBONfeK2ogvWhUleZLoL4k5bXIpywByeQluzkEjkViZimLLZvI
LVNKhu/6MqoFeC3N/zbrXk1vJG1Pn05dc9z9YjFJT+bcYBzfepMlVrSHN1TvhQto
GlQKO62jYcUshMogQcK6kmRvx7YU/vuC8P3jGkkXmm6FFTFD7GwTBWLjIdEcQX7X
8pWBfWr7t/4AMMPRddeSKkfo36vT8i6HJxnuPv91ac8FKwh28D0o7Rcc2A69XaH/
bKiLI79oJjBz75Nytn/VClvLal2G4OLBFU+nYjijrzCfujnGZSoPG8vSc09DgFoW
rRjDmEH5kO2cXD73kChSiUguUUTHNQxSDpISiYGxgIhDiQanUrwqaAPqCQUv/GJW
VqNCj7kmkszExLzt3fmcKmQsxxyOnGXFhsgHF//7TSbpUmvY5J03jgsB5k5hI5OU
2oWR6R6/rL0h0NqeCuhoqC6uDxwVN4cKb9VO38JWOtLP1McJkuqV2Gd0WZrpso4J
eeJlg0GmMfg+iRSovw+QQGN9CoE61wc2isauqnb6JjfsZ6Y/hs6tY/vIOiAp1pnC
PRULvdsDcYtfFk5rEYYx9sGtbnNCBQgh6QARAQABiQIlBBgBAgAPBQJb7Y7EAhsM
BQkSzAMAAAoJEK/p97XXK5b5jKkQANhQ5XT6uhfvxcIaBg330p41GClSGGLdGsaK
Z7jcqb9bh/7CTifacV4Rlp0eGSBXB2Q/b6zRIun7s53vB3WSUfzFGi9eqUzPHosi
KGPPjap4Z6nLAFdx2DSvQAqO1vmVBc9lOQkuWpWIEMiCGCP9SnShzWRGUkOgDb0S
7au5eFbNQl/yXsyixv7yjLO0MGn0Bx1PYHEPfh5Hk2xfywRzFh0DkcSRbokGP6CJ
J/C6pm2B7cRbjBxKb4KWVPa4FATruBcc0RN/A879tdpyYQGv/xTjQWQW5/4/E9vk
LXPghrCqh1DYUS8OMf5ZnLmn3lcPw1l9pbAK9lTy4GMpUr0qxXQD+qi804MEUctz
LT9SNfxQphOjm6Vqr5urW2KL3u0fW8LTeocsX33fL72bMI8IIQCQF6gGAFsg4O2W
YstfLzV6lN5Z6mKWPUichdyLHbX7diMaF6nwAWVMiApnYECYlBzW7nhMvuu+lKWe
zEzam3X6NELtt48BcvAFFjmp/aMSg58RpQiey/30BfbjMf+bR1ji7I6Q2xvuPS1H
kMUCMnEmUJRrA6Z3VGi6MtVhIpjczBHlXKfzIS7vpuaUBrgYBY/+wMwncIZnxgSr
Hz3eSvJjWX7Ox7hzhGlY0v/Ji9D/ywBcl91SwffMu+m5ipHBLTf5B3vmI4ir314z
x31TBRs8
=6oe1
-----END PGP PUBLIC KEY BLOCK-----
-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v1

mQENBFtFMqABCADVj0x3jMIM2LxYnSTsu0WNH9atY12+10Ty+V6S7kLA9LyOXtut
0jdH6T0Ln/tQxmDQnbgFv4w5G+dh/Vdrra6g8afKS/NtWmoskOhD9vmJ+bXiSVYY
BkjmNKL6TSTspoUQR9vYgg8Uc+zktjaSFvP8X1QBtY4MhDIyKLGMdftnB9sRB2gV
V6RHruugVdVqOgHQv1iKdkJhiOCsjV3Zfc5YY+b7QSdwRPtoe5Rj7Uxh7AIL1dju
DeCjIrMVLdI4U+Jmvt4o6+LUkd7uo0mzLApneDz8yxft+anIYcus+mmbAdW26Us5
NJieXLlqE2Cs+vvOCsI5Jc3EKPeVwsNzQCInABEBAAG0LU1pa2UgV2lsbGlhbXNv
biA8bWlrZV93aWxsaWFtc29uQHZpcm5ldHguY29tPokBPgQTAQIAKAUCW0UyoAIb
AwUJCWYBgAYLCQgHAwIGFQgCCQoLBBYCAwECHgECF4AACgkQELOR9Y4P1jowJgf/
R4HGOF4MdxJsd3PeKkcVHrRfyYgQOCY7zeDViQlxSXisF4BBYOivHNBDzMnk2JVf
xojGZceDwAY42Y4Fu46IJzThdAo6uVCQYoSHFo/hlf5zF9TfhIpJed47CEPKuWAP
aXVhwGiB5Fs6CH9keH7C0Fzquu4gL98k+nd6zATj/sVsAHF7jSd0A+rQivl2uXvN
liMJ1nSLBWql6i2JJv9cc9rKBQ2DmAD2V0nZTdTOkMtaNaxa04BNHKy4Vd42Oe1U
LfHQ2XxLgVtHN26lW+EooTOLqQWvHO8AbgKo6npuF2ekPTyTKeUtX0hwxcjxSv4X
4bfJEJ3529oFiUIcGMEV7bkBDQRbRTKgAQgA0V95fvIEk57HpOQcq1nINWPOAsuq
wxA8T/HbU79yjqnq9FblfLVOiiwvAWKktlbNNQmfapdEPlQRsBsOusgYwnisgt+l
1XKmgTIFJuJZYgG1S+EX2iPmj1CHpp/FEFSr+1KaWBaojlhPDrBc+nQyKhtDLmWJ
YoNzk5XjwBRjkOoyjtHY2j+8uwhs4eQAWtOLOsO/93n7T5LlOLlM8nJxtT1Fbxpl
cbh8+rqnNGN3qJYssPo3P+oGUCVnfxJzX1wcZfvAOmnrTlM5GDR0KE0igYU94tOO
ZjmM2LoBloXpTsLuLldzAlmBazf335DHt/1kFgmlVKX/1dopu/qKNRPtfwARAQAB
iQElBBgBAgAPBQJbRTKgAhsMBQkJZgGAAAoJEBCzkfWOD9Y6pz8H/iE13EIpzbc7
7WA5lLruyzsCEKbI77xYUf4v0VDHZE2vrNbZ5xcfW+/9DxIcg7TQ1PGqsQAw26Ya
24xe2LYkkB/oC+CiagZ6OIu/bKCRUed1lOyrHc+ir9dmi3MOWcNG6sJSaCWWbKrk
7nF58QmSBcSAM9TZOd2EkR2z4vEXfaSvVcI5bENwRyjeMAlww941qiLOTGRTdbGc
7sM2vA1Qawri0h6LgJttBImB1SEUlEWf4vf35cg3/EPjaE9smM+0XMaM1G4GTyd3
ITJmfjJI2pkY5SVAcB+Q4MpMci/0W1F+w8An4X7ct9jt1AGImDkrccirAejJp+VF
bnfQA1Jq5Ak=
=D7rh
-----END PGP PUBLIC KEY BLOCK-----
EOF_KEY_FILE
  if [ $CENTOS == 0 ]; then
    apt-key $KEYRING add $gabrielfile
    rm $gabrielfile
  fi
}

#####################################################
#
# Gabriel Setup Functions
#
#####################################################

#
# This function creates a cron file to keep Gabriel updated
#
# Input: None
#
# returns 0 on success
#
function create_crontab()
{
  if [ $DARWIN -eq 1 ]; then
    return 0
  fi
  if [ ! -d /etc/cron.d ]; then
     if [ -d /etc/cron.daily ]; then
       if [ ! -e /etc/cron.daily/gabriel ]; then
         echo "#!/bin/sh" > /etc/cron.daily/gabriel
         echo "/usr/local/bin/gabriel_cmd --upgrade" >> /etc/cron.daily/gabriel
       fi
     fi
     return 0
  fi
  if [ $DARWIN -eq 1 ] || [ -e /etc/cron.d/gabriel ]; then
    if [ -e /etc/cron.d/gabriel ] && grep -q gabriel_cmd /etc/cron.d/gabriel; then
      return 0
    fi 
  fi

  # generate a random minute value for when to check for updates
  min=`echo $((RANDOM % 60))`
  echo "PATH=/usr/bin:/bin:/usr/sbin:/sbin" > /etc/cron.d/gabriel
  echo "$min * * * * root /usr/local/bin/gabriel_cmd --upgrade" >> /etc/cron.d/gabriel
  return 0
}

function setup_yum_location()
{
  if [ $CENTOS == 0 ]; then
    setup_deb_location
    return 0
  fi

  add_virnetx_key

  if [ $ARM7 -eq 1 ]; then
    SYSLOC=pi/yum
  else
    SYSLOC=yum
  fi

  gabrielfile=/etc/yum.repos.d/Gabriel.repo
  if [ ! -e $gabrielfile ]; then
    echo | tee $gabrielfile > /dev/null << EOF
[gabrielserver]
name=Virnetx Gabriel service see http://gabrielsecure.com
baseurl=url
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=file:///usr/local/lib/gabriel/gabriel_key.pem
EOF
    sed -i "s/baseurl=.*/baseurl=https:\/\/sw.myvirnetx.com\/$SYSLOC/" $gabrielfile
  fi
  if [ ! -z $1 ]; then
    CHANDIR=`echo $1 | sed s#\/##g`
    if [ -z $CHANDIR ]; then
      sed -i "s/baseurl=.*/baseurl=https:\/\/sw.myvirnetx.com\/$SYSLOC/" $gabrielfile
    else
      sed -i "s/baseurl=.*/baseurl=https:\/\/sw.myvirnetx.com\/$CHANDIR\/$SYSLOC/" $gabrielfile
    fi
  fi
}

function setup_deb_location()
{
  if [ $CENTOS == 1 ]; then
    setup_yum_location
    return 0
  fi
  add_virnetx_key
  if [ ! -e /usr/lib/apt/methods/https ]; then
    DEBIAN_FRONTEND=noninteractive apt-get install apt-transport-https -y
  fi
  if [ ! -e /etc/apt/sources.list.d/gabriel.list ]; then
    if [ $ARM7 -eq 1 ]; then
      echo 'deb https://deb.myvirnetx.com/pi/debian stable main' > /etc/apt/sources.list.d/gabriel.list
    else
      echo 'deb https://deb.myvirnetx.com/debian stable main' > /etc/apt/sources.list.d/gabriel.list
    fi
  fi

  return 0
}

#
# Checks if GabrielService is installed - installs it if it is not
#
# Input: None
#
# returns 0 on success
#
function check_apt_install()
{
  if [ $DARWIN -eq 0 ] && [ ! -e /usr/local/bin/GabrielService ]; then

    require_root
    setup_local_user
    setup_ini
    setup_deb_location

    if [ $CENTOS == 1 ]; then
      yum -y install gabriel
    else
      DEBIAN_FRONTEND=noninteractive apt-get update -y
      DEBIAN_FRONTEND=noninteractive apt-get install gabrielserver -y
    fi

    if [ ! -e /usr/local/bin/GabrielService ]; then
      if [ -z $SILENT_INSTALL ] || [ $SILENT_INSTALL != 1 ]; then
        echo "The install of Gabriel seems to have run into an error, try again?"
        read -e get_yes_no
        case $get_yes_no in
          [Yn]* ) echo "continue"
                  ;;
          * ) echo "exiting"
              exit
              ;;
        esac
        check_apt_install
      fi
    fi
  fi
  return 0
}

#
# Sets a file suid bit
#
# Input: None
#
# returns 0 on success
#
function set_suid()
{
  require_root
  FILE=$1
  chown root:gabriel $FILE
  chmod 750 $FILE
  chmod u+s $FILE
  return 0
}

#
# Sets up ini file
#
function setup_ini()
{
  get_local_user
  INIFILE=$GAB_USER_HOME/.gabriel/HKCU_registry.ini
  if [ ! -e $INIFILE ]; then
    require_root
    echo \[Software\\VirnetX\\Gabriel Connection\] > $INIFILE
    echo "ConfigVersion=4" >> $INIFILE
    echo "Registrar=$REGISTRYURL" >> $INIFILE
    if [ ! -z $USE_VTUN ] && [ "$USE_VTUN" == "yes" ]; then
      echo "UseVirtualAdapter=1" >> $INIFILE
    else
      echo "UseVirtualAdapter=0" >> $INIFILE
    fi
    if [ $ARM7 -eq 1 ]; then
      echo "DeviceType=computer" >> $INIFILE
    else
      echo "DeviceType=server" >> $INIFILE
    fi
    echo "" >> $INIFILE
    echo \[Software\\VirnetX\\Gabriel Connection\\V-Gabriel Service\] >> $INIFILE
    echo "WebRoot=/usr/local/lib/gabriel/web" >> $INIFILE
    if [ $ARM7 -eq 1 ]; then
      echo "" >> $INIFILE
      echo \[Software\\VirnetX\\Gabriel Connection\\V-Gabriel Service\\MyServices\\SecureChat\] >> $INIFILE
      echo "ClientInstalled=1" >> $INIFILE
    fi
    if [ $EUID -eq 0 ]; then
      chown -R $GABRIEL_LOCAL_USER $GAB_USER_HOME/.gabriel/
    fi
    chgrp -R gabriel $GAB_USER_HOME/.gabriel/
    chmod 640 $INIFILE
    chmod 750 $GAB_USER_HOME/.gabriel/
  else
    update_webroot
  fi

  return 0
}

#
# Installs the Gabriel service
#
# Input: Uses Globals
#          GABRIEL_LOCAL_USER - the local user
#
# returns 0
#
function install_service()
{
  gabrielfile=$(mktemp /tmp/gabriel.service.XXXXXXXXX)
  echo | tee $gabrielfile > /dev/null << EOF
[Unit]
Description=Virnetx Gabriel service see http://gabrielsecure.com

[Service]
Type=simple
User=GABRIEL_LOCAL_USER
ExecStart=/usr/local/bin/GabrielService
ExecStopPost=+/usr/local/bin/gabriel_cmd --resolv
StandardOutput=null
Restart=always
KillMode=process

[Install]
WantedBy=multi-user.target
Alias=GabrielService.service
EOF

  START_GABRIEL=1
  
  sed -i s/GABRIEL_LOCAL_USER/$GABRIEL_LOCAL_USER/ $gabrielfile
  CHANGEFILE=1
  if [ -e /lib/systemd/system/gabriel.service ]; then
    diff $gabrielfile /lib/systemd/system/gabriel.service > /dev/null
    CHANGEFILE=$?
    if [ $CHANGEFILE -eq 1 ]; then
      START_GABRIEL=0
      if [ -e /bin/systemctl ]; then
        if systemctl status gabriel | grep -q "^\s*Active:\s*active"; then
          START_GABRIEL=1
        fi
        systemctl stop gabriel
        systemctl disable gabriel
      else
        if service gabriel status | grep -q "^\s*Active:\s*active"; then
          START_GABRIEL=1
        fi
        service gabriel stop
        service gabriel disable
      fi
    fi
  fi
  if [ $CHANGEFILE -eq 1 ]; then
    cp $gabrielfile /lib/systemd/system/gabriel.service
    chmod 644 /lib/systemd/system/gabriel.service
    echo Enable Gabriel service
    if [ -e /bin/systemctl ]; then
      systemctl enable gabriel
    else
      service gabriel enable
    fi
    echo Gabriel service enabled
  fi
  rm $gabrielfile
  
  if [ "$START_GABRIEL" == "1" ]; then
    if [ -e /bin/systemctl ]; then
      if ! systemctl status gabriel | grep -q "^\s*Active:\s*active"; then
        echo Start Gabriel service
        systemctl start gabriel
        echo Gabriel service started
      fi
    else
      if ! service gabriel status | grep -q "^\s*Active:\s*active"; then
        echo Start Gabriel service
        service gabriel start
        echo Gabriel service started
      fi
    fi
  fi
  return 0
}

#
# Stops Gabriel if it is running
#
# Input: None
#
# returns 0
#
function stop_if_running
{
  if [ -e /bin/systemctl ]; then
    systemctl stop gabriel &> /dev/null
  else
    service gabriel stop &> /dev/null
  fi
  reload_resolv
  return 0
}

#
# Reload resolv.conf
#
# Input: None
#
# returns 0
#
function reload_resolv()
{
  iptables-save | grep -v "Gabriel DNS Capture" | grep -v "Added by Gabriel" | iptables-restore
}

#
# Check to see if the os that we are installing on is one that we support
#
# Input:
#
# returns 0 on success
#
function check_os()
{
  if [ $DARWIN -eq 1 ] || [ -e /usr/local/bin/GabrielService ] || [ -e /usr/local/lib/gabriel/forced_install ]; then
    echo "bypass os check"
    return 0
  fi

  GOOD=0
  if [ -z `which lsb_release` ]; then
    if grep -q Debian /etc/issue; then
      DISTRO="Debian"
      RELEASE=`head -1 /etc/issue | awk '{print $3}'`
      case $RELEASE in
        7 ) CODENAME=wheezy
            ;;
        8 ) CODENAME=jessie
            ;;
        9 ) CODENAME=stretch
           ;;
        10 ) CODENAME=buster
           ;;
        11 ) CODENAME=bullseye
           ;;
        * ) CODENAME=unknown
           ;;
      esac
    elif [ -e /etc/redhat-release ]; then
      RELEASE=`grep VERSION_ID /etc/os-release | awk -F\" '{print $2}'`
      DISTRO="RedHat"
    else
      DISTRO="Unknown Distro"
      RELEASE=""
    fi
  else
    DISTRO=`lsb_release -a 2> /dev/null | grep "Distributor ID" | awk '{print $3}'`
    RELEASE=`lsb_release -a 2> /dev/null | grep "Release" | awk '{print $2}'`
    CODENAME=`lsb_release -a 2> /dev/null | grep "Codename" | awk '{print $2}'`
  fi
  case $DISTRO in
    Ubuntu )
      case $RELEASE in
         16.04 ) GOOD=1;;
         18.04 ) GOOD=1;;
         20.04 ) GOOD=1;;
         * ) echo Ubuntu $RELEASE not supported;;
      esac;;
    Debian )
      case $CODENAME in
        jessie ) GOOD=1;;
        * ) echo Debian $CODENAME not supported;;
      esac;;
    Raspbian )
      case $CODENAME in
        stretch ) GOOD=1;;
        buster ) GOOD=1;;
        * ) echo Raspbian $CODENAME not supported;;
      esac;;
    RedHat )
      case $RELEASE in
        7 ) GOOD=1;;
        8 ) GOOD=1;;
        * ) echo CentOs/RedHat $RELEASE not supported;;
      esac;;
    * ) echo $DISTRO not supported;;
  esac
  if [ $GOOD -eq 0 ]; then
    echo "$DISTRO $RELEASE is not a supported distribution."
    require_root
    if [ -z $SILENT_INSTALL ] || [ $SILENT_INSTALL != 1 ]; then
      echo "$DISTRO $RELEASE is not a supported distribution. Type 'force' to continue"
      read -e get_string_ans
      if [ "x$get_string_ans" == 'xforce' ]; then
        GOOD=1
        mkdir -p /usr/local/lib/gabriel/
        touch /usr/local/lib/gabriel/forced_install
      fi
    fi
    if [ $GOOD -eq 0 ]; then
      return 1
    fi
  fi
  return 0
}


#
# Updates Gabriel 
#
# Input: None
#
# returns 0 on success
#
function update_gabriel()
{
  require_root
  #
  # We are just making sure that Gabriel is setup the way we want
  # This function can be used to keep the environment that runs
  # Gabriel up-to-date with the current release
  #
  setup_local_user || return 1
  setup_ini || return 1
  install_service || return 1
  setup_deb_location || return 1
  check_update_chan || return 1
  create_crontab || return 1
}

#
# Updates Gabriel
#
# Input: None
#
# returns 0 on success
#
function post_install()
{
  require_root
  setup_local_user || return 1
  set_suid /usr/local/bin/GabrielService
  set_suid /usr/local/bin/DnsWatch
  for i in InstallUpdates VSPUtility activate_gabriel.sh gabriel_cmd; do
    if [ -e /usr/local/bin/$i ]; then
      chmod 750 /usr/local/bin/$i
      chown root:gabriel /usr/local/bin/$i
    fi
  done
  setup_ini || return 1
  install_service || return 1

  #
  # we were setting the apt key and location here but we will let the first update
  # do that
  #

  create_crontab || return 1
}

# this will look to see if there are any updates available via apt-get
# if there are it will stop Gabriel, fetch and install the updates
# and restart Gabriel
#
# this will get called from GabrielService on every start and every 24 hours
function upgrade_gabriel()
{
  if [ $DARWIN -eq 1 ]; then
    return
  fi

  require_root
  update_gabriel
  UPGRADE_LOGFILE=/var/log/gabriel_update.log
  touch $UPGRADE_LOGFILE
  echo "" >> $UPGRADE_LOGFILE
  echo "------------------------" >> $UPGRADE_LOGFILE
  date >> $UPGRADE_LOGFILE
  echo "Current install:" >> $UPGRADE_LOGFILE
  /usr/local/bin/GabrielService --version >> $UPGRADE_LOGFILE

  if [ $UPDATE_CHANNEL -eq 0 ]; then
    echo "Update channel is set to 0 so we are skipping the update check" >> $UPGRADE_LOGFILE
    return;
  fi
  if [ $CENTOS == 1 ]; then
    check_update_yum
  else
    check_update_apt
  fi
}


function check_update_yum()
{
  UPGRADE_LOGFILE=/var/log/gabriel_update.log
  echo "------------------------" >> $UPGRADE_LOGFILE
  echo "Does gabrielserver need an update?" >> $UPGRADE_LOGFILE
  HASUPDATE=`yum -q check-update gabriel`
  if [ "x$HASUPDATE" == "x" ]; then
    echo no
    return
  else
    echo $HASUPDATE >> $UPGRADE_LOGFILE
  fi
  echo "------------------------" >> $UPGRADE_LOGFILE
  echo "stopping Gabriel" >> $UPGRADE_LOGFILE
  stop_if_running
  
  echo "------------------------" >> $UPGRADE_LOGFILE
  echo "running yum update" >> $UPGRADE_LOGFILE
  yum -y update gabriel >> $UPGRADE_LOGFILE 2>&1

  echo "------------------------" >> $UPGRADE_LOGFILE
  echo "restarting Gabriel" >> $UPGRADE_LOGFILE
  if [ -e /bin/systemctl ]; then
    systemctl start gabriel
  else
    service gabriel start
  fi
}
  
function start_gabriel()
{
  require_root
  if [ -e /bin/systemctl ]; then
    systemctl start gabriel
  else
    service gabriel start
  fi
}

function status_gabriel()
{
  if [ -e /bin/systemctl ]; then
    systemctl status gabriel
  else
    service gabriel status
  fi
}
  
function check_update_apt()
{
  UPGRADE_LOGFILE=/var/log/gabriel_update.log
  echo "------------------------" >> $UPGRADE_LOGFILE
  echo "running apt-get update" >> $UPGRADE_LOGFILE
  DEBIAN_FRONTEND=noninteractive apt-get update >> $UPGRADE_LOGFILE 2>&1

  # if there is an update ready to be instaled then this command will output a line like:
  #     Inst gabrielserver [7.353] (7.360 gabriel apt repository:deb.myvirnetx.com [amd64])
  OUTPUT=`DEBIAN_FRONTEND=noninteractive apt-get -V -u -s upgrade |grep gabrielserver | grep "=>"`
  if [[ $? -eq 0 ]]; then
    echo "------------------------" >> $UPGRADE_LOGFILE
    echo "Update looks to be available for Gabriel" >> $UPGRADE_LOGFILE
    echo $OUTPUT >> $UPGRADE_LOGFILE

    echo "------------------------" >> $UPGRADE_LOGFILE
    echo "stopping Gabriel" >> $UPGRADE_LOGFILE
    stop_if_running

    # install the update
    echo "------------------------" >> $UPGRADE_LOGFILE
    echo "running apt-get install --only-upgrade gabrielserver -y" >> $UPGRADE_LOGFILE
    DEBIAN_FRONTEND=noninteractive apt-get install --only-upgrade gabrielserver -y  >> $UPGRADE_LOGFILE 2>&1

    # restart_gabriel
    echo "------------------------" >> $UPGRADE_LOGFILE
    echo "restarting Gabriel" >> $UPGRADE_LOGFILE
    if [ -e /bin/systemctl ]; then
      systemctl start gabriel
    else
      service gabriel start
    fi
  else
    echo "No updates seem to be available for Gabriel" >> $UPGRADE_LOGFILE
  fi
}



UPDATE_CHANNEL="1"

#
# Checks the update channel that the user wants
#
# Input: 
#   GAB_USER_HOME the home dir of the Gabriel user
#
# returns 0
#
function check_update_chan()
{
  get_local_user
  if [ -e $GAB_USER_HOME/.gabriel/HKCU_registry.ini ]; then
    DEVSET=`grep -v '#' $GAB_USER_HOME/.gabriel/HKCU_registry.ini | grep Developer= | awk -F= '{print $2}' | awk '{print $1}'`
    if [ ! -z $DEVSET ] && [ "$DEVSET" == "1" ]; then
      export UPDATE_CHANNEL=`grep -v '#' $GAB_USER_HOME/.gabriel/HKCU_registry.ini | grep AutoUpdate= | awk -F= '{print $2}' | awk '{print $1}'`
    fi
  fi
  if [ -z $UPDATE_CHANNEL ]; then
    if [ -e /usr/local/lib/gabriel/update_chan ]; then
      export UPDATE_CHANNEL=`cat /usr/local/lib/gabriel/update_chan`
    fi 
    if [ -z $UPDATE_CHANNEL ]; then
      export UPDATE_CHANNEL=1
    fi
  fi
  set_channel
  return 0
}

#
# Saves the registry channel to the ini
#
# Input: None
#
# returns 0 on success
#
function save_chan_to_ini()
{
  get_local_user
  if [ -e $GAB_USER_HOME/.gabriel/HKCU_registry.ini ]; then
    inifile=$(mktemp /tmp/ini.XXXXXXXXX)
    sed s/Developer=0/Developer=1/ $GAB_USER_HOME/.gabriel/HKCU_registry.ini | sed s/AutoUpdate=./AutoUpdate=$UPDATE_CHANNEL/ > $inifile
    cp $inifile $GAB_USER_HOME/.gabriel/HKCU_registry.ini
    rm $inifile
  fi
}

function update_webroot()
{
  get_local_user
  if [ -e $GAB_USER_HOME/.gabriel/HKCU_registry.ini ]; then
    if grep -q "WebRoot=~/.gabriel/web/gui" $GAB_USER_HOME/.gabriel/HKCU_registry.ini; then
      inifile=$(mktemp /tmp/ini.XXXXXXXXX)
      sed 's#WebRoot=~/.gabriel/web/gui#WebRoot=/usr/local/lib/gabriel/web#' $GAB_USER_HOME/.gabriel/HKCU_registry.ini > $inifile
      cp $inifile $GAB_USER_HOME/.gabriel/HKCU_registry.ini
      rm $inifile
    fi
  fi
}

#
# Sets the update channel
#
# Input:
#   UPDATE_CHANNEL - The update channel that the user wants
#
# returns 0 on success
#
function set_channel()
{
  if [ $DARWIN -eq 1 ]; then
    return
  fi
  require_root
  mkdir -p /usr/local/lib/gabriel
  echo $UPDATE_CHANNEL > /usr/local/lib/gabriel/update_chan
  if [ $ARM7 -eq 1 ]; then
    SYSLOC=pi/debian
  else
    SYSLOC=debian
  fi
  case $UPDATE_CHANNEL in
    1 ) echo "setting update channel to production"
        CHANDIR="/"
        ;;
    2 ) echo "setting update channel to beta"
        CHANDIR="/beta/"
        ;;
    3 ) echo "setting update channel to alpha"
        CHANDIR="/alpha/"
        ;;
    0 ) echo "setting update channel to production - autoupdate should be off"
        CHANDIR="/"
        ;;
    * ) echo "setting update channel to $UPDATE_CHANNEL"
        CHANDIR="/alpha${UPDATE_CHANNEL}/"
        ;;
  esac
  if [ $CENTOS == 1 ]; then
    setup_yum_location ${CHANDIR}
  else
    echo "deb https://deb.myvirnetx.com${CHANDIR}${SYSLOC} stable main" > /etc/apt/sources.list.d/gabriel.list
  fi
}

#
# Function called always on run to check if we need to install
#
# if --install on the command line this function will exit
#
function install_main()
{
  if [ $# == 0 ] || [ "$1" == "--install" ] || [ "$1" == "-install" ]; then

    # do an install if no args or if --install given
    # if --install given exit

    if [ ! -z $1 ] && [ "$1" == "--install" ] || [ "$1" == "-install" ]; then
      export SILENT_INSTALL=1
    fi
    check_os || exit
    check_apt_install || exit

    if [ ! -z $1 ] && [ "$1" == "--install" ] || [ "$1" == "-install" ]; then
      echo installed
      exit
    else
      if [ -e /usr/local/bin/activate_gabriel.sh ]; then
        /usr/local/bin/activate_gabriel.sh --activate
      fi
    fi
  else
    case $1 in
      --update ) update_gabriel
                exit;;
      --postinstall ) post_install
                      exit;;
      --upgrade ) upgrade_gabriel
                exit;;
      --resolv ) reload_resolv
                 exit;;
      --set-channel=* ) if [ $DARWIN -eq 0 ]; then
                          require_root
                        fi
                        export UPDATE_CHANNEL=`echo $1 | sed 's/--set-channel=//'`;
                        save_chan_to_ini;
                        set_channel;
                        exit;;
    --start ) start_gabriel
              exit;;
    --stop ) stop_if_running
             exit;;
    --restart ) stop_if_running
                start_gabriel
                exit;;
      --status ) status_gabriel
                 exit;;
      -h|--help ) echo "Install specific options"
                  echo "$0 --install"
                  echo "  will ensure Gabriel binaries are installed"
                  echo "$0 --resolv"
                  echo "  will restart the resolv service on Gabriel exit"
                  echo "$0 --update"
                  echo "  will setup an old system to have same env as current"
                  echo "$0 --upgrade"
                  echo "  will check to see if there is a new version of Gabriel to install"
                  echo "$0 --set-channel=?"
                  echo "  will set the channel to the requested number"
                  echo "  production ('1') or beta ('2') or alpha ('3')"
                  echo "$0 --start"
                  echo "  Starts Gabriel"
                  echo "$0 --stop"
                  echo "  Stops Gabriel"
                  echo "$0 --restart"
                  echo "  Restarts Gabriel"
                  echo "$0 --status"
                  echo "  Gets status of the Gabriel service"
                  echo "";;
    esac
  fi
}

install_main $*

#
# This is a bash script that finds python and then launches the code following
# the tag with the python interpeter - the python should be
# compatable with both python 2 and python 3
#
# note that we prefer the python3 interpreter if we can find it
#

if [ -z $GABRIEL_PYTHON ]; then
  BIN=
  if [ ! -z `which python3` ]; then
    BIN=`which python3`
  elif [ -e /usr/bin/python3 ]; then
    BIN=/usr/bin/python3
  elif [ -e /Library/Frameworks/Python.framework/Versions/3.6/bin/python3 ]; then
    BIN=/Library/Frameworks/Python.framework/Versions/3.6/bin/python3
  elif [ ! -z `which python` ]; then
    BIN=`which python`
    if [ -t 1 ] && [ ! -e /usr/local/lib/gabriel_python_warn ]; then
      echo "Python v2 is deprecited, please upgrade to python3. Python 2 will stop working in future builds." 1>&2
      echo "touch /usr/local/lib/gabriel_python_warn to suppress this message" 1>&2
      echo "" 1>&2
    fi
  elif [ -e /usr/bin/python ]; then
    BIN=/usr/bin/python
    if [ -t 1 ] && [ ! -e /usr/local/lib/gabriel_python_warn ]; then 
      echo "Python v2 is deprecited, please upgrade to python3. Python 2 will stop working in future builds." 1>&2
      echo "touch /usr/local/lib/gabriel_python_warn to suppress this message" 1>&2
      echo "" 1>&2
    fi
  fi
else
  BIN=`which $GABRIEL_PYTHON`
fi

if [ -z $BIN ]; then
  echo This script depends on python3 to run many of its options.
  if [ `uname -s` == "Darwin" ]; then
    echo Python3 is normally installed by default on osx but this script cant find it
  else
    echo All gabriel_cmd options are not available, install python3 by running:
    if [ $CENTOS == 0 ]; then
      echo sudo apt install python3
    else
      echo yum install python3
    fi
  fi
  exit
fi

arglist="import sys; sys.argv=[\"$0\"]"
while [ ! -z "$1" ]; do
  arglist=${arglist}\;sys.argv.append\(\"$1\"\)
  shift
done

#echo using $BIN

python_file=$(mktemp /tmp/gab.python.XXXXXXXXX)
chmod 700 $python_file
(echo $arglist; tail -n$((`wc -l $0|awk '{print $1}'`-`grep -n PYTHON_CODE_AFTER_HERE $0 | grep -v grep | awk -F: '{print $1}'`)) $0) > $python_file
$BIN $python_file
#echo $BIN $python_file
rm $python_file

exit
#######
#
# end of the bash script
#
######
PYTHON_CODE_AFTER_HERE

def excepthook(*args):
  print("in excepthook")
try:
  sys.excepthook = excepthook
except:
  pass

import os
import glob
import json
import re
import urllib
import argparse
import time
import platform
import os.path
import sys
from os import path
try:
  import urllib.parse
except:
  pass
try:
  from urllib import quote
except ImportError:
  from urllib.parse import quote
try:
  from subprocess import PIPE, Popen
except:
  pass

curlflag=False
noRetryFlag=False

#
# Check to see if a value is an integer
#
# param
#   val_to_test - the value to test
#
# return True if the value is an iteger, False if it is not
#
def isInt(val_to_test):
  try:
    int(val_to_test)
    return True
  except ValueError:
    return False

####################################################
# 
# BEGIN Param handling
#
####################################################

#
# Add processing of args in common to all parsers
#
# param
#   parser - the parser to add the in common args
#
# return N/A
#
def commonflag(parser, jsonflag=True):
  if jsonflag:
    parser.add_argument("--json",
                        action='store_true',
                        help="returns the result using the json string from the web cmds")
  parser.add_argument("--curl",
                      action='store_true',
                      help="shows each curl command")
  parser.add_argument("--noretry",
                      action='store_true',
                      help="turns off the default behavior of retrying if gabriel does not respond to web requests")

#
# Add the params for the fullhelp command
#
# param
#   subparsers - the subparsers list to add this command to
#
# return N/A
#
def fullhelp_load(subparsers):
  parser = subparsers.add_parser("fullhelp",
                                 help="Generates a help file for this script")
  parser.add_argument("--wiki",
                      action='store_true',
                      help="Generates wiki formated help")
  parser.set_defaults(dohelp=True)
  commonflag(parser)

#
# Add the params for the domainuser command
#
# param
#   mainsubparsers - the mainsubparsers list to add this command to
#
# return N/A
#
def domainuser_load(mainsubparsers):
  parser = mainsubparsers.add_parser("domainuser",
                                 help="Domain User admin")
  subparsers = parser.add_subparsers(dest='domainuser_subs')   
  domainuser_add_load(subparsers)
  domainuser_del_load(subparsers)

#
# Add the params for the group command
#
# param
#   mainsubparsers - the mainsubparsers list to add this command to
#
# return N/A
#
def group_load(mainsubparsers):
  parser = mainsubparsers.add_parser("group",
                                 help="Maintain user's group")
  subparsers = parser.add_subparsers(dest='group_subs')
  group_add_load(subparsers)
  group_del_load(subparsers)
  group_list_load(subparsers)
  group_listpeers_load(subparsers)
  group_addpeer_load(subparsers)
  group_delpeer_load(subparsers)

#
# Add the params for the peer request command
#
# param
#   mainsubparsers - the mainsubparsers list to add this command to
#
# return N/A
#
def peer_request_load(mainsubparsers):
  parser = mainsubparsers.add_parser("request",
                                 help="Maintain Peer Requests")
  subparsers = parser.add_subparsers(dest='peer_request_subs')
  peer_request_list_load(subparsers)
  peer_request_accept_load(subparsers)
  peer_request_reject_load(subparsers)

#
# Show the server clients
#
# return N/A
#
def peer_serverclients_load(mainsubparsers):
  parser = mainsubparsers.add_parser("serverclients",
                                 help="Gets the list of server clients")
  parser.add_argument('--setactive',
                      dest='setactive',
                      required=False,
                      help="The account to set to the active account")
  parser.set_defaults(func=peer_serverclients)
  commonflag(parser)

#
# Show each peer's servers
#
# return N/A
#
def peer_servers_load(mainsubparsers):
  parser = mainsubparsers.add_parser("servers",
                                 help="Gets the list of servers for a peer")
  parser.set_defaults(func=peer_servers)
  commonflag(parser)

#
# Add the params for the peer command
#
# param
#   mainsubparsers - the mainsubparsers list to add this command to
#
# return N/A
#
def peer_load(mainsubparsers):
  parser = mainsubparsers.add_parser("peer",
                                 help="Maintain Peers")
  subparsers = parser.add_subparsers(dest='peer_subs')
  peer_request_load(subparsers)
  peer_showdevices_load(subparsers)
  peer_serverclients_load(subparsers)
  peer_servers_load(subparsers)
  peer_list_load(subparsers)
  peer_add_load(subparsers)
  peer_del_load(subparsers)
  peer_policy_load(subparsers)

#
# Add the params for the localservice command
#
# param
#   mainsubparsers - the mainsubparsers list to add this command to
#
# return N/A
#
def localservice_load(mainsubparsers):
  parser = mainsubparsers.add_parser("localservice",
                                 help="Maintain Local Services")
  subparsers = parser.add_subparsers(dest='localservice_subs')
  localservice_get_load(subparsers)
  localservice_del_load(subparsers)
  localservice_add_load(subparsers)
  localservice_edit_load(subparsers)
  localservice_addgroup_load(subparsers)
  localservice_delgroup_load(subparsers)
  localservice_getgroups_load(subparsers)

#
# Add the params for the account command
#
# param
#   mainsubparsers - the mainsubparsers list to add this command to
#
# return N/A
#
def account_load(mainsubparsers):
  parser = mainsubparsers.add_parser("account",
                                 help="Maintain Local Accounts")
  subparsers = parser.add_subparsers(dest='account_subs')
  account_activate_load(subparsers)
  account_list_load(subparsers)
  account_getactive_load(subparsers)
  account_setactive_load(subparsers)
  account_deldevice_load(subparsers)
  account_showdevices_load(subparsers)

#
# Add the params for the grouplog command
#
# param
#   mainsubparsers - the mainsubparsers list to add this command to
#
# return N/A
#
def grouplog_load(mainsubparsers):
  parser = mainsubparsers.add_parser("grouplog",
                                 help="Get and set grouplog values for debug")
  subparsers = parser.add_subparsers(dest='grouplog_subs')
  grouplog_get_load(subparsers)
  grouplog_set_load(subparsers)

#
# Add the params for the domainuser add sub command
#
# param
#   mainsubparsers - the mainsubparsers list to add this command to
#
# return N/A
#
def domainuser_add_load(subparsers):
  parser = subparsers.add_parser("add",
                                 help="Creates a new user")
  parser.add_argument('--user',
                      dest='user',
                      required=True,
                      help="The user to create")
  parser.add_argument("--password",
                      dest='password',
                      required=True,
                      help="The password for the user")
  parser.add_argument("--domain",
                      dest='domain',
                      required=True,
                      help="The domain for the user")
  parser.add_argument("--first",
                      dest='first',
                      required=True,
                      help="The first name of the user")
  parser.add_argument("--last",
                      dest='last',
                      required=True,
                      help="The last name of the user")
  parser.add_argument("--email",
                      dest='email',
                      required=True,
                      help="The email of the user")
  parser.add_argument("--adminuser",
                      dest='adminuser',
                      required=True,
                      help="The domain admin user")
  parser.add_argument("--adminpass",
                      dest='adminpass',
                      required=True,
                      help="The admin password")
  parser.set_defaults(func=domainuser_add_load)
  commonflag(parser)

#
# Add the params for the domainuser del sub command
#
# param
#   mainsubparsers - the mainsubparsers list to add this command to
#
# return N/A
#
def domainuser_del_load(subparsers):
  parser = subparsers.add_parser("del",
                                 help="Deletes a domain user")
  parser.add_argument('--user',
                      dest='user',
                      required=True,
                      help="The user to delete")
  parser.add_argument("--domain",
                      dest='domain',
                      required=True,
                      help="The domain for the user")
  parser.add_argument("--adminuser",
                      dest='adminuser',
                      required=True,
                      help="The domain admin user")
  parser.add_argument("--adminpass",
                      dest='adminpass',
                      required=True,
                      help="The admin password")
  parser.set_defaults(func=domainuser_del)
  commonflag(parser)

#
# Add the params for the group add sub command
#
# param
#   mainsubparsers - the mainsubparsers list to add this command to
#
# return N/A
#
def group_add_load(subparsers):
  parser = subparsers.add_parser("add",
                                 help="Creates a group of friends")
  parser.add_argument('--group',
                      dest='group',
                      required=True,
                      help="The name of the group to create")
  parser.set_defaults(func=group_add)
  commonflag(parser)

#
# Add the params for the group del sub command
#
# param
#   mainsubparsers - the mainsubparsers list to add this command to
#
# return N/A
#
def group_del_load(subparsers):
  parser = subparsers.add_parser("del",
                                 help="Deletes a group of friends")
  parser.add_argument('--group',
                      dest='group',
                      required=True,
                      help="The name of the group to delete")
  parser.add_argument('--really_i_want_to_delete_this_group',
                      action='store_true',
                      required=True,
                      help="Flag to prevent this from being run by mistake")
  parser.set_defaults(func=group_del)
  commonflag(parser)

#
# Add the params for the group list sub command
#
# param
#   mainsubparsers - the mainsubparsers list to add this command to
#
# return N/A
#
def group_list_load(subparsers):
  parser = subparsers.add_parser("list",
                                 help="List the groups of friends")
  parser.set_defaults(func=group_list)
  commonflag(parser)

#
# Add the params for the group listpeers sub command
#
# param
#   mainsubparsers - the mainsubparsers list to add this command to
#
# return N/A
#
def group_listpeers_load(subparsers):
  parser = subparsers.add_parser("listpeers",
                                 help="List peers in a group")
  parser.set_defaults(func=group_listpeers)
  commonflag(parser)
  parser.add_argument('--group',
                      dest='group',
                      required=True,
                      help="The name of the group to list")

#
# Add the params for the group addpeer sub command
#
# param
#   mainsubparsers - the mainsubparsers list to add this command to
#
# return N/A
#
def group_addpeer_load(subparsers):
  parser = subparsers.add_parser("addpeer",
                                 help="Add a peer to a group")
  parser.set_defaults(func=group_addpeer)
  commonflag(parser)
  parser.add_argument('--group',
                      dest='group',
                      required=True,
                      help="The name of the group to add a peer to")
  parser.add_argument('--peer',
                      dest='peer',
                      required=True,
                      help="The name of the peer to add")

#
# Add the params for the group delpeer sub command
#
# param
#   mainsubparsers - the mainsubparsers list to add this command to
#
# return N/A
#
def group_delpeer_load(subparsers):
  parser = subparsers.add_parser("delpeer",
                                 help="Remove a peer from a group")
  parser.set_defaults(func=group_delpeer)
  commonflag(parser)
  parser.add_argument('--group',
                      dest='group',
                      required=True,
                      help="The name of the group to remove a peer from")
  parser.add_argument('--peer',
                      dest='peer',
                      required=True,
                      help="The name of the peer to remove")

#
# Add the params for the account list sub command
#
# param
#   mainsubparsers - the mainsubparsers list to add this command to
#
# return N/A
#
def account_list_load(subparsers):
  parser = subparsers.add_parser("list",
                                 help="Gets the list of local accounts")
  parser.set_defaults(func=account_list)
  commonflag(parser)

#
# Add the params for the account getactive sub command
#
# param
#   mainsubparsers - the mainsubparsers list to add this command to
#
# return N/A
#
def account_getactive_load(subparsers):
  parser = subparsers.add_parser("getactive",
                                 help="Prints the active account")
  parser.set_defaults(func=account_getactive)
  commonflag(parser)

#
# Add the params for the account setactive sub command
#
# param
#   mainsubparsers - the mainsubparsers list to add this command to
#
# return N/A
#
def account_setactive_load(subparsers):
  parser = subparsers.add_parser("setactive",
                                 help="Sets the active account")
  parser.set_defaults(func=account_setactive)
  commonflag(parser)
  parser.add_argument('--account',
                      dest='account',
                      required=True,
                      help="The account to set to active")

#
# Add the params for the peer list sub command
#
# param
#   mainsubparsers - the mainsubparsers list to add this command to
#
# return N/A
#
def peer_list_load(subparsers):
  parser = subparsers.add_parser("list",
                                 help="Gets the list of peers")
  parser.set_defaults(func=peer_list)
  commonflag(parser)

#
# Add the params for the account showdevices sub command
#
# param
#   mainsubparsers - the mainsubparsers list to add this command to
#
# return N/A
#
def account_showdevices_load(subparsers):
  parser = subparsers.add_parser("showdevices",
                                 help="Gets the list of devices")
  parser.set_defaults(func=account_showdevices)
  commonflag(parser)

#
# Add the params for the peer showdevices sub command
#
# param
#   mainsubparsers - the mainsubparsers list to add this command to
#
# return N/A
#
def peer_showdevices_load(subparsers):
  parser = subparsers.add_parser("showdevices",
                                 help="Gets the list of devices for a peer")
  parser.add_argument('--setactive',
                      dest='setactive',
                      required=False,
                      help="The account to set to the active account")
  parser.set_defaults(func=peer_showdevices)
  commonflag(parser)

#
# Add the params for the peer policy sub command
#
# param
#   mainsubparsers - the mainsubparsers list to add this command to
#
# return N/A
#
def peer_policy_load(mainsubparsers):
  parser = mainsubparsers.add_parser("policy",
                                 help="Peer policy function")
  subparsers = parser.add_subparsers(dest='peer_policy_subs')
  peer_policy_get_load(subparsers)
  peer_policy_add_load(subparsers)
  peer_policy_del_load(subparsers)

#
# Add the params for the peer policy get sub command
#
# param
#   mainsubparsers - the mainsubparsers list to add this command to
#
# return N/A
#
def peer_policy_get_load(subparsers):
  parser = subparsers.add_parser("get",
                                 help="Gets the list of peers in the default policy")
  parser.set_defaults(func=peer_policy_get)
  commonflag(parser)

#
# Add the params for the peer policy add sub command
#
# param
#   mainsubparsers - the mainsubparsers list to add this command to
#
# return N/A
#
def peer_policy_add_load(subparsers):
  parser = subparsers.add_parser("add",
                                 help="Adds a peer to the default policy")
  parser.add_argument('--peer', '--peers',
                      dest='peer',
                      required=True,
                      help="The name of the peer or peers (comma delimited) to add 'peerA,peerB'")
  parser.set_defaults(func=peer_policy_add)
  commonflag(parser, False)

#
# Add the params for the peer policy del sub command
#
# param
#   mainsubparsers - the mainsubparsers list to add this command to
#
# return N/A
#
def peer_policy_del_load(subparsers):
  parser = subparsers.add_parser("del",
                                 help="Removes a peer from the default policy")
  parser.add_argument('--peer', '--peers',
                      dest='peer',
                      required=True,
                      help="The name of the peer or peers (comma delimited) to remove 'peerA,peerB'")
  parser.set_defaults(func=peer_policy_del)
  commonflag(parser, False)



#
# Add the params for the localservice get sub command
#
# param
#   mainsubparsers - the mainsubparsers list to add this command to
#
# return N/A
#
def localservice_get_load(subparsers):
  parser = subparsers.add_parser("get",
                                 help="Gets the list of local services")
  parser.set_defaults(func=localservice_get)
  commonflag(parser)

#
# Add the params for the localservice del sub command
#
# param
#   mainsubparsers - the mainsubparsers list to add this command to
#
# return N/A
#
def localservice_del_load(subparsers):
  parser = subparsers.add_parser("del",
                                 help="Removes a local service")
  parser.set_defaults(func=localservice_del)
  commonflag(parser)
  parser.add_argument('--name',
                      dest='name',
                      required=True,
                      help="The name of the service to remove")

#
# Add the params for the localservice add sub command
#
# param
#   mainsubparsers - the mainsubparsers list to add this command to
#
# return N/A
#
def localservice_add_load(subparsers):
  parser = subparsers.add_parser("add",
                                 help="Adds a local service")
  parser.set_defaults(func=localservice_add)
  commonflag(parser)
  parser.add_argument('--name',
                      dest='name',
                      required=True,
                      help="The name of the service to add")
  parser.add_argument('--service_type',
                      dest='service_type',
                      required=False,
                      default='none',
                      help="The service type ex: 'Html' - defaults to None")
  parser.add_argument('--dest_address',
                      dest='dest_address',
                      required=True,
                      help="The name or ip of the destination service")
  parser.add_argument('--dest_port','--dest_tcp_port',
                      dest='dest_tcp_port',
                      required=False,
                      help="The tcp port of the destination service")
  parser.add_argument('--dest_udp_port',
                      dest='dest_udp_port',
                      required=False,
                      help="The udp port of the destination service")
  parser.add_argument('--mapped_port','--maped_tcp_port',
                      dest='mapped_tcp_port',
                      required=False,
                      help="The tcp local port of the service")
  parser.add_argument('--mapped_udp_port',
                      dest='mapped_udp_port',
                      required=False,
                      help="The udp local port of the service")

  parser.add_argument('--allow_non_vpn',
                      dest='allow_non_vpn',
                      action='store_true',
                      help="If set then non VPN access is set for the port, defaults to False")
  parser.add_argument('--allow_all',
                      dest='allow_all',
                      action='store_true',
                      help="If set then all Gabriel users can access the port, defaults to False")
  try:
    if isVtun():
      parser.add_argument('--set_as_local_bookmark',
                          dest='bookmark',
                          action='store_true',
                          help="If set then this is a local bookmark - only used for VTUN, defaults to False")
  except:
    pass

#
# Add the params for the localservice add sub command
#
# param
#   mainsubparsers - the mainsubparsers list to add this command to
#
# return N/A
#
def localservice_edit_load(subparsers):
  parser = subparsers.add_parser("edit",
                                 help="Edit a local service")
  parser.set_defaults(func=localservice_edit)
  commonflag(parser)
  parser.add_argument('--name',
                      dest='name',
                      required=True,
                      help="The name of the service to add")
  parser.add_argument('--service_type',
                      dest='service_type',
                      required=False,
                      help="The service type ex: 'Html' - defaults to None")
  parser.add_argument('--dest_address',
                      dest='dest_address',
                      required=False,
                      help="The name or ip of the destination service")
  parser.add_argument('--dest_port','--dest_tcp_port',
                      dest='dest_tcp_port',
                      required=False,
                      help="The tcp port of the destination service")
  parser.add_argument('--dest_udp_port',
                      dest='dest_udp_port',
                      required=False,
                      help="The udp port of the destination service")
  parser.add_argument('--mapped_port','--maped_tcp_port',
                      dest='mapped_tcp_port',
                      required=False,
                      help="The tcp local port of the service")
  parser.add_argument('--mapped_udp_port',
                      dest='mapped_udp_port',
                      required=False,
                      help="The udp local port of the service")
  parser.add_argument('--allow_non_vpn',
                      dest='allow_non_vpn',
                      action='store_true',
                      help="If set then non VPN access is set for the port")
  parser.add_argument('--no_allow_non_vpn',
                      dest='no_allow_non_vpn',
                      action='store_true',
                      help="If set then non VPN access is not set for the port")
  parser.add_argument('--allow_all',
                      dest='allow_all',
                      action='store_true',
                      help="If set then all Gabriel users can access the port")
  parser.add_argument('--no_allow_all',
                      dest='no_allow_all',
                      action='store_true',
                      help="If set then all Gabriel users can not access the port")
  try:
    if isVtun():
      parser.add_argument('--set_as_local_bookmark',
                          dest='bookmark',
                          action='store_true',
                          help="If set then this is a local bookmark - only used for VTUN, defaults to False")
      parser.add_argument('--no_set_as_local_bookmark',
                          dest='no_bookmark',
                          action='store_true',
                          help="If set then this is a local bookmark - only used for VTUN, defaults to False")
  except:
    pass

#
# Add the params for the localservice addgroup sub command
#
# param
#   mainsubparsers - the mainsubparsers list to add this command to
#
# return N/A
#
def localservice_addgroup_load(subparsers):
  parser = subparsers.add_parser("addgroup",
                                 help="Adds a group to a local service")
  parser.set_defaults(func=localservice_addgroup)
  commonflag(parser)
  parser.add_argument('--name',
                      dest='name',
                      required=True,
                      help="The name of the service to change")
  parser.add_argument('--group',
                      dest='group',
                      required=False,
                      help="The name of the group to add")
  parser.add_argument('--domain',
                      dest='domain',
                      required=False,
                      help="The domain to give access to, IE domain.scom for *.domain.scom")

#
# Add the params for the localservice delgroup sub command
#
# param
#   mainsubparsers - the mainsubparsers list to add this command to
#
# return N/A
#
def localservice_delgroup_load(subparsers):
  parser = subparsers.add_parser("delgroup",
                                 help="Removes a group from a local service")
  parser.set_defaults(func=localservice_delgroup)
  commonflag(parser)
  parser.add_argument('--name',
                      dest='name',
                      required=True,
                      help="The name of the service to remove a group permission from")
  parser.add_argument('--group',
                      dest='group',
                      required=False,
                      help="The name of the group to remove")
  parser.add_argument('--domain',
                      dest='domain',
                      required=False,
                      help="The domain to remove access from, IE domain.scom for *.domain.scom")

#
# Add the params for the localservice getgroups sub command
#
# param
#   mainsubparsers - the mainsubparsers list to add this command to
#
# return N/A
#
def localservice_getgroups_load(subparsers):
  parser = subparsers.add_parser("getgroups",
                                 help="Finds what groups have permission to use a local service")
  parser.set_defaults(func=localservice_getgroups)
  commonflag(parser)
  parser.add_argument('--name',
                      dest='name',
                      required=True,
                      help="The name of the service to check group permissions for")

#
# Add the params for the peer request list sub command
#
# param
#   mainsubparsers - the mainsubparsers list to add this command to
#
# return N/A
#
def peer_request_list_load(subparsers):
  parser = subparsers.add_parser("list",
                                 help="Gets the list of peer requests")
  parser.set_defaults(func=peer_request_list)
  commonflag(parser)

#
# Add the params for the peer add sub command
#
# param
#   mainsubparsers - the mainsubparsers list to add this command to
#
# return N/A
#
def peer_add_load(subparsers):
  parser = subparsers.add_parser("add",
                                 help="Adds a peer")
  parser.set_defaults(func=peer_add)
  commonflag(parser)
  parser.add_argument('--user',
                      dest='user',
                      required=True,
                      help="The peer to add")
  parser.add_argument('--acct',
                      dest='account',
                      required=False,
                      help='The account to add the peer to')

#
# Add the params for the peer request accept sub command
#
# param
#   mainsubparsers - the mainsubparsers list to add this command to
#
# return N/A
#
def peer_request_accept_load(subparsers):
  parser = subparsers.add_parser("accept",
                                 help="Accepts a peer request")
  parser.set_defaults(func=peer_request_accept)
  commonflag(parser)
  parser.add_argument('--peer',
                      dest='peer',
                      required=True,
                      help="The peer to accept")

#
# Add the params for the peer request reject sub command
#
# param
#   mainsubparsers - the mainsubparsers list to add this command to
#
# return N/A
#
def peer_request_reject_load(subparsers):
  parser = subparsers.add_parser("reject",
                                 help="Rejects a peer request")
  parser.set_defaults(func=peer_request_reject)
  commonflag(parser)
  parser.add_argument('--peer',
                      dest='peer',
                      required=True,
                      help="The peer to reject")

#
# Add the params for the account activate sub command
#
# param
#   mainsubparsers - the mainsubparsers list to add this command to
#
# return N/A
#
def account_activate_load(subparsers):
  parser = subparsers.add_parser("activate",
                                 help="Activates a device")
  parser.set_defaults(func=account_activate)
  commonflag(parser)
  parser.add_argument('--devicename',
                      dest='name',
                      required=True,
                      help="The full securename of the device to activate")
  group = parser.add_mutually_exclusive_group(required=True)
  group.add_argument('--password',
                      dest='password',
                      help="The password for the account")
  group.add_argument('--token',
                      dest='token',
                      help="The one time token for the account")
  parser.add_argument('--hide',
                      dest='isHidden',
                      help="If supplied the device will be hidden to other accounts")
  parser.add_argument('--onetime',
                      dest='onetime',
                      help="If supplied use the onetime passkey for this account")
  parser.add_argument('--noprompt',
                      action='store_true',
                      dest='noprompt',
                      help="If onetime password is asked for return rather than wait for a prompt for the one time")

#
# Add the params for the peer del sub command
#
# param
#   mainsubparsers - the mainsubparsers list to add this command to
#
# return N/A
#
def peer_del_load(subparsers):
  parser = subparsers.add_parser("del",
                                 help="Removes a peer")
  parser.set_defaults(func=peer_del)
  commonflag(parser)
  parser.add_argument('--user',
                      dest='user',
                      required=True,
                      help="The user to delete")
  parser.add_argument('--acct',
                      dest='account',
                      help='(opt) The account to remove the peer from')
  parser.add_argument('--policy',
                      dest='policy',
                      help='(opt) The policy to remove the peer from')

#
# Add the params for the vpninfo command
#
# param
#   subparsers - the subparsers list to add this command to
#
# return N/A
#
def vpninfo_load(subparsers):
  parser = subparsers.add_parser("vpninfo",
                                 help="Returns info about a active vpns")
  parser.set_defaults(func=vpninfo)
  commonflag(parser)

#
# Add the params for the webgui command
#
# param
#   subparsers - the subparsers list to add this command to
#
# return N/A
#
def webgui_load(subparsers):
  parser = subparsers.add_parser("webgui",
                                 help="Launches a browser set to the webgui")
  parser.set_defaults(func=webgui)
  commonflag(parser)

#
# Add the params for the loglevel command
#
# param
#   subparsers - the subparsers list to add this command to
#
# return N/A
#
def loglevel_load(subparsers):
  parser = subparsers.add_parser("loglevel",
                                 help="Gets or sets the log level")
  parser.add_argument('--level',
                      dest='level',
                      help='(opt) The level to set')
  parser.set_defaults(func=loglevel)
  commonflag(parser)

#
# Add the params for the settings command
#
# param
#   subparsers - the subparsers list to add this command to
#
# return N/A
#
def settings_load(mainsubparsers):
  parser = mainsubparsers.add_parser("settings",
                                 help="various settings")
  subparsers = parser.add_subparsers(dest='settings_subs')
  settings_reservedip_load(subparsers)

#
# Add the params for the settings reservedip command
#
# param
#   subparsers - the subparsers list to add this command to
#
# return N/A
#
def settings_reservedip_load(mainsubparsers):
  parser = mainsubparsers.add_parser("reservedip",
                                 help="Gets/Adds/Deletes reserved ip addresses")
  subparsers = parser.add_subparsers(dest='settings_reservedip_subs')
  settings_reservedip_get_load(subparsers)
  settings_reservedip_add_load(subparsers)
  settings_reservedip_del_load(subparsers)

#
# Add the params for the grouplog get sub command
#
# param
#   subparsers - the subparsers list to add this command to
#
# return N/A
#
def settings_reservedip_get_load(subparsers):
  parser = subparsers.add_parser("get",
                                 help="Gets a list of reserved ip blocks")
  parser.set_defaults(func=settings_reservedip_get)
  commonflag(parser)

#
# Add the params for the grouplog get sub command
#
# param
#   subparsers - the subparsers list to add this command to
#
# return N/A
#
def settings_reservedip_add_load(subparsers):
  parser = subparsers.add_parser("add",
                                 help="Adds a reserved ip block")
  parser.set_defaults(func=settings_reservedip_add)
  parser.add_argument('--ip',
                      dest='ip',
                      required=True,
                      help="The ip the block uses")
  parser.add_argument('--mask',
                      dest='mask',
                      required=True,
                      help="The netmask of the block")
  commonflag(parser)

#
# Add the params for the grouplog get sub command
#
# param
#   subparsers - the subparsers list to add this command to
#
# return N/A
#
def settings_reservedip_del_load(subparsers):
  parser = subparsers.add_parser("del",
                                 help="Removes a reserved ip block")
  parser.set_defaults(func=settings_reservedip_del)
  parser.add_argument('--ip',
                      dest='ip',
                      required=True,
                      help="The ip the block uses")
  parser.add_argument('--mask',
                      dest='mask',
                      required=True,
                      help="The netmask of the block")
  commonflag(parser)

#
# Add the params for the grouplog get sub command
#
# param
#   subparsers - the subparsers list to add this command to
#
# return N/A
#
def grouplog_get_load(subparsers):
  parser = subparsers.add_parser("get",
                                 help="Gets a list of group logs and their state")
  parser.set_defaults(func=grouplog_get)
  commonflag(parser)

#
# Add the params for the grouplog set sub command
#
# param
#   subparsers - the subparsers list to add this command to
#
# return N/A
#
def grouplog_set_load(subparsers):
  parser = subparsers.add_parser("set",
                                 help="Sets the group logging to a new state")
  parser.set_defaults(func=grouplog_set)
  commonflag(parser)
  parser.add_argument('--group',
                      dest='group',
                      required=True,
                      help="The group name or id to set")
  parser.add_argument('--state',
                      dest='state',
                      required=True,
                      help="The state to set the group logging (off,track,full)")

#
# Add the params for the chat command
#
# param
#   subparsers - the subparsers list to add this command to
#
# return N/A
#
def chat_load(subparsers):
  parser = subparsers.add_parser("chat",
                                 help="Sends a chat to a user")
  parser.set_defaults(func=chat)
  commonflag(parser)
  parser.add_argument('--peer',
                      dest='peer',
                      required=True,
                      help="The peer to send the chat to")
  parser.add_argument('--msg',
                      dest='msg',
                      required=True,
                      help="The message to send")

#
# Add the params for the getchats command
#
# param
#   subparsers - the subparsers list to add this command to
#
# return N/A
#
def getchats_load(subparsers):
  parser = subparsers.add_parser("getchats",
                                 help="Gets pending chat messages")
  parser.set_defaults(func=getchats)
  commonflag(parser)
  parser.add_argument('--lastid',
                      dest='lastid',
                      help="The id of the last chat already read")
  parser.add_argument('--acct',
                      dest='account',
                      help="The account from which to read chats")
  parser.add_argument('--peer',
                      dest='peer',
                      help="The peer authorig the chats")
  parser.add_argument('--timeout',
                      dest='timeout',
                      help="how long to wait for the next chat (default is 3 seconds)")

def linuxonly(args):
  print("Command only works on linux")

#
# Add the params for the testmode command
#
# param
#   subparsers - the subparsers list to add this command to
#
# return N/A
#
def testmode_load(mainsubparsers):
  if isLinux():
    parser = mainsubparsers.add_parser("testmode",
                                 help="testmode settings to force relay/tcp modes")
    subparsers = parser.add_subparsers(dest='testmode_subs')
    testmode_relay_load(subparsers)
    testmode_tcponly_load(subparsers)
    testmode_udponly_load(subparsers)
    testmode_normal_load(subparsers)
    testmode_udpmtu_load(subparsers)
  else:
    parser = mainsubparsers.add_parser("testmode",
                                        help="testmode settings to force relay/tcp modes - linux only")
    parser.set_defaults(func=linuxonly)

#
# Add the params for the testmode relay sub command
#
# param
#   mainsubparsers - the mainsubparsers list to add this command to
#
# return N/A
#
def testmode_relay_load(subparsers):
  parser = subparsers.add_parser("relay",
                                 help="Sets the system to force the use of a relay")
  parser.set_defaults(func=testmode_relay)

#
# Add the params for the testmode tcponly sub command
#
# param
#   mainsubparsers - the mainsubparsers list to add this command to
#
# return N/A
#
def testmode_tcponly_load(subparsers):
  parser = subparsers.add_parser("tcponly",
                                 help="Sets the system to force the use of tcp only vpns, ie block udp vpns")
  parser.set_defaults(func=testmode_tcponly)

#
# Add the params for the testmode udponly sub command
#
# param
#   mainsubparsers - the mainsubparsers list to add this command to
#
# return N/A
#
def testmode_udponly_load(subparsers):
  parser = subparsers.add_parser("udponly",
                                 help="Sets the system to force the use of udp only vpns, ie block tcp vpns")
  parser.set_defaults(func=testmode_udponly)

#
# Add the params for the testmode normal sub command
#
# param
#   mainsubparsers - the mainsubparsers list to add this command to
#
# return N/A
#
def testmode_normal_load(subparsers):
  parser = subparsers.add_parser("normal",
                                 help="Sets the system back to normal mode for vpns")
  parser.set_defaults(func=testmode_normal)

#
# Add the params for the testmode udpmtu sub command
#
# param
#   mainsubparsers - the mainsubparsers list to add this command to
#
# return N/A
#
def testmode_udpmtu_load(subparsers):
  parser = subparsers.add_parser("udpmtu",
                                 help="Sets the system to drop udp over a given MTU for vpns")
  parser.set_defaults(func=testmode_udpmtu)
  parser.add_argument('--start',
                      dest='start',
                      default=1400,
                      help="The start of the MTU size to reject")
  parser.add_argument('--end',
                      dest='end',
                      default=1500,
                      help="The end of the MTU size to reject")

#def autochat_load(subparsers):
#  parser = subparsers.add_parser("autochat",
#                                 help="Sends auto responses to chats")
#  parser.set_defaults(func=autochat)
#  parser.add_argument('--regex',
#                      dest='regex',
#                      help="Regex command file to use")

#
# Add the params for the account deldevice sub command
#
# param
#   subparsers - the subparsers list to add this command to
#
# return N/A
#
def account_deldevice_load(subparsers):
  parser = subparsers.add_parser("deldevice",
                                 help="Removes a device")
  parser.set_defaults(func=account_deldevice)
  commonflag(parser)
  parser.add_argument('--device',
                      dest='device',
                      required=True,
                      help="The device to delete")
  parser.add_argument('--acct',
                      dest='account',
                      help='(opt) The account to remove the device from')

####################################################
#
# END Param handling
#
####################################################

#
# main function that is called at startup
#
# param
#   None
#
# return N/A
#
def main():
  parser = argparse.ArgumentParser(description='The command line api for GabrielService web interface')
  subparsers = parser.add_subparsers(dest='sub_name')
  fullhelp_load(subparsers)
  domainuser_load(subparsers)
  group_load(subparsers)
  peer_request_load(subparsers)
  peer_load(subparsers)
  localservice_load(subparsers)
  account_load(subparsers)
  grouplog_load(subparsers)
  vpninfo_load(subparsers)
  webgui_load(subparsers)
  loglevel_load(subparsers)
  settings_load(subparsers)
  if path.exists("/usr/local/bin/GabrielService") or path.exists("/Applications/Gabriel.app"):
    chat_load(subparsers)
    getchats_load(subparsers)
  if isDeveloper():
    testmode_load(subparsers)
  try:
    args = parser.parse_args()
  except Exception as ex:
    print("Parser caught " + str(ex))
    return
  if hasattr(args, 'curl') and args.curl:
    global curlflag
    curlflag=True
  if hasattr(args, 'noretry') and args.noretry:
    global noRetryFlag
    noRetryFlag=True
  if hasattr(args, 'func'):
    #print("xxxx Args Has func")
    args.func(args)
  else:
    wikiFlag=True
    if not hasattr(args, 'wiki') or not args.wiki:
      wikiFlag=False
    if not hasattr(args, 'dohelp') or not args.dohelp:
      return 1
    fullhelp(parser, 0, wikiFlag)
#    for i in parser._actions:
#      if isinstance(i, argparse._SubParsersAction):
#        for name, subcmd in i.choices.items():
#          print(subcmd)
#          for j in subcmd._actions:
#            if isinstance(i, argparse._SubParsersAction):
#              print(j)
#          help = ""
#          for actions in i._choices_actions:
#             if actions.dest == name:
#               help = actions.help
#          if wikiFlag:
#            print("= " + name + " : " + help + "=")
#            print("<pre>")
#          else:
#            print("\n--------------------------------------\n")
#            print(name + " : " + help)
#            print("\n")
#          print(subcmd.format_help())
#          if wikiFlag:
#            print("</pre>")
  return



####################################################
#
# BEGIN Function implementation
#
####################################################

#
# Prints all of the help 
#
# param
#   parser - the param list parser
#   level - when printing how many levels do we print
#   wikiFlag - should we print in the wiki format
#   prefixname - optional prefix to add to each print
#
# return N/A
#
def fullhelp(parser, level, wikiFlag, prefixname=""):
  for i in parser._actions:
    if isinstance(i, argparse._SubParsersAction):
      for name, subcmd in i.choices.items():
        help = ""
        for actions in i._choices_actions:
           if actions.dest == name:
             help = actions.help
        if wikiFlag:
          wikiPrefix="="
          for x in range(level):
            wikiPrefix += "="
          print(wikiPrefix + " " + prefixname + name + " : " + help + " " + wikiPrefix)
          print("<pre>")
        else:
          print("\n" + "--------------------------------------\n")
          print(prefixname + name + " : " + help)
          print("\n")
        print(subcmd.format_help())
        if wikiFlag:
          print("</pre>")
        fullhelp(subcmd, level+1, wikiFlag, prefixname + name + " ")

#
# Gets the ini file name for Gabriel.
#   If you have permissions you can get the name of it in a diff dir
#   /home is what most unix distros use
#   /Users is a dir that MacOS uses as well as some BSD variants
#
# param
#   N/A
#
# return The name of the ini file
#
def get_ini_filename():
  filearray=glob.glob('/Users/*/.gabriel/HKCU_registry.ini')
  if len(filearray) > 0:
    filename = filearray[0];
  else:
    filearray=glob.glob('/home/*/.gabriel/HKCU_registry.ini')
    if len(filearray) > 0:
      filename = filearray[0];
    else:
      filename=os.path.expanduser("~/.gabriel/HKCU_registry.ini")
  if filename == None or filename == "":
    raise Exception("Can't find HKCU_registry.ini")
  return filename

#
# Gets the token to allow web access to Gabriel
#
# param
#   tokenname - The string to replace WebToken with
#
# return String with the WebToken
#
def get_token(tokenname):
  filename=get_ini_filename()
  if not os.path.isfile(filename):
    raise Exception("Can't find " + filename)
  token=""
  for line in open(filename, 'r'):
    if re.search("^\s*WebToken=", line):
      token=line.replace("WebToken",tokenname).strip()
  if token == "":
    print("Could not find WebToken in " + filename)
    exit()
  return token

#
# Finds out if vtun is set
#
# param
#   N/A
#
# return True if vtun is set
#
def isVtun():
  filename=get_ini_filename()
  if not os.path.isfile(filename):
    raise Exception("Can't find " + filename)
  for line in open(filename, 'r'):
    if re.search("^\s*UseVirtualAdapter=\s*1", line):
      return True
  return False  

#
# Finds out if developer is set
#
# param
#   N/A
#
# return True if developer flag is set
#
def isDeveloper():
  filename=get_ini_filename()
  if not os.path.isfile(filename):
    return False
  for line in open(filename, 'r'):
    if re.search("^\s*Developer=\s*1", line):
      return True
  return False

#
# Finds out if this is a linux box
#
# param
#   N/A
#
# return True if this is on linux
#
def isLinux():
  return re.search("^\s*linux", sys.platform)
  #return True

#
# Gets the web url for a given command
#
# param
#   cmd - The command that you want to run
#
# return the url with the command
#
def get_authed(cmd):
  token=get_token("token")
  handler="gabriel"
  return "localhost:7780/" + handler + "?" + token + "&m=" + cmd

#
# Runs curl for a given command
#
# param
#   cmd - The command to run
#   argvec - a list of args to add to the command
#
# return A string with the web response
#
def curl_cmd(cmd, *argvec):
  output=""
  retrycount=5
  global noRetryFlag
  while output=="":
    args=""
    for arg in argvec:
      name,value = arg.split("=", 1)
      args+="&" + name + "=" + quote(value)
    curlcmd = "curl -s -e http://localhost '" + get_authed(cmd) + args + "'"
    if curlflag:
      print(curlcmd)
    output=os.popen(curlcmd).read()
    if noRetryFlag or retrycount==0:
      return output
    retrycount -= 1
    if output == "":
      print("Curl command failed to connect to Gabriel, will retry " + str(retrycount) + " more times")
      time.sleep(5)
  return output

#
# Gets an array of the accounts from Gabriel
#   Utility function
#
# param
#   N/A
#
# return array of accounts
#
def get_acct_array():
  output = curl_cmd("GETACCOUNTS")
  try:
    accts_json = json.loads(output)
    if "accounts" not in accts_json:
      print("GETACCOUNTS did not return successfully")
      exit()
    return accts_json["accounts"]
  except:
    if (output == ""):
      print("JSON response from GETACCOUNTS was empty")
    else:
      print(output)
      print("Could not parse reply from GETACCOUNTS")

#
# Show a list of accounts
#
# param
#   args.json - flag indicating output should be in json vs human readable
#
# return N/A
#
def account_list(args):
  output = curl_cmd("GETACCOUNTS")
  try:
    accts_json = json.loads(output)
    if "accounts" not in accts_json:
      print("GETACCOUNTS did not return successfully")
      exit()
    if args.json:
      print(json.dumps(accts_json["accounts"], indent=2));
    else:
      for acct in accts_json["accounts"]:
        print(acct)
  except:
    if (output == ""):
      print("JSON response from GETACCOUNTS was empty")
    else:
      print(output)
      print("json.loads had an exception")

#
# Show a list of devices for a given peer
#
# param
#   args.json - flag indicating output should be in json vs human readable
#
# return json string for the GETDEVICES with the peer
#
def showdevicesforpeer(args, peer):
  activeact = account_getactive()
  output = curl_cmd("GETDEVICES","name=" + peer)
  try:
    devices_json = json.loads(output)
    if "name" not in devices_json:
      print("GETDEVICES did not return successfully")
      exit()
    if not args.json:
      #print(output)
      if "localDevice" in devices_json:
        item=devices_json["localDevice"];
        print(activeact + " -> " + peer + " -> " + item["name"] + " : " + item["presence"] + ", " + item["deviceType"])
      #if "defaultServer" in devices_json:
      #  print(activeact + " -> " + peer + " -> " + devices_json["defaultServer"] + " (Default Server)")
      if "servers" not in devices_json:
        print(activeact + " -> " + peer + "-- no servers found")
      else:
        hasserver=False
        for item in devices_json["servers"]:
          hasserver=True
          label = "server"
          if "defaultServer" in devices_json and (item["name"] == devices_json["defaultServer"] or (item["name"] == (devices_json["defaultServer"]+"."+peer))):
            label = "Default server"
          print(activeact + " -> " + peer + " -> " + item["name"] + " (" + label + ") : " + item["presence"] + ", " + item["deviceType"])
      if "devices" not in devices_json:
        print(activeact + " -> " + peer + "-- no devices found")
      else:
        hasdevice=False
        for item in devices_json["devices"]:
          hasdevice=True
          print(activeact + " -> " + peer + " -> " + item["name"] + " : " + item["presence"] + ", " + item["deviceType"])
    return output;
    postact=account_getactive()
    if postact != activeact:
      print("started with " + activeact + " ended with " + postact);
  except:
    if (output == ""):
      print("JSON response from GETDEVICES was empty")
    else:
      print(output)
      print("JSON parsing failed on return from GETDEVICES")

#
# Show a list of servers for a given peer
#
# param
#   args.json - flag indicating output should be in json vs human readable
#
# return json string for the GETDEVICES with the peer
#
def showserversforpeer(args, peer):
  activeact = account_getactive()
  output = curl_cmd("GETDEVICES","name=" + peer)
  try:
    devices_json = json.loads(output)
    if "name" not in devices_json:
      print("GETDEVICES did not return successfully")
      exit()
    if not args.json:
      #print(output)
      if "servers" not in devices_json:
        print(activeact + " -> " + peer + "-- no servers found")
      else:
        hasdevice=False
        for item in devices_json["servers"]:
          hasdevice=True
          print(activeact + " -> " + peer + " -> " + item["name"])
    return output;
  except:
    if (output == ""):
      print("JSON response from GETDEVICES was empty")
    else:
      print(output)
      print("JSON parsing failed on return from GETDEVICES")

#
# Show the devices for a given peer
#
# param
#   args.json - Flag indicating output should be in json vs human readable
#   args.setactive - Sets the active user to this user
#
# return N/A
#
def peer_showdevices(args):
  if "setactive" in args and args.setactive != None:
    activeact = args.setactive
    _account_setactive(args.setactive)
  else:
    activeact = account_getactive()
  retJson='{"peerdevices":['
  firstrun=True
  output = curl_cmd("GETPEERS")
  try:
    peers_json = json.loads(output)
    if "peers" not in peers_json:
      print("GETPEERS did not return successfully")
      exit()
    for item in peers_json["peers"]:
      if args.json:
        if firstrun:
          firstrun=False
        else:
          retJson += ","
        retJson += '{"peer" : "' + item["name"] + '",'
        retJson += '"devices" : '
      retJson+=showdevicesforpeer(args, item["name"])
      retJson+="}"
    if args.json:
      retJson+="]}"
      print(retJson)
#      try:
#        jsonOut = json.loads(retJson)
#        print("validated")
#      except:
#        print("json output validate failed")
    postact = account_getactive()
    if activeact != account_getactive():
      print("WARNING - Active account missmatch " + activeact + " " + postact)
  except:
    if (output == ""):
      print("JSON response for GETPEERS was empty")
    else:
      print(output)
      print("JSON parsing of GETPEERS reply failed")


def peer_serverclients(args):
  retJson='{"serverclients":['
  firstrun=True
  for acct in get_acct_array():
    output = curl_cmd("GETPEERS","account=" + acct)
    try:
      peers_json = json.loads(output)
      if "peers" not in peers_json:
        print("GETPEERS did not return successfully")
        exit()
      if args.json:
        if firstrun:
          firstrun=False
        else:
          retJson += ","
        retJson+=output
      else:
        for item in peers_json["serverclients"]:
          print(acct + " -> " + item)
    except:
      if (output == ""):
        print("JSON reply from GETPEERS was empty")
      else:
        print(output)
        print("JSON parsing of reply from GETPEERS failed")
      return
  if args.json:
    retJson+="]}"
    print(retJson)
#    try:
#      jsonOut = json.loads(retJson)
#      print("validated")
#    except:
#      print("json output validate failed")

#
# Show the servers for peers
#
# param
#   args.json - Flag indicating output should be in json vs human readable
#   args.setactive - Sets the active user to this user
#
# return N/A
#
def peer_servers(args):
  if "setactive" in args and args.setactive != None:
    activeact = args.setactive
    _account_setactive(args.setactive)
  else:
    activeact = account_getactive()
  retJson='{"peerdevices":['
  firstrun=True
  output = curl_cmd("GETPEERS")
  try:
    peers_json = json.loads(output)
    if "peers" not in peers_json:
      print("GETPEERS did not return successfully")
      exit()
#    if args.json:
#      retJson+=output
    for item in peers_json["peers"]:
      if args.json:
        if firstrun:
          firstrun=False
        else:
          retJson += ","
        retJson += '{"peer" : "' + item["name"] + '",'
        retJson += '"devices" : '
      retJson+=showserversforpeer(args, item["name"])
      retJson+="}"
    if args.json:
      retJson+="]}"
      print(retJson)
#      try:
#        jsonOut = json.loads(retJson)
#        print("validated")
#      except:
#        print("json output validate failed")
    postact = account_getactive()
    if activeact != account_getactive():
      print("WARNING - Active account missmatch " + activeact + " " + postact)
  except:
    if (output == ""):
      print("JSON response for GETPEERS was empty")
    else:
      print(output)
      print("JSON parsing of GETPEERS reply failed")

#
# Shows the devices for a given acct
#
# param
#   args.json - Flag indicating output should be in json vs human readable
#
# return json output from the GETDEVICES call
#
def showdevicesforlocaldevice(args, acct):
  output = curl_cmd("GETDEVICES","account=" + acct)
  try:
    devices_json = json.loads(output)
    if "name" not in devices_json:
      print("GETDEVICES did not return successfully")
      exit()
    if not args.json:
      #print(output)
      if "localDevice" in devices_json:
        item=devices_json["localDevice"];
        print(acct + " -> " + item["name"] + " : " + item["presence"] + ", " + item["deviceType"])
      if "devices" not in devices_json:
        print(acct + "-- no devices found")
      else:
        hasdevice=False
        for item in devices_json["devices"]:
          hasdevice=True
          print(acct + " -> " + item["name"] + " : " + item["presence"] + ", " + item["deviceType"])
        if not hasdevice:
          print(acct + "-- no devices found")
  except:
    if (output == ""):
      print("JSON reply from GETDEVICES was empty")
    else:
      print(output)
      print("JSON parsing of reply from GETDEVICES failed")
  return output;
 
#
# Shows the devices for all the accounts
#
# param
#   args.json - Flag indicating output should be in json vs human readable
#
# return N/A
#
def account_showdevices(args):
  retJson='{"accounts":['
  firstrun=True
  for acct in get_acct_array():
    if firstrun:
      firstrun=False
    else:
      retJson += ","
    retJson += showdevicesforlocaldevice(args, acct);
  retJson+="]}"
  if args.json:
    print(retJson)
#    try:
#      jsonOut = json.loads(retJson)
#      print("validated")
#    except:
#      print("json output validate failed")

#
# Gets a list of peers
#
# param
#   args.json - Flag indicating output should be in json vs human readable
#
# return N/A
#
def peer_list(args):
  retJson = '{"peers":['
  firstrun=True
  for acct in get_acct_array():
    output = curl_cmd("GETPEERS","account=" + acct)
    try:
      peers_json = json.loads(output)
      if "peers" not in peers_json:
        print("GETPEERS did not return successfully")
        exit()
      if args.json:
        if firstrun:
          firstrun=False
        else:
          retJson += ","
        retJson+=output
      else:
        for item in peers_json["peers"]:
          print(acct + " -> " + item["name"])
    except:
      if (output == ""):
        print("JSON reply from GETPEERS was empty")
      else:
        print(output)
        print("JSON parsing of reply from GETPEERS failed")
      return
  if args.json:
    retJson+="]}"
    print(retJson)
#    try:
#      jsonOut = json.loads(retJson)
#      print("validated")
#    except:
#      print("json output validate failed")


#
# Print the join requests for each device
#
# param
#   args.json - Flag indicating output should be in json vs human readable
#
# return N/A
#
def peer_request_list(args):
  active=account_getactive()
  retJson=""
  for acct in get_acct_array():
    _account_setactive(acct)
    output = curl_cmd("GETJOINREQUESTS","account=" + acct)
    try:
      peers_json = json.loads(output)
      peers_json['account']=acct;
      if args.json:
        if retJson=="":
          retJson='{"requests":['
        else:
          retJson+=","
          retJson+=json.dumps(peers_json, indent=2)
      else:
        for item in peers_json["outgoing"]:
          print(acct + " -> " + item["name"] + " " + item["time"])
        for item in peers_json["incoming"]:
          print(acct + " <- " + item["name"] + " " + item["time"])
    except:
      if (output == ""):
        print("JSON return from GETJOINREQUESTS was empty")
      else:
        print(output)
        print("Unable to parse JSON output from GETJOINREQUESTS")
  if args.json:
    if retJson!="":
      retJson+="]}"
    tempjson=json.loads(retJson);
    print(json.dumps(tempjson, indent=2))
  _account_setactive(active)

#
# Gets the active account
#
# param
#   args - if non null prints the active account
#
# return the string with the active account in it
#
def account_getactive(args=None):
  output=curl_cmd("GETACCOUNTS")
  try:
    peers_json=json.loads(output)
    if "activeAccount" in peers_json:
      if args != None:
        print(peers_json["activeAccount"])
      return peers_json["activeAccount"]
  except:
    print(output)
    print("Unable to parse JSON output from GETACCOUNTS")
  print("account_getactive failed")
  exit()

#
# Utility function to set the active account
#
# param
#   name - the name of the account to set active
#
# return N/A
#
def _account_setactive(name):
  output=curl_cmd("SETACCOUNT","name="+name)

#
# Method called by parser function to set the acctive account
#
# param
#   args.account - The user to set as the active account
#
# return N/A
#
def account_setactive(args):
  return _account_setactive(args.account)

#
# Show the devices for a given peer
#
# param
#   args.user - The peer to add
#   args.account - (Opt) the account to add the peer to
#
# return N/A
#
def peer_add(args):
  if "account" in args and args.account != None:
    output=curl_cmd("INVITEPEER","peer="+args.user, "account="+args.account)
  else:
    output=curl_cmd("INVITEPEER","peer="+args.user)
  print(output)

#
# Utility function to send a message to a peer
#
# param
#   msg - Message to send
#   peer - peer to send the message to
#
# return N/A
#
def _chat(msg, peer):
  if peer.isdigit():
    target="threadId="+peer
  elif peer.count(".") > 2:
    target="peer="+quote(peer)
  else:
    target="peer=*."+quote(peer)
  print(target)
  output=curl_cmd("SENDMSG",target,"message="+msg)

#
# Allows calling of chat from parser method
#
# param
#   args.msg - The message to send
#   args.peer - The peer to send the message to
#
# return N/A
#
def chat(args):
  _chat(args.msg, args.peer)

#
# Gets the chat messages
#
# param
#   args.account - The account to get the chats from
#   args.lastid - (opt) The id of the last chat we care about
#   args.timeout - (opt) The timeout to use in waiting for the chats
#
# return N/A
#
def getchats(args):
  #lastid, timeout
  lastid=str(0)
  timeout=str(3)
  currentaccount = account_getactive()
  if "account" in args and args.account != None:
    account = args.account
    _account_setactive(account)
  else:
    account = currentaccount

  if "lastid" in args and args.lastid != None and args.lastid != '':
    lastid=args.lastid
  if "timeout" in args and args.timeout != None:
    timeout=args.timeout
  output=curl_cmd("GETCONVERSATIONS", "lastid=0", "timeout="+timeout)
  if args.json:
    print(output)
  else:
    jsonout = json.loads(output)
    newlastid = 0;
    if not "peers" in jsonout:
      print("No chats found")
      return
    for peer in jsonout["peers"]:
      if "name" in peer:
        name=re.sub("^\*.", "", peer["name"])
        #print(name)
        if not "convo" in peer:
          continue
        for convo in peer["convo"]:
          newlastid = max(newlastid, convo["id"])
          authorOk = ("peer" in args and args.peer != None and name == args.peer)
          authorOk = authorOk or (("peer" not in args or args.peer == None) and convo["author"] != currentaccount)
          if convo["id"] > int(lastid) and authorOk:
            message=convo["message"]
            message = message.replace("\n","\\n")
            message = message.replace("\r","\\r")
            message = message.replace("\t","\\t")
            line=name + "\t" + str(convo["id"]) + "\t" + convo["author"] + "\t" + message
            print(line)
    print(newlastid)
  if currentaccount != account:
    _account_setactive(currentaccount)

#
# Function to set relay testmode
#
# param
#
# return N/A
#
def testmode_relay(args):
  # we are going to block inbound xxx
  testmode_normal(args)
  p = Popen("sudo iptables -w -I INPUT -p udp --dport 7770 -j DROP -m comment --comment 'gabriel_cmd testmode'", shell=True, stdout=PIPE, stderr=PIPE)
  stdout, stderr = p.communicate()
  p = Popen("sudo iptables -w -I INPUT -p tcp --dport 7770 -j DROP -m comment --comment 'gabriel_cmd testmode'", shell=True, stdout=PIPE, stderr=PIPE)
  stdout, stderr = p.communicate()

#
# Function to set relay testmode
#
# param
#
# return N/A
#
def testmode_tcponly(args):
  # we need to remove outbound udp 
  testmode_normal(args)
  p = Popen("sudo iptables -w -I INPUT -p udp --dport 7770 -j DROP -m comment --comment 'gabriel_cmd testmode'", shell=True, stdout=PIPE, stderr=PIPE)
  stdout, stderr = p.communicate()

#
# Function to set relay testmode
#
# param
#
# return N/A
#
def testmode_udponly(args):
  testmode_normal(args)
  p = Popen("sudo iptables -w -I INPUT -p tcp --dport 7770 -j DROP -m comment --comment 'gabriel_cmd testmode'", shell=True, stdout=PIPE, stderr=PIPE)
  stdout, stderr = p.communicate()

#
# Function to set relay testmode
#
# param
#
# return N/A
#
def testmode_normal(args):
  try:
    p = Popen("sudo iptables-save | grep -v 'gabriel_cmd testmode' | sudo iptables-restore", shell=True, stdout=PIPE, stderr=PIPE)
    stdout, stderr = p.communicate()
    print(stdout.decode(encoding='UTF-8'))
  except Exception as e:
    print(e)
    print("nope") 
  #try:
  #  p = Popen("sudo iptables-save",shell=True, stdout=PIPE, stderr=PIPE)
  #  stdout, stderr = p.communicate()
  #  print(stdout.decode(encoding='UTF-8'))
  #except Exception as e:
  #  print(e)
  #  print("nope 2")
  
  #p = Popen("sudo iptables -w -D INPUT -p udp --dport 7770 -j DROP -m comment --comment 'gabriel_cmd testmode'", shell=True, stdout=PIPE, stderr=PIPE)
  #p = Popen("sudo iptables -w -D INPUT -p tcp --dport 7770 -j DROP -m comment --comment 'gabriel_cmd testmode'", shell=True, stdout=PIPE, stderr=PIPE)
  #stdout, stderr = p.communicate()
  #p = Popen("sudo iptables -w -D INPUT -p udp -m length --length 1400:1500 -j DROP -m comment --comment 'gabriel_cmd testmode'", shell=True, stdout=PIPE, stderr=PIPE)
  #stdout, stderr = p.communicate()

#
# Function to set relay testmode
#
# param
#
# return N/A
#
def testmode_udpmtu(args):
  try:
    testmode_normal(args)
  except Exception as e:
    print(e)
  
  cmd = "sudo iptables -w -I INPUT -p udp -m length --length " + str(args.start) + ":" + str(args.end) + " -j DROP -m comment --comment 'gabriel_cmd testmode'"
  p = Popen(cmd, shell=True, stdout=PIPE, stderr=PIPE)
  stdout, stderr = p.communicate()

#
# Function to setup autochats - TBD
#
# param
#   args.json - Flag indicating output should be in json vs human readable
#
# return json string for the GETDEVICES with the peer
#
def autochat(args):
  jsonValid=False 
  fullup=True
  while not jsonValid:
    try:
      output=curl_cmd("GETCONVERSATIONS", "lastid=0", "timeout=3")
      jsonout = json.loads(output)
      if fullup:
        jsonValid=True
      else:
        time.sleep(5)
        print("Got a valid response - wait for full up")
        fullup=True
    except:
      print("Can not get valid chats from Gabriel, is it running?")
      sys.stdout.flush()
      fullup=False
      time.sleep(3)
  firstrun=True
  lastid = 0;
  active = account_getactive()
  reply=re.compile(r'^test\b | ^respond\b | ^please\brespond\b', flags=re.I | re.X)
  while True:
    if not "peers" in jsonout:
      print("No chats found")
    else:
      newlast=lastid
      for peer in jsonout["peers"]:
        if "name" in peer:
          name=re.sub("^\*.", "", peer["name"])
          if not "convo" in peer:
            continue
          for convo in peer["convo"]:
            newlast = max(newlast, convo["id"])
            if convo["author"] != active:
              if reply.match(convo["message"]):
                if firstrun:
                   print(convo["message"])
                if not firstrun and convo["id"] > lastid:
                  print("Auto responding to '" + convo["message"] + "'")
                  print(name)
                  _chat("Auto responding to '" + convo["message"] + "'", name)
                  #print("**** " + convo["message"])
      lastid=newlast
      firstrun=False
    jsonValid=False
    while not jsonValid:
      time.sleep(3)
      try:
        output=curl_cmd("GETCONVERSATIONS", "lastid=0", "timeout=3")
        jsonout = json.loads(output)
        jsonValid=True
      except:
        print("json not valid - is Gabriel running?")
        sys.stdout.flush()

#
# Accept the peer request
#
# param
#   args.peer - The peer to accept the request from
#   args.account - (opt) the account to accept from
#
# return N/A
#
def peer_request_accept(args):
  account=""
  if "account" in args and args.account != None:
    account = args.account
  else:
    account = account_getactive()
  output=curl_cmd("INVITEACTION",
                  "action=ACCEPT",
                  "name="+args.peer,
                  "account="+account);

#
# Reject the peer request
#
# param
#   args.peer - The peer to reject the join request
#   args.account - (opt) The account to reject  from
#
# return N/A
#
def peer_request_reject(args):
  account=""
  if "account" in args and args.account != None:
    account = args.account
  else:
    account = account_getactive()
  output=curl_cmd("INVITEACTION",
                  "action=REJECT",
                  "name="+args.peer,
                  "account="+account);

#
# Activates an account
#
# param
#   args.isHidden - Flag indicating the device should be hidden
#   args.name - The full device name
#   args.password - the account password
#   args.json - Flag indicating the output should be the json output
#
# return N/A
#
def account_activate(args):
  isHidden="false"
  output=""
  if "isHidden" in args and args.isHidden != None:
    isHidden = args.isHidden
  if hasattr(args, 'password') and args.password != None and args.password != "":
    if hasattr(args, 'onetime') and args.onetime != None and args.onetime != "":
      output=curl_cmd("ACTIVATENAME",
                      "name="+args.name,
                      "pass="+args.password,
                      "isHidden="+isHidden,
                      "otp="+args.onetime)
    else:
      output=curl_cmd("ACTIVATENAME",
                      "name="+args.name,
                      "pass="+args.password,
                      "isHidden="+isHidden)
  elif hasattr(args, 'token') and args.token != None and args.token != "":
    if hasattr(args, 'onetime') and args.onetime != None and args.onetime != "":
      output=curl_cmd("ACTIVATENAME",
                      "name="+args.name,
                      "activationtoken="+args.token,
                      "isHidden="+isHidden,
                      "otp="+args.onetime)
    else:
      output=curl_cmd("ACTIVATENAME",
                      "name="+args.name,
                      "activationtoken="+args.token,
                      "isHidden="+isHidden)
  else:
    print("One of token or password must be defined\n")
    exit(1)
  if (output == ""):
    print("ACTIVATENAME failed")
    return
  if args.json:
    print(output)
  exitret=1
  try:
    jsonout = json.loads(output)
    if jsonout["error"] != "":
      isotp=0
      try:
        otpout = json.loads(jsonout["error"])
        #{"message":"prompt otp","channel":2,"prompt":""}
        if "message" in otpout:
          prompt="Enter the one time password"
          if "channel" in otpout:
            if otpout["channel"] == 2:
              prompt=prompt + " from your Gabriel device"
            elif otpout["channel"] == 1:
              prompt=prompt + " from your email"
          if hasattr(args, 'noprompt') and args.noprompt:
            print(prompt)
            exitret=0
          else:
            args.onetime = input(prompt+"\n")
            account_activate(args)
      except Exception as e:
        if not args.json:
          print(jsonout["error"].replace('<br>', '\n'))
        exitret=1
    else:
      if not args.json:
        print(jsonout["success"])
      exitret=0
  except Exception as e:
    #print("message parse caught " + str(e))
    print(output)
    print("json.loads threw an exception")
  exit(exitret)


#
# Gets the vpn status details
#
# param
#   args.json - Flag indicating output should be in json vs human readable
#
# return N/A
#
def vpninfo(args):
  output=curl_cmd("GETDEVICESTATUS")
  if args.json:
    print(output)
  else:
    jsonout = json.loads(output)
    for vpn in jsonout:
      if isinstance(vpn, dict) and "connectedAs" in vpn:
        print(vpn["connectedAs"] + " -> " + vpn["name"])
        print("\t" + vpn["connection"])
        print("\t" + vpn["uptime"] + " uptime")
        print("\t" + vpn["roundtrip"] + " roundtrip")
        print("\tDirect UDP: " + str(vpn["udpDirect"]))

#
# Utility function for - Gets the group log levels
#
# param
#   jsonflag - Flag indicating output should be in json vs human readable
#   showgroups - show group names instead of id
#
# return N/A
#
def _grouplog_get(jsonflag, showgroups):
  output=curl_cmd("GETSYSTEMSTATUS")
  if jsonflag:
    print(output)
  else:
    jsonout = json.loads(output)
    if "groupLogging" not in jsonout:
      print("Error SYSTEMSTATUS cant find groupLogging")
    for group in jsonout["groupLogging"]:
      if isinstance(group, dict) and "name" in group:
        id_to_name = {
          0:"Off",
          1:"Track Message",
          2:"Full Content"
        }
        logstate=id_to_name.get(group["state"], "Unknown")
        if showgroups:
          print(str(group["id"]) + "\t" + group["name"] + "(" + logstate + ")")
        else:
          print(group["name"] + "(" + str(group["id"]) + ")\t" + logstate)

#
# Gets the group log levels
#
# param
#   args.json - Flag indicating output should be in json vs human readable
#
# return N/A
#
def grouplog_get(args):
  _grouplog_get(args.json, False)


def grouplog_name_to_id(groupname):
  lowergroup=groupname.lower()
  output=curl_cmd("GETSYSTEMSTATUS")
  jsonout = json.loads(output)
  if "groupLogging" not in jsonout:
    print("Error SYSTEMSTATUS cant find groupLogging")
  for group in jsonout["groupLogging"]:
    if isinstance(group, dict) and "name" in group:
      if group["name"].lower() == lowergroup:
        return int(group["id"])
  return -1

#
# Sets the group log level
#
# param
#   args.json - Flag indicating output should be in json vs human readable
#   args.group - (opt) id of the group 
#   args.state - (opt) state 0,1,2 or "off","track","full"
#
# return N/A
#
def grouplog_set(args):
  group=-1
  state=-1
  if "group" in args and args.group != None:
    if isInt(args.group) and int(args.group) >= 0:
      group = int(args.group)
    else:
      group = grouplog_name_to_id(args.group)
  if "state" in args and args.state != None:
    if isInt(args.state):
      state = int(args.state)
      if (state < 0 or state > 3):
        print("state issue")
        state = -1
    else:
      state_to_id = {
        "off":0,
        "track":1,
        "full":2
      }
      state=state_to_id.get(args.state, -1);
  if (state == -1):
    print("State " + args.state + " not recognized")
    return
  if (group == -1):
    print("Group " + args.group + " not recognized")
    return
  curl_cmd("ENABLEMESSAGELOG","groupId=" + str(group),"state=" + str(state))
  if not args.json:
    print("\nCurrent state of message logging:")
  _grouplog_get(args.json, False)
  

#
# Deletes a device
#
# param
#   args.json - Flag indicating output should be in json vs human readable
#   args.account - account to delete the device from
#   args.device - device to delete
#
# return N/A
#
def account_deldevice(args):
  account=""
  if "account" in args and args.account != None:
    account = args.account
  else:
    account = account_getactive()
  #print(account)
  output=curl_cmd("DEVICEACTION","action=DELETE","name="+args.device, "account="+account)
  #print(output)

#
# Deletes a peer
#
# param
#   args.json - Flag indicating output should be in json vs human readable
#   args.account - Sets the active user to this user
#   args.policy - (opt) The policy to use
#   args.user - The name of the peer to delete
#
# return N/A
#
def peer_del(args):
  account=""
  currentaccount = account_getactive()
  if "account" in args and args.account != None:
    account = args.account
    _account_setactive(account)
  else:
    account = currentaccount
  policy='default'
  if "policy" in args and args.policy != None:
    policy = args.policy
  output=curl_cmd("REMOVEPEER", "peer=*." + args.user)
  output=curl_cmd("EDITPEERPOLICY",
                  "type=DELETE",
                  "name="+args.user,
                  "account="+account,
                  "policy="+policy)
  if currentaccount != account:
    _account_setactive(currentaccount)
  #note that the output does not reflect the action having been done yet...
  #The web api is setup for the gui's async approach
  #print(output)

#
# Adds a domain user
#
# param
#   args.adminuser - The admin user account
#   args.adminpass - The admin user password
#   args.user - The user to create
#   args.domain - The domain to add the user to
#   args.password - The password for the user
#   args.first - The first name of the user
#   args.last - The last name of the user
#   args.email - The email address of the user
#
# return N/A
#
def domainuser_add(args):
  curlcmd  = "curl -s -X POST -d "
  curlcmd += "'adminuser=" + args.adminuser
  curlcmd += "&adminpass=" + args.adminpass
  curlcmd += "&username=" + args.user+ "." + args.domain
  curlcmd += "&password=" + args.password
  curlcmd += "&first=" + args.first
  curlcmd += "&last=" + args.last
  curlcmd += "&email=" + args.email + "' "
  curlcmd += "'https://www.virnetx.net/api/v1/domains/"
  curlcmd += args.domain
  curlcmd += "/users'"
  print(curlcmd)
  print(os.popen(curlcmd).read())

#
# Deletes a domain user
#
# param
#   args.adminuser - The admin user account
#   args.adminpass - The admin user password
#   args.user - The user to create
#   args.domain - The domain to add the user to
#
# return N/A
#
def domainuser_del(args):
  curlcmd  = "curl -s -X POST -d "
  curlcmd += "'adminuser=" + args.adminuser
  curlcmd += "&adminpass=" + args.adminpass
  curlcmd += "&username=" + args.user + "." + args.domain + "'"
  curlcmd += " 'https://www.virnetx.net/api/v1/domains/"
  curlcmd += args.domain
  curlcmd += "/users/delete'"
  print(curlcmd)
  print(os.popen(curlcmd).read())


#
# Adds a domain user
#
# param
#   acct - The admin user account
#   output - The admin user password
#   jsonflag - Flag indicating if output should be in json
#
# return json output string
#
def _printgroups(acct, output, jsonflag):
  if jsonflag:
    return output
  peers_json = json.loads(output)
  if "groups" not in peers_json:
    print("GETPEERS did not return successfully\n")
    exit()
  try:
    for item in peers_json["groups"]:
      grouparr=item["name"].split("|")
      if len(grouparr) > 1:
        print(acct + " -> " + grouparr[1] + " (local)")
      else:
        print(acct + " -> " + item["name"])
  except Exception as e:
    print("caught " + str(e))
  return output

#
# Adds a group
#
# param
#   args.group - The group to add
#   args.json - Flag indicating if the output is in json
#
# return N/A
#
def group_add(args):
  groupname=getfullgroupname(args.group)
  if groupname != "":
    print("Group: " + args.group + " already found")
    return
  output = curl_cmd("EDITGROUP","type=ADD", "name="+args.group, "peerGroup=1")
  acct = account_getactive()
  _printgroups(acct, output, args.json)

#
# Delete a group
#
# param
#   args.group - The group to delete
#   args.json - Flag indicating the output should be a json string
#
# return N/A
#
def group_del(args):
  groupname=getfullgroupname(args.group)
  if groupname == "":
    print("Group: " + args.group + " not found")
    return
  output = curl_cmd("EDITGROUP","type=DELETE", "name="+groupname)
  acct = account_getactive()
  _printgroups(acct, output, args.json)

#
# Lists the groups
#
# param
#   args.json - Flag indicating the output should be a json string
#
# return N/A
#
def group_list(args):
  retJson = '{"peers":['
  firstrun=True
  for acct in get_acct_array():
    output = curl_cmd("GETPEERS","account=" + acct)
    if firstrun:
      firstrun=False
    else:
      retJson += ","
    retJson += _printgroups(acct, output, args.json)
  if args.json:
    retJson+="]}"
    print(retJson)
#    try:
#      jsonOut = json.loads(retJson)
#      print("validated")
#    except:
#      print("json output validate failed")

#
# Get the full name of a group from a short group name
#
# param
#   shortgroup - The group to get the full name of
#
# return the full group name as a string
#
def getfullgroupname(shortgroup):
  retstr=""
  output=curl_cmd("GETPEERS")
  try:
    peers_json = json.loads(output)
    if "groups" not in peers_json:
      print("GETPEERS did not return successfully\n")
    for item in peers_json["groups"]:
      fullgroup = str(item["name"])
      if shortgroup == fullgroup:
        retstr=shortgroup
      else:
        grouparr=fullgroup.split("|")
        if len(grouparr) > 1 and grouparr[1] == shortgroup:
          retstr=fullgroup
  except Exception as e:
    print("Caught " + str(e))
  return retstr

#
# Adds a domain user
#
# param
#   groupname - The group to get the id of
#
# return Integer id of the group
#
def getgroupidfromname(groupname):
  retstr=groupname
  output=curl_cmd("GETPEERS")
  try:
    peers_json = json.loads(output)
    if "groups" not in peers_json:
      print("GETPEERS did not return successfully\n")
    for item in peers_json["groups"]:
      fullgroup = str(item["name"])
      fullgroup = fullgroup[1:] #strip off the _
      grouparr=fullgroup.split("|")
      if len(grouparr) > 1 and grouparr[1] == groupname:
        retstr=grouparr[0]
  except Exception as e:
    print("Caught " + str(e))
  return retstr

#
# Gets the group name from an id
#
# param
#   id - Id of the group to get
#
# return String name of the group
#
def getgroupnamefromid(id):
  retstr=id
  output=curl_cmd("GETPEERS")
  try:
    peers_json = json.loads(output)
    if "groups" not in peers_json:
      print("GETPEERS did not return successfully\n")
    for item in peers_json["groups"]:
      fullgroup = str(item["name"])
      fullgroup = fullgroup[1:] #strip off the _
      grouparr=fullgroup.split("|")
      if len(grouparr) > 1 and grouparr[0] == id:
        retstr=grouparr[1]
  except Exception as e:
    print("Caught " + str(e))
  return retstr

#
# Utility function - List the peers in a group
#
# param
#   output - The json string with the peers in it
#   group - The group to get the peers from
#   jsonflag - Flag indicating the output should be in json vs human readable
#
# return N/A
#
def _group_listpeers(output, group, jsonflag):
  peers_json = json.loads(output)
  retJson = '{\n  "name":"' + group + '",\n  "peers":[\n    '
  jsonFirst = True
  for item in peers_json["groups"]:
    if item["name"] == group:
      for peer in item["members"]:
        if jsonflag:
          if not jsonFirst:
            retJson += ",\n    "
          jsonFirst = False
          retJson += '"' + peer + '"'
        else:
          print(peer)
  if jsonflag:
    retJson += ']\n}\n'
    print(retJson)
#    try:
#      jsonOut = json.loads(retJson)
#      print("validated")
#    except:
#      print("json output validate failed")

#
# List the peers in a group
#
# param
#   args.group - The group to get the peers of
#   args.json - Flag indicating the output should be in json vs human readable
#
# return N/A
#
def group_listpeers(args):
  acct = account_getactive()
  groupname=getfullgroupname(args.group)
  if groupname == "":
      print("Group: " + args.group + " not found")
      return
  output = curl_cmd("GETPEERS","account=" + acct) 
  _group_listpeers(output, groupname, args.json)

#
# Adds a peer to a group
#
# param
#   args.group - The group to get the peers of
#   args.peer - The peer to add to the group
#   args.json - Flag indicating the output should be in json vs human readable
#
# return N/A
#
def group_addpeer(args):
  acct = account_getactive()
  try:
    groupname=getfullgroupname(args.group)
    if groupname == "":
      print("Group: " + args.group + " not found")
      return
    output = curl_cmd("EDITPEERGROUP","type=ADD", "account="+acct, "group="+groupname, "users="+args.peer)
    _group_listpeers(output, groupname, args.json)
  except:
    print("AddPeer caught exception")

#
# Delete a peer from a group
#
# param
#   args.group - The group to get the peers of
#   args.peer  - The peer to remove from the group
#   args.json - Flag indicating the output should be in json vs human readable
#
# return N/A
#
def group_delpeer(args):
  acct = account_getactive()
  groupname=getfullgroupname(args.group)
  if groupname == "":
      print("Group: " + args.group + " not found")
      return
  output = curl_cmd("EDITPEERGROUP","type=DELETE", "account="+acct, "group="+groupname, "users="+args.peer)
  _group_listpeers(output, groupname, args.json)

#
# Start a command
#
# param
#   cmd - The command to run
#   arg - The arg string for the command
#
# return N/A
#
def launch(cmd, arg):
  os.popen('nohup ' + cmd + ' ' + arg)

#
# Prints the peer policy from the json string
#
# param
#   output - the json output
#   jsonflag - if true print json, false print the peers
#
# return N/A
#
def _print_peer_policy(output, jsonflag):
  if jsonflag:
    print(output)
  else:
    try:
      policy_json = json.loads(output)
      for item in policy_json["policies"]:
        print("Policy: " + item["name"])
        for peer in item["peers"]:
          print("\t"+peer)
    except:
      print("Error parsing json policy")

#
# Gets the peer policy
#
# param
#   args - the args passed in from the cmd line
#
# return N/A
#
def peer_policy_get(args):
  output = curl_cmd("GETPOLICIES")
  _print_peer_policy(output, args.json)

#
# Gets the peer policy
#
# param
#   args - the args passed in from the cmd line
#
# return N/A
#
def peer_policy_add(args):
  output = curl_cmd("EDITPEERPOLICY", "type=ADD", "policy=default", "name="+args.peer)
  # just look for error
  try:
    json_out = json.loads(output)
    if "error" in json_out and json_out["error"] != "":
      print(json_out["error"])
  except:
    pass
  # - async processing on output - dont print _print_peer_policy(output, args.json)

#
# Gets the peer policy
#
# param
#   args - the args passed in from the cmd line
#
# return N/A
#
def peer_policy_del(args):
  output = curl_cmd("EDITPEERPOLICY", "type=DELETE", "policy=default", "name="+args.peer)
  # just look for error
  try:
    json_out = json.loads(output)
    if "error" in json_out and json_out["error"] != "":
      print(json_out["error"])
  except:
    pass
  # - async processing on output - dont print _print_peer_policy(output, args.json)

#
# Gets the Localservices
#
# param
#   output - The json string to pull the localservices from
#   jsonflag - Flag indicating the output should be in json vs human readable
#
# return N/A
#
def _localservice_get(output, jsonflag):
  if jsonflag:
    print(output)
    return
  try:
    services_json = json.loads(output)
    if "error" in services_json and services_json["error"] != "":
      errorstr = services_json["error"]
      if services_json["error"] == "SGW_Error_NotLicensed":
        errorstr = "Secure Gateway licences have been exceeded"
      print("An error was returned: " + errorstr)
    for item in services_json["localServices"]:
      try:
        print(str(item["serviceName"]) + "\t" + str(item["mappedTcpPort"]) + " -> " + str(item["targetIp"]) + ":" + str(item["targetTcpPort"]) + " (vpn-only: " + str(item["vpnOnly"]) + ", allowRemote: " + str(item["allowRemote"]) + ")" )
        #print(item)
      except:
        print(item)
  except:
    if (output == ""):
      print("JSON string was empty for localservices")
    else:
      print(output)
      print("parsing of output from localservices failed")
    return

#
# Gets the local services
#
# param
#   args.json - Flag indicating the output should be in json vs human readable
#
# return N/A
#
def localservice_get(args):
  output = curl_cmd("GETLOCALSERVICES")
  _localservice_get(output, args.json)

#
# Delete a localservice 
#
# param
#   args.json - Flag indicating the output should be in json vs human readable
#   args.name - The name of the localservice to delete
#
# return N/A
#
def localservice_del(args):
  output = curl_cmd("REMOVELOCALSERVICE", "serviceName=" + args.name)
  _localservice_get(output, args.json)

#
# List the peers in a group
#
# param
#   args.json - Flag indicating the output should be in json vs human readable
#   args.name - The name of the Localservice
#   args.mapped_tcp_port - (opt) The mapped tcp Port to use
#   args.mapped_udp_port - (opt) The mapped udp port to use
#   args.dest_tcp_port - (opt) The dest tcp port to use
#   args.dest_udp_port - (opt) The dest udp to use
#   args.dest_addr - The destination address
#   args.service_type - The service type eg 'http'
#
# return N/A
#
def localservice_add(args):
  maxtcpport=3700
  maxudpport=3700
  mappedTcpPort=0
  targetTcpPort=0
  mappedUdpPort=0
  targetUdpPort=0
  try:
    if (not (hasattr(args, 'dest_tcp_port') and args.dest_tcp_port != None)) and (not (hasattr(args, 'dest_udp_port') and args.dest_udp_port != None)):
      print("--dest_tcp_port or --dest_udp_port must be set")
      return
    if hasattr(args, 'dest_tcp_port') and args.dest_tcp_port != None:  
      targetTcpPort = args.dest_tcp_port
      if hasattr(args, 'mapped_tcp_port') and args.mapped_tcp_port != None:
        mappedTcpPort=args.mapped_tcp_port
        #print("setting port")
      elif not isVtun():
        #print("not vtun")
        mappedTcpPort=targetTcpPort
      else:
        #print("vtun")
        output = curl_cmd("GETLOCALSERVICES")
        try:
          services_json = json.loads(output)
          for item in services_json["localServices"]:
            try:
              if item["serviceName"] == args.name:
                mappedTcpPort = item["mappedTcpPort"]
              if item["mappedTcpPort"] >= maxtcpport:
                maxtcpport = item["mappedTcpPort"] + 1
            except:
              print(item)
          if mappedTcpPort == 0:
            mappedTcpPort = maxtcpport
        except:
          if (output == ""):
            print("JSON string was empty for GETLOCALSERVICES")
          else:
            print(output)
            print("Parsing of JSON output for GETLOCALSERVICES failed")
          return
    if hasattr(args, 'dest_udp_port') and args.dest_udp_port != None:
      targetUdpPort = args.dest_udp_port
      if hasattr(args, 'mapped_udp_port') and args.mapped_udp_port != None:
        mappedUdpPort=args.mapped_udp_port
        #print("setting port")
      elif not isVtun():
        #print("not vtun")
        mappedUdpPort=targetUdpPort
      else:
        output = curl_cmd("GETLOCALSERVICES")
        try:
          services_json = json.loads(output)
          for item in services_json["localServices"]:
            try:
              if item["serviceName"] == args.name:
                mappedUdpPort = item["mappedUdpPort"]
              if item["mappedUdpPort"] >= maxudpport:
                maxudpport = item["mappedUdpPort"] + 1
            except:
              print(item)
          if mappedUdpPort == 0:
            mappedUdpPort = maxudpport
        except:
          if (output == ""):
            print("JSON string was empty for GETLOCALSERVICES")
          else:
            print(output)
            print("Parsing of JSON output for GETLOCALSERVICES failed")
          return
  except Exception as ex:
    print("caught error in parsing output from Gabriel: " + str(ex))
  serviceName = args.name
  targetIp = args.dest_address
  serviceType = args.service_type
  vpnOnly=1
  allowRemote=1
  allowAllGab=0
  if hasattr(args, 'allow_non_vpn') and args.allow_non_vpn:
    vpnOnly = 0 
  if hasattr(args, 'bookmark') and args.bookmark:
    allowRemote=0
  if hasattr(args, 'allow_all') and args.allow_all:
    allowAllGab=1
  try:
    portMaps=[]
    if (mappedTcpPort != 0):
      portMaps.append("mappedTcpPort="+str(mappedTcpPort))
      portMaps.append("targetTcpPort="+str(targetTcpPort))
    if (mappedUdpPort != 0):
      portMaps.append("mappedUdpPort="+str(mappedUdpPort))
      portMaps.append("targetUdpPort="+str(targetUdpPort))
    output = curl_cmd("SETLOCALSERVICE", "serviceName=" + serviceName, "targetIp="+targetIp, "serviceType="+serviceType, "vpnOnly="+str(vpnOnly), "allowRemote="+str(allowRemote), "AllowAll="+str(allowAllGab), *portMaps)
    _localservice_get(output, args.json)
  except Exception as ex:
    print("Curl SETLOCALSERVICE caught " + str(ex))

#
# List the peers in a group
#
# param
#   args.json - Flag indicating the output should be in json vs human readable
#   args.name - The name of the Localservice
#   args.mapped_tcp_port - (opt) The mapped tcp Port to use
#   args.mapped_udp_port - (opt) The mapped udp port to use
#   args.dest_tcp_port - (opt) The dest tcp port to use
#   args.dest_udp_port - (opt) The dest udp to use
#   args.dest_addr - The destination address
#   args.service_type - The service type eg 'http'
#
# return N/A
#
def localservice_edit(args):
  output = curl_cmd("GETLOCALSERVICES")
  serviceFound=False
  try:
    services_json = json.loads(output)
    for item in services_json["localServices"]:
      try:
        if item["serviceName"] == args.name:
          if hasattr(args, "mapped_tcp_port") and args.mapped_tcp_port != None:
            item["mappedTcpPort"] = int(args.mapped_tcp_port)
          if hasattr(args, "mapped_udp_port") and args.mapped_udp_port != None:
            item["mappedUdpPort"] = int(args.mapped_udp_port)
          if hasattr(args, "dest_tcp_port") and args.dest_tcp_port != None:
            item["targetTcpPort"] = int(args.dest_tcp_port)
          if hasattr(args, "dest_udp_port") and args.dest_udp_port != None:
            item["targetUdpPort"] = int(args.dest_udp_port)
          if hasattr(args, "service_type") and args.service_type != None:
            item["serviceType"] = args.service_type
          if hasattr(args, 'bookmark') and args.bookmark:
            item["allowRemote"]=False
          if hasattr(args, 'no_bookmark') and args.no_bookmark:
            item["allowRemote"]=True
          if hasattr(args, 'allow_non_vpn') and args.allow_non_vpn:
            item["vpnOnly"]=False
          if hasattr(args, 'no_allow_non_vpn') and args.no_allow_non_vpn:
            item["vpnOnly"]=True
          if hasattr(args, 'allow_all') and args.allow_all:
            item["allowAll"]=True
          if hasattr(args, 'no_allow_all') and args.no_allow_all:
            item["allowAll"]=False
#{'serviceName': 'web.servers.virnetx.scom-80.web.servers.virnetx.scom', 'mappedUdpPort': 3700, 'targetUdpPort': 80, 'mappedTcpPort': 3700, 'targetTcpPort': 80, 'targetIp': 'web.servers.virnetx.scom', 'allowRemote': False, 'isBookmark': True, 'allowAll': False, 'vpnOnly': False, 'serviceType': 'http', 'allowedGroups': [], 'isEnabled': True}

          output = curl_cmd("SETLOCALSERVICE", "serviceName=" + item["serviceName"], "targetIp="+item["targetIp"], "serviceType="+item["serviceType"], "vpnOnly="+str(item["vpnOnly"]), "allowRemote="+str(item["allowRemote"]), "allowAll="+str(item["allowAll"]), "mappedUdpPort="+str(item["mappedUdpPort"]), "targetUdpPort="+str(item["targetUdpPort"]), "mappedTcpPort="+str(item["mappedTcpPort"]), "targetTcpPort="+str(item["targetTcpPort"]))
          serviceFound=True
          _localservice_get(output, args.json)
      except:
        print("Error in finding service")
    if serviceFound != True:
      print("Could not find service named " + args.name)
  except:
    print("Error in parsing output from GETLOCALSERVICES")


#
# Gets the groups for a name
#
# param
#   output - the json string to search the names of
#   name - The name to get the groups for
#   jsonflag - Flag indicating the output should be in json vs human readable
#
# return N/A
#
def _getgroupsforname(output, name, jsonflag):
  try:
    services_json = json.loads(output)
    for item in services_json["localServices"]:
      try:
        if item["serviceName"] == name:
          if jsonflag:
            print(json.dumps(item, indent=2))
          else: 
            print("Groups for " + item["serviceName"] + ":")
            for group in item["allowedGroups"]:
              print("  " +  getgroupnamefromid(group))
      except:
        print(item)
  except:
    if (output == ""):
      print("JSON response was empty while fetching group id for group name")
    else:
      print(output)
      print("json parser error")

#
# Adds a group to a localservice
#
# param
#   args.name - The name of the localservice
#   args.group - The group to add to the localservice
#     or
#   args.domain - The *.domain to add to the localservice
#   args.json - Flag indicating the output should be in json vs human readable
#
# return N/A
#
def localservice_addgroup(args):
  serviceName = args.name
  if hasattr(args, 'domain') and args.domain != None:
    group="*." + args.domain
  elif hasattr(args, 'group') and args.group != None:
    group = getgroupidfromname(args.group)
  else:
    print("--group or --domain must be specified")
    return
  output = curl_cmd("ADDLOCALSERVICEACCESS", "serviceName=" + serviceName, "group=" + group)
  _getgroupsforname(output, args.name, args.json)

#
# Remove a group from localservice
#
# param
#   args.group - The group to get the peers of
#   args.json - Flag indicating the output should be in json vs human readable
#
# return N/A
#
def localservice_delgroup(args):
  serviceName = args.name
  if hasattr(args, 'domain') and args.domain != None:
    group="*." + args.domain
  elif hasattr(args, 'group') and args.group != None:
    group = getgroupidfromname(args.group)
    if group == "":
      print("Group: " + args.group + " not found")
      return
  else:
    print("--group or --domain must be specified")
    return
  output = curl_cmd("REMOVELOCALSERVICEACCESS", "serviceName=" + serviceName, "group=" + group)
  _getgroupsforname(output, args.name, args.json)

#
# Gets a list of groups for a localservice
#
# param
#   args.name - The name of the group
#   args.json - Flag indicating the output should be in json vs human readable
#
# return N/A
#
def localservice_getgroups(args):
  output = curl_cmd("GETLOCALSERVICES")
  _getgroupsforname(output, args.name, args.json)
 
#
# Launch a webgui
#
# param
#
# return N/A
#
def webgui(args):
  token=get_token("authCode")
  url="http://127.0.0.1:7780/gui.html?" + token
  if platform.system() == "Darwin":
    launch("open", url)
    return
  elif platform.system() == "Linux":
    try:
      if os.path.exists("/usr/bin/xdg-open"):
        launch("/usr/bin/xdg-open", url) 
      elif os.path.exists("/usr/bin/chromium-browser"):
        launch("/usr/bin/chromium-browser", url)
      elif os.path.exists("/usr/bin/firefox"):
        launch("/usr/bin/firefox", url)
      return
    except Error:
      print("An error occured launching the url")
  print("Paste this into your browser: " + url)

#
# Sets and/or gets the log level
#
# param
#   args.level - (opt) The log level - if set the level will be set to it
#   args.json - Flag indicating the output should be in json vs human readable
#
# return N/A
#
def loglevel(args):
  if args.level:
    output = curl_cmd("LOGLEVEL", "level="+args.level.upper())
  else:
    output = curl_cmd("LOGLEVEL")
  try:
    logjson = json.loads(output)
    if "newLevel" not in logjson:
      print("LOGLEVEL did not return successfully")
      exit()
    if (args.json):
      print(output)
    else:
      print("Log level set to: " + logjson["newLevel"])
  except:
    print("parsing of response from LOGLEVEL failed")

#
# Sets and/or gets the log level
#
# param
#   args.level - (opt) The log level - if set the level will be set to it
#   args.json - Flag indicating the output should be in json vs human readable
#
# return N/A
#
def _reserved_ip(output, jsonFlag):
  if (jsonFlag):
    print(output)
  else:
    try:
      addrs_json = json.loads(output)
      if "userIP" not in addrs_json:
        print("Could not find any user reserved IP addresses")
        return
      print("IP Addr\t\tNetmask")
      for pair in addrs_json["userIP"]:
        print(pair["addr"] + "\t" + pair["mask"])
    except Exception as e:
      if (output == ""):
        print("JSON response from reserved ips was empty")
      else:
        print("Could not parse reply from IPADDRESSESREPLY" + str(e))

#
# Sets and/or gets the log level
#
# param
#   args.level - (opt) The log level - if set the level will be set to it
#   args.json - Flag indicating the output should be in json vs human readable
#
# return N/A
#
def settings_reservedip_get(args):
  _reserved_ip(curl_cmd("GETIPADDRESSES"), args.json)

#
# Sets and/or gets the log level
#
# param
#   args.level - (opt) The log level - if set the level will be set to it
#   args.json - Flag indicating the output should be in json vs human readable
#
# return N/A
#
def settings_reservedip_add(args):
  _reserved_ip(curl_cmd("EDITPRIVATEADDRESSES", "action=ADD", "new=" + args.ip + " " + args.mask), args.json)

#
# Sets and/or gets the log level
#
# param
#   args.level - (opt) The log level - if set the level will be set to it
#   args.json - Flag indicating the output should be in json vs human readable
#
# return N/A
#
def settings_reservedip_del(args):
  _reserved_ip(curl_cmd("EDITPRIVATEADDRESSES", "action=DELETE", "old=" + args.ip + " " + args.mask), args.json)

#
# start the main function
#
try:
  main()
except:
  exit(1)
