#!/bin/bash
# Copyright (C) 2015  Alex-Daniel Jakimenko <alex.jakimenko@gmail.com>
#
# 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 3 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, see <http://www.gnu.org/licenses/>.

set -e # fatal errors

REPO_LINK='https://raw.githubusercontent.com/kensanata/oddmuse/2.3.5/'

exit_reason=''

# We will use alternating colors so that it is easier to see which part
# was just printed. Otherwise it is pretty hard to use.
color1=$(tput setaf 4)
color2=$(tput setaf 6)
colorHeading=$(tput setaf 2)
colorNone=$(tput sgr0)

prompt() {
    local answer prompt default

    if [[ ! $2 || ${2^} = Y* ]]; then
	prompt='Y/n'
	default='Y'
    elif [[ ${2^} = N* ]]; then
	prompt='y/N'
	default='N'
    fi

    while :; do
	if [[ $curColor == "$color2" ]]; then # TODO more colors?
	    curColor=$color1
	else
	    curColor=$color2
	fi
	read -r -p "$curColor$1$colorNone [$prompt] " answer

	[[ ! $answer ]] && answer=$default

	if [[ ${answer^} = Y* ]]; then
	    echo
	    return 0
	fi
	if [[ ${answer^} = N* ]]; then
	    echo
	    return 1
	fi
    done
}

err() {
    printf "%s\n" "$1"
    exit_reason='err'
    exit
}

clean() {
    case $exit_reason in
	ok)
	    echo 'Good luck! (:'
	    exit 0;
	    ;;
	quit)
	    echo 'You have aborted this script.'
	    exit 1
	    ;;
	*)
	    echo 'This script terminated unexpectedly. :('
	    exit 1
    esac
}
trap clean EXIT

echo "==$colorHeading Welcome! $colorNone=="
echo 'This script will guide you through the process of **setting up a new** Oddmuse wiki.'
echo 'It will also attempt to explain every step.'
echo
echo 'Every step will ask your confirmation. It will look like "[Y/n]".'
echo 'Enter "y" (yes) or "n" (no) to answer the question.'
echo 'Uppercase letter means that this action is the default and you can just press Enter.'
echo
echo 'At any moment you can press Ctrl-C to abort the process.'
echo

echo "==$colorHeading Main script $colorNone=="
echo 'First of all, we have to download the main script and put it into ##cgi-bin## directory.'

if [[ ! -d 'cgi-bin' ]]; then
    echo
    echo 'It seems like your ##cgi-bin## directory is missing.'
    echo
    if ! prompt 'Do you want to create cgi-bin now?' Y; then
	echo 'You decided not to create ##cgi-bin## folder.'
	echo 'This script was meant for simple setups with cgi-bin folder.'
	echo 'See https://oddmuse.org/wiki/Setup for manual installation instructions.'
	exit_reason='quit'
	exit
    fi
    mkdir -- 'cgi-bin' || err 'Cannot create cgi-bin directory. This may be caused by the lack of permissions.'
    echo '* ##cgi-bin## directory was created.'
    chmod 755 -- 'cgi-bin'
    echo '* ##cgi-bin## permissions were set to 755 (rwxr-xr-x).'
    cat <<'EOF' > 'cgi-bin/.htaccess'
Options +ExecCGI
SetHandler cgi-script
EOF
    echo '* ##cgi-bin/.htaccess## file was created with these contents:'
    echo '{{{'
    cat 'cgi-bin/.htaccess'
    echo '}}}'
fi

echo

if ! prompt 'Download wiki.pl right now?' Y; then
    echo 'You have decided not to download the script, but you cannot use Oddmuse without downloading it first.'
    echo
    echo 'See https://oddmuse.org/wiki/Setup for manual installation instructions.'
    exit
fi
wget -nv -O cgi-bin/wiki.pl "$REPO_LINK/wiki.pl" || err 'Cannot download the main script (wiki.pl).'

echo
echo '* ##wiki.pl## was successfully downloaded into your ##cgi-bin## directory.'

chmod +x 'cgi-bin/wiki.pl'
echo '* ##cgi-bin/wiki.pl## file is now executable.'
echo
echo "==$colorHeading Data directory $colorNone=="
echo 'You have to specify some location for permanent data storage.'
echo
echo 'If you wont do that, the wiki will run in **temporary mode**.'
echo
echo 'In temporary mode, any change is stored in /tmp (and therefore will be eventually deleted).'
echo
echo 'In order to keep the data you must specify ##$DataDir##.'
echo
echo 'The easiest way to do that is to set ##WikiDataDir## environment variable in ##.htaccess##.'
echo

echo 'This will be appended to your ##.htaccess## file:'
echo '{{{'
echo 'SetEnv WikiDataDir ../wiki'
echo '}}}'
echo

if ! prompt 'Set WikiDataDir environment variable?' Y; then
    echo 'You have decided not to use WikiDataDir environment variable.'
    echo
    echo 'This means that you have to use a wrapper script instead.'
    echo
    echo 'See https://oddmuse.org/wiki/Setup for more instructions.'
    exit
