#!/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 [show|accept]'           'Interactively agree or show/agree to End User License Agreement.'
  isInstalledTV || return
  ABecho 'teamviewer setup'                           'Configure headless modes (non-gui/console)'
  echo
  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
  [ "$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 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 --system --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 CollectUserConfig()
{
  isInstalledTV || return

  local logs="$TV_BASE_DIR/logfiles"

  for file in "$logs"/* ; do
    [ -h "$file" ] || continue

    local name="$(basename "$file")"
    local logdest="$(readlink "$file")"
    local cfgfile="${logdest/%"$TV_USER_LOCAL_SUBPATH/$log_dir/"/"$TV_USER_CONFIG_SUBPATH/client.conf"}"
    local dstname="client_$name.conf"	        # see StripPersonalInformation

    [ "$logdest" != "$cfgfile" ] || continue    # substitution failed
    [ -e "$cfgfile"            ] || continue    # no user config file found

    cp "$cfgfile" "$ziplog_dir/$cfg_dir/$dstname"
  done
}

function SelectZipper()
{

  if cmdExists zip; then
    archive+='.zip'
    cmd='zip -r9'
  elif cmdExists tar && cmdExists gzip; then
    archive+='.tar.gz'
    cmd='tar -zchf'
  fi

  if [ -z "$cmd" ]; then
    Yecho 'Please install either\n* zip   or\n* tar and gzip to allow creation of a compressed archive'
    die 'Could not create a compressed archive of log files - no suitable compressor found'
  fi
}

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)"
  local cmd

  echo 'Creating a zip archive from TeamViewer log files, config files, and some system information'

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

  CollectUserConfig

  StripPersonalInformation "$ziplog_dir/$cfg_dir"

  CollectSystemInformation "$ziplog_dir/$sysinfo_dir"

  SelectZipper

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

    rm -f $archive
    $cmd $archive "$cfg_dir" "$log_dir" "$sysinfo_dir" || die "Done. An error ($?) occurred when creating archive $archive"

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

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

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

