package MySQL::Admin::GUI;
use strict;
use warnings;
use utf8;
use DBI::Library::Database qw(:all);
use HTML::Menu::Pages;
use MySQL::Admin qw(:all :cgi-lib);
use HTML::Entities;
use User::pwent;
use MySQL::Admin::Settings;
use MySQL::Admin::Translate;
use MySQL::Admin::Config;
use MySQL::Admin::Session;
use HTML::Menu::TreeView qw(:all);
use HTML::Editor::BBCODE;
use CGI::QuickForm;
use HTML::Editor;
use Encode;
use Fcntl qw(:flock);
use Symbol;
use URI::Escape;
# use diagnostics;
use CGI::Carp qw(fatalsToBrowser);
require Exporter;
use vars
  qw( $m_bMainTemplate $DefaultClass $ACCEPT_LANGUAGE @EXPORT @ISA $m_bMod_perl %m_hUniq $m_hrParams $m_hrSettings $m_hrLng $m_nStart $m_nEnd $m_nRight $m_sAction $m_sSid $m_sStyle $m_sTitle $m_sUser $m_sCurrentDb $m_sCurrentHost  $m_sCurrentUser $m_sCurrentPass $m_nSkipCaptch );
@MySQL::Admin::GUI::EXPORT =
  qw( ContentHeader Body ChangeDb Unique openFile action applyRights maxlength);
@ISA                        = qw( Exporter MySQL::Admin );
$MySQL::Admin::GUI::VERSION = '0.95';
$m_bMod_perl                = ($ENV{MOD_PERL}) ? 1 : 0;
local $^W = 0;
our @m_processlist;
our $m_bFirstTime = 0;
our $m_oDatabase;
our $m_dbh;

=head1 NAME

MySQL::Admin::GUI - Just a MySQL administration Web-App

=head1 SYNOPSIS

use MySQL::Admin::GUI;

ContentHeader("config/settings.pl");

print Body();

=head2 EXPORT

  action Body maxlength openFile

=cut

=head2 ContentHeader

    ContentHeader("/path/to/your/settings.pl");

=cut

