#!/bin/bash

# command line parameters that are not essential for normal TeamViewer usage

function PrintHelp()
{
  PrintVersion
  echo
  ABecho 'teamviewer'                    'Start TeamViewer user interface (if not running).'
  echo
  ABecho 'teamviewer help'               'Print this help screen.'
  ABecho 'teamviewer version'            'Print version information.'
  ABecho 'teamviewer info'               'Print version, status, id.'
  ABecho 'teamviewer ziplog'             'Create a zip containing all teamviewer logs (useful when contacting support).'
  echo
  ABecho 'teamviewer license [accept]'   'Show/agree to End User License Agreement.'
  isInstalledTV || return
  ABecho 'teamviewer passwd [PASSWD]'    'Set a password (useful when installing remote (ssh).'
  echo
  ABecho 'teamviewer daemon status'      'Show current status of the TeamViewer daemon.'
  ABecho 'teamviewer daemon start'       'Start		TeamViewer daemon.'
  ABecho 'teamviewer daemon stop'        'Stop		TeamViewer daemon.'
  ABecho 'teamviewer daemon restart'     'Stop/Start	TeamViewer daemon.'
  ABecho 'teamviewer daemon disable'     "Disable	TeamViewer daemon - don't start daemon on system startup."
  ABecho 'teamviewer daemon enable'      'Enable		TeamViewer daemon - start daemon on system startup (default).'
  echo
#;if [ "$TV_PKGTYPE" == "TAR_IN" -o "$TV_PKGTYPE" == "RPM" -o  "$TV_PKGTYPE" == "DEB" ] ; then
#;  ABecho 'teamviewer headless-setup'      'Setup Xvfb headless mode'
#;  echo
#;fi
  [ "$TV_PKGTYPE" == "TAR_IN" ] || return
  ABecho 'teamviewer uninstall [force]'  "Uninstall TAR package. Force: don't ask for confirmation."
  echo
}

function PrintVersion()
{
  ABecho "TeamViewer" "$TV_VERSION  ($TV_PKGTYPE)"
}

function PrintInfo()
{
  PrintVersion
  echo
  PrintDaemonStatus
  echo
  PrintTeamViewerID
}

function PrintDaemonStatus()
{
  local cmd="$(daemonCtl 'status')"
  local txt="n/a"

  if [ isInstalledTV ] ; then
    txt="$(eval "$cmd")"
    [ $? = 0 ] || txt='n/a (error)'
  fi
  
  ABecho "teamviewerd status" "$txt"
}

function PrintTeamViewerID()
{
  local config="$TV_BASE_DIR/config/global.conf"
  local txt='not found'
  local tvid
  
  [ -e "$config" ] && tvid=$( grep 'ClientID' "$config" | cut --delimiter='=' -f2 )
  [ -n "$tvid"   ] && txt="$tvid"

  ABecho "TeamViewer ID:" "$tvid"

  if [ -z "$tvid" ] && isInstalledTV; then
    echo "Try restarting the TeamViewer daemon (e.g. teamviewer --daemon restart)"
  fi
}

function AcceptLicense()
{
  local accept="$1"
  local confirm
  local config="$TV_BASE_DIR/config/global.conf"
  local licenseFile="$TV_BASE_DIR/doc/License.txt"
  local eulaAccepted='[int32] EulaAccepted = 1'
  local eulaAcceptedV='[int32] EulaAcceptedRevision = 6'
  local eulaURL=" Read the full license agreement at: http://www.teamviewer.com/link/?url=271351"
  
  installedTVorDie
  
  if grep -q "$(escapeBrackets "$eulaAccepted")" "$config" 2>/dev/null ; then
    BDecho "$eulaURL"
    echo
    Gecho " License agreement has already been accepted"
    echo
    exit
  fi

  if [ "$accept" = 'accept' ]; then
    confirm='y'
  else
   ( # subshell
    IFS=$'\n'
    local indent=''
    local text
    if cmdExists iconv; then
      text=$(iconv -f ISO-8859-15 -t UTF-8 "$licenseFile")
    else
      text=$(cat "$licenseFile")
    fi
    for line in $text ; do
      if [ -z $indent ]; then
        BDecho "   $line"
        indent='x'
      else
        echo "$line"
      fi
    done
   )
    echo
    echo
    BDecho "$eulaURL"
    echo
    read -n 1 -p " Do you accept the license agreement? (Y/n)" confirm
  fi

  [ -n "$confirm" ] && [ "$confirm" != 'y' ] && [ "$confirm" != 'Y' ] && return
  
  isSuperUser || Rdie "You need to be root to accept the license agreement."

  Run_Daemon 'stop' > /dev/null

  echo "$eulaAccepted"  >> "$config"
  echo "$eulaAcceptedV" >> "$config"
  echo " License agreement has been accepted."

  Run_Daemon 'start' > /dev/null || die 'failed to restart the daemon'
  echo
}