fi
echo >> '.htaccess'
echo 'SetEnv WikiDataDir ../wiki' >> '.htaccess'
echo '* WikiDataDir variable is now conigured to ##../wiki## (relative to ##cgi-bin## directory).'
echo

echo "==$colorHeading Basic setup $colorNone=="
echo
if [[ ! -d 'wiki/' ]]; then
    echo "===$colorHeading wiki/ $colorNone==="
    echo '##wiki/## directory will contain all data associated with your wiki, that is:'
    echo '* Pages and kept pages (previous versions)'
    echo '* Modules (also called Extensions)'
    echo '* Temp files and logs'
    echo '* And some other less relevant stuff'
    echo
    prompt 'Create ##wiki/## directory?' Y
    mkdir 'wiki'
    echo '##wiki/## directory was created.'
    echo
fi

if [[ ! -d 'wiki/modules/' ]]; then
    echo "===$colorHeading wiki/modules/ $colorNone==="
    echo '##wiki/modules/## can contain perl files that extend the functionality of the core.'
    echo 'These could be your own modules, or one of the 200+ contributed modules.'
    echo 'You can see a structured list of modules on https://oddmuse.org/wiki/Site_Map'
    echo
    prompt 'Create ##wiki/modules## directory?' Y
    mkdir 'wiki/modules'
    echo '##wiki/modules/## directory was created.'
    echo
fi

if [[ ! -f 'wiki/config' ]]; then
    echo "===$colorHeading wiki/config $colorNone==="
    default_config=$'use utf8; # allow utf-8 characters in config file\n'
    echo '##wiki/config## can contain perl code that will be ran during the core initialization on each request.'
    echo
    echo 'Config file will be initialized in ##wiki/config## with these contents:'
    echo '{{{'
    echo "$default_config"
    echo '}}}'
    echo
    prompt 'Initialize config file?' Y
    printf "%s\n" "$default_config" >> 'wiki/config'
    echo 'Config file was initialized.'
    echo
fi

if [[ ! -f '.htaccess' ]]; then
    main_htaccess='# Do not let people see your directory structure
Options -Indexes

# Make your wiki accessible with just /SomePage instead of /cgi-bin/run.pl/SomePage
RewriteEngine On
RewriteRule ^([^/]*)$ /cgi-bin/run.pl/$1 [QSA,L]
RewriteRule ^$ cgi-bin/run.pl [QSA,L,PT]'
    echo "===$colorHeading .htaccess $colorNone==="
    echo '##.htaccess## is a configuration file that is used by several web servers (e.g. Apache).'
    echo '##.htaccess## file will be created with these contents:'
    echo '{{{'
    echo "$main_htaccess"
    echo '}}}'
    echo
    prompt 'Create ##.htaccess## file?' Y
    printf "%s\n" "$main_htaccess" >> '.htaccess'
    echo '##.htaccess## was created.'
    echo
fi

if [[ ! -f 'wiki/.htaccess' ]]; then
    wiki_htaccess='# Hide this directory from world
Deny from all'
    echo "===$colorHeading wiki/.htaccess $colorNone==="
    echo 'We have to hide files in ##wiki/## from public.'
    echo '##wiki/.htaccess## file be created with these contents:'
    echo '{{{'
    echo "$wiki_htaccess"
    echo '}}}'
    echo
    prompt 'Create ##wiki/.htaccess## file?' Y
    printf "%s\n" "$wiki_htaccess" >> 'wiki/.htaccess'
    echo '##wiki/.htaccess## was created.'
    echo
fi

echo "==$colorHeading Config file $colorNone=="
echo 'Now we will do a couple of modifications to the ##wiki/config## file.'
echo
echo 'Config file is just a perl script that is ran by the core during initialization.'
echo
echo 'Feel free to edit it yourself manually at any time!'
echo
echo "===$colorHeading Password $colorNone==="
echo 'It is a good idea to have administrator password set.'
echo
echo 'This script will hash your salted password with sha256 and then it'
echo 'will save that hash in your config file.'
echo
echo 'Although salt is used, it is still easy to bruteforce sha256 hashes.'
echo 'If you think that bcrypt is a better option, you can change your config file later.'
echo
echo 'Please use a strong password (we will let you decide yourself which'
echo 'password is strong enough, you can use any characters).'
echo
prompt 'Do you want to set your password now?' Y
echo '//You will not see what you are typing, this is OK.//'
read -rs -p "Password:" password
echo
echo

password_config='use Digest::SHA qw(sha256_hex);
$PassHashFunction = \&sha256_hex;
'

salt=$(head -c 32 /dev/urandom | xxd -p -c 32) # urandom is OK for generating random strings
password_config+="\$PassSalt = '$salt'; # random salt. Generated with: head -c 32 /dev/urandom | xxd -p -c 32"$'\n'
password_config+="\$AdminPass = '$(printf "%s" "$password$salt" | sha256sum | cut -d ' ' -f 1)'"'; # Generated with: printf "%s" "$password$salt" | sha256sum'$'\n'
printf "%s\n" "$password_config" >> 'wiki/config'
echo 'This was written to your config file:'
echo '{{{'
echo "$password_config"
echo '}}}'
echo


