#!/bin/sh
# oztivo update script, $Revision: 1.15 $
#
# (c) 2006 Simon Quigley. Small changes by Warren Toomey
#
#
# WARNING! WARNING! This script is not guaranteed to perfectly upgrade your
# OzTiVo image from 1.3/1.4/1.5 up to 1.6.x. In fact, you may end up with
# an OzTiVo disk which does not work at all, forcing you to perform a new
# 1.6.x install anyway. You agree that by running this script, you shoulder
# the entire responsibility for getting your TiVo working again, and that
# you will live with any loss of recordings, season passes etc.
#
#

RSYNC_URL=http://131.244.9.101/TiVo/files/programs/rsync
TARBALL=http://131.244.9.101/TiVo/files/updates/13-14.tar.gz
CONF_FILE="/etc/oztivo.conf"
TMPCONF_FILE="/tmp/oztivo.conf"
TCLIENT="/etc/tclient.conf"

########### Functions #################
# Check the timing variable: must exist have have values between 1 and 31.
check_timing()
{
  if [ -z "$timing" ]; then
    netcfg="No timing parameter in $1"; return
  fi

  if [ "$timing" -lt 1 -o "$timing" -gt 31 ]; then
    netcfg="Timing parameter $timing not between 1-31 in $1"; return
  fi
}

# Check the ip, mask and gateway variables.
check_ip()
{
  if [ -z "$ip" ]; then
    netcfg="No ip parameter in $1"; return
  fi

  # DHCP, is good
  if [ "$ip" = "DHCP" ]; then return; fi

  # Check valid IP address: not pretty
  echo $ip | grep -E -q '^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$'
  if [ "$?" -ne 0 ]; then
    netcfg="Invalid IP address $ip in $1"; return
  fi

  # Check valid netmask
  echo $netmask | grep -E -q '^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$'
  if [ "$?" -ne 0 ]; then
    netcfg="Invalid netmask $netmask in $1"; return
  fi

  # Check valid gateway
  echo $gateway | grep -E -q '^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$'
  if [ "$?" -ne 0 ]; then
    netcfg="Invalid gateway $gateway in $1"; return
  fi

  # Ensure that the gateway and ip are different
  if [ "$ip" = "$gateway" ]; then
    netcfg="IP address and gateway are identical ($gateway) in $1"; return
  fi
}

check_mac()
{
  if [ -z "$mac" ]; then
    netcfg="No mac parameter in $1"; return
  fi
  # Check valid MAC address: not pretty
  echo $mac | grep -E -q \
  '^[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}$'
  if [ "$?" -ne 0 ]; then
    netcfg="Invalid MAC address $mac in $1"; return
  fi
}

check_wep()
{
  if [ -z "$ssid" ]; then
    netcfg="No ssid parameter in $1"; return
  fi
  if [ -z "$wep" ]; then
    netcfg="No wep parameter in $1"; return
  fi
  if [ "$wep" = "n" ]; then return; fi

  # wep must be 64 or 128
  if [ "$wep" -ne 64 -a "$wep" -ne 128 ]; then
    netcfg="WEP selected but wep is $wep, not 64 or 128 in $1"; return
  fi

  if [ -z "$wepkey" ]; then
    netcfg="$wep bit WEP selected but no wepkey parameter in $1"; return
  fi

  # Check WEP key size
  keylength=`echo $wepkey |wc -c`
  if [ "$wep" -eq 64 -a "$keylength" -ne 11 ]; then
    netcfg="64 bit WEP selected but wepkey is not 10 chars long in $1"; return
  fi
  if [ "$wep" -eq 128 -a "$keylength" -ne 27 ]; then
    netcfg="128 bit WEP selected but wepkey is not 26 chars long in $1"; return
  fi
}

