#!/bin/bash
# +--------------------------------------------------------------------------+
# | OpenFW UTM Community                                                          |
# +--------------------------------------------------------------------------+

SWROOT="/var/efw"
CONF_FILE="${SWROOT}/external-backups/settings"
BASE_PATH="/var/efw/external-backups"
CRON_FILE="/etc/cron.d/external-backups"
LOG_FILE="/var/log/messages"

BACKUP_TYPE=""
GLOBAL_MIRROR="off"

MEGA_ENABLED="off"
MEGA_USER=""
MEGA_PASSWORD=""
MEGA_DIR=""

FTP_ENABLED="off"
FTP_HOST=""
FTP_USER=""
FTP_PASSWORD=""
FTP_DIR=""
FTP_PORT="21"
FTP_PASSIVE="off"

SFTP_ENABLED="off"
SFTP_HOST=""
SFTP_USER=""
SFTP_PASSWORD=""
SFTP_DIR=""
SFTP_PORT="22"

SMB_ENABLED="off"
SMB_HOST=""
SMB_DOMAIN=""
SMB_USER=""
SMB_PASSWORD=""
SMB_DIR=""

GDRIVE_ENABLED="off"
GDRIVE_DIR="CONFIGS"

LOCAL_BACKUP_DIR="/var/backups/"

mkdir -p "$BASE_PATH"

load_config() {
    if [ -f "$CONF_FILE" ]; then
        while IFS='=' read -r key value; do
            key=$(echo "$key" | tr -d '\r' | xargs)
            value=$(echo "$value" | tr -d '\r' | xargs)
            [ -z "$key" ] && continue
            case "$key" in
                BACKUP_TYPE) BACKUP_TYPE="$value" ;;
                GLOBAL_MIRROR) GLOBAL_MIRROR="$value" ;;
                MEGA_ENABLED) MEGA_ENABLED="$value" ;;
                MEGA_USER) MEGA_USER="$value" ;;
                MEGA_PASSWORD) MEGA_PASSWORD="$value" ;;
                MEGA_DIR) MEGA_DIR="$value" ;;
                FTP_ENABLED) FTP_ENABLED="$value" ;;
                FTP_HOST) FTP_HOST="$value" ;;
                FTP_USER) FTP_USER="$value" ;;
                FTP_PASSWORD) FTP_PASSWORD="$value" ;;
                FTP_DIR) FTP_DIR="$value" ;;
                FTP_PORT) FTP_PORT="$value" ;;
                FTP_PASSIVE) FTP_PASSIVE="$value" ;;
                SFTP_ENABLED) SFTP_ENABLED="$value" ;;
                SFTP_HOST) SFTP_HOST="$value" ;;
                SFTP_USER) SFTP_USER="$value" ;;
                SFTP_PASSWORD) SFTP_PASSWORD="$value" ;;
                SFTP_DIR) SFTP_DIR="$value" ;;
                SFTP_PORT) SFTP_PORT="$value" ;;
                SMB_ENABLED) SMB_ENABLED="$value" ;;
                SMB_HOST) SMB_HOST="$value" ;;
                SMB_DOMAIN) SMB_DOMAIN="$value" ;;
                SMB_USER) SMB_USER="$value" ;;
                SMB_PASSWORD) SMB_PASSWORD="$value" ;;
                SMB_DIR) SMB_DIR="$value" ;;
                GDRIVE_ENABLED) GDRIVE_ENABLED="$value" ;;
                GDRIVE_DIR) GDRIVE_DIR="$value" ;;
            esac
        done < "$CONF_FILE"
    fi
}

get_cron_value() {
    local prefix="$1"
    local field="$2"
    local val=""
    if [ -f "$CONF_FILE" ]; then
        val=$(grep "^${prefix}_CRON_${field}=" "$CONF_FILE" | cut -d'=' -f2- | tr -d '\r' | xargs)
    fi
    if [ -z "$val" ] || [[ "$val" == *"|"* ]]; then
        echo "*"
    else
        echo "$val"
    fi
}

