use utf8;
use warnings;
no warnings 'redefine';
use vars qw($r);
use File::stat;
use Fcntl qw(:flock);
use Symbol;
use Search::Tools::UTF8;
use POSIX qw(sysconf _PC_CHOWN_RESTRICTED);
use POSIX 'floor';

sub EditFile {
    my $name = defined param('name') ? param('name') : $m_sAction;
    my @n = $m_oDatabase->fetch_array( "select file from `actions` where action=?", $name );
    FileOpen("$m_hrSettings->{cgi}{bin}/Content/$n[0]");
} ## end sub EditFile

sub round {
    my $x = shift;
    floor( $x + 0.5 );
} ## end sub round

sub showDir {
    my $sSubfolder = param('subfolder') ? param('subfolder') : shift;
    $sSubfolder = defined $sSubfolder ? $sSubfolder : $m_hrSettings->{cgi}{DocumentRoot};
    $sSubfolder =~ s?/$??g;
    my $links = $sSubfolder =~ m?^(.*/)[^/]+$? ? $1            : $sSubfolder;
    my $fname = $sSubfolder =~ m?^.*/([^/]+)$? ? qq(<b>$1</b>) : $sSubfolder;
    $links =~ s?//?/?g;
    my $elinks     = uri_escape($links);
    my $esubfolder = uri_escape($sSubfolder);
    $r = 0;
    my $orderby  = defined param('orderBy')  ? param('orderBy')  : 'NULL';
    my $byColumn = defined param('byColumn') ? param('byColumn') : 'a';
    my $state = defined param('desc') ? param('desc') == 1 ? 1 : 0 : 0;
    my $newstate = $state ? 0 : 1;
    my @t = readFiles( $sSubfolder, 0 );
    my $fileview = new HTML::Menu::TreeView();
  SWITCH: {

        if ( defined param('sort') ) {
            $fileview->sortTree(1);
            $fileview->desc( $state ? 1 : 0 );
            last SWITCH;
        } ## end if ( defined param('sort'...))
        if ( $byColumn eq 0 or $byColumn eq 1 or $byColumn eq 2 ) {
            $fileview->orderByColumn($byColumn);
            $fileview->desc( $state ? 1 : 0 );
            last SWITCH;
        } ## end if ( $byColumn eq 0 or...)
        if ( $orderby eq 'mTime' ) {
            @t = sort { lc( $a->{mtime} ) cmp lc( $b->{mtime} ) } @t;
            @t = reverse @t if $state;
            last SWITCH;
        } ## end if ( $orderby eq 'mTime')
        if ( $orderby eq 'Size' ) {
            @t = sort { $a->{size} <=> $b->{size} } @t;
            @t = reverse @t if $state eq 1;
            last SWITCH;
        } ## end if ( $orderby eq 'Size')
        $fileview->folderFirst(1);
    } ## end SWITCH:
    $fileview->TrOver(1);
    $fileview->columns(
        a(
            {
                href =>
"javascript:requestURI('$m_hrSettings->{cgi}{serverName}$ENV{SCRIPT_NAME}?action=FileOpen&file=$esubfolder&sort=1&desc=$newstate','FileOpen','FileOpen');",
                class => "treeviewLink$m_hrSettings->{size}",
                align => 'left',
            },
            'Name'
          )
          . (
            param('sort')
            ? (
                $state
                ? qq| <img src="/style/$m_sStyle/$m_hrSettings->{size}/mimetypes/up.png" border="0" alt="" title="up" width="16" height="16" />|
                : qq| <img src="/style/$m_sStyle/$m_hrSettings->{size}/mimetypes/down.png" border="0" alt="" title="down"/>|
              )
            : ''
          )
          . ' ',
        a(
            {
                href =>
"javascript:requestURI('$m_hrSettings->{cgi}{serverName}$ENV{SCRIPT_NAME}?action=FileOpen&file=$esubfolder&orderBy=Size&desc=$newstate','FileOpen','FileOpen')",
                class => "treeviewLink$m_hrSettings->{size}",
                align => "left"
            },
            'Size'
          )
          . (
            $orderby eq 'Size'
            ? (
                $state
                ? qq| <img src="/style/$m_sStyle/$m_hrSettings->{size}/mimetypes/up.png" border="0" alt="" title="up" width="16" height="16" />|
                : qq| <img src="/style/$m_sStyle/$m_hrSettings->{size}/mimetypes/down.png" border="0" alt="" title="down"/>|
              )
            : ''
          )
          . ' ',
        a(
            {
                href =>
"javascript:requestURI('$m_hrSettings->{cgi}{serverName}$ENV{SCRIPT_NAME}?action=FileOpen&file=$esubfolder&byColumn=1&desc=$newstate','FileOpen','FileOpen')",
                class => "treeviewLink$m_hrSettings->{size}",
                align => "left"
            },
            'Permission'
          )
          . (
            $byColumn == 0 && !param('sort')
            ? (
                $state
                ? qq| <img src="/style/$m_sStyle/$m_hrSettings->{size}/mimetypes/up.png" border="0" alt="" title="up" width="16" height="16" />|
                : qq| <img src="/style/$m_sStyle/$m_hrSettings->{size}/mimetypes/down.png" border="0" alt="" title="down" />|
              )
            : ''
          )
          . ' ',
        a(
            {
                href =>
"javascript:requestURI('$m_hrSettings->{cgi}{serverName}$ENV{SCRIPT_NAME}?action=FileOpen&file=$esubfolder&byColumn=2&desc=$newstate','FileOpen','FileOpen')",
                class => "treeviewLink$m_hrSettings->{size}",
                align => "left"
            },
            'UID'
          )
          . (
            $byColumn == 2
            ? (
                $state
                ? qq| <img src="/style/$m_sStyle/$m_hrSettings->{size}/mimetypes/up.png" border="0" alt="" title="up" width="16" height="16" />|
                : qq| <img src="/style/$m_sStyle/$m_hrSettings->{size}/mimetypes/down.png" border="0" alt="" title="down"/>|
              )
            : ''
          )
          . ' ',
        a(
            {
                href =>
"javascript:requestURI('$m_hrSettings->{cgi}{serverName}$ENV{SCRIPT_NAME}?action=FileOpen&file=$esubfolder&byColumn=3&desc=$newstate','FileOpen','FileOpen')",
                class => "treeviewLink$m_hrSettings->{size}",
                align => "left"
            },
            'GID'
          )
          . (
            $byColumn eq 3
            ? (
                $state
                ? qq| <img src="/style/$m_sStyle/$m_hrSettings->{size}/mimetypes/up.png" border="0" alt="" title="up" width="16" height="16"/>|
                : qq| <img src="/style/$m_sStyle/$m_hrSettings->{size}/mimetypes/down.png" border="0" alt="" title="down" />|
              )
            : ''
          )
          . ' ',
        a(
            {
                href =>
"javascript:requestURI('$m_hrSettings->{cgi}{serverName}$ENV{SCRIPT_NAME}?action=FileOpen&file=$esubfolder&orderBy=mTime&desc=$newstate','FileOpen','FileOpen')",
                class => "treeviewLink$m_hrSettings->{size}",
                align => "left"
            },
            'Last Modified'
          )
          . (
            $orderby eq 'mTime'
            ? (
                $state
                ? qq| <img src="/style/$m_sStyle/$m_hrSettings->{size}/mimetypes/up.png" border="0" alt="" title="up" width="16" height="16"/>|
                : qq| <img src="/style/$m_sStyle/$m_hrSettings->{size}/mimetypes/down.png" border="0" alt="" title="down"/>|
              )
            : ''
          )
          . ' ',
        '',
    ) if $#t >= 0;
    my $hf      = "javascript:requestURI('$m_hrSettings->{cgi}{serverName}$ENV{SCRIPT_NAME}?action=FileOpen&file=$elinks','FileOpen','FileOpen')";
    my $toolbar = div(
        { align => 'left' },
        a(
            {
                onclick =>
"prompt('Enter File Name',function(a){if(a != null )requestURI('$m_hrSettings->{cgi}{serverName}$ENV{SCRIPT_NAME}?action=newFile&file='+encodeURIComponent(a)+'&dir=$esubfolder','newFile','newFile')});",
                class => 'toolbarButton'
            },
            'New File'
          )
          . ' '
          . a(
            {
                onclick =>
"prompt('Neues Verzeichnis',function(a){if(a != null )requestURI('$m_hrSettings->{cgi}{serverName}$ENV{SCRIPT_NAME}?action=makeDir&file=$esubfolder&d='+encodeURIComponent(a),'makeDir','makeDir')});",
                class => 'toolbarButton'
            },
            'New Directory'
          )
          . ' '
          . (
            $^O ne 'MSWin32' ? a(
                {
                    onclick =>
"prompt('Enter Chmod: 0755',function(a){if(a != null ) requestURI('$m_hrSettings->{cgi}{serverName}$ENV{SCRIPT_NAME}?action=chmodFile&file=$esubfolder&chmod='+encodeURIComponent(a),'chmodFile','chmodFile')});",
                    class => 'toolbarButton'
                },
                'Chmod',
            ) : ''
          )
          . ' '
          . (
            $^O ne 'MSWin32' ? a(
                {
                    onclick =>
"var a;prompt('Enter User:',function(argv){a= argv;prompt('Enter Group:',function(b){if(a != null  && b != null)requestURI('$m_hrSettings->{cgi}{serverName}$ENV{SCRIPT_NAME}?action=chownFile&file=$esubfolder&user='+encodeURIComponent(a)+'&gid='+encodeURIComponent(b),'chownFile','chownFile')});});",
                    class => 'toolbarButton'
                },
                'Chown',
            ) : ''
          )
    );
    print
qq(<table class="ShowTables marginTop"><tr class="captionRadius"><td class="captionRadius" colspan="7"><a href="$hf" class="treeviewLink$m_hrSettings->{size}">$links $fname</a></td></tr><tr><td colspan="7" class="toolbar"><div id="toolbarcontent" class="toolbarcontent">$toolbar</div></td></tr><tr><td colspan="7" style="padding:0px;padding-bottom:1em;vertical-align:top;">)
      . ( $#t >= 0 ? $fileview->Tree( \@t, $m_sStyle ) : '' )
      . q(</td></tr></table>);
} ## end sub showDir

sub readFiles {
    my @TREEVIEW;
    my $dir  = shift;
    my $edir = uri_escape($dir);
    my $rk   = shift;
    $r++ if ($rk);
    if ( -d "$dir" && -r "$dir" ) {
        opendir DIR, $dir or warn "files.pl sub readFiles: $dir $!";
        foreach my $d ( readdir(DIR) ) {
            my $fl = "$dir/$d";
            my $sb = stat($fl);
          TYPE: {
                last TYPE if ( $d =~ /^\.+$/ );
                my $efl = uri_escape($fl);
                my $href =
                  "javascript:requestURI('$m_hrSettings->{cgi}{serverName}$ENV{SCRIPT_NAME}?action=FileOpen&file=$efl','FileOpen','FileOpen')";
                my ( $sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst ) = localtime( $sb->mtime );
                $year += 1900;
                $mon  = sprintf( "%02d", $mon );
                $mday = sprintf( "%02d", $mday );
                $min  = sprintf( "%02d", $min );
                $hour = sprintf( "%02d", $hour );
                $sec  = sprintf( "%02d", $sec );
                my $trdelete = translate('delete');
                my $trnew    = translate('new');
                my $trrename = translate('rename');

                if ( -d $fl ) {
                    push @TREEVIEW, {
                        text    => $d,
                        href    => "$href",
                        empty   => 1,
                        subtree => [ {}, {} ],
                        mtime   => $sb->mtime,
                        size    => $sb->size,
                        columns => [
                            sprintf( "%s", $sb->size ),
                            ( $^O ne 'MSWin32' ? sprintf( "%04o", $sb->mode & 07777 ) : '' ),
                            ( $^O ne 'MSWin32' ? getpwuid( $sb->uid )->name : '' ),
                            ( $^O ne 'MSWin32' ? $sb->gid : '' ),
                            "$year-$mon-$mday $hour:$min:$sec",
                            qq|<table cellpading="0" cellspacing="0">
                            <tr><td class="batch">&#xe906;<a class="treeviewLink16" href="javascript:prompt('Enter Filename:',function(a){if(a != null )requestURI('$m_hrSettings->{cgi}{serverName}$ENV{SCRIPT_NAME}?action=renameFile&file=$efl&newName='+encodeURIComponent(a),'renameFile','renameFile')});" title="$trrename">$trrename</a></td>|
                              . (
                                $^O ne 'MSWin32'
                                ? qq|<td class="batch">&#xe971;<a class="treeviewLink16" href="javascript:prompt('Enter User:',function(c){ a = c; prompt('Enter Group:',function(b){ if(a != null  && b != null)requestURI('$m_hrSettings->{cgi}{serverName}$ENV{SCRIPT_NAME}?action=chownFile&file=$efl&user='+encodeURIComponent(a)+'&gid='+encodeURIComponent(b),'chownFile','chownFile')});});" title="Chown">Chown</a></td>|
                                : ''
                              )
                              . (
                                $^O ne 'MSWin32'
                                ? qq|<td class="batch">&#xe972;<a class="treeviewLink16" href="javascript:prompt('Enter Chmod: 0755',function(a){if(a != null )requestURI('$m_hrSettings->{cgi}{serverName}$ENV{SCRIPT_NAME}?action=chmodFile&file=$efl&chmod='+encodeURIComponent(a),'chmodFile','chmodFile')});" title="Chmod">Chmod</a></td>|
                                : ''
                              )
                              . qq|<td class="batch">&#xe9ac;<a class="treeviewLink16" href="javascript:confirm2('$trdelete ?',function(a){requestURI('$m_hrSettings->{cgi}{serverName}$ENV{SCRIPT_NAME}?action=deleteFile&file=$efl','deleteFile','deleteFile')});" title="$trdelete">$trdelete</a></td>

                            </td></tr></table>|
                        ],
                    };
                    last TYPE;
                } ## end if ( -d $fl )
                if ( -f $fl ) {
                    my $suffix = $d =~ /\.([^\.]+)$/ ? $1 : '';
                    push @TREEVIEW, {
                        text    => "$d",
                        href    => "$href",
                        mtime   => $sb->mtime,
                        size    => $sb->size,
                        columns => [
                            sprintf( "%s",   $sb->size ),
                            sprintf( "%04o", $sb->mode & 07777 ),
                            ( $^O ne 'MSWin32' ? getpwuid( $sb->uid )->name : '' ),
                            $sb->gid,
                            "$year-$mon-$mday $hour:$min:$sec",
                            qq|

				  <table cellpading="0" cellspacing="0"><tr>

				  <td class="batch" style="font-size:14px;">&#xe906;<a class="treeviewLink16" href="javascript:prompt('Enter Filename:',function(a){if(a != null )requestURI('$m_hrSettings->{cgi}{serverName}$ENV{SCRIPT_NAME}?action=renameFile&file=$efl&newName='+encodeURIComponent(a),'renameFile','renameFile');});" title="$trrename">$trrename</a></td>

				  |
                              . (
                                $^O ne 'MSWin32'
                                ? qq|<td class="batch" style="font-size:14px;">&#xe971;<a class="treeviewLink16" href="javascript:prompt('Enter User:',function(c){a=c;prompt('Enter Group:',function(b){if(a != null  && b != null)requestURI('$m_hrSettings->{cgi}{serverName}$ENV{SCRIPT_NAME}?action=chownFile&file=$efl&user='+encodeURIComponent(a)+'&gid='+encodeURIComponent(b),'chownFile','chownFile');});});" title="Chown">Chown</a></td>|
                                : ''
                              )
                              . (
                                $^O ne 'MSWin32'
                                ? qq|<td class="batch" style="font-size:14px;">&#xe972;<a class="treeviewLink16" href="javascript:prompt('Enter Chmod: 0755',function(a){;if(a != null )requestURI('$m_hrSettings->{cgi}{serverName}$ENV{SCRIPT_NAME}?action=chmodFile&file=$efl&chmod='+encodeURIComponent(a),'chmodFile','chmodFile');});" title="Chmod">Chmod</a></td>|
                                : ''
                              )
                              . qq|<td class="batch" style="font-size:14px;">&#xe9ac;<a class="treeviewLink16" href="javascript:confirm2('$trdelete ?',function(a){requestURI('$m_hrSettings->{cgi}{serverName}$ENV{SCRIPT_NAME}?action=deleteFile&file=$efl','deleteFile','deleteFile');});" title="$trdelete">$trdelete</a></td>

				  </tr></table>|,
                        ],
                        image => ( -e "$m_hrSettings->{cgi}{DocumentRoot}/style/$m_sStyle/$m_hrSettings->{size}/mimetypes/$suffix.png" )
                        ? "$suffix.png"
                        : 'link_overlay.png',
                    };
                } ## end if ( -f $fl )
            } ## end TYPE:
        } ## end foreach my $d ( readdir(DIR...))
        $r = 0;
        return @TREEVIEW;
    } ## end if ( -d "$dir" && -r "$dir")
} ## end sub readFiles

sub FileOpen {
    my $f = defined param('file') ? param('file') : shift;
    return unless defined $f;
  SWITCH: {
        if ( -d $f ) {
            &showDir($f);
            last SWITCH;
        } ## end if ( -d $f )
        if ( -T $f ) {
            my $content = openFile($f);
            &showEditor( $f, $content, 'saveFile', $f );
            last SWITCH;
        } else {
            print br() . qq(<div align="center">) . translate('no_ascii_file') . "</div>";
        } ## end else [ if ( -T $f ) ]
        if ( $f =~ /png|jpg|jpeg|gif$/ && $f =~ m~/var/www/htdocs/(.*)$~ ) {
            print br() . qq(<div align="center"><img alt="" src="/$1" align="center"/>) . br() . "</div>";
            last SWITCH;
        } ## end if ( $f =~ /png|jpg|jpeg|gif$/...)
        print br() . translate("UnsopportedFileType") . br();
    } ## end SWITCH:
} ## end sub FileOpen

sub saveFile {
    my $txt   = param('txt');
    my $sFile = param('file');
    $txt =~ s/\r\n/\n/g;
    my $fh = gensym();
    unless ( -d $sFile ) {
        open $fh, ">:encoding(UTF-8)", "$sFile.bak" or warn "files.pl::saveFile $/ $! $/ $sFile $/";
        flock $fh, 2;
        seek $fh, 0, 0;
        truncate $fh, 0;
        print $fh $txt;
        close $fh;
        rename "$sFile.bak", $sFile or warn "files.pl::saveFile $/ $! $/" if ( -e "$sFile.bak" );
        chmod( 0755, $sFile ) if ( $sFile =~ m?\.pl? && $^O ne 'MSWin32' );
        FileOpen($sFile);
    } elsif ( defined param('title') && defined param('file') ) {
        my $sf = param('file') . '/' . param('title');
        open $fh, ">$sf.bak" or warn "files.pl::saveFile $/ $! $/ $sf $/";
        flock $fh, 2;
        seek $fh, 0, 0;
        truncate $fh, 0;
        print $fh $txt;
        close $fh;
        rename "$sf.bak", $sf or warn "files.pl::saveFile $/ $! $/" if ( -e "$sf.bak" );
        FileOpen($sf);
    } ## end elsif ( defined param('title'...))
} ## end sub saveFile

sub showEditor {
    my $h = shift;
    my $t = shift;
    unless ( is_valid_utf8($t) ) {
        utf8::decode($t);
    } ## end unless ( is_valid_utf8($t))
    my $a   = shift;
    my $fi  = shift;
    my $efl = $h;
    $efl =~ s?^(.+)/([^/]+)$?$1?;
    my $linkText = $h;
    $linkText =~ s?^(.+)/([^/]+)$?$1/<b>$2</b>?;
    $m_sJson->{m_sFile} = $t;
    my $link =
qq|<a href="javascript:requestURI('$m_hrSettings->{cgi}{serverName}$ENV{SCRIPT_NAME}?action=FileOpen&file=$efl','FileOpen','FileOpen')">$linkText</a>|;
    print qq|<div class="ShowTables marginTop">

    <form accept-charset="utf-8" action ="$m_hrSettings->{cgi}{serverName}$ENV{SCRIPT_NAME}" onsubmit="document.getElementById('txt').value = GetEditorLines();submitForm(this,'$a','$a');return false;" method="post">

    <table cellspacing="5" cellpadding="0" border="0" align="center" summary="files.pl" width="95%">
      <tbody>
      <tr>
	  <td>$link</td>
	</tr>
	<tr>

	<td>

	<pre id="editor"></pre>

	<textarea name="txt" id="txt" style="display:none;"></textarea>

	</td>

	</tr>

	<tr>

	  <td align="right"><input type="submit" name="save" value="Save"/>

	  <input type="hidden" value="$a" name="action"/>

	  <input type="hidden" value="$fi" name="file"/>

	  </td>

	</tr>

      </tbody>

    </table>

    </form></div><script>html =1;</script>|;
} ## end sub showEditor

sub newFile {
    my $d = defined param('dir') ? param('dir') : '';
    my $sFile = param('file');
    unless ( -e $sFile ) {
        open( IN, ">$d/$sFile" ) or die $!;
        close IN;
        print translate('newfileadded') if -e $sFile;
    } else {
        print translate('fileExists ') if -e $sFile;
    } ## end else
    &showDir($d);
} ## end sub newFile

sub makeDir {
    my $d     = param('d');
    my $sFile = param('file');
    unless ( -d "$sFile/$d" ) {
        mkdir "$sFile/$d";
        print translate('newfileadded') if -d $sFile;
    } else {
        print translate('fileExists');
    } ## end else
    &showDir($sFile);
} ## end sub makeDir

sub renameFile {
    my $file    = param('file');
    my $newName = param('newName');
    my $dir     = $file =~ /(.*\/)[^\/]+$/ ? $1 : '/';
    rename $file, "$dir$newName";
    &showDir($dir);
} ## end sub renameFile

sub chownFile {
    my $user  = param('user');
    my $uid   = getpwnam($user);
    my $gid   = param('gid');
    my $g     = getgrnam($gid);
    my $sFile = param('file');
    $can_chown_giveaway = not sysconf(_PC_CHOWN_RESTRICTED);
    print 'Not allowed' unless $can_chown_giveaway;
    my $cnt = chown $uid, $g, $sFile;
    print 'Ok' if $cnt > 0;
    my $d = $sFile =~ m?^(.*)/[^/]+$? ? $1 : $m_hrSettings->{cgi}{bin};
    &showDir($d);
} ## end sub chownFile

sub chmodFile {
    my $chmod = param('chmod');
    my $sFile = param('file');
    chmod oct($chmod), $sFile if $chmod =~ /\d\d\d\d/ && -e $sFile;
    my $d = $sFile =~ m?^(.*)/[^/]+$? ? $1 : $m_hrSettings->{cgi}{bin};
    &showDir($d);
} ## end sub chmodFile

sub deleteFile {
    my $sFile = param('file');
    unlink $sFile if -e $sFile;
    rmdir $sFile  if -d $sFile;
    my $d = $sFile =~ m?^(.*)/[^/]+$? ? $1 : $m_hrSettings->{cgi}{bin};
    &showDir($d);
} ## end sub deleteFile
