# See bottom of file for license and copyright information
package Foswiki::Configure::Checkers::BasicSanity;
use base 'Foswiki::Configure::Checker';

use strict;

sub new {
    my ( $class, $item ) = @_;
    my $this = $class->SUPER::new($item);
    $this->{LocalSiteDotCfg} = undef;
    $this->{errors}          = 0;

    return $this;
}

# return true if we have fatal errors
sub insane() {
    my $this = shift;
    return $this->{errors};
}

sub ui {
    my $this   = shift;
    my $result = '';
    my $badLSC = 0;

    $this->{LocalSiteDotCfg} = Foswiki::findFileOnPath('LocalSite.cfg');
    unless ( $this->{LocalSiteDotCfg} ) {
        $this->{LocalSiteDotCfg} = Foswiki::findFileOnPath('Foswiki.spec') || '';
        $this->{LocalSiteDotCfg} =~ s/Foswiki\.spec/LocalSite.cfg/;
    }

    # Get default settings by reading .spec files
    require Foswiki::Configure::Load;
    Foswiki::Configure::Load::readDefaults();

    $Foswiki::defaultCfg = _copy( \%Foswiki::cfg );

    if ( !$this->{LocalSiteDotCfg} ) {
        $this->{errors}++;
        $result .= <<HERE;
Could not find where LocalSite.cfg is supposed to go.
Edit your LocalLib.cfg and set \$twikiLibPath to point to the 'lib' directory
for your install.
Please correct this error before continuing.
HERE
    }
    elsif ( -e $this->{LocalSiteDotCfg} ) {
        eval { Foswiki::Configure::Load::readConfig(); };
        if ($@) {
            $result .= <<HERE;
Existing configuration file has a problem
that is causing a Perl error - the following message(s) was generated:
<pre>$@</pre>
You can continue, but configure will not pick up any of the existing
settings from this file unless you correct the perl error.
HERE
            $badLSC = 1;
        }
        elsif ( !-w $this->{LocalSiteDotCfg} ) {
            $result .= <<HERE;
Cannot write to existing configuration file
$this->{LocalSiteDotCfg} is not writable.
You can view the configuration, but you will not be able to save.
Check the file permissions.
HERE
        }
        elsif ( (my $mess = $this->checkCfg(\%Foswiki::cfg)) ) {
            $result .= <<HERE;
The existing configuration file
$this->{LocalSiteDotCfg} doesn't seem to contain a good configuration
for Foswiki. The following problems were found:<br>
$mess
You are recommended to repair these problems manually, or delete
$this->{LocalSiteDotCfg} and start the configuration process again.
HERE
        }

    }
    else {

        # Doesn't exist (yet)
        my $errs = $this->checkCanCreateFile( $this->{LocalSiteDotCfg} );

        if ($errs) {
            $result .= <<HERE;
Configuration file $this->{LocalSiteDotCfg} does not exist, and I cannot
write a new configuration file due to these errors:
<pre/>$errs<pre>
You can view the default configuration, but you will not be able to save.
HERE
            $badLSC = 1;
        }
        else {
            $result .= <<HERE;
Could not find existing configuration file <code>$this->{LocalSiteDotCfg}</code>.
<h3>Do you run configure for the first time?</h3>
Please fill in the required paths in the
<a rel="nofollow" href="#GeneralPathSettingslink" onclick="foldBlock('GeneralPathSettings'); return false;">
General path settings</a> section below and click 'Next' to save before returning to configure to complete configuration.
<h3>Did you save the configuration before?</h3>
Please check for the existence of <code>lib/LocalSite.cfg</code>, and make sure the webserver user can read it.
HERE
            $badLSC = 1;
        }
    }

    # If we got this far without definitions for key variables, then
    # we need to default them. otherwise we get peppered with
    # 'uninitialised variable' alerts later.
    foreach my $var qw( DataDir DefaultUrlHost PubUrlPath
      PubDir TemplateDir ScriptUrlPath LocalesDir ) {

        # NOT SET tells the checker to try and guess the value later on
        $Foswiki::cfg{$var} = 'NOT SET' unless defined $Foswiki::cfg{$var};
      }

      # Make %ENV safer for CGI
      $Foswiki::cfg{DETECTED}{originalPath} = $ENV{PATH} || '';
    unless ( $Foswiki::cfg{SafeEnvPath} ) {

        # Grab the current path
        if ( defined( $ENV{PATH} ) ) {
            $ENV{PATH} =~ /(.*)/;
            $Foswiki::cfg{SafeEnvPath} = $1;
        }
        else {

            # Can't guess
            $Foswiki::cfg{SafeEnvPath} = '';
        }
    }
    $ENV{PATH} = $Foswiki::cfg{SafeEnvPath};
    delete @ENV{qw( IFS CDPATH ENV BASH_ENV )};

    return ( $result, $badLSC );
}

sub _copy {
    my $n = shift;

    return undef unless defined($n);

    if ( UNIVERSAL::isa( $n, 'ARRAY' ) ) {
        my @new;
        for ( 0 .. $#$n ) {
            push( @new, _copy( $n->[$_] ) );
        }
        return \@new;
    }
    elsif ( UNIVERSAL::isa( $n, 'HASH' ) ) {
        my %new;
        for ( keys %$n ) {
            $new{$_} = _copy( $n->{$_} );
        }
        return \%new;
    }
    elsif ( UNIVERSAL::isa( $n, 'Regexp' ) ) {
        return qr/$n/;
    }
    elsif ( UNIVERSAL::isa( $n, 'REF' ) || UNIVERSAL::isa( $n, 'SCALAR' ) ) {
        $n = _copy($$n);
        return \$n;
    }
    else {
        return $n;
    }
}

# Check that an existing LocalSite.cfg doesn't contain crap.

sub checkCfg {
    my ($this, $entry, $keys) = @_;
    $keys ||= '';
    my $mess = '';

    if (ref($entry) eq 'HASH') {
        foreach my $el (keys %$entry) {
            $mess .= $this->checkCfg($entry->{$el}, "$keys\{$el}");
        }
    }
    elsif (ref($entry) eq 'ARRAY') {
        foreach my $i (0..scalar(@$entry)) {
            $mess .= $this->checkCfg($entry->[$i], "$keys\[$i]")
        }
    }
    else {
        if (defined $entry && $entry =~ /NOT SET/) {
            $mess .=
              "<div>\$Foswiki::cfg::$keys has been guessed and may be incorrect</div>";
        }
    }
    return $mess;
}

1;
__DATA__
#
# Foswiki - The Free and Open Source Wiki, http://foswiki.org/
#
# Copyright (C) 2008 Foswiki Contributors. All Rights Reserved.
# Foswiki Contributors are listed in the AUTHORS file in the root
# of this distribution. NOTE: Please extend that file, not this notice.
#
# Additional copyrights apply to some or all of the code in this
# file as follows:
#
# Copyright (C) 2000-2006 TWiki Contributors. All Rights Reserved.
# TWiki Contributors are listed in the AUTHORS file in the root
# of this distribution. NOTE: Please extend that file, not this notice.
#
# 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 2
# of the License, or (at your option) any later version. For
# more details read LICENSE in the root of this distribution.
#
# 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.
#
# As per the GPL, removal of this notice is prohibited.
#
