#!/bin/bash

# v-update-sys-hestia-git
# Downloads and compiles/installs packages from GitHub repositories
# Options:  REPOSITORY BRANCH INSTALL [PACKAGES]
# Example:  v-update-sys-hestia-git hestiacp staging/beta install all
#           - Will download from the hestiacp repository
#           - Pulls code from staging/beta branch
#           - install: installs package immediately
#           - install-auto: installs package and schedules automatic updates from Git
#           - 'all': (optional) - compiles nginx and php alongside panel.
#                                 this option takes a long time, only use when needed


# Define download function
download_file() {
    local url=$1
    local destination=$2
    local force=$3

    # Default destination is the curent working directory
    local dstopt=""

    if [ ! -z "$(echo "$url" | grep -E "\.(gz|gzip|bz2|zip|xz)$")" ]; then
        # When an archive file is downloaded it will be first saved localy
        dstopt="--directory-prefix=$ARCHIVE_DIR"
        local is_archive="true"
        local filename="${url##*/}"
        if [ -z "$filename" ]; then
            >&2 echo "[!] No filename was found in url, exiting ($url)"
            exit 1
        fi
            if [ ! -z "$force" ] && [ -f "$ARCHIVE_DIR/$filename" ]; then
            rm -f $ARCHIVE_DIR/$filename
        fi
        elif [ ! -z "$destination" ]; then
            # Plain files will be written to specified location
            dstopt="-O $destination"
        fi
        # check for corrupted archive
        if [ -f "$ARCHIVE_DIR/$filename" ] && [ "$is_archive" = "true" ]; then
        tar -tzf "$ARCHIVE_DIR/$filename" > /dev/null 2>&1
        if [ $? -ne 0 ]; then
            >&2 echo "[!] Archive $ARCHIVE_DIR/$filename is corrupted, redownloading"
            rm -f $ARCHIVE_DIR/$filename
        fi
    fi

    if [ ! -f "$ARCHIVE_DIR/$filename" ]; then
        wget $url -q $dstopt --show-progress --progress=bar:force --limit-rate=3m
    fi

    if [ ! -z "$destination" ] && [ "$is_archive" = "true" ]; then
        if [ "$destination" = "-" ]; then
            cat "$ARCHIVE_DIR/$filename"
        elif [ -d "$(dirname $destination)" ]; then
            cp "$ARCHIVE_DIR/$filename" "$destination"
        fi
    fi
}

# Set compiling directory
BUILD_DIR='/tmp/hestiacp-src'
DEB_DIR="$BUILD_DIR/debs"
INSTALL_DIR='/usr/local/hestia'
ARCHIVE_DIR="${BUILD_DIR}/archive"

# Set command variables
fork=$1
branch=$2
install=$3
flags=$4