obscure_password() {
    local plaintext="$1"
    rclone obscure "$plaintext" 2>/dev/null | tr -d '\n' | tr -d '\r'
}

generate_mega_conf() {
    if [ "$MEGA_ENABLED" = "on" ] && [ -n "$MEGA_USER" ] && [ -n "$MEGA_PASSWORD" ]; then
        local obscured_pass=$(obscure_password "$MEGA_PASSWORD")
        cat <<EOF > "$BASE_PATH/mega.conf"
[mega]
type = mega
user = $MEGA_USER
pass = $obscured_pass
EOF
        chmod 600 "$BASE_PATH/mega.conf"
    else
        rm -f "$BASE_PATH/mega.conf"
    fi
}

generate_ftp_conf() {
    if [ "$FTP_ENABLED" = "on" ] && [ -n "$FTP_HOST" ]; then
        local obscured_pass=$(obscure_password "$FTP_PASSWORD")
        cat <<EOF > "$BASE_PATH/ftp.conf"
[ftp]
type = ftp
host = $FTP_HOST
port = $FTP_PORT
user = $FTP_USER
pass = $obscured_pass
EOF
        chmod 600 "$BASE_PATH/ftp.conf"
    else
        rm -f "$BASE_PATH/ftp.conf"
    fi
}

generate_sftp_conf() {
    if [ "$SFTP_ENABLED" = "on" ] && [ -n "$SFTP_HOST" ]; then
        local obscured_pass=$(obscure_password "$SFTP_PASSWORD")
        cat <<EOF > "$BASE_PATH/sftp.conf"
[sftp]
type = sftp
host = $SFTP_HOST
port = $SFTP_PORT
user = $SFTP_USER
pass = $obscured_pass
EOF
        chmod 600 "$BASE_PATH/sftp.conf"
    else
        rm -f "$BASE_PATH/sftp.conf"
    fi
}

generate_smb_conf() {
    if [ "$SMB_ENABLED" = "on" ] && [ -n "$SMB_HOST" ] && [ -n "$SMB_DIR" ]; then
        local obscured_pass=$(obscure_password "$SMB_PASSWORD")
        cat <<EOF > "$BASE_PATH/smb.conf"
[smb]
type = smb
host = $SMB_HOST
user = $SMB_USER
pass = $obscured_pass
domain = $SMB_DOMAIN
EOF
        chmod 600 "$BASE_PATH/smb.conf"
    else
        rm -f "$BASE_PATH/smb.conf"
    fi
}

generate_gdrive_conf() {
    local token_file="$BASE_PATH/gdrive-token.json"
    local conf_file="$BASE_PATH/gdrive.conf"

    if [ -s "$token_file" ]; then
        if [ ! -f "$conf_file" ] || [ "$token_file" -nt "$conf_file" ]; then
            local raw_token=$(cat "$token_file" | tr -d '\n' | tr -d '\r')
            
            if [ -n "$raw_token" ]; then
                cat <<EOF > "$conf_file"
[gdrive]
type = drive
scope = drive
token = $raw_token
EOF
                chmod 600 "$conf_file"
            fi
        fi
    fi
}

