#!/usr/bin/perl -w
# -----------------------------------------------------------------------------
#
#   Copyright (c) 1999-2001 by Klaus Reger <K.Reger@wwwdb.org>
#
#   You may distribute under the terms of either the GNU General Public
#   License or the Artistic License, as specified in the Perl README file.
#
#   THIS IS BETA SOFTWARE!
#
#   THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
#   IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
#   WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
#
#   $Id: INSTALL.pl,v 1.5 2002/03/18 15:19:30 k_reger Exp $
#
# -----------------------------------------------------------------------------
# Program-Data
# -----------------------------------------------------------------------------
# Project  :
# System   :
# Program  :
# Module   : $RCSfile: INSTALL.pl,v $
# Version  : $Revision: 1.5 $
# Date     : $Date: 2002/03/18 15:19:30 $
# State    : $State: Exp $
#
# Description:
#   This script installs WWWdb
#
# -----------------------------------------------------------------------------
# --- Change-log -------------
# $Log: INSTALL.pl,v $
# Revision 1.5  2002/03/18 15:19:30  k_reger
# - setup second tmp-dir also
#
# Revision 1.4  2002/03/12 08:09:37  k_reger
# - Keep some files in non-devel version
# - refresh translation-files
#
# Revision 1.3  2002/03/05 16:09:26  k_reger
# - patch the most important-config-files
# - mysql-import
# - enter interactively some information
# - scan development-version automatically
# - finer grained message-printing
#
# Revision 1.2  2002/02/28 13:43:56  k_reger
# - Configure Apache
# - Install Database-content
# - fix basic-configuration-files
#
# --- Known Bugs -------------
# FIXME: export POSTGRES_HOME=/
# FIXME: make DBIx::Recordset silent
# --- TODO -------------------
# - Implement modes: CHECK, INTERACTIVE, FORCE_INSTALL
# - See the F I X M Es in the code
# - Pass options over commandline
# ----------------------------------------------------------------------------

use Cwd;
use strict;

my %hDefaultInstallOpt =
(
 "DISTRIBUTION"       => "SuSE 7.x",
 "APACHE_DIR"         => ["/etc/httpd", "/opt/httpd"],
 "APACHE_CONFIG_FILE" => ["httpd.conf"],
 "RC_APACHE"          => "rcapache reload",
 "CONTRIB_DIR"        => "contrib",
 "DB_TYPE"            => "Pg",
 "DB_NAME"            => "",
 "DB_HOST"            => "localhost",
 "DB_USER"            => "wwwrun",
 "DB_PASS"            => "",
 "MAKE_TEST"          => 0,
 "HTTP_CGI_BIN"       => "/usr/local/httpd/cgi-bin",
 "WWWDB_ROOT"         => "/usr/local/httpd/htdocs",
 "HOSTNAME"           => "localhost",
 "VERBOSE_LEVEL"      => 1,
 "MODE"               => "INSTALL", # CHECK, INSTALL, INTERACTIVE, FORCE_INSTALL
 "TO_INSTALL"         => "MODULES,APACHE,WWWDB,DATABASE",

 "ENV_POSTGRES_INCLUDE" => "/usr/include/pgsql",
 "ENV_POSTGRES_LIB"     => "/usr/lib",
);

my %hInstallParam = ();

&Install();