# Read $1 and determine if it is good or bad. Sets netcfg to "OK" if OK,
# or some other string on error.
validate_oztivoconf()
{
  # Assume that everything looks OK.
  netcfg="OK"

  # File doesn't exist, error
  if [ ! -f "$1" ]; then
    netcfg="Config file $1 does not exist"; return
  fi

  # Before loading the file, unset everything possible
  unset nic; unset ip; unset mac; unset hostname; unset timing;
  unset modem; unset pppondss; unset emulator;
  unset emulatorport; unset netmask; unset gateway
  unset ssid; unset wep; unset wepkey

  # Load the variables
  source $1
  if [ "$?" -ne 0 ]; then
    netcfg="Failed to load $1"; return
  fi

  # Promote legacy stuff
  if [ "$modem" = 1 ]; then nic=Modem; fi
  if [ "$pppondss" = 1 ]; then nic=PPPonDSS; fi

  if [ -z "$nic" ]; then
    netcfg="No nic parameter in $1"; return
  fi

  # Check the nic setting
  case $nic in
    TurboNet)
        check_timing $1
        check_mac $1
        check_ip $1
        ;;
    Cachecard)
        check_mac $1
        check_ip $1
        ;;
    AirNet)
        check_timing $1
        check_wep $1
        check_ip $1
        ;;
    TiVoNet)
        check_ip $1
        ;;
    PPPonDSS)
        ;;
    Modem)
        ;;
    *)  netcfg="Unknown nic $nic in $1"; return
        ;;
  esac

  # Missing emulator and port
  if [ -z "$emulator" ]; then
    netcfg="No emulator parameter in $1"; return
  fi

  if [ -z "$emulatorport" ]; then
    netcfg="No emulatorport parameter in $1"; return
  fi
}

# If the CONF_FILE is missing or invalid, ask the user
# for the details
create_conf_file()
{
    echo
    if [ ! -f "$CONF_FILE" ]; then
        echo "This TiVo is missing the networking config file oztivo.conf."
    else
        echo "Your existing networking config file oztivo.conf won't"
        echo "work with the 1.6.2 image for this reason:"
        echo "  ===> $netcfg"
        echo "Here is the existing file:"
        cat $CONF_FILE
        echo
    fi
    echo "Please answer a few questions to create a new one:"

	echo "# OzTiVo menu configuration settings file" > $TMPCONF_FILE
	echo "# Please do not edit this file" >> $TMPCONF_FILE
	echo "# Run the nic_config_tivo tool to reconfigure" >> $TMPCONF_FILE

	# work out the network card
	echo "Please enter your network card type. Note: these are case sensitive."
	echo -n "[TurboNet/Cachecard/AirNet/TiVoNet/PPPonDSS/Modem]: "
	read NIC
	echo "nic=$NIC" >> $TMPCONF_FILE

	# IP Address
	if [ "$NIC" != "PPPonDSS" -a "$NIC" != "Modem" ]; then
		echo -n "Please enter an IP address, or the word DHCP [xxx.xxx.xxx.xxx/DHCP]: "
		read IP
		if [ "$IP" = "DHCP" ]; then
			echo "ip=DHCP" >> $TMPCONF_FILE
		else    echo "ip=$IP" >> $TMPCONF_FILE

			echo -n "Please enter a subnet mask, e.g 255.255.255.0 [xxx.xxx.xxx.xxx]: "
			read SUBNET
			echo "netmask=$SUBNET" >> $TMPCONF_FILE

			echo -n "Please enter a gateway IP, e.g 192.168.0.1 [xxx.xxx.xxx.xxx]: "
			read GATEWAY
			echo "gateway=$GATEWAY" >> $TMPCONF_FILE

		fi

	fi
	
	# MAC Address
	if [ "$NIC" = "TurboNet" -o "$NIC" = "Cachecard" ]; then
		if [ "$NIC" = "TurboNet" ]; then
			echo -n "Please enter the MAC address to use, eg 00:0B:AD:10:10:10: "
		elif [ "$NIC" = "Cachecard" ]; then
			echo -n "Please enter the MAC address to use, eg 00:0B:AD:A0:0A:1D: "
		fi
		read MAC
		echo "mac=$MAC" >> $TMPCONF_FILE
		echo "timing=4" >> $TMPCONF_FILE
	fi

	# wireless
	if [ "$NIC" = "AirNet" ]; then
		# essid
		echo -n "Please enter the ESSID to use, eg mywlan [xxxxxxxx]: "
		read ESSID
		echo "timing=6" >> $TMPCONF_FILE
	  echo "ssid=$ESSID" >> $TMPCONF_FILE

		# wep
		echo -n "Are you using WEP? [n/64/128]: "
		read WEP
		echo "wep=$WEP" >> $TMPCONF_FILE
		
		if [ "$WEP" != "n" ]; then
			# wepkey
			echo -n "Please enter your WEP key (10 chars for 64 bit, 26 for 128 bit) [xxxxxxxxxx]: "
			read WEPKEY
      echo "wepkey=$WEPKEY" >> $TMPCONF_FILE
		fi
	fi

	# dhcp hostname
	echo "hostname=oztivo" >> $TMPCONF_FILE

	# modem config
	if [ "$NIC" = "Modem" ]; then
		# ugh. ask for dialup number
		echo -n "Please enter the dialup number [xxxxxxxx]: "
		read PHONE
		echo "phone=$PHONE" >> $TMPCONF_FILE

		# now username
		echo -n "Please enter your username [xxxxxxxx]: "
		read USERNAME
		echo "username=$USERNAME" >> $TMPCONF_FILE
 
		# replace the username in the ppp-options file
		if [ -n "`grep ^user /etc/ppp-options`" ]; then
			# change setting
			cat /etc/ppp-options | sed "s/user.*/user $USERNAME/" > /etc/ppp-options
		else
			echo "user $USERNAME" >> /etc/ppp-options
		fi

		# now password
		echo -n "Please enter your password [xxxxxxxx]: "
		read PASSWORD
		echo "password=$PASSWORD" >> $TMPCONF_FILE

		# wallop the chap/pap secrets files with the currently entered password
		echo -e "*\t*\t$PASSWORD" > /etc/chap-secrets
		echo -e "*\t*\t$PASSWORD" > /etc/pap-secrets

		# now write tclient.conf
		cp $TCLIENT /etc/tclient.conf.backup
		if [ -n "`grep ^127: $TCLIENT`" ]; then
			# change setting
			cat $TCLIENT | sed "s/^127:.*/127:$PHONE:127.0.0.1:8000:$USERNAME:$PASSWORD:/" > $TCLIENT
		else
			echo "127:$PHONE:127.0.0.1:8000:$USERNAME:$PASSWORD:" >> $TCLIENT
		fi

	fi

	# emulator, force minnie
	echo "emulator=minnie.tuhs.org" >> $TMPCONF_FILE
	echo "emulatorport=80" >> $TMPCONF_FILE

	# Finally, make the real config file. We do this in case
	# the user ctrl-C's above, which would leave a partial $CONF_FILE
	cp $TMPCONF_FILE $CONF_FILE
}