update_cron() {
    echo "# Auto-generated by external-backups script. Do not edit directly." > "$CRON_FILE"
    
    if [ "$MEGA_ENABLED" = "on" ] ; then
        echo "$(get_cron_value MEGA MIM) $(get_cron_value MEGA HOR) $(get_cron_value MEGA DIA_MES) $(get_cron_value MEGA MES) $(get_cron_value MEGA DIA_SEM) root /usr/local/bin/external-backups --mega-cron" >> "$CRON_FILE"
    fi
    if [ "$FTP_ENABLED" = "on" ] ; then
        echo "$(get_cron_value FTP MIM) $(get_cron_value FTP HOR) $(get_cron_value FTP DIA_MES) $(get_cron_value FTP MES) $(get_cron_value FTP DIA_SEM) root /usr/local/bin/external-backups --ftp-cron" >> "$CRON_FILE"
    fi
    if [ "$SFTP_ENABLED" = "on" ] ; then
        echo "$(get_cron_value SFTP MIM) $(get_cron_value SFTP HOR) $(get_cron_value SFTP DIA_MES) $(get_cron_value SFTP MES) $(get_cron_value SFTP DIA_SEM) root /usr/local/bin/external-backups --sftp-cron" >> "$CRON_FILE"
    fi
    if [ "$SMB_ENABLED" = "on" ] ; then
        echo "$(get_cron_value SMB MIM) $(get_cron_value SMB HOR) $(get_cron_value SMB DIA_MES) $(get_cron_value SMB MES) $(get_cron_value SMB DIA_SEM) root /usr/local/bin/external-backups --smb-cron" >> "$CRON_FILE"
    fi
    if [ "$GDRIVE_ENABLED" = "on" ] ; then
        echo "$(get_cron_value GDRIVE MIM) $(get_cron_value GDRIVE HOR) $(get_cron_value GDRIVE DIA_MES) $(get_cron_value GDRIVE MES) $(get_cron_value GDRIVE DIA_SEM) root /usr/local/bin/external-backups --gdrive-cron" >> "$CRON_FILE"
    fi

    chmod 644 "$CRON_FILE"
    /etc/init.d/fcron restart >/dev/null 2>&1
}

write_log() {
    local msg="$1"
    local timestamp=$(date "+%b %d %H:%M:%S")
    local hostname=$(hostname -s)
    echo "${timestamp} ${hostname} backup[$$]: ${msg}" >> "$LOG_FILE"
}

do_mega_backup() {
    [ "$MEGA_ENABLED" != "on" ] && return 1
    [ ! -f "$BASE_PATH/mega.conf" ] && return 1
    
    local rclone_log=$(mktemp)
    local status=0

    if [ "$GLOBAL_MIRROR" = "on" ]; then
        rclone sync "$LOCAL_BACKUP_DIR" "mega:$MEGA_DIR" --config "$BASE_PATH/mega.conf" --log-level NOTICE 2> "$rclone_log" >/dev/null
        status=$?
    else
        rclone copy "$LOCAL_BACKUP_DIR" "mega:$MEGA_DIR" --config "$BASE_PATH/mega.conf" --log-level NOTICE 2> "$rclone_log" >/dev/null
        status=$?
    fi

    if [ -s "$rclone_log" ]; then
        while IFS= read -r line; do
            write_log "rclone: $line"
        done < "$rclone_log"
    fi

    rm -f "$rclone_log"
    return $status
}

do_ftp_backup() {
    [ "$FTP_ENABLED" != "on" ] && return 1
    [ ! -f "$BASE_PATH/ftp.conf" ] && return 1
    
    local rclone_log=$(mktemp)
    local status=0

    if [ "$GLOBAL_MIRROR" = "on" ]; then
        rclone sync "$LOCAL_BACKUP_DIR" "ftp:$FTP_DIR" --config "$BASE_PATH/ftp.conf" --log-level NOTICE 2> "$rclone_log" >/dev/null
        status=$?
    else
        rclone copy "$LOCAL_BACKUP_DIR" "ftp:$FTP_DIR" --config "$BASE_PATH/ftp.conf" --log-level NOTICE 2> "$rclone_log" >/dev/null
        status=$?
    fi

    if [ -s "$rclone_log" ]; then
        while IFS= read -r line; do
            write_log "rclone: $line"
        done < "$rclone_log"
    fi

    rm -f "$rclone_log"
    return $status
}

do_sftp_backup() {
    [ "$SFTP_ENABLED" != "on" ] && return 1
    [ ! -f "$BASE_PATH/sftp.conf" ] && return 1
    
    local rclone_log=$(mktemp)
    local status=0

    if [ "$GLOBAL_MIRROR" = "on" ]; then
        rclone sync "$LOCAL_BACKUP_DIR" "sftp:$SFTP_DIR" --config "$BASE_PATH/sftp.conf" --log-level NOTICE 2> "$rclone_log" >/dev/null
        status=$?
    else
        rclone copy "$LOCAL_BACKUP_DIR" "sftp:$SFTP_DIR" --config "$BASE_PATH/sftp.conf" --log-level NOTICE 2> "$rclone_log" >/dev/null
        status=$?
    fi

    if [ -s "$rclone_log" ]; then
        while IFS= read -r line; do
            write_log "rclone: $line"
        done < "$rclone_log"
    fi

    rm -f "$rclone_log"
    return $status
}

