pl: Schreibberechtigung in Verzeichnis

Beitrag lesen


package FileMan; # Datei Manager

use base main;
use strict;
use warnings;
use POSIX qw(strftime);
use MIME::Base64 qw(encode_base64);
use IO::File;

sub data{
    my $self = shift;
    $self->{DATAS} = $self->splitdata(<DATA>);
    $self->{BODY} = $self->{DATAS}{entries};
    $self->nocache;
}

sub init{
    my $self = shift;
    $self->nocache;
}

sub entries{
    my $self = shift;
    my $chdir = shift;
    chdir $chdir;
    opendir(my $dir, $chdir);
    my @e = readdir $dir;
    my @files = grep{-f} sort @e;
    my @dirs = grep{-d && -r} sort @e;
    shift @dirs; shift @dirs;
    
    my $stat = [stat $chdir];
    $self->{BODY} = $self->{DATAS}{entries};
    $self->{STASH}{dirs}  = [];
    $self->{STASH}{files} = [];
    $self->{STASH}{cwd}   = $chdir; 
    $self->{STASH}{mode}  = sprintf("%o", (stat($chdir))[2] & 07777);
    #"$stat->[5] $) ";
    #sprintf("%o", (stat($chdir))[2] & 07777);
    
    foreach my $d(@dirs){
        push @{$self->{STASH}{dirs}},{
            dirname => $d,
            cwd => $chdir,
            chdir => do{
                my $ndir = "$chdir/$d";
                $ndir =~ s/\//&#x25;2F/g;
                $ndir;
            },
        };
    }

    if( $chdir ne $self->eav('basedir')){
        unshift @{$self->{STASH}{dirs}},{
            dirname => 'SUPERDIR',
            chdir => do{
                my @sd = split '/', $chdir;
                pop @sd;
                my $ndir = join '/', @sd;
                $ndir =~ s/\//&#x25;2F/g;
                $ndir;
            }
        };
    }


    my $i = 0;
    foreach my $f(@files){
        my $stat = [stat "$chdir/$f"];
        push @{$self->{STASH}{files}},{
            filename => $f,
            mtime    => strftime("%d.%m.%Y %X", localtime $stat->[9]),
            size     => $stat->[7],
            type     => XR::xr($self->{DATAS}{type}, $self->checktype("$chdir/$f")),
            class    => $i % 2 ? qq(class='preemphasis') : '',
            url      => $self->{URL},
            index    => $i,
            mode     => sprintf("%o", $stat->[2] & 07777),
            owner    => $stat->[4] == $> ? 'Ja' : 'Nein',
        };
        $i++;
    }
    $self->{STASH}{anzahldateien} = scalar @files || 0;
}

sub checktype{
    my $self = shift;
    my $file = shift;
    my $suffix = do{
        $file =~ /\.(\w+)$/;
        $1 ? $1 : '';
    };
    return { bin_chk => 'checked', fullname => $file  } unless $suffix;
    
    if($suffix eq 'txt' || $suffix eq 'ini' || $suffix eq 'pm' || $suffix eq 'js' || $suffix eq 'css' || $suffix eq 'cgi' || $suffix eq 'html' || $suffix eq 'htm'){
        return {txt_chk => 'checked', fullname => $file};
    }
    elsif($suffix eq 'jpg' || $suffix eq 'jpeg' || $suffix eq 'png' || $suffix eq 'gif'){
        return {img_chk => 'checked', fullname => $file};
    }
    elsif($suffix eq 'bin'){
        return {bin_chk => 'checked', fullname => $file};
    }
    else{
        return {bin_chk => 'checked', fullname => $file};
    }
}

sub browse{
    my $self = shift;
    $self->entries( $self->eav('basedir') );
}