########### End Functions #################

# get any -n flag from the command-line
if [ $# -eq 1 ]; then
	if [ $1 = "-n" ]; then
		noflag=$1
	fi
fi

# put disk in read/write mode
/hack/bin/makerw.sh

# Stop now if this is a UK 2.5.5 tivo
# Unfortunately, dbget can return "ret" when the MFS is locked,
# so we loop until we get something sensible
tivoswversion="ret"
while [ "$tivoswversion" = "ret" ]; do
  tivoswversion=`dbget /SwSystem/ACTIVE Name|cut -b1-3`
done

if [ "$tivoswversion" != "3.0" ]; then
	# don't use this script on non-3.0 MFS database
	echo "Error: this script cannot upgrade this TiVo, as it does not have a"
	echo "3.0 version MFS database. It seems to have a $tivoswversion MFS database."
	# disk in read only mode
	/hack/bin/makero.sh
	exit 1
fi

# check for wget
WGET=`find / -name "wget" | head -1`		# We only want one of them

if [ ! -f "$WGET" ]; then
	# missing wget
	echo "Error: Please download and install wget."
	exit 1
fi

# check for rsync
RSYNC=`find / -name "rsync" | head -1`		# We only want one of them

if [ ! -f "$RSYNC" ]; then
	# missing rsync
	# download it
	cd /devbin	
	$WGET $RSYNC_URL
	chmod 755 rsync
fi

echo
echo "Welcome to the upgrade_oztivo script. Before we begin the upgrade,"
echo "please type in some letters followed by the Enter key on the line below."
echo "This will indicate if your Telnet client is configured correctly:"
#
# See if they are sending us CRLF instead of just CR. We can't deal with CRLF.
#
stty cbreak
read line
stty sane
linelen=`echo $line |wc -c`
if [ "$linelen" -lt 2 ]; then
   echo; echo
   echo "It looks like you have your Telnet client misconfigured, as it is"
   echo "sending two Enter keys for every one that you type. If you are"
   echo "running Putty, right-click on the top of the Putty window, click on"
   echo "Change Settings, click on the Telnet category, and deselect this:"
   echo "         Return key sends Telnet New Line instead of ^M"
   echo
   echo "If you are using a different Telnet client, then set it to send CR"
   echo "when you type the Enter key, and not CRLF."
   echo; echo
   exit 1
else
   echo
   echo "Good, your Telnet client appears to be configured correctly."
   echo
fi


# identify version.

if [ -f /etc/oztivo_version ]; then
	# it's 1.4 or newer
	# grab the first few chars
	VERSION=`cat /etc/oztivo_version|cut -b1-3`
elif [ -f /etc/oztivo-version ]; then
	# 1.3 most likely
	# grab the first few chars
	VERSION=`cat /etc/oztivo-version|cut -b1-3`
fi

# ask user to confirm
echo "You seem to be running a $VERSION oztivo image on this TiVo."
echo "If this not correct, please enter the correct version."
echo -n "[pre-gs/1.3/1.4/1.5/1.6]: "
read USER_VERSION

# check entered version
if [ "$USER_VERSION" = "pre-gs" ]; then
	# don't support upgrading pre-gs images
	echo "Sorry, upgrading a pre-GS image is best done by reimaging your tivo disk(s)."

	# disk in read only mode
	/hack/bin/makero.sh

	exit 1
elif [ "$USER_VERSION" = "1.3" -o "$USER_VERSION" = "1.4" -o "$USER_VERSION" = "1.5" -o "$USER_VERSION" = "1.6" ]; then
	# override detected
	VERSION=$USER_VERSION
	if [ "$USER_VERSION" = "1.3" -o "$USER_VERSION" = "1.4" -o "$USER_VERSION" = "1.5" ]; then
		echo "ok, upgrading from $VERSION to 1.6."
	fi
fi

if [ "$VERSION" = "1.6" ]; then
	# don't use this script on 1.6 image
	echo "Error: please use the update_oztivo script, or key in clear, 9, 2, clear (on remote) on an existing 1.6 tivo."

	# disk in read only mode
	/hack/bin/makero.sh

	exit 1
fi

# Loop until the networking config file is OK
while true; do
  validate_oztivoconf $CONF_FILE
  if [ "$netcfg" = "OK" ]; then break; fi
  create_conf_file
done

# check the tclient.conf
if [ -z "`cat /etc/tclient.conf|grep 127::|grep 127.0.0.1`" ]; then
	# not configured to use emuproxyZA, rewrite tclient.conf
	cp $TCLIENT /etc/tclient.conf.backup
	cat $TCLIENT | sed 's/^127::.*/127::127.0.0.1:8000:::/' > $TCLIENT
fi

# backup the user's rc.sysinit files
echo "Backing up your rc.sysinit files."
cp /etc/rc.d/rc.sysinit /etc/rc.d/rc.sysinit.backup
cp /etc/rc.d/rc.sysinit.author /etc/rc.d/rc.sysinit.author.backup
cp /etc/rc.d/rc.net /etc/rc.d/rc.net.backup

# move resolv.conf, to make sure rsync creates the symlink
mv /etc/resolv.conf /etc/resolv.conf.backup

if [ "$VERSION" = "1.3" ]; then
	# need to upgrade to 1.4 first
	echo "Upgrading your 1.3 TiVo to 1.4, before upgrading to 1.6."
	echo "Please be patient, the following may take a while."
	if [ ! -f "/hack/13-14.tar.gz" ]; then
		# download tarball
		cd /hack
                echo "Doing $WGET $TARBALL"
		$WGET $TARBALL	
	fi

	if [ -z "$noflags" ]; then
		# unpack tarball
		cd /
		tar -zxvf /hack/13-14.tar.gz
		rm -f /hack/13-14.tar.gz
	fi
fi

# put disk in read/write mode still/again (funny auto ro remounts on 1.3)
/hack/bin/makerw.sh

# check excludes file
if [ ! -f /etc/update_exclude ]; then
	touch /etc/update_exclude
fi

# run rsync
echo "Now upgrading to 1.6."
cd /
/devbin/rsync $noflags -rvltpD 131.244.9.101::oztivo_1.6 . --exclude-from=/etc/update_exclude

# copy persist scripts in, so that GS messages get changed on the next boot
if [ -f /hack/var/persist.tar.gz ]; then
	# convoluted way to populate /var/persist
	# tar -z doesn't work to do this..
	cd /var
	cp /hack/var/persist.tar.gz /var
	mv /hack/var/persist.tar.gz /hack/var/used.persist.tar.gz
	gzip -d persist.tar.gz
	tar -xf persist.tar
	rm /var/persist.tar
	cd /
fi

# done

echo
echo "Displaying contents of /etc/oztivo.conf"
echo
cat /etc/oztivo.conf
echo
echo "Please check the details in the oztivo.conf file are correct"
echo "if not then please delete /etc/oztivo.conf"
echo "and run upgrade_oztivo again, selecting version 1.5"
echo
echo "Otherwise if all is ok, please reboot your TiVo"
echo "OzTiVo filesystem has been upgraded to 1.6"

# disk in read only mode
/hack/bin/makero.sh

exit 0
