#!/bin/bash
# -*- coding:utf-8 -*-
# file KLEIDER/web/src/aktuell/redirects
# 2014-04-30 Herbert Schiemann <h.schiemann@herbaer.de>
# aktuelle URL-Umleitungen pflegen

# Zähler, Variable, Aktionen
declare_vars ()
{
   # Ein Leerzeichen als Wert bedeutet, dass Positionsargumente verarbeitet werden
   _argv="";

   # Suchpfad für rc-Dateien, : - getrennte Liste von Verzeichnispfaden
   # Falls leer, wird die Option --rc nicht speziell behandelt
   # g_configpath=$HOME/etc/redirects:. ;

   # Zähler
   g_counters="  \
      verbose    \
      overwrite  ";

   # Variable
   g_variables=" \
      srcdir     \
      stsrc      \
      rdsrc      \
      aktdir     \
      htaccfile  \
      ixfile     \
      tempdir    ";

   # Aktionen
   g_actions="   \
      htaccess   \
      xhtml      ";
} # declare_vars

# setzt Vorgabe-Werte
set_defaults ()
{
   local w=$(realpath $0);
   w=${w%/src/aktuell/redirects};
   [[ -n "$verbose"   ]] || verbose=1 ;
   [[ -n "$rdsrc"     ]] || rdsrc="$w/supplement/redirects.xml" ;
   [[ -n "$aktdir"    ]] || aktdir="$w/docroot/aktuell" ;
   [[ -n "$htaccfile" ]] || htaccfile="$aktdir/.htaccess" ;
   [[ -n "$ixfile"    ]] || ixfile="$aktdir/index.xhtml." ;
   [[ -n "$srcdir"    ]] || srcdir="$w/src/aktuell" ;
   [[ -n "$stsrc"     ]] || stsrc="$w/src/style" ;
   [[ -n "$tempdir"   ]] || tempdir="$w/web/temp" ;
} # set_defaults