do_smb_backup() {
    [ "$SMB_ENABLED" != "on" ] && return 1
    [ ! -f "$BASE_PATH/smb.conf" ] && return 1
    
    local rclone_log=$(mktemp)
    local status=0

    if [ "$GLOBAL_MIRROR" = "on" ]; then
        rclone sync "$LOCAL_BACKUP_DIR" "smb:$SMB_DIR" --config "$BASE_PATH/smb.conf" --log-level NOTICE 2> "$rclone_log" >/dev/null
        status=$?
    else
        rclone copy "$LOCAL_BACKUP_DIR" "smb:$SMB_DIR" --config "$BASE_PATH/smb.conf" --log-level NOTICE 2> "$rclone_log" >/dev/null
        status=$?
    fi

    if [ -s "$rclone_log" ]; then
        while IFS= read -r line; do
            write_log "rclone: $line"
        done < "$rclone_log"
    fi

    rm -f "$rclone_log"
    return $status
}

do_gdrive_backup() {
    [ "$GDRIVE_ENABLED" != "on" ] && return 1
    [ ! -f "$BASE_PATH/gdrive.conf" ] && return 1
    
    local rclone_log=$(mktemp)
    local status=0

    if [ "$GLOBAL_MIRROR" = "on" ]; then
        rclone sync "$LOCAL_BACKUP_DIR" "gdrive:$GDRIVE_DIR" --config "$BASE_PATH/gdrive.conf" --log-level NOTICE 2> "$rclone_log" >/dev/null
        status=$?
    else
        rclone copy "$LOCAL_BACKUP_DIR" "gdrive:$GDRIVE_DIR" --config "$BASE_PATH/gdrive.conf" --log-level NOTICE 2> "$rclone_log" >/dev/null
        status=$?
    fi

    if [ -s "$rclone_log" ]; then
        while IFS= read -r line; do
            write_log "rclone: $line"
        done < "$rclone_log"
    fi

    rm -f "$rclone_log"
    return $status
}

load_config

case "$1" in
    --mega-cron)
        write_log "Starting scheduled MEGA backup task."
        if do_mega_backup; then
            write_log "MEGA backup completed successfully."
        else
            write_log "Error: MEGA backup task failed."
        fi
        ;;
    --mega-sendnow)
        do_mega_backup
        ;;
    --ftp-cron)
        write_log "Starting scheduled FTP backup task."
        if do_ftp_backup; then
            write_log "FTP backup completed successfully."
        else
            write_log "Error: FTP backup task failed."
        fi
        ;;
    --ftp-sendnow)
        do_ftp_backup
        ;;
    --sftp-cron)
        write_log "Starting scheduled SFTP backup task."
        if do_sftp_backup; then
            write_log "SFTP backup completed successfully."
        else
            write_log "Error: SFTP backup task failed."
        fi
        ;;
    --sftp-sendnow)
        do_sftp_backup
        ;;
    --smb-cron)
        write_log "Starting scheduled SMB backup task."
        if do_smb_backup; then
            write_log "SMB backup completed successfully."
        else
            write_log "Error: SMB backup task failed."
        fi
        ;;
    --smb-sendnow)
        do_smb_backup
        ;;
    --gdrive-cron)
        write_log "Starting scheduled Google Drive backup task."
        if do_gdrive_backup; then
            write_log "Google Drive backup completed successfully."
        else
            write_log "Error: Google Drive backup task failed."
        fi
        ;;
    --gdrive-sendnow)
        do_gdrive_backup
        ;;
    *)
        generate_mega_conf
        generate_ftp_conf
        generate_sftp_conf
        generate_smb_conf
        generate_gdrive_conf
        update_cron
        ;;
esac

exit 0