function SetPasswd()
{
  local pwd="$1"
  [ -n "$pwd" ] || die 'no password specified'

  installedTVorDie
  isSuperUser || die 'You need root permissions for this operation'

  Run_Daemon 'stop' > /dev/null
  
  "$TV_BIN_DIR/teamviewerd" --passwd "$pwd"
  case $? in
    0  ) echo 'ok'	;;
    11 ) echo 'password too short - use at least 8 characters [E11]'	;;
    12 ) echo 'password too long  - use 12 or less characters [E12]'	;;
    13 ) echo 'password not accepted - illegal char detected [E13]'	;;
    14 ) echo 'passwort invalid - validation failed [E14]'	;;
    *  ) echo 'unknown response'	;;
   esac
  
  Run_Daemon 'start' > /dev/null || die 'failed to restart the daemon'
  echo
}

function ExportLicense()
{
  local license="$1"
  local path='/tmp/tv_global.conf'

  [ -n "$license" ] || die 'no license specified'

  isSuperUser || die 'You need root permissions for this operation'

  Run_Daemon 'stop' > /dev/null
  
  "$TV_BIN_DIR/teamviewerd" --export-license "$license" "$path"
  case $? in
    0  ) echo "ok - license exported to '$path'"		;;
    11 ) echo "destination '$path' not accessible"		;;
    *  ) echo 'unknown response'	;;
   esac
  
  Run_Daemon 'start' > /dev/null || die 'failed to restart the daemon'
  echo
}

function StripPersonalInformation()
{
  local config
  local config_dir="$1"
  local strip_global=(
    '[bin  ] Certificate'
    '[bin  ] CertificateKey'
    '[bin  ] MultiPwdMgmtPwdData'
    '[bin  ] PermanentPassword'
    '[bin  ] PK'
    '[bin  ] SK'
    '[bin  ] SRPPasswordMachineIdentifier'
    )
  local strip_client=(
    '[bin  ] BuddyLoginTokenAES'
    '[bin  ] BuddyLoginTokenSecretAES'
    )

  ( # subshell: preserve pwd
    cd "$config_dir"

    # global.conf
    config='global.conf'
    for s in "${strip_global[@]}"; do
      StripItem "$config" "$s"
    done
  
    # client.conf
    for config in *'/client.conf' ; do
      [ -e "$config" ] || continue
      for s in "${strip_client[@]}"; do
        StripItem "$config" "$s"
      done
    done
  )
}

function StripItem()
{
  local file="$1"
  local pattern="$2 ="
  local sedpattern="$(escapeBrackets "$pattern")"

  grep -q "$sedpattern" "$file" || return

  sed -i -e "/$sedpattern/d" "$file"
  echo "# $pattern (stripped)" >> "$file"
}

function escapeBrackets()
{
  local pattern="${1/[/\\[}"
  pattern="${pattern/]/\\]}"
  echo "$pattern"
}

function InfoArch()
{
  local a64=' '; has64BitSupport && a64='X'
  local a32=' '; has32BitSupport && a32='X'

  HeadEcho "DistArch:" "$(uname -m)	( Loader:	[$a32] ld32	[$a64] ld64 )"
}

function InfoDistro()				# log information about the Linux distribution
{
  local files=$(cd /etc; ls *-release *-version *_version 2> /dev/null)
  local rfile
  local fhead

  echo     "Distribution:"

  cmdExists lsb_release && fhead=$(lsb_release -idrc)		# first, try lsb_release
  if [ -n "$fhead" ]; then
    IndentEcho "$fhead" '      '
  else
    HeadEcho "  Files" "$(echo "$files" | tr '\n' ' ')"		# try various files
  
    for rfile in $files ; do
      echo "    $rfile:"
      fhead=$(head -n 10 "/etc/$rfile")
      IndentEcho "$fhead" '      '
    done
  fi
}

