#!/bin/bash

# CDKey - CDSoft bootable USB key
# Copyright (C) 2011-2012 Christophe Delord
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#
# For further information about CDKey you can visit
# http://cdsoft.fr/cdkey

#######################################################################
# CDKey content
#######################################################################

LABEL=_CDKEY_

cdkey()
{
    (   NAME="System Rescue CD & save.py"
        VERSION=2.7.0
        URL=http://sunet.dl.sourceforge.net/project/systemrescuecd/sysresccd-x86/$VERSION/systemrescuecd-x86-$VERSION.iso
        SAVE=http://www.cdsoft.fr/save/save.py
        $SRCD && free 400 && install_SRCD
    )
    (   NAME="Avira Antivir"
        URL=http://dlpro.antivir.com/package/rescue_system/common/en/rescue_system-common-en.iso
        $ANTIVIR && free 250 && install_ANTIVIR
    )
    (   NAME="Linux Mint Gnome (32 bit)"
        VERSION=12
        URL=http://mirrors.ordimatic.net/mint/stable/$VERSION/linuxmint-$VERSION-gnome-dvd-32bit.iso
        $MINT && $GNOME && $I386 && free 1200 && install_UBUNTU
    )
    (   NAME="Linux Mint Gnome (64 bit)"
        VERSION=12
        URL=http://mirrors.ordimatic.net/mint/stable/$VERSION/linuxmint-$VERSION-gnome-dvd-64bit.iso
        $MINT && $GNOME && $AMD64 && free 1200 && install_UBUNTU
    )
    (   NAME="Linux Mint KDE   (32 bit)"
        VERSION=12
        URL=http://mirrors.ordimatic.net/mint/stable/$VERSION/linuxmint-$VERSION-kde-dvd-32bit.iso
        $MINT && $KDE && $I386 && free 1200 && install_UBUNTU
    )
    (   NAME="Linux Mint KDE   (64 bit)"
        VERSION=12
        URL=http://mirrors.ordimatic.net/mint/stable/$VERSION/linuxmint-$VERSION-kde-dvd-64bit.iso
        $MINT && $KDE && $AMD64 && free 1200 && install_UBUNTU
    )
    (   NAME="Linux Mint LXDE  (32 bit)"
        VERSION=12
        URL=http://mirrors.ordimatic.net/mint/stable/$VERSION/linuxmint-$VERSION-lxde-cd-32bit.iso
        $MINT && $LXDE && $I386 && free 700 && install_UBUNTU
    )
    (   NAME="Ubuntu  (Gnome, 32 bit)"
        VERSION=12.04
        CODE=precise
        URL=http://www-ftp.lip6.fr/pub/linux/distributions/Ubuntu/releases/$CODE/ubuntu-$VERSION-desktop-i386.iso
        $UBUNTU && $GNOME && $I386 && free 750 && install_UBUNTU
    )
    (   NAME="Ubuntu  (Gnome, 64 bit)"
        VERSION=12.04
        CODE=precise
        URL=http://www-ftp.lip6.fr/pub/linux/distributions/Ubuntu/releases/$CODE/ubuntu-$VERSION-desktop-amd64.iso
        $UBUNTU && $GNOME && $AMD64 && free 750 && install_UBUNTU
    )
    (   NAME="Kubuntu (KDE,   32 bit)"
        VERSION=12.04
        CODE=precise
        URL=http://www-ftp.lip6.fr/pub/linux/distributions/Ubuntu/releases/kubuntu/$CODE/kubuntu-$VERSION-desktop-i386.iso
        $UBUNTU && $KDE && $I386 && free 750 && install_UBUNTU
    )
    (   NAME="Kubuntu (KDE,   64 bit)"
        VERSION=12.04
        CODE=precise
        URL=http://www-ftp.lip6.fr/pub/linux/distributions/Ubuntu/releases/kubuntu/$CODE/kubuntu-$VERSION-desktop-amd64.iso
        $UBUNTU && $KDE && $AMD64 && free 750 && install_UBUNTU
    )
    (   NAME="Xubuntu (XFCE,  32 bit)"
        VERSION=12.04
        CODE=precise
        URL=ftp://ftp.free.fr/mirrors/ftp.xubuntu.com/releases/$VERSION/release/xubuntu-$VERSION-desktop-i386.iso
        $UBUNTU && $XFCE && $I386 && free 750 && install_UBUNTU
    )
    (   NAME="Xubuntu (XFCE,  64 bit)"
        VERSION=12.04
        CODE=precise
        URL=ftp://ftp.free.fr/mirrors/ftp.xubuntu.com/releases/$VERSION/release/xubuntu-$VERSION-desktop-amd64.iso
        $UBUNTU && $XFCE && $AMD64 && free 750 && install_UBUNTU
    )
    (   NAME="Debian stable   (32 bit)"
        VERSION=stable
        ISO=debian-$VERSION-$(echo $NAME | tr -d -c "0-9").iso
        URL=http://ftp.nl.debian.org/debian/dists/$VERSION/main/installer-i386/current/images/netboot/mini.iso
        $DEBIAN && $I386 && free 18 && install_DEBIAN
    )
    (   NAME="Debian stable   (64 bit)"
        VERSION=stable
        ISO=debian-$VERSION-$(echo $NAME | tr -d -c "0-9").iso
        URL=http://ftp.nl.debian.org/debian/dists/$VERSION/main/installer-i386/current/images/netboot/mini.iso
        $DEBIAN && $AMD64 && free 18 && install_DEBIAN
    )
    (   NAME="Debian unstable (32 bit)"
        VERSION=unstable
        ISO=debian-$VERSION-$(echo $NAME | tr -d -c "0-9").iso
        URL=http://ftp.nl.debian.org/debian/dists/$VERSION/main/installer-i386/current/images/netboot/mini.iso
        $DEBIAN && $I386 && free 18 && install_DEBIAN
    )
    (   NAME="Debian unstable (64 bit)"
        VERSION=unstable
        ISO=debian-$VERSION-$(echo $NAME | tr -d -c "0-9").iso
        URL=http://ftp.nl.debian.org/debian/dists/$VERSION/main/installer-i386/current/images/netboot/mini.iso
        $DEBIAN && $AMD64 && free 18 && install_DEBIAN
    )
}