# Zeigt eine kurze Hilfe an
show_help ()
{
   local cmd=${0#*/} ;
   set_defaults ;
   cat << .HELP ;
$cmd --version
$cmd --help
$cmd ([Aktion] | [Option])*

Aktionen
--htaccess         Konfigurationsdatei für URL-Umleitungen erzeugen
--xhtml            XHTML-Datei zu Umleitungen erzeugen

Einstellungen
--[no_]verbose         Erhöht den Umfang der Ausgabe des Scripts ($verbose)
--[no_]overwrite       Existierende Dateien überschreiben ($overwrite)
--rdsrc     RDSRC      XML-Quelldatei der umzuleitenden URLs
                       ($rdsrc)
--aktdir    AKTDIR     Serververzeichnis für umzuleitenden URLs
                       ($aktdir)
--htaccfile HTACCFILE  Pfad der Konfigurationsdatei
                       ($htaccfile)
--ixfile    IXFILE     Pfad der Indexdatei
                       ($ixfile)
--srcdir    SRCDIR     Verzeichnis der Skripte
                       ($srcdir)
--stsrc     STSRC      weiteres Skriptverzeichnis zum Stil
                       ($stsrc)
--tempdir   TEMPDIR    Verzeichnis für temporäre Dateien
                       ($tempdir)
.HELP
} # show_help

# Zeigt die Version an
show_version ()
{
   cat << .VERSION ;
$0
aktuelle URL-Umleitungen pflegen
2014-04-20, Herbert Schiemann, h.schiemann@herbaer.de
GPL Version 2 oder neuer
.VERSION
} # show_version

# Variable und Zähler initialisieren
init_vars () {
   local v;
   declare_vars ;
   for v in $g_counters $g_variables $g_actions; do
      eval "$v=" ;
   done;
} # init_vars

# Argumente verarbeiten
read_args ()
{
   local wd ;
   local lastwd ;
   local var ;
   local ok ;

   has_actions=0 ;
   for wd in "$@"; do
      if [[ "$lastwd" = "--" ]]; then
          _argv="$_argv $wd";
      elif [[ -n "$lastwd" ]]; then
         if [[ "$wd" =~ ^[\ a-zA-Z0-9./_#-]+$ ]]; then
            if [[ "$lastwd" == "rc" && -n "$g_configpath" ]]; then
               if ! read_configuration $wd; then
                  (( verbose )) && echo "Kann Konfiguration $wd nicht lesen" ;
                  exit 10 ;
               fi ;
            else
               ok=0 ;
               for var in $g_variables; do
                  if [[ "$var" == "$lastwd" ]]; then
                     (( ++ok )) ;
                     eval "$var=\"$wd\"" ;
                     break ;
                  fi ;
               done ;
               if (( ! ok )); then
                  (( verbose )) && echo "Unbekannte Option --$lastwd $wd" ;
                  exit 11 ;
               fi ;
            fi ;
         else
            (( verbose )) && echo "Ungültiger Optionswert --$lastwd $wd" ;
            exit 12;
         fi;
         lastwd= ;
      else
         case "$wd" in
            --version )
               show_version ;
               exit 0 ;
               ;;
            --help )
               show_version ;
               show_help ;
               exit 0 ;
               ;;
            -- )
               if [[ -n "$_argv" ]]; then
                  lastwd=--;
                  continue;
               else
                  (( verbose )) && echo "Ungültige Option $wd" ;
                  exit 13 ;
               fi ;
               ;;
            --* )
               if [[ "$wd" =~ ^--[a-z][a-z0-9_]*$ ]]; then
                  lastwd=${wd#--} ;
                  ok=0 ;
                  for var in $g_counters ; do
                     if   [[ "$lastwd" == $var    ]]; then
                        eval "(( ++$lastwd ))" ;
                     elif [[ "$lastwd" == "no_$var" ]]; then
                        eval "${lastwd#no_}=0" ;
                     else
                        continue;
                     fi;
                     (( ++ok )) ;
                     break ;
                  done;
                  if (( !ok )); then
                     for var in $g_actions; do
                        if [[ "$lastwd" == "$var" ]]; then
                           eval "(( ++$var ))" ;
                           (( ++ok ));
                           has_actions=1;
                           break;
                        elif [[ "$lastwd" == "no_$var" ]]; then
                           eval "(( ++no_$var ))" ;
                           (( ++ok ));
                           break;
                        fi;
                     done;
                  fi;
                  (( ok )) && lastwd=;
               else
                  (( verbose )) && echo "Ungültige Option $wd" ;
                  exit 14 ;
               fi ;
               ;;
            * )
               if [[ -n $_argv ]]; then
                   _argv="$_argv $wd";
               else
                   (( verbose )) && echo "Ungültige Option $wd" ;
                   exit 15 ;
               fi;
               ;;
         esac ;
      fi ;
   done ;
   if [[ -n $lastwd && "$lastwd" != "--" ]]; then
      (( verbose )) && echo "Unverarbeitete Option --$lastwd";
      exit 16 ;
   fi ;
   [[ "$_argv" =~ ^[[:space:]]+$ ]] && _argv="" ;
} # read_args

# Aktionen ausführen
run_actions ()
{
   local act ;
   for act in $g_actions; do
     eval "(( ! has_actions && ! no_$act || $act )) && process_$act";
   done;
} # run_actions

# show_variables VARNAME1 VARNAME2
# Werte der Variablen anzeigen
show_variables ()
{
   local v ;
   for v in $g_counters $g_variables $g_actions $1; do
      eval "echo \"$v = \$$v\"" ;
   done;
} # show_variables

# Können die Eingabedateien gelesen werden?
# check_infiles first/path/to/file path/to/second_file ;
check_infiles ()
{
   local f ;
   for f in "$@"; do
      if [[ ! -f "$f" ]]; then
         (( verbose )) && echo "\"$f\" ist keine gewöhnliche Datei";
         return 1;
      fi;
      if [[ ! -s "$f" ]]; then
         (( verbose )) && echo "\"$f\" ist leer";
         return 1;
      fi;
      if [[ ! -r "$f" ]]; then
         (( verbose )) && echo "Kann Datei \"$f\" nicht lesen";
         return 1;
      fi;
   done;
   return 0;
} # check_infiles