function CollectALSAInformation()
{
  local alsa="$1"/alsa

  function ALSAInformationHeader()
  {
    echo -e "\n" >> $alsa
    echo $1 >> $alsa
    echo "======================================" >> $alsa
    echo >> $alsa
  }

  echo "ALSA system information" > $alsa
  echo "++++++++++++++++++++++++++++++++++++++" >> $alsa

  if cmdExists alsa-info ; then

    alsa-info --output $alsa --no-upload > /dev/null

  else

    ALSAInformationHeader "ALSA dmesg"
    dmesg | grep -i alsa >> $alsa

    ALSAInformationHeader "Sound Devices"
    find /dev/snd | sort >> $alsa

    if cmdExists aplay ; then
      ALSAInformationHeader "Playback information"
      echo -e "Devices:" >> $alsa
      aplay -l >> $alsa
      echo -e "\n\nStreams:\n" >> $alsa
      aplay -L >> $alsa
    fi

    if cmdExists arecord ; then
      ALSAInformationHeader "Capture information"
      echo -e "Devices:" >> $alsa
      arecord -l >> $alsa
      echo -e "\n\nStreams:\n" >> $alsa
      arecord -L >> $alsa
    fi

    if cmdExists amixer ; then
      ALSAInformationHeader "Mixer information"
      for control in /dev/snd/controlC* ; do
        card=${control#/dev/snd/controlC}
        echo -e "\nhw:$card:\n======" >> $alsa
        amixer -c $card scontents >> $alsa
      done
    fi

  fi
}

function CollectPulseAudioInformation()
{
  local pulseaudio="$1"/pulseaudio

  cmdExists pactl || return

  pactl info > "$pulseaudio"
  echo -e "\n======================================\n" >> $pulseaudio
  pactl list short >> "$pulseaudio"
  echo -e "\n======================================\n" >> $pulseaudio
  pactl list >> "$pulseaudio"
}

function CollectSystemInformation()
{
  local sysinfo_dir="$1"
  local logs=(/var/log/X*.log* /proc/cpuinfo /proc/sys/kernel/shmmax)

  mkdir "$sysinfo_dir" || die "failed to create $sysinfo_dir"

  ( # subshell: preserve pwd
    cd "$sysinfo_dir"

    PATH=$PATH:/sbin:/usr/sbin

    # supported architecture information (32/64bit)
    InfoArch > 'architectures'

    # distribution information
    InfoDistro > 'release'

    # network interfaces
    cmdExists ifconfig && ifconfig -a > 'ifconfig'

    # uname -a
    cmdExists uname && uname -a > 'uname'

    # dbus names
    cmdExists dbus-send && dbus-send --print-reply --dest=org.freedesktop.DBus / org.freedesktop.DBus.ListNames > 'dbus-send' 2>&1

    # PCI
    cmdExists lspci && lspci > 'lspci'

    # USB
    cmdExists lsusb && lsusb > 'lsusb'

    # Kernel modules
    cmdExists lsmod && lsmod > 'lsmod'

    # ALSA info
    CollectALSAInformation "$sysinfo_dir"

    # PulseAudio
    CollectPulseAudioInformation "$sysinfo_dir"

    # copy X logs, some proc info
    for file in "${logs[@]}" ; do
      [ -f "$file" ] && cp -p "$file" .
    done
  )
}

function CreateZipLogTmpDir()
{
#  local ziplog_dir="/tmp/tv_ziplog_${RANDOM}_$(date +%M%S%N)"
#  while [ -d "$ziplog_dir" ]; do ziplog_dir="$ziplog_dir"A; done	# use unique name 
#  mkdir $ziplog_dir || die "Error creating folder '$ziplog_dir' in /tmp"
#  echo "$ziplog_dir"
  mktemp -d -p /tmp tv_ziplog_XXXXXX || die "Error creating temporary dir in /tmp"
}

function CreateZipLog()
{
  local ziplog_dir="$(CreateZipLogTmpDir)"
  local cfg_dir="config"
  local log_dir="logfiles"
  local sysinfo_dir="sysinfo"
  local archive="/tmp/tvlog_$(hostname)_$(date +%F)"
 
  echo "Creating a zip archive from all files in $log_dir and $cfg_dir"

  cp -Lrp "$TV_BASE_DIR/$cfg_dir" $ziplog_dir
  cp -Lrp "$TV_BASE_DIR/$log_dir" $ziplog_dir

  StripPersonalInformation "$ziplog_dir/$cfg_dir"

  CollectSystemInformation "$ziplog_dir/$sysinfo_dir"

  ( # subshell: preserve pwd
    cd "${ziplog_dir}"

    if cmdExists zip; then
      archive="$archive.zip"
      rm -f $archive
      zip -r9 $archive "$cfg_dir" "$log_dir" "$sysinfo_dir" || die "Done. An error ($?) occurred when creating archive $archive"
    else
      archive="$archive.tar.gz"
      rm -f $archive
      tar -zchf $archive "$cfg_dir" "$log_dir" "$sysinfo_dir" || die "Done. An error ($?) occurred when creating archive $archive"
    fi

    rm -fR $ziplog_dir		# delete temporary data
    chmod 666 $archive		# allow every user to read and delete

    Gecho "\n** Success**\n"
    echo "Archive written to $archive"
    echo
  ) || return

  isInstalledTV && (isSuperUser || Yecho "Warning: Ziplog should be executed as root or some important information may be missing")
}