sub control{
    my $self = shift;
    if( my $chdir = $self->param('chdir') ){
        $self->entries( $chdir );
    }
    elsif(my $fullname = $self->param('edit')){
        $self->eav('title', $fullname);
        $self->{BODY} = $self->{DATAS}{editform};
        $self->{NO_MENU} = 1;
        my $ftype = $self->param('ftype');
        $self->{STASH}{ftype} = $ftype;
        #$ftype =~ s/\//_/;
        $self->{STASH}{fullname} = $fullname;
        $self->{STASH}{filename} = do{
            $fullname =~ /.*\/(.*)$/;
            $1 ? $1 : '';
        };
        
        my $stat = [stat $fullname];

        $self->{STASH}{owner_read}    = 'checked' if 1 & $stat->[2] >> 8;
        $self->{STASH}{owner_write}   = 'checked' if 1 & $stat->[2] >> 7;
        $self->{STASH}{owner_execute} = 'checked' if 1 & $stat->[2] >> 6;
        $self->{STASH}{group_read}    = 'checked' if 1 & $stat->[2] >> 5;
        $self->{STASH}{group_write}   = 'checked' if 1 & $stat->[2] >> 4;
        $self->{STASH}{group_execute} = 'checked' if 1 & $stat->[2] >> 3;
        $self->{STASH}{other_read}    = 'checked' if 1 & $stat->[2] >> 2;
        $self->{STASH}{other_write}   = 'checked' if 1 & $stat->[2] >> 1;
        $self->{STASH}{other_execute} = 'checked' if 1 & $stat->[2] >> 0;
        
        $self->{STASH}{backurl} = sprintf("%s?edit=%s;ftype=%s", $self->{URL}, $fullname, $ftype);
        
        if($ftype eq 'image/jpeg'){
            $self->{BODY} .= $self->{DATAS}{image_jpeg_form};
            $self->{STASH}{binary} = do{
                my $fh = IO::File->new;
                $fh->open($fullname, O_BINARY|O_RDONLY) or die $!;
                read($fh, my $binary, -s $fh);
                $fh->close;
                encode_base64($binary, '');
            };
        }
        elsif($ftype eq 'text/plain'){
            $self->{BODY} .= $self->{DATAS}{text_plain_form};
            $self->{STASH}{content} = do{
                @ARGV = $fullname;
                local $/ = undef;
                my $doc = <>;
                $doc =~ s/</&lt;/g;
                $doc;
            };
        }
        elsif($ftype eq 'text/html'){
            $self->{BODY} .= $self->{DATAS}{text_html_form};
            $self->{STASH}{content} = do{
                @ARGV = $fullname;
                local $/ = undef;
                <>;
            };
        }
        else{
            $self->{BODY} .= $self->{DATAS}{binary_form};
        }
    }
    elsif( $self->param('download') ){
        my $fullname = $self->param('fullname');
        my $ftype    = $self->param('ftype');
        my $filename = $self->param('filename');
        $self->header(
            "Content-Type"        => $ftype,
            "Content-Disposition" => qq(Attachment; filename="$filename"),
            "Content-Length"      => length($self->{CONTENT}),
        );
        my $fh =IO::File->new;
        $fh->open($fullname, O_RDONLY|O_BINARY) or die $!;
        read($fh, $self->{CONTENT}, -s $fh);
        $fh->close;
    }
    elsif($self->param('delete')){
        my $filename = $self->param('fullname');
        unlink($filename);
        $self->{NO_MENU} = 1;
        $self->{BODY} = qq(<p>Bitte Fenster schließen und darunterliegende Seite neu laden!</p>);
    }
    elsif($self->param('chmod')){
        my @owner = $self->param('owner') ? $self->param('owner') : ();
        my @group = $self->param('group') ? $self->param('group') : ();
        my @other = $self->param('other') ? $self->param('other') : ();
        my $owner = 0;
        my $group = 0;
        my $other = 0;
        
        
        if(scalar @owner){ $owner += $_ for @owner }
        if(scalar @group){ $group += $_ for @group }
        if(scalar @other){ $other += $_ for @other }
        
        my $fullname = $self->param('fullname');
        my $chmod = sprintf("%s%s%s", $owner, $group, $other); 
        
        qx(chmod $chmod $fullname);
        
        $self->redirect($self->param('backurl'));
    }
    elsif($self->param('upload')){
        my $cwd = $self->param('cwd');
        chdir $cwd;
        return $self->errorP( descr => 'Keine Datei!' ) if ! $self->param('upfiles');
        
        foreach my $r ( $self->param('upfiles') ){
            my $fh = IO::File->new;
            $fh->open($r->{filename}, O_CREAT|O_BINARY|O_RDWR ) or return $self->errorP( descr => "Keine Schreibberechtigung in '$cwd'\n");
            $r->{iohandle}->seek(0,0);
            read($r->{iohandle}, my $buffer, $r->{content_length});
            $fh->print($buffer);
            $fh->close;
        }
        
    
        my $redir = sprintf("%s%s", $self->{URL}, $self->param('cwd') eq $self->eav('basedir') ? '' : qq(?chdir=@{[$self->param('cwd')]}) );
        $self->redirect($redir);
    }
    else{}
}