# Können die Ausgabedateien erstellt werden?
# erstellt fehlende Verzeichnisse und löscht existierende Dateien
# nach Maßgabe der Variablen overwrite
# check_outfiles first/path/to/file path/to/second_file ;
check_outfiles ()
{
   local fp;
   local dir;
   local verb;
   (( verbose )) && verb=--verbose ;
   for fp in "$@"; do
      if [[ ! -e $fp ]]; then
         dir=${fp%/*};
         if [[ -n $dir && ! -e $dir ]]; then
            mkdir -p $verb $dir ;
            if [[ ! -d $dir ]]; then
               (( verbose )) && echo "$dir ist kein Verzeichnis";
               return 1;
            fi;
         fi;
      elif [[ -d $fp ]]; then
         (( verbose )) && echo "$fp ist ein Verzeichnis";
         return 1;
      elif (( overwrite )); then
         (( verbose )) && echo "lösche $fp";
         rm $fp;
      else
         (( verbose )) && echo "$fp existiert";
         return 1;
      fi;
      (( verbose )) && echo "$fp";
   done;
   return 0;
} # check_outfiles

# gzip-komprimierte Datei(en) hinzufügen
add_gzip ()
{
   local f;
   local g;
   for f in "$@"; do
      [[ -f $f ]] || continue;
      g=${f%.}.gz ;
      [[ -f $g ]] && rm $g;
      [[ -e $g ]] && continue;
      (( verbose )) && echo "erstelle $g";
      gzip --best --stdout $f > $g ;
   done ;
} # add_gzip

# Hilfsfunktion: temporäre Javascript und CSS-Dateien erzeugen
# proc_tempfiles subdir
proc_tempfiles ()
{
   local sd=$1 ;
   for s in $srcdir/*.js ; do
      [[ -f $s ]] || continue;
      o=$td/${s#$srcdir/} ;
      check_outfiles $o               \
      && $stsrc/clean_js.pl --in $s --out $o ;
   done;
   for s in $srcdir/*.css ; do
      [[ -f $s ]] || continue;
      o=$td/${s#$srcdir/} ;
      check_outfiles $o                                               \
      && $stsrc/clean_css.pl --in $s --imageprefix '${imageprefix}' --out $o ;
   done;
} # proc_tempfiles

# Konfigurationsdatei für URL-Umleitungen erzeugen
process_htaccess ()
{
   (( verbose )) && echo "process_htaccess" ;
   local t=$srcdir/redirects_htaccess.xslt ;
   check_infiles $t $rdsrc   || return 1;
   check_outfiles $htaccfile || return 1;
   xsltproc -o $htaccfile $t $rdsrc ;
} # process_htaccess

# XHTML-Datei zu Umleitungen erzeugen
process_xhtml ()
{
   (( verbose )) && echo "process_xhtml" ;
   local t=$srcdir/redirects_ht.xslt ;
   check_infiles $t $rdsrc || return 1;
   check_outfiles $ixfile  || return 1;
   local td="$tempdir/$(date +%Y%m%d%H%M%S%N)" ;
   local t2=$td/redirects_ht.xslt ;
   proc_tempfiles $td ;
   xsltproc                                                       \
      --stringparam p_tmpprefix $td/                              \
      --stringparam p_shortids none                               \
      $stsrc/styleincl_step_1.xslt $t                             \
      | xsltproc -o $t2 --xinclude $stsrc/styleincl_step_2.xslt - ;
   xsltproc                                       \
      --stringparam p_localbase $srcdir/local.xml \
      -o $ixfile $t2 $rdsrc                       ;
   add_gzip $ixfile ;
   rm --recursive $td;
} # process_xhtml

# Sicherheit
export PATH=/bin:/usr/bin:$HOME/bin ;
IFS=$' \t\n' ;
set -o noclobber ;   # existierende Dateien werden nicht überschrieben
shopt -s extglob nullglob ;

init_vars ;
read_args "$@" ;
set_defaults ;

(( verbose > 1 )) && show_variables " HOME ";

run_actions ;
exit 0;
# end of file KLEIDER/web/src/aktuell/redirects