echo "==$colorHeading Essential set of modules $colorNone=="
echo 'Now we will install a couple of modules.'
echo
echo 'Oddmuse is very modular in nature, some of the very'
echo 'essential stuff was separated from the core.'
echo
echo 'Although you can still use Oddmuse without any modules, we'
echo 'think that any healthy wiki will require some of them.'
echo
echo 'This is discussed in https://oddmuse.org/wiki/Essential_Set_of_Modules'
echo
echo 'Next steps will guide you through installing some of the modules.'
echo

echo "===$colorHeading creole.pl $colorNone==="
echo 'First of all, you need something that will handle the syntax on your wiki.'
echo
echo 'These modules will give you bold, italics, tables, sometimes additional link'
echo 'patterns, ordered/unordered lists and lots of other stuff.'
echo
echo 'There are several modules for this, but [[Creole Markup Extension]] is'
echo 'currently the best choice.'
echo
prompt 'Do you want to install [[Creole Markup Extension]]?' Y

wget -nv -O wiki/modules/creole.pl "$REPO_LINK/modules/creole.pl" || err 'Cannot download the module (creole.pl).'
echo
echo '* [[Creole Markup Extension]] was installed into ##wiki/modules/creole.pl##.'
echo

echo "===$colorHeading questionasker.pl $colorNone==="
echo 'Any website that has an edit form is bound to accumulate spam over time.'
echo
echo 'Unfortunately, that’s the Internet we are living in - spam bots crawl'
echo 'the web and attempt to put stuff into anything that they can find.'
echo
echo 'Once you get at least one successful spam edit, you will be added to'
echo 'the list and bots will attempt to post spam all the time.'
echo
echo 'There is no solution that will keep your wiki 100% free from spam,'
echo 'but there are some good ways to mitigate it.'
echo
echo '[[QuestionAsker Extension]] will add a question to the edit form.'
echo 'Once it is answered, the user gets a cookie and will not be asked the question again.'
echo 'Surprisingly, this keeps almost all of the spambots away.'
echo
prompt 'Do you want to install [[QuestionAsker Extension]]?' Y

wget -nv -O wiki/modules/questionasker.pl "$REPO_LINK/modules/questionasker.pl" || err 'Cannot download the module (questionasker.pl).'
echo
echo '* [[QuestionAsker Extension]] was installed into ##wiki/modules/questionasker.pl##.'
echo

echo "===$colorHeading ban-contributors.pl $colorNone==="
echo 'Several times per year some spam will get through.'
echo 'You will rollback your pages, but after some time it will appear again.'
echo
echo 'That’s when you might want to ban some IPs.'
echo
echo '[[Ban Contributors Extension]] will help you with that!'

echo 'Whenever you rollback a page, it will provide several ways to prevent'
echo 'that spam from getting in again.'
echo
echo 'Basically, it will add a convenient way to ban some IPs.'
echo
prompt 'Do you want to install [[Ban Contributors Extension]]?' Y

wget -nv -O wiki/modules/ban-contributors.pl "$REPO_LINK/modules/ban-contributors.pl" || err 'Cannot download the module (ban-contributors.pl).'

echo
echo '* [[Ban Contributors Extension]] was installed into ##wiki/modules/ban-contributors.pl##.'
echo
if [[ ! -f 'wiki/css/wiki.css' ]]; then
    echo "==$colorHeading CSS $colorNone=="
    echo 'By default, the main script will attempt to use default stylsheet.'
    echo
    echo 'https://oddmuse.org is also using the default stylesheet.'
    echo 'Feel free to visit it to get the impression.'
    echo
    echo 'However, you probably want your users to download it from your own server.'
    echo
    echo 'If you want to add your own modifications - just edit that css file directly.'
    echo
    prompt 'Do you want to fetch default CSS into ##css/wiki.css##?' Y # TODO
    echo
    mkdir -p 'css'
    wget -nv -O css/wiki.css "$REPO_LINK/css/wiki.css" || err 'Cannot download default stylesheet.'

    stylesheet_config="\$StyleSheet = 'css/wiki.css'"
    printf "%s\n" "$stylesheet_config" >> 'wiki/config'
    echo 'This was written to your config file:'
    echo '{{{'
    echo "$stylesheet_config"
    echo '}}}'
fi

echo
echo
echo "==$colorHeading Finish $colorNone=="
echo 'Congratulations! You went through all of the steps.'
echo 'Now open your website and enjoy the result.'
echo
echo 'If you have problems or questions, please write a comment on https://oddmuse.org/.'
echo 'We will be glad to help you!'
echo
echo 'Tell others about your wiki!'
echo 'You can add your website to the list on https://oddmuse.org/wiki/Users'
echo
exit_reason='ok'