#######################################################################
# Check root permissions
#######################################################################

export PATH=$PATH:/sbin:/usr/sbin
[ "$UID" -eq 0 ] || exec sudo $0 $*

#######################################################################
# CDKey profile
#######################################################################

if [ $# -gt 0 ]
then
    AMD64=false
    I386=false
    SRCD=false
    ANTIVIR=false
    MINT=false
    UBUNTU=false
    DEBIAN=false
    GNOME=false
    KDE=false
    XFCE=false
    LXDE=false
    while [ $1 ]
    do
        case "$(echo $1 | tr A-Z a-z)" in
            (*64*)      AMD64=true;;
            (*32*)      I386=true;;
            (*save*)    SRCD=true;;
            (*srcd*)    SRCD=true;;
            (*antivir*) ANTIVIR=true;;
            (*mint*)    MINT=true;;
            (*ubuntu*)  UBUNTU=true;;
            (*kubuntu*) UBUNTU=true; KDE=true;;
            (*xubuntu*) UBUNTU=true; XFCE=true;;
            (*debian*)  DEBIAN=true;;
            (*gnome*)   GNOME=true;;
            (*kde*)     KDE=true;;
            (*xfce*)    XFCE=true;;
            (*lxde*)    LXDE=true;;
        esac
        shift
    done
    $AMD64 || I386=true
    if $UBUNTU
    then
        $KDE || $XFCE || GNOME=true
    fi
    if $MINT
    then
        $KDE || $LXDE || GNOME=true
    fi
else
    AMD64=true
    I386=true
    SRCD=true
    ANTIVIR=true
    MINT=true
    UBUNTU=true
    DEBIAN=true
    GNOME=true
    KDE=true
    XFCE=true
    LXDE=true
fi

#######################################################################
# Tools
#######################################################################

error()
{
    echo "$*"
    exit 1
}

free()
{
    test $(df /tmp/cdkey | tail -1 | awk '{print $4}') -ge $[$1*1024]
}

get()
{
    [ -e $2 ] && return
    wget $1 -O $2
    user=$(stat -c %U $0)
    chown $user:$user $2
    touch $2
}

extract_iso()
{
    mkdir -p /tmp/iso
    mount -o loop,ro $1 /tmp/iso
    mkdir -p $2
    cp -a /tmp/iso/* $2/
    umount /tmp/iso
    rmdir /tmp/iso
}

extract()
{
    mkdir -p /tmp/iso
    mount -o loop,ro $1 /tmp/iso
    src=$2
    mkdir -p $src
    shift 2
    while [ $1 ]
    do
        cp /tmp/iso/$1 $src/
        shift
    done
    umount /tmp/iso
    rmdir /tmp/iso
}

separator()
{
    if ! grep -Fq -- "-- $1" $MENU
    then
        cat <<EOF >> $MENU
LABEL -- $1
    MENU DISABLE

EOF
    fi
}

help()
{
    echo TEXT HELP
    echo $* | fold -s -w 60 | sed 's/^/  /'
    echo ENDTEXT
}

#######################################################################
# Search a CDKey partition
#######################################################################

MAXSIZE=16

echo "Choose the CDKey partition:"

parts=( )
menu=( )
i=0
blkid -g
while read major minor blocks name
do
    if [[ "$name" =~ sd[a-z][1-9] ]]
    then
        [ $blocks -le $[MAXSIZE*1024*1024] ] || continue
        part_type=$(blkid /dev/$name -o value -s TYPE)
        part_label=$(blkid /dev/$name -o value -s LABEL)
        size="$[blocks/1024/1024] GiB"
        [ $blocks -le $[8*1024*1024] ] && size="$[blocks/1024] MiB"
        [ "$part_type" = vfat ] || continue
        [ -z "$part_label" -o "${part_label:0:1}" = "_" ] || continue
        parts[$i]=$name
        menu[$i]="$part_label ($name, $size)"
        i=$[i+1]
    fi
done < /proc/partitions

select item in "${menu[@]}"
do
    [ -n "$item" ] || continue
    for ((i=0; i < ${#menu[*]}; i++))
    do
        [ "$item" = "${menu[$i]}" ] && break
    done
    if [ "$item" = "${menu[$i]}" ]
    then
        PART=${parts[$i]}
        DEV=${PART:0:3}
        break
    fi
done

[ -n "$PART" ] || error "No CDKey partition found"

#######################################################################
# Format the CDKey partition
#######################################################################

echo "Format $PART"
umount /dev/$PART 2>/dev/null
#cat /usr/lib/syslinux/mbr.bin > /dev/$DEV
mkfs.vfat -F 32 -n "$LABEL" /dev/$PART
syslinux -ma /dev/$PART
sync

#######################################################################
# Mount the CDKey partition
#######################################################################

MENU=/tmp/cdkey/syslinux/syslinux.cfg

mount_cdkey()
{
    mkdir -p /tmp/cdkey
    mount /dev/$PART /tmp/cdkey
    mkdir -p $(dirname $MENU)
    cp -a /usr/lib/syslinux/{memdisk,vesamenu.c32,chain.c32} $(dirname $MENU)/
    get http://cdsoft.fr/cdkey/cdkey.png cdkey.png
    cp cdkey.png $(dirname $MENU)/
    cat <<EOF > $MENU
UI vesamenu.c32
MENU TITLE C D K e y
MENU BACKGROUND cdkey.png

MENU WIDTH 80
MENU MARGIN ???
MENU PASSWORDMARGIN 3
MENU ROWS ???
MENU CMDLINEROW ???
MENU HELPMSGROW 27
MENU HSHIFT 0
MENU VSHIFT 0
MENU TABMSGROW ???

MENU COLOR border       34;40   #ff4c628b #00000000 none
MENU COLOR title        1;34;40 #ff4c628b #00000000 none
MENU COLOR sel          7;34;40 #ffeeeeee #ff4c628b none
MENU COLOR unsel        34;40   #ff4c628b #00000000 none
MENU COLOR disabled     30;40   #ff263145 #20777777 none
MENU COLOR help         34;40   #ff4c628b #00000000 none
MENU COLOR msg07        34;40   #ff4c628b #00000000 none
MENU COLOR tabmsg       34;40   #ff4c628b #00000000 none
MENU COLOR screen       34;40   #ffffffff #00000000 none
MENU COLOR scrollbar    34;40   #ff4c628b #00000000 none
MENU COLOR cmdmark      34;40   #ff4c628b #00000000 none
MENU COLOR cmdline      34;40   #ff4c628b #00000000 none

EOF
}

umount_cdkey()
{
    # Fix syslinux menu
    N=$(grep "^\(MENU SEPARATOR\|LABEL\)" $MENU | wc -l)
    [ $N -gt 21 ] && N=21
    sed -i "s/^MENU ROWS .*/MENU ROWS $N/" $MENU
    #sed -i "s/^MENU HELPMSGROW .*/MENU HELPMSGROW $[N+6]/" $MENU
    sed -i "s/^MENU CMDLINEROW .*/MENU CMDLINEROW $[N+6]/" $MENU
    sed -i "s/^MENU TABMSGROW .*/MENU TABMSGROW $[N+6]/" $MENU
    M=$(python -c "W=max(len(l[6:].strip()) for l in open('$MENU') if l.startswith('LABEL ')); print int(40-W/2)-2-W%2")
    sed -i "s/^MENU MARGIN .*/MENU MARGIN $M/" $MENU
    umount /tmp/cdkey
    rmdir /tmp/cdkey
    sync
    echo "Your CDKey is ready."
}

mount_cdkey
trap 'umount_cdkey' EXIT

#######################################################################
# Install CDKey packages
#######################################################################

install_SRCD()
{
    echo $NAME
    ROOT=srcd
    ISO=$(basename $URL)
    SRCD=/tmp/cdkey/$ROOT
    get $URL $ISO
    extract_iso $ISO $SRCD
    mv $SRCD/isolinux/{rescuecd,initram.igz,memdisk} $SRCD/
    rm -rf $SRCD/{bootprog,isolinux,usb_inst,usbstick.html,usb_inst.sh}
    cat $SRCD/bootdisk/freedos.img | gunzip > /tmp/freedos
    python -c "f=open('/tmp/freedos','rb'); s=f.read().replace(':: ?mkeyb GR', 'mkeyb ${LANG:0:2}    '); f.close(); open('/tmp/freedos','wb').write(s)"
    cat /tmp/freedos | gzip -9 > $SRCD/bootdisk/freedos.img
    cat <<EOF > $SRCD/autorun
RC=/root/.zsh/rc/save.rc
mkdir -p \$(dirname \$RC)
cat <<. > \$RC
while [ \\\$(tty) = /dev/tty1 ]
do
    python /livemnt/boot/save.py
    sync
    echo "Press 'enter' to continue"
    line
done
.
chmod +x \$RC
EOF
    get $SAVE save.py
    cp save.py /tmp/cdkey/
    separator "Connected (DHCP)"
    cat <<EOF >> $MENU
LABEL Save
    KERNEL /$ROOT/rescuecd
    APPEND subdir=$ROOT setkmap=${LANG:0:2} dodhcp ar_nowait
    INITRD /$ROOT/initram.igz
    $(help Start save.py to backup and restore your computer)

LABEL System Rescue CD (Xorg)
    KERNEL /$ROOT/rescuecd
    APPEND subdir=$ROOT setkmap=${LANG:0:2} dodhcp ar_disable dostartx
    INITRD /$ROOT/initram.igz
    $(help Start System Rescue CD graphic interface from $(basename $URL))

LABEL System Rescue CD (Console)
    KERNEL /$ROOT/rescuecd
    APPEND subdir=$ROOT setkmap=${LANG:0:2} dodhcp ar_disable
    INITRD /$ROOT/initram.igz
    $(help Start System Rescue CD console from $(basename $URL))

EOF
    separator "Local (no DHCP)"
    cat <<EOF >> $MENU
LABEL Save
    MENU DEFAULT
    KERNEL /$ROOT/rescuecd
    APPEND subdir=$ROOT setkmap=${LANG:0:2} ar_nowait
    INITRD /$ROOT/initram.igz
    $(help Start save.py to backup and restore your computer)

LABEL System Rescue CD (Xorg)
    KERNEL /$ROOT/rescuecd
    APPEND subdir=$ROOT setkmap=${LANG:0:2} ar_disable dostartx
    INITRD /$ROOT/initram.igz
    $(help Start System Rescue CD graphic interface from $(basename $URL))

LABEL System Rescue CD (Console)
    KERNEL /$ROOT/rescuecd
    APPEND subdir=$ROOT setkmap=${LANG:0:2} ar_disable
    INITRD /$ROOT/initram.igz
    $(help Start System Rescue CD console from $(basename $URL))

EOF
    separator "Utilities"
    cat <<EOF >> $MENU
LABEL FreeDos
    KERNEL /$ROOT/memdisk
    APPEND floppy
    INITRD /$ROOT/bootdisk/freedos.img
    $(help "Start FreeDos (free MS DOS alternative based on $(basename $URL))")

LABEL Memtest86+
    KERNEL /$ROOT/bootdisk/memtestp
    $(help "Test your RAM (based on $(basename $URL))")

EOF
}

install_ANTIVIR()
{
    echo $NAME
    ROOT=avira
    ISO=$(basename $URL)
    ANTIVIR=/tmp/cdkey/$ROOT
    if [ -e $ISO ]
    then
        AGE=$[($(date +%s) - $(stat -c %Y $ISO))/60/60/24]
        [ $AGE -gt 3 ] && rm -f $ISO
    fi
    get $URL $ISO
    extract_iso $ISO $ANTIVIR
    mv $ANTIVIR/{antivir,avupdate,system} /tmp/cdkey
    (cd /tmp/cdkey/avupdate/unix; ./avupdate)
    rm -rf $ANTIVIR/{html,autorun.inf,autorun_usb.inf,avira.ico,index.html,isolinux.bin,isolinux.cfg,welcome.msg}
    separator "Antivirus"
    cat <<EOF >> $MENU
LABEL $NAME
    KERNEL /$ROOT/vmlinuz
    APPEND ramdisk_size=133551 root=/dev/ram0 rw console=/dev/vc/4
    INITRD /$ROOT/initrd.gz
    $(help "Scan your computer and remove viruses (based on $NAME)")

EOF
}

install_UBUNTU()
{
    echo $NAME
    ROOT=ubuntu
    ISO=$(basename $URL)
    UBUNTU=/tmp/cdkey/$ROOT
    get $URL $ISO
    mkdir -p $UBUNTU
    cp $ISO $UBUNTU/
    extract $ISO $UBUNTU wubi.exe 2>/dev/null
    extract $ISO $UBUNTU mint4win.exe 2>/dev/null
    extract $ISO $UBUNTU/${ISO/.iso} /casper/vmlinuz casper/initrd.lz
    case "$NAME" in
        (*Mint*)    separator "Linux Mint"; seed=mint.seed;;
        (*)         separator "Ubuntu";     seed=ubuntu.seed;;
    esac
    cat <<EOF >> $MENU
LABEL $NAME
    KERNEL /$ROOT/${ISO/.iso}/vmlinuz
    APPEND locale=${LANG:0:5} bootkbd=${LANG:0:2} console-setup/layoutcode=${LANG:0:2} file=/cdrom/preseed/$seed boot=casper iso-scan/filename=/$ROOT/$ISO noeject noprompt --
    INITRD /$ROOT/${ISO/.iso}/initrd.lz
    $(help "Start $NAME from $(basename $URL)")

EOF
}

install_DEBIAN()
{
    echo $NAME
    ROOT=debian
    DEBIAN=/tmp/cdkey/$ROOT
    if [ -e $ISO ]
    then
        AGE=$[($(date +%s) - $(stat -c %Y $ISO))/60/60/24]
        [ $AGE -gt 60 ] && rm -f $ISO
    fi
    get $URL $ISO
    extract_iso $ISO $DEBIAN/${ISO/.iso}
    separator "Debian installer"
    cat <<EOF >> $MENU
LABEL $NAME
    KERNEL /$ROOT/${ISO/.iso}/linux
    APPEND vga=788
    INITRD /$ROOT/${ISO/.iso}/initrd.gz
    $(help "Install $NAME from Internet (based on $(basename $URL))")

EOF
}

cdkey