1;#########################################################################
__DATA__

--entries------------------------------------------------------------------
<h2>Verzeichnisse</h2>

<p><strong>CurrentWorkDir (%mode%):</strong> <code>%cwd%</code></p>

<ul style="padding:0.2em">
    %loop_dirs%
        <li style="display:inline;padding:0.3em"> <a href="?chdir=%chdir%">%dirname%</a> </li>
    %endloop%
</ul>

<h2>%anzahldateien% Dateien</h2>

<table class="grid" id="tabtab">
<thead>
<tr style="cursor:pointer"  id="tabtab_thead_tr">
    <th>Dateiname</th>
    <th>Type</th>
    <th>Edit</th>
    <th>mtime</th>
    <th>Größe</th>
    <th>Rechte</th>
    <th>Owner</th>
</tr>
</thead>

<tbody>
    %loop_files%
    <tr %class%>
        <td> %filename% </td>
        <td> %type% </td>
        <td title="%filename%"> <button type="button" onClick="editfile(this.form)">...</button> </form></td>
        <td> %mtime% </td>
        <td> %size% </td>
        <td> %mode% </th>
        <td> %owner% </td>
    </tr>
    %endloop%
</tbody>
</table>

<form enctype="multipart/form-data" method="POST">
    <fieldset><legend><strong>Dateien hochladen:</strong></legend>
        <input type="hidden" name="cwd" value="%cwd%">
        <input type="file" name="upfiles" multiple>
        <button name="upload" value="1" onClick="throbber(true)">Upload Now!</button>
    </fieldset>
</form>

<script type="text/javascript">
function editfile(form){
    window.open('%url%?'+$(form).serialize(), 'EditFile', 'width=750,height=750,left=50,top=80,scrollbars=yes');
}


$(document).ready(function(){ 
    $("#tabtab").tablesorter(); 
    $("#tabtab_thead_tr").css('cursor',' pointer');
}); 
</script>

--type---------------------------------------------------------------------
<form>
<input type="hidden" name="edit" value="%fullname%">
Text:<input type="radio" name="ftype" value="text/plain" %txt_chk% >
Html:<input type="radio" name="ftype" value="text/html" %html_chk% >
Img:<input type="radio"  name="ftype" value="image/jpeg"  %img_chk% >
Bin:<input type="radio"  name="ftype" value="application/octet-stream"  %bin_chk% >

--text_plain_form----------------------------------------------------------

<pre>%content%</pre>

--text_html_form-----------------------------------------------------------


<div>%content%</div>

--image_jpeg_form----------------------------------------------------------

<p><img src="data:image/jpeg;base64,%binary%" alt="IMG"></p>

--binary_form--------------------------------------------------------------

--editform-----------------------------------------------------------------

<form>
    <fieldset style="border-style:solid"><legend><strong>Aktionen:</strong></legend>
        <input type="hidden" name="backurl" value="%backurl%">
        <input type="hidden" name="fullname" value='%fullname%'>
        <input type="hidden" name="filename" value='%filename%'>
        <input type="hidden" name="ftype" value='%ftype%'>
        <button name="download" value="1">Download</button>
        <button name="delete" value="1" onClick="return confirm('Datei \'%filename%\' löschen?')">Löschen</button>
        <button name="chmod" value="1">Chmod</button>
    </fieldset>
    <table class="grid" style="width:100%">
        <tr>
            <th>Owner</th>
            <th>Group</th>
            <th>Other</th>
        </tr>
        <tr>
            <td><input name="owner" value="4" type="checkbox" %owner_read%> Lesen</td>
            <td><input name="group" value="4" type="checkbox" %group_read%> Lesen</td>
            <td><input name="other" value="4" type="checkbox" %other_read%> Lesen</td>
        </tr>
        <tr>
            <td><input name="owner" value="2" type="checkbox" %owner_write%> Schreiben</td>
            <td><input name="group" value="2" type="checkbox" %group_write%> Schreiben</td>
            <td><input name="other" value="2" type="checkbox" %other_write%> Schreiben</td>
        </tr>
        <tr>
            <td><input name="owner" value="1" type="checkbox" %owner_execute%> Ausführen</td>
            <td><input name="group" value="1" type="checkbox" %group_execute%> Ausführen</td>
            <td><input name="other" value="1" type="checkbox" %other_execute%> Ausführen</td>
        </tr>
    </table>
</form>

<script>
    window.onunload = function(){
        window.opener.location.reload();
    };
</script>