# Set Version for compiling
BUILD_VER=$(curl -s https://raw.githubusercontent.com/$fork/hestiacp/$branch/src/deb/hestia/control | grep "Version:" | cut -d' ' -f2)
BUILD_ARCH='amd64'
HESTIA_V="${BUILD_VER}_${BUILD_ARCH}"
NGINX_V=$(curl -s https://raw.githubusercontent.com/$fork/hestiacp/$branch/src/deb/nginx/control |grep "Version:" |cut -d' ' -f2)
OPENSSL_V='1.1.1g'
PCRE_V='8.43'
ZLIB_V='1.2.11'
PHP_V=$(curl -s https://raw.githubusercontent.com/$fork/hestiacp/$branch/src/deb/php/control |grep "Version:" |cut -d' ' -f2)

# Create build directories
rm -rf $BUILD_DIR
mkdir -p $DEB_DIR
mkdir -p $ARCHIVE_DIR

# Set package dependencies for compiling
SOFTWARE='build-essential libxml2-dev libz-dev libcurl4-gnutls-dev unzip openssl libssl-dev pkg-config setpriv'

# Define a timestamp function
timestamp() {
    date +%s
}

# Set install flags
if [ ! -z "$1" ]; then
    fork_check=$(curl -s --head -w %{http_code} https://raw.githubusercontent.com/$fork/hestiacp/main/src/deb/hestia/control -o /dev/null)
    if [ $fork_check -ne "200" ]; then
        echo "ERROR: invalid repository name specified."
        exit 1
    else
        echo "[!] Download code from GitHub repository: $fork"
        fork="$1"
    fi
else
    fork="hestiacp"
fi

if [ ! -z "$2" ]; then
    branch_check=$(curl -s --head -w %{http_code} https://raw.githubusercontent.com/$fork/hestiacp/$branch/src/deb/hestia/control -o /dev/null)
    if [ $branch_check -ne "200" ]; then
        echo "ERROR: invalid branch name specified."
        exit 1
    else
        /usr/local/hestia/bin/v-change-sys-config-value 'RELEASE_BRANCH' "$branch"
        echo "[!] Changed system release branch to: $branch."
    fi
else
    source /usr/local/hestia/conf/hestia.conf
    branch=$RELEASE_BRANCH
fi

if [ -z "$branch" ]; then
    echo "ERROR: No branch detected."
    exit
fi


# Install needed software
echo "[*] Updating APT package cache..."
apt-get -qq update > /dev/null 2>&1
echo "[*] Checking for missing dependencies and installing required libraries..."
apt-get -qq install -y $SOFTWARE > /dev/null 2>&1

# Fix for Debian PHP Envroiment
ln -s /usr/include/x86_64-linux-gnu/curl /usr/local/include/curl > /dev/null 2>&1

# Get system cpu cores
NUM_CPUS=$(grep "^cpu cores" /proc/cpuinfo | uniq |  awk '{print $4}')

# Check for existence of flags argument and set packages to build
if [ ! -z "$flags" ]; then
    if [ "$flags" = "all" ]; then
        HESTIA_B='true'
        NGINX_B='true'
        PHP_B='true'
    fi
else
    HESTIA_B='true'
fi

# Set git repository raw path
GIT_REP='https://raw.githubusercontent.com/'$fork'/hestiacp/'$branch'/src/deb'

# Generate Links for sourcecode
HESTIA_ARCHIVE_LINK='https://github.com/'$fork'/hestiacp/archive/'$branch'.tar.gz'
NGINX='https://nginx.org/download/nginx-'$NGINX_V'.tar.gz'
OPENSSL='https://www.openssl.org/source/openssl-'$OPENSSL_V'.tar.gz'
PCRE='https://ftp.pcre.org/pub/pcre/pcre-'$PCRE_V'.tar.gz'
ZLIB='https://www.zlib.net/zlib-'$ZLIB_V'.tar.gz'
PHP='http://de2.php.net/distributions/php-'$PHP_V'.tar.gz'

# Forward slashes in branchname are replaced with dashes to match foldername in github archive.
branch=$(echo "$branch" |sed 's/\//-/g');

#################################################################################
#
# Building hestia-nginx
#
#################################################################################

if [ "$NGINX_B" = true ] ; then

    echo "[*] Building Package: hestia-nginx (backend web server)..."
    # Change to build directory
    cd $BUILD_DIR

    # Check if target directory exist
    if [ -d $BUILD_DIR/hestia-nginx_$NGINX_V ]; then
          #mv $BUILD_DIR/hestia-nginx_$NGINX_V $BUILD_DIR/hestia-nginx_$NGINX_V-$(timestamp)
          rm -r $BUILD_DIR/hestia-nginx_$NGINX_V
    fi

    # Create directory
    mkdir $BUILD_DIR/hestia-nginx_$NGINX_V

    # Download and unpack source files
    download_file $NGINX | tar xz
    download_file $OPENSSL | tar xz
    download_file $PCRE | tar xz
    download_file $ZLIB | tar xz

    # Change to nginx directory
    cd nginx-$NGINX_V

    # configure nginx
    ./configure   --prefix=/usr/local/hestia/nginx \
                  --with-http_ssl_module \
                  --with-openssl=../openssl-$OPENSSL_V \
                  --with-openssl-opt=enable-ec_nistp_64_gcc_128 \
                  --with-openssl-opt=no-nextprotoneg \
                  --with-openssl-opt=no-weak-ssl-ciphers \
                  --with-openssl-opt=no-ssl3 \
                  --with-pcre=../pcre-$PCRE_V \
                  --with-pcre-jit \
                  --with-zlib=../zlib-$ZLIB_V

    # Check install directory and remove if exists
    if [ -d "$BUILD_DIR$INSTALL_DIR" ]; then
        rm -r "$BUILD_DIR$INSTALL_DIR"
    fi

    # Create the files and install them
    make -j $NUM_CPUS && make DESTDIR=$BUILD_DIR install

    # Cleare up unused files
    cd $BUILD_DIR
    rm -r nginx-$NGINX_V openssl-$OPENSSL_V pcre-$PCRE_V zlib-$ZLIB_V

    # Prepare Deb Package Folder Structure
    cd hestia-nginx_$NGINX_V/
    mkdir -p usr/local/hestia etc/init.d DEBIAN

    # Download control, postinst and postrm files
    cd DEBIAN
    download_file $GIT_REP/nginx/control
    download_file $GIT_REP/nginx/copyright
    download_file $GIT_REP/nginx/postinst
    download_file $GIT_REP/nginx/postrm

    # Set permission
    chmod +x postinst postrm

    # Move nginx directory
    cd ..
    mv $BUILD_DIR/usr/local/hestia/nginx usr/local/hestia/

    # Get Service File
    cd etc/init.d
    download_file $GIT_REP/nginx/hestia
    chmod +x hestia

    # Get nginx.conf
    cd ../../
    rm usr/local/hestia/nginx/conf/nginx.conf
    download_file $GIT_REP/nginx/nginx.conf -O usr/local/hestia/nginx/conf/nginx.conf

    # copy binary
    cp usr/local/hestia/nginx/sbin/nginx usr/local/hestia/nginx/sbin/hestia-nginx

    # change permission and build the package
    cd $BUILD_DIR
    chown -R  root:root hestia-nginx_$NGINX_V
    dpkg-deb --build hestia-nginx_$NGINX_V
    mv *.deb $DEB_DIR

    # clear up the source folder
    rm -r hestia-nginx_$NGINX_V
fi


#################################################################################
#
# Building hestia-php
#
#################################################################################

if [ "$PHP_B" = true ] ; then
    echo "[*] Building Package: hestia-php (backend engine)..."
    # Change to build directory
    cd $BUILD_DIR

    # Check if target directory exist
    if [ -d $BUILD_DIR/hestia-php_$PHP_V ]; then
          #mv $BUILD_DIR/hestia-php_$PHP_V $BUILD_DIR/hestia-php_$PHP_V-$(timestamp)
          rm -r $BUILD_DIR/hestia-php_$PHP_V
    fi

    # Create directory
    mkdir ${BUILD_DIR}/hestia-php_$PHP_V

    # Download and unpack source files
    download_file $PHP | tar xz

    # Change to php directory
    cd php-$PHP_V

    # Configure PHP
    ./configure     --prefix=/usr/local/hestia/php \
                    --enable-fpm \
                    --with-fpm-user=admin \
                    --with-fpm-group=admin \
                    --with-libdir=lib/x86_64-linux-gnu \
                    --with-mysqli \
                    --with-curl \
                    --enable-mbstring

    # Create the files and install them
    make -j $NUM_CPUS && make INSTALL_ROOT=$BUILD_DIR install

    # Cleare up unused files
    cd $BUILD_DIR
    rm -r php-$PHP_V

    # Prepare Deb Package Folder Structure
    cd hestia-php_$PHP_V/
    mkdir -p usr/local/hestia DEBIAN

    # Download control, postinst and postrm files
    cd DEBIAN
    download_file $GIT_REP/php/control
    download_file $GIT_REP/php/copyright

    # Move php directory
    cd ..
    mv ${BUILD_DIR}/usr/local/hestia/php usr/local/hestia/

    # Get php-fpm.conf
    download_file $GIT_REP/php/php-fpm.conf -O usr/local/hestia/php/etc/php-fpm.conf

    # Get php.ini
    download_file $GIT_REP/php/php.ini -O usr/local/hestia/php/lib/php.ini

    # copy binary
    cp usr/local/hestia/php/sbin/php-fpm usr/local/hestia/php/sbin/hestia-php

    # change permission and build the package
    cd $BUILD_DIR
    chown -R  root:root hestia-php_$PHP_V
    dpkg-deb --build hestia-php_$PHP_V
    mv *.deb $DEB_DIR

    # clear up the source folder
    rm -r hestia-php_$PHP_V
fi


#################################################################################
#
# Building hestia
#
#################################################################################

if [ "$HESTIA_B" = true ] ; then
    echo "[*] Building Package: hestia (Control Panel)..."
    # Change to build directory
    cd $BUILD_DIR

    # Check if target directory exist
    if [ -d $BUILD_DIR/hestia_$HESTIA_V ]; then
          #mv $BUILD_DIR/hestia_$HESTIA_V $BUILD_DIR/hestia_$HESTIA_V-$(timestamp)
          rm -r $BUILD_DIR/hestia_$HESTIA_V
    fi

    # Create directory
    mkdir $BUILD_DIR/hestia_$HESTIA_V

    # Download and unpack source files
    download_file $HESTIA_ARCHIVE_LINK '-' 'fresh' | tar xz

    # Prepare Deb Package Folder Structure
    cd hestia_$HESTIA_V/
    mkdir -p usr/local/hestia DEBIAN

    # Download control, postinst and postrm files
    cd DEBIAN
    download_file $GIT_REP/hestia/control
    download_file $GIT_REP/hestia/copyright
    download_file $GIT_REP/hestia/postinst

    # Set permission
    chmod +x postinst

    # Move needed directories
    cd $BUILD_DIR/hestiacp-$branch
    mv bin func install web ../hestia_$HESTIA_V/usr/local/hestia/

    # Set permission
    cd ../hestia_$HESTIA_V/usr/local/hestia/bin
    chmod +x *

    # change permission and build the package
    cd $BUILD_DIR
    chown -R root:root hestia_$HESTIA_V
    dpkg-deb --build hestia_$HESTIA_V
    mv *.deb $DEB_DIR

    # clear up the source folder
    rm -r hestia_$HESTIA_V
    rm -r hestiacp-$branch
fi


#################################################################################
#
# Install Packages
#
#################################################################################

# Define package installation functions
warning_message() {
    echo ""
    echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
    echo "WARNING - Development builds should not be installed on"
    echo "systems with live production data without understanding"
    echo "the potential risks that are involved!"
    echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
    echo ""
}

install_build() {
    echo "Installing packages..."
    for i in $DEB_DIR/*.deb; do
        # Install all available packages
        dpkg -i $i
    done
    # Remove temporary files
    rm -rf $BUILD_DIR
}

# Define installation routine

if [ "$install" = "install" ] || [ "$install" = "yes" ] || [ "$install" = "install-auto" ]; then 
    install_build
    if [ "$install" = "install-auto" ]; then
        $HESTIA/bin/v-add-cron-hestia-autoupdate git
    fi
else
    warning_message
    read -p "Do you wish to proceed with the installation? [y/n] " answer
    if [ "$answer" = 'y' ] || [ "$answer" = 'Y'  ]; then
        install_build
        unset $answer
    else
        echo "Installation of development build aborted."
        echo "Removing temporary files..."
        rm -rf $BUILD_DIR
        unset $answer
        echo ""
    fi
fi