sub ContentHeader {
    my $m_hrSettingsfile = shift;
    init($m_hrSettingsfile) unless $m_bMod_perl and $m_bFirstTime;

    $m_nSkipCaptch = 0;
    $m_bMainTemplate = param('m_blogin') eq 'true' ? 1 : 0;

    #todo klären wiso m_hrLng durch init nicht gesetzt wird.

    *m_hrLng     = \$MySQL::Admin::Translate::lang;
    $m_oDatabase = new DBI::Library::Database();
    $m_oDatabase->serverName($m_hrSettings->{cgi}{serverName});
    $m_oDatabase->floodtime($m_hrSettings->{floodtime});

    $m_dbh = $m_oDatabase->initDB(
                                  {
                                   name     => $m_hrSettings->{database}{name},
                                   host     => $m_hrSettings->{database}{host},
                                   user     => $m_hrSettings->{database}{user},
                                   password => $m_hrSettings->{database}{password},
                                  }
                                 )
      unless $m_bFirstTime;
    $m_bFirstTime = 1;

    $m_sAction = param('action') ? param('action') : $m_hrSettings->{defaultAction};
    translate($m_sAction);
    $m_sAction = ($m_sAction =~ /^(\w{3,50})$/) ? $1 : $m_hrSettings->{defaultAction};
    $m_sCurrentHost = param('m_shost') ? param('m_shost') : $m_hrSettings->{database}{CurrentHost};
    $m_sCurrentUser = param('m_suser') ? param('m_suser') : $m_hrSettings->{database}{CurrentUser};
    $m_sCurrentPass = param('m_spass') ? param('m_spass') : $m_hrSettings->{database}{CurrentPass};

    if (param('m_ChangeCurrentDb')) {
        $m_sCurrentDb                          = param('m_ChangeCurrentDb');
        $m_hrSettings->{database}{CurrentDb}   = $m_sCurrentDb;
        $m_hrSettings->{database}{CurrentHost} = $m_sCurrentHost;
        $m_hrSettings->{database}{CurrentUser} = $m_sCurrentUser;
        $m_hrSettings->{database}{CurrentPass} = $m_sCurrentPass;
        $m_sAction                             = 'ShowTables';
        saveSettings($m_hrSettingsfile);
    } else {
        $m_sCurrentDb = $m_hrSettings->{database}{CurrentDb};
    }
    my $cookiepath = $m_hrSettings->{cgi}{cookiePath};

    $m_sSid =
        defined cookie(-name => 'sid') ? cookie(-name => 'sid')
      : defined param('sid') ? param('sid')
      : '123'
      unless $m_sAction eq 'logout';
    $m_sUser = $m_oDatabase->getName($m_sSid);
    $m_sUser = defined $m_sUser ? $m_sUser : 'guest';
    my @aCookies;
    if ($m_sAction eq 'logout' or ($m_sUser eq 'guest' and $m_sAction ne 'login')) {
        my $cookie = cookie(
                            -name    => 'sid',
                            -value   => '',
                            -expires => '-1d',
                            -path    => "$cookiepath"
                           );
        push @aCookies, $cookie;
        print header(
                     -type                        => 'text/xml',
                     -charset                     => 'UTF-8',
                     -access_control_allow_origin => '*',
                     -cookie                      => [@aCookies]
                    );
        $m_sUser   = 'guest';
        $m_sSid    = '123';
        $m_sAction = $m_bMainTemplate ? $m_hrSettings->{defaultAction} : 'news'
          if ($m_sAction eq 'logout');
    } elsif ($m_sAction eq 'login') {
        my $ip = remote_addr();
        my $u  = param('user');
        my $p  = param('pass');
        $m_nSkipCaptch = 0;
        eval('
        use Authen::Captcha;
        my $captcha = Authen::Captcha->new(data_folder   => "$m_hrSettings->{cgi}{bin}/config/",output_folder => "$m_hrSettings->{cgi}{DocumentRoot}/images");
        $m_nSkipCaptch = $captcha->check_code(param("captcha"), param("md5"));
        ');
        $m_nSkipCaptch = 1 if $@;
        if (defined $u && defined $p && defined $ip && $m_nSkipCaptch > 0) {
            use MD5;
            my $md5 = new MD5;
            $md5->add($u);
            $md5->add($p);
            my $cyrptpass = $md5->hexdigest();
            my $result    = 1;
            if ($m_oDatabase->checkPass($u, $cyrptpass)) {
                $m_sSid = $m_oDatabase->setSid($u, $p, $ip);
                my $cookie = cookie(
                                    -name    => 'sid',
                                    -value   => "$m_sSid",
                                    -path    => "$cookiepath",
                                    -expires => '+1y'
                                   );
                push @aCookies, $cookie if $result eq 1;
                print header(
                             -type                        => 'text/xml',
                             -access_control_allow_origin => '*',
                             -charset                     => 'UTF-8',
                             -cookie                      => [@aCookies]
                            );
                $m_sUser = $u;
                $m_sAction = $m_bMainTemplate ? $m_hrSettings->{defaultAction} : 'news';
            } else {
                print header(
                             -type                        => 'text/xml',
                             -access_control_allow_origin => '*',
                             -charset                     => 'UTF-8',
                            );
            }
        } else {
            print header(
                         -type                        => 'text/xml',
                         -access_control_allow_origin => '*',
                         -charset                     => 'UTF-8',
                        );
        }
    } else {
        print header(
                     -type                        => 'text/xml',
                     -access_control_allow_origin => '*',
                     -charset                     => 'UTF-8'
                    );
    }
    $m_nRight = $m_oDatabase->userright($m_sUser);
    print qq(<?xml version="1.0" encoding="UTF-8"?>\n<xml>\n\n);
    print qq|<output id="sid"><![CDATA[
    <script>
    m_sid     = "$m_sSid";
    cAction   = "$m_sAction";
    size      = $m_hrSettings->{size};
    right     = $m_nRight;
    htmlright = $m_hrSettings->{htmlright};
    style     = "$m_hrSettings->{cgi}{style}";
    </script>]]></output>|;
}

=head2 Body

  print Body();

=cut

sub Body {
    CGI::upload_hook(\&hook);
    $m_sStyle = $m_hrSettings->{cgi}{style};
    $m_nStart = param('von') ? param('von') : 0;
    $m_nStart = ($m_nStart =~ /^(\d+)$/) ? $1 : 0;
    $m_nEnd   = param('bis') ? param('bis') : 30;
    $m_nEnd   = ($m_nEnd =~ /^(\d+)$/) ? $1 : 0;
    if ($m_nStart < 0) {
        $m_sAction = 'exploit';
        $m_nStart  = 0;
    }
    $m_nRight = defined $m_nRight ? $m_nRight : 0;
    my $exploit = 0;
    my $query =
      "select actions.action,actions.file,actions.title,actions.right,actions.sub,actions_set.output_id from actions join actions_set on actions.action = actions_set.foreign_action where actions_set.action = ?";
    $query .= " || actions_set.action = 'default'" if $m_bMainTemplate;
    my @action_set = $m_oDatabase->fetch_AoH($query, $m_sAction);
    $exploit = 1 if $@;
    for (my $i = 0 ; $i <= $#action_set ; $i++) {
        my $action = $action_set[$i];
        $m_sTitle = $action->{title};
        if ($m_nRight >= $action->{right}) {
            print qq|<output id="$action->{output_id}"><![CDATA[|;
            do("$m_hrSettings->{cgi}{bin}/Content/$action->{file}")
              if -e "$m_hrSettings->{cgi}{bin}/Content/$action->{file}";
            eval($action->{sub}) if $action->{sub} ne 'main';
            print q|]]></output>|;
            print qq|<output id="errorMessage"><![CDATA[$@]]></output>| if $@;
        } else {
            $exploit = 1;
        }
    }
    if ($exploit) {
        print qq|<output id="content"><![CDATA[|;
        do("$m_hrSettings->{cgi}{bin}/Content/exploit.pl");
        print q|]]></output>|;
        print qq|<output id="errorMessage"><![CDATA[$@ ]]></output>| if $@;
    }

    #     else{#change main Db
    ChangeDb(
             {
              name     => $m_hrSettings->{database}{name},
              host     => $m_hrSettings->{database}{host},
              user     => $m_hrSettings->{database}{user},
              password => $m_hrSettings->{database}{password},
             }
            );

    #     }
    #     clearSession();
    #
    print '</xml>';
}

=head2 ChangeDb

    my %db = {

	    name => '',

	    host   => '',

	    user => '',

	    password => '',

    };

    ChangeDb(\%db);

=cut

sub ChangeDb {
    my $hash = shift;
    my $m_sTitle = $hash->{title} if (defined $hash->{title});
    $m_dbh = $m_oDatabase->initDB(
                                  {
                                   name     => $hash->{name},
                                   host     => $hash->{host},
                                   user     => $hash->{user},
                                   password => $hash->{password},
                                  }
                                 );
}

=head2 Unique()

  $unique =Unique();

=cut

sub Unique {
    my $unic;
    do { $unic = int(rand(1000000)); } while (defined $m_hUniq{$unic});
    $m_hUniq{$unic} = 1;
    return $unic;
}

=head2 openFile

        my $file = openFile("filename");

=cut

sub openFile {
    my $file = shift;
    if (-e $file) {
        use Fcntl qw(:flock);
        use Symbol;
        my $fh = gensym;
        open $fh, $file or warn "$!: $file $/";
        seek $fh, 0, 0;
        my $lines;
        while (my $line = <$fh>) {
            $lines .= $line;
        }
        close $fh;
        return $lines;
    } else {
        warn "file exestiert nicht $/";
    }
}

=head2 applyRights()

updates the user rights to a treeviewLink

        applyRights(\@tree);

=cut

sub applyRights {
    my $t = shift;
    for (my $i = 0 ; $i < @$t ; $i++) {
        my $r = @$t[$i]->{right} ? @$t[$i]->{right} : 0;
        if ($r > $m_nRight) {
            undef @$t[$i];
        } elsif (ref @$t[$i]->{subtree}[0] eq "HASH" ) {
            applyRights(\@{@$t[$i]->{subtree}});
        }
    }
}

=head2 action

        my %action = {

                title => '',

                src   => 'ea67',#webfont

                location => '',#url

                style => 'optional',

        };

        print action{\%action);

=cut

sub action {
    my $hash     = shift;
    my $title    = $hash->{title} if (defined $hash->{title});
    my $src      = $hash->{src} if (defined $hash->{src});
    my $location = $hash->{location} if (defined $hash->{location});
    if ($location !~ /^javascript:/) {
        $location = "requestURI('$location',this.id,'$title')";
    }
    return
      qq(<a onclick="$location" class="batch">&#x$src;</a><a class="link" href="javascript:$location" >$title</a> );
}

=head2  maxlength()
     
     maxlength($length ,\$text);

=cut

sub maxlength {
    my $maxWidth = shift;
    ++$maxWidth;
    my $txt = shift;
    if (length($$txt) > $maxWidth) {
        my $maxLength = $maxWidth;
        my $i++;
        while ($i < length($$txt)) {
            if (substr($$txt, $i, 1) eq "<") {
                $maxLength = $maxWidth;
                do { $i++ } while (substr($$txt, $i, 1) ne ">" and $i < length($$txt));
            }
            if (substr($$txt, $i, 1) eq "&") {
                $maxLength = $maxWidth;
                do { $i++ } while (substr($$txt, $i, 1) ne ";" and $i < length($$txt));
            }
            $maxLength = (substr($$txt, $i, 1) =~ /\S/) ? --$maxLength : $maxWidth;
            if ($maxLength eq 0) {
                substr($$txt, $i, 1) = " ";
                $maxLength = $maxWidth;
            }
            $i++;
        }
    }
}

=head1 SEE ALSO

L<CGI> L<MySQL::Admin>
L<DBI> L<DBI::Library> L<DBI::Library::Database>
L<MySQL::Admin::Main> L<HTML::TabWidget>  L<HTML::Menu::Pages>


=head1 AUTHOR

Dirk Lindner <lze@cpan.org>

=head1 COPYRIGHT AND LICENSE

Copyright (C) 2005-2015 by Hr. Dirk Lindner

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public License
as published by the Free Software Foundation;
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 Lesser General Public License for more details.

=cut

1;