sub Install()
{
    my $cVersion;
    my $bDevelopVersion;
    my $cCurrDir = cwd();
    my $cWWWdbRoot;
    my $cDatabaseName;


    # Find out WWWdb-Version
    open WWWDB, "<WWWdb.cgi" or
        die "Can't open WWWdb.cgi";

    while (<WWWDB>)
    {
        if (/\$VERSION\s*=\s*\'(.*)\'/)
        {
            $cVersion = $1;
        }

        if (/\$iDevelopmentVersionMGL\s*=\s*(.*);/)
        {
            $bDevelopVersion = $1;
        }
    }
    close WWWDB;

    unless ($hDefaultInstallOpt{"DB_NAME"})
    {
        $cDatabaseName = "wwwdb_" . $cVersion;
        $cDatabaseName =~ s/\W/_/g;

        $hDefaultInstallOpt{"DB_NAME"} = $cDatabaseName;
    }

    $cWWWdbRoot = sprintf ("%s/WWWdb-%s",
                           $hDefaultInstallOpt{"WWWDB_ROOT"},
                           $cVersion);

    unlink "INSTALL.log";

    if ($hDefaultInstallOpt{"VERBOSE_LEVEL"} > 0)
    {
        printf STDERR "Welcome to the WWWdb-Installer!\n\n";
        printf STDERR "We are going to install Version $cVersion\n\n";
    }

    foreach (keys %hDefaultInstallOpt)
    {
        if (/^ENV_(.*)/)
        {
            $ENV{$1} = $hDefaultInstallOpt{$_};
        }
    }

    {
        foreach ("TO_INSTALL", "HOSTNAME", "DB_TYPE",
                 "DB_NAME", "DB_HOST", "DB_USER", "DB_PASS")
        {
            my $cInput;

            printf STDOUT ("%20s [%s]: ",
                           $_,
                           $hDefaultInstallOpt{$_});

            $cInput = <STDIN>;

            chomp $cInput;

            $hDefaultInstallOpt{$_} = $cInput
                if $cInput;
        }

    }

    {

        if ($hDefaultInstallOpt{"TO_INSTALL"} =~ m/MODULES/)
        {
            my @lModulesToInstall = ();

            # Prepare your Perl-Distribution

            no strict;

            my @lPrereqPM =
                ('CGI,0',
                 'CGI::Cache,0',
                 'CGI::Carp,0',
                 'Carp::Assert,0',
                 # $bDevelopVersion ? 'Time::Hires,0': "",
                 # 'Carp,0',
                 'DBI,0',
                 ($hDefaultInstallOpt{"DB_TYPE"} eq "Pg") ? 'DBD::Pg,0': "",
                 ($hDefaultInstallOpt{"DB_TYPE"} eq "Oracle") ? 'DBD::Oracle,0': "",
                 ($hDefaultInstallOpt{"DB_TYPE"} eq "mysql") ? 'Msql-Mysql-modules,0,DBD::mysql': "",
                 'DBIx::Recordset,0',
                 'Digest::MD5,0',
                 'ExtUtils::MakeMaker,0',
                 'File::Basename,0',
                 'File::Find,0',
                 'FileHandle,0',
                 'Getopt::Std,0',
                 'HTML::Tagset,0',
                 'HTML::Parser,0,HTML::Entities',
                 'HTML::Template,0',
                 'HTML::Tree,0,HTML::TreeBuilder',
                 'Locale::PGetText,0',
                 'POSIX,0',
                 'DelimMatch,0,Text::DelimMatch',
                 'PDF-Create,0,PDF::Create',
                 # 'MissingTestModule,0',
                 $bDevelopVersion ? 'Data::Dumper,0': "",
                 $bDevelopVersion ? 'CGI::Debug,0': "",
                 );

            printf STDERR "Checking installed perl-modules ...\n"
                if ($hDefaultInstallOpt{"VERBOSE_LEVEL"} > 0);

            foreach (@lPrereqPM)
            {

                (my $cModule, my $cVersion, my $cMethod) = split ",", $_;

                next unless $cModule;

                $cMethod = $cModule
                    unless $cMethod;

                my $bFound = 0;

                {
                    eval "require $cMethod";

                    if ($@) {
                        printf STDERR "$cModule is missing\n";

                        push @lModulesToInstall, $cModule;
                    }
                    else
                    {
                        printf STDERR "%s (%s) is OK\n", $cModule, ($cModule->VERSION || "unknown")
                            if ($hDefaultInstallOpt{"VERBOSE_LEVEL"} > 5);
                        $bFound = 1;

                        eval "no $cMethod";
                    }
                }
            }

            if (@lModulesToInstall)
            {
                my $cOutputTo = ($hDefaultInstallOpt{"VERBOSE_LEVEL"} > 5?
                                 " >>".cwd()."/INSTALL.log": " >/dev/null");

                # To make it easier to install this modules, they are packed in the
                # ./contrib-subtree.
                &Error("No contrib-directory with perl-modules found!\n")
                    unless -d $hDefaultInstallOpt{"CONTRIB_DIR"};


                chdir $hDefaultInstallOpt{"CONTRIB_DIR"};
                my $cContribDir = cwd();

                foreach (@lModulesToInstall)
                {
                    my $cModule = $_;
                    my @lMatchFiles = ();

                    printf STDERR "\nInstalling module $cModule:\n"
                        if ($hDefaultInstallOpt{"VERBOSE_LEVEL"} > 0);

                    $cModule =~ s/::/-/;

                    @lMatchFiles = <$cModule . "*.t*gz">;

                    @lMatchFiles = grep { /$cModule-[0-9.]+\.t(ar\.)?gz/ } @lMatchFiles;

                    $cModule = $lMatchFiles[0];


                    &MySystem("tar xvfz " . $cModule . $cOutputTo);

                    $cModule =~ s/\.t(ar\.)?gz$//;

                    printf STDERR "cd " . $cModule . "\n"
                        if ($hDefaultInstallOpt{"VERBOSE_LEVEL"} > 5);
                    chdir $cModule;

                    &MySystem("perl Makefile.PL");
                    &MySystem("make" . $cOutputTo);
                    &MySystem("make test", 0, 1)
                        if $hDefaultInstallOpt{"MAKE_TEST"};
                    &MySystem("make install" . $cOutputTo, 1);

                    chdir $cContribDir;

                    &MySystem("rm -rf '$cModule'", 1)
                        if -d $cModule;
                }

                chdir $cCurrDir;
            }

            printf STDERR "All modules are installed\n"
                if ($hDefaultInstallOpt{"VERBOSE_LEVEL"} > 1);

        }


        # Now we install WWWdb ...
        if ($hDefaultInstallOpt{"TO_INSTALL"} =~ m/WWWDB/)
        {
			printf STDERR "\nInstalling WWWdb:\n"
				if ($hDefaultInstallOpt{"VERBOSE_LEVEL"} > 0);

            my $cOutputTo = ($hDefaultInstallOpt{"VERBOSE_LEVEL"} > 5?
                             "": " >/dev/null");

            # Now we prepare the WWWdb-modules for installation
            &MySystem("perl Makefile.PL".$cOutputTo);
            &MySystem("make".$cOutputTo);
            &MySystem("make trans" . $cOutputTo);
            &MySystem("make install".$cOutputTo, 1);
            &MySystem("make clean".$cOutputTo, 1);

            &MySystem(sprintf ("mkdir %s",
                               $hDefaultInstallOpt{"HTTP_CGI_BIN"}))
                unless -d $hDefaultInstallOpt{"HTTP_CGI_BIN"};

            &MySystem(sprintf ("mkdir %s",
                               $hDefaultInstallOpt{"WWWDB_ROOT"}))
                unless -d $hDefaultInstallOpt{"WWWDB_ROOT"};

            &MySystem("mkdir $cWWWdbRoot")
                unless -d $cWWWdbRoot;

#           &MySystem(sprintf
#                     ("ln -sf %s/WWWdb-%s %s/WWWdb",
#                      $hDefaultInstallOpt{"WWWDB_ROOT"},
#                      $cVersion,
#                      $hDefaultInstallOpt{"WWWDB_ROOT"}));

            # Install the script WWWdb.cgi:
            &MySystem(sprintf
                      ("cp WWWdb.cgi %s/WWWdb-%s.cgi",
                       $hDefaultInstallOpt{"HTTP_CGI_BIN"},
                       $cVersion));

            &MySystem(sprintf
                      ("ln -f %s/WWWdb-%s.cgi %s/WWWdb.cgi",
                       $hDefaultInstallOpt{"HTTP_CGI_BIN"},
                       $cVersion,
                       $hDefaultInstallOpt{"HTTP_CGI_BIN"}));

            # Remove some files, that may be leftover from the development-process
            unless ($bDevelopVersion)
            {
                &MySystem(sprintf "rm -f  lib/WWWdb/Db/WWWdb.??");
                &MySystem(sprintf "rm -f  lib/WWWdb/Db/WWWdb_[012]*.??");
                &MySystem(sprintf "rm -rf tmp/cache");
            }

            #      Install the WWWdb-data-directory (here with a symbolic link)
            &MySystem(sprintf "cp -ar * %s", $cWWWdbRoot);
            &MySystem(sprintf "chown -R %s %s", $hDefaultInstallOpt{"DB_USER"}, $cWWWdbRoot);



			foreach ("$cWWWdbRoot/tmp", "$cWWWdbRoot/lib/WWWdb/tmp")
			{
				#      Create and set the right permissions for the tmp-directory
				#      $ mkdir tmp
				&MySystem("mkdir $_")
					unless -d "$_";
				
				#      $ chmod 777 tmp
				&MySystem("chmod 777 $_");
				&MySystem(sprintf ("chown %s %s",
								   $hDefaultInstallOpt{"DB_USER"},
								   $_));
			}

            &SubstFile("$cWWWdbRoot/lib/WWWdb/Pre.rc",
                       {"<HOSTNAME>" => $hDefaultInstallOpt{"HOSTNAME"}
                        });

        }

        if ($hDefaultInstallOpt{"TO_INSTALL"} =~ m/APACHE/)
        {
            my $cApacheConfig = "";
            my $bWWWdbIsIncluded = 0;
            my $cApacheConfigEntry;

            #      Configure the Apache-Server (if you haven't done this with a previous
            #      version of WWWdb):

            #      must be compiled and installed with perl_mod
            #      make apache recognize URIs of the form:
            #      http://localhost/WWWdb/<Session-Id>/<Database>/<Config-file>

            printf STDERR "Now we check your apache-server:\n"
                if ($hDefaultInstallOpt{"VERBOSE_LEVEL"} > 0);

            foreach (@{$hDefaultInstallOpt{"APACHE_DIR"}})
            {
                my $cApacheDir = $_;

                if (-d $cApacheDir)
                {

                    # search apache config-file
                    foreach (@{$hDefaultInstallOpt{"APACHE_CONFIG_FILE"}})
                    {
                        if (-f $cApacheDir . "/" . $_)
                        {
                            $hInstallParam{"APACHE_DIR"}         = $cApacheDir;
                            $hInstallParam{"APACHE_CONFIG_FILE"} = $_;

                            last;
                        }
                    }
                }
            }

            &Error("Apache-directory was not found, Sorry!\n")
                unless $hInstallParam{"APACHE_DIR"};

            &MySystem(sprintf ("cp Apache/WWWdb.conf %s",
                               $hInstallParam{"APACHE_DIR"}));

            $cApacheConfig = sprintf("%s/%s",
                                     $hInstallParam{"APACHE_DIR"},
                                     $hInstallParam{"APACHE_CONFIG_FILE"});

            open APACHE_CONF, "<$cApacheConfig" or
                die "Can't open apache-config-file: $cApacheConfig";

            $cApacheConfigEntry =
                sprintf("Include %s/WWWdb.conf\n",
                        $hInstallParam{"APACHE_DIR"});

            while (<APACHE_CONF>)
            {

                $bWWWdbIsIncluded = 1
                    if /^$cApacheConfigEntry$/;
            }

            close APACHE_CONF;

            unless ($bWWWdbIsIncluded)
            {
                print STDERR "Configuring apache\n"
                    if ($hDefaultInstallOpt{"VERBOSE_LEVEL"} > 0);

                printf STDERR ("  Found apache-config in directory %s,\n" .
                               "  and a configfile named %s.\n",
                               $hInstallParam{"APACHE_DIR"},
                               $hInstallParam{"APACHE_CONFIG_FILE"})
                    if ($hDefaultInstallOpt{"VERBOSE_LEVEL"} > 5);

                open APACHE_CONF, ">>$cApacheConfig" or
                    die "Can't open apache-config-file: $cApacheConfig";

                print APACHE_CONF "\n\n# Translate WWWdb-URIs\n";
                print APACHE_CONF $cApacheConfigEntry;

                close APACHE_CONF;

            }

            # Now the apache-sever must be restarted:
            &MySystem($hDefaultInstallOpt{"RC_APACHE"}, 1);

            # Install the Trans-URI-configfile
            unless (-f "/etc/WWWdb_TransUri.rc")
            {
                &MySystem(sprintf ("cp WWWdb_TransUri.rc /etc/WWWdb_TransUri.rc"));

                &SubstFile("/etc/WWWdb_TransUri.rc",
                           {"<HOSTNAME>" => $hDefaultInstallOpt{"HOSTNAME"},
                            "<VERSION>"  => $cVersion
                            });
            }

        }

        # Prepare your Database
        if ($hDefaultInstallOpt{"TO_INSTALL"} =~ m/DATABASE/)
        {

            chdir($cWWWdbRoot);

            #      Set your db-name etc in lib/WWWdb/Db/<Db>.rc
            #      $ vi lib/WWWdb/Db/<Db>.rc

            &MySystem(sprintf
                      ("cp lib/WWWdb/Db/%s.rc lib/WWWdb/Db/%s.rc",
                       $hDefaultInstallOpt{"DB_TYPE"},
                       $hDefaultInstallOpt{"DB_NAME"}));

            &MySystem(sprintf
                      ("cp lib/WWWdb/Db/WWWdb_Orig.pl lib/WWWdb/Db/%s.pl",
                       $hDefaultInstallOpt{"DB_NAME"}));

            # Create links for the db-dummys '' and Default.
            foreach my $cType ("rc", "pl")
            {
                foreach my $cFile ("", "Default", "WWWdb")
                {
                    &MySystem(sprintf
                      ("ln -sf %s/lib/WWWdb/Db/%s.%s lib/WWWdb/Db/%s.%s",
                       $cWWWdbRoot,
                       $hDefaultInstallOpt{"DB_NAME"},
                       $cType,
                       $cFile,
                       $cType))
                        unless -f "lib/WWWdb/Db/$cFile.$cType";
                }
            }

            &SubstFile("lib/WWWdb/Db/".$hDefaultInstallOpt{"DB_NAME"}.".rc",
                       {"<DB_NAME>" => $hDefaultInstallOpt{"DB_NAME"},
                        "<DB_HOST>" => $hDefaultInstallOpt{"DB_HOST"},
                        "<DB_USER>" => $hDefaultInstallOpt{"DB_USER"},
                        "<DB_PASS>" => $hDefaultInstallOpt{"DB_PASS"}
                    });

            # Create the database itself
            if ($hDefaultInstallOpt{"DB_TYPE"} eq "Pg")
            {
                # FIXME: find out if db-user exists
                # create database-user
                &MySystem(sprintf
                          ("createuser --createdb --no-adduser -U postgres %s",
                           $hDefaultInstallOpt{"DB_USER"}), 0, 0);

                # FIXME: find out if db exists
                # create database
                &MySystem(sprintf ("createdb -U %s %s",
                                   $hDefaultInstallOpt{"DB_USER"},
                                   $hDefaultInstallOpt{"DB_NAME"}), 0, 0);
            }
            elsif ($hDefaultInstallOpt{"DB_TYPE"} eq "mysql")
            {
                &MySystem(sprintf ('echo "GRANT ALL PRIVILEGES ON *.* TO %s@localhost ' .
                                   '      IDENTIFIED BY \'%s\' WITH GRANT OPTION" |' .
                                   '  mysql --user=root mysql',
                                   $hDefaultInstallOpt{"DB_USER"},
                                   $hDefaultInstallOpt{"DB_PASS"}));

                # FIXME: find out if db exists
                # create database
                &MySystem(sprintf ("mysqladmin create -u %s %s",
                                   $hDefaultInstallOpt{"DB_USER"},
                                   $hDefaultInstallOpt{"DB_NAME"}), 0, 0);
            }


            chdir "$cWWWdbRoot/lib/WWWdb/Db";

            # load database
            &MySystem(sprintf ("./CreateNewDb.sh -ci -b %s -D %s -U %s",
                               $hDefaultInstallOpt{"DB_TYPE"},
                               $hDefaultInstallOpt{"DB_NAME"},
                               $hDefaultInstallOpt{"DB_USER"}));


            #      Enter the url http://<hostname>/wwwdb and enjoy !!!!
        }
    }

    printf STDERR "Installation of WWWdb ($cVersion) finished!\n\n";
    printf STDERR ("Point your Browser to http://%s/wwwdb to try it out!\n\n",
                   $hDefaultInstallOpt{"HOSTNAME"});


}

sub Error($)
{
    my $cMessagePI = shift;

    print STDERR $cMessagePI;

    exit -1;

}


sub MySystem($;$$)
{
    my $cCommandPI   = shift;
    my $bAsRootPI    = shift || 0;
    my $bExitOnErrPI = shift;

    $bExitOnErrPI = 1
        unless defined $bExitOnErrPI;

    my $cResult = "";
    my $bSkipExec = 1 && ($bAsRootPI && ($< != 0));

    printf STDERR "%s%s\n", $bSkipExec? "# ": "", $cCommandPI
        if ($hDefaultInstallOpt{"VERBOSE_LEVEL"} > 5);

    unless ($bSkipExec)
    {
        system($cCommandPI);

        $cResult = $?;

        &Error(sprintf("command %s failed, Error = %d\n",
                       $cCommandPI,
                       $cResult))
            if (($cResult != 0) && $bExitOnErrPI);
    }

    return $cResult;
}




sub SubstFile($%)
{
    my $cFileNamePI = shift;
    my $hReplace    = shift;

    my @lFileContent;

    open REPLACEFILE, "<$cFileNamePI"
        or die "File $cFileNamePI can't be opened for reading";

    @lFileContent = <REPLACEFILE>;

    close REPLACEFILE;

    open REPLACEFILE, ">$cFileNamePI"
        or die "File $cFileNamePI can't be opened for writing";

    foreach my $cLine (@lFileContent)
    {
        foreach (keys %{$hReplace})
        {
            $cLine =~ s/$_/$hReplace->{$_}/g;
        }

        print REPLACEFILE $cLine;
    }

    close REPLACEFILE;

}


