X-Git-Url: https://git.p6c8.net/devedit.git/blobdiff_plain/f0cd6d2f27ac9fcf1b121b9c2f7f8eb40b7a222c..09cce7f643af390fa39802d68b87d6f2e17295c4:/modules/Command.pm
diff --git a/modules/Command.pm b/modules/Command.pm
index 635d43d..506e0c0 100644
--- a/modules/Command.pm
+++ b/modules/Command.pm
@@ -5,38 +5,52 @@ package Command;
#
# Execute Dev-Editor's commands
#
-# Author: Patrick Canterino
-# Last modified: 2003-12-02
+# Author: Patrick Canterino
+# Last modified: 2009-05-04
+#
+# Copyright (C) 1999-2000 Roland Bluethgen, Frank Schoenmann
+# Copyright (C) 2003-2009 Patrick Canterino
+# All Rights Reserved.
+#
+# This file can be distributed and/or modified under the terms of
+# of the Artistic License 1.0 (see also the LICENSE file found at
+# the top level of the Dev-Editor distribution).
#
use strict;
use vars qw(@EXPORT);
+use Fcntl;
use File::Access;
use File::Copy;
use File::Path;
-use HTML::Entities;
-use Output;
+use Digest::MD5 qw(md5_hex);
use POSIX qw(strftime);
use Tool;
-my $script = $ENV{'SCRIPT_NAME'};
+use CGI qw(header
+ escape);
+
+use Output;
+use Template;
+
+my $script = encode_html($ENV{'SCRIPT_NAME'});
+my $users = eval('getpwuid(0)') && eval('getgrgid(0)');
my %dispatch = ('show' => \&exec_show,
'beginedit' => \&exec_beginedit,
- 'canceledit' => \&exec_unlock,
'endedit' => \&exec_endedit,
'mkdir' => \&exec_mkdir,
'mkfile' => \&exec_mkfile,
- 'workwithfile' => \&exec_workwithfile,
- 'workwithdir' => \&exec_workwithdir,
+ 'upload' => \&exec_upload,
'copy' => \&exec_copy,
'rename' => \&exec_rename,
'remove' => \&exec_remove,
- 'rmdir' => \&exec_rmdir,
- 'unlock' => \&exec_unlock
+ 'remove_multi' => \&exec_remove_multi,
+ 'chprop' => \&exec_chprop,
+ 'about' => \&exec_about
);
### Export ###
@@ -59,10 +73,16 @@ sub exec_command($$$)
{
my ($command,$data,$config) = @_;
- return error("Unknown command: $command") unless($dispatch{$command});
+ foreach(keys(%dispatch))
+ {
+ if(lc($_) eq lc($command))
+ {
+ my $output = &{$dispatch{$_}}($data,$config);
+ return $output;
+ }
+ }
- my $output = &{$dispatch{$command}}($data,$config);
- return $output;
+ return error($config->{'errors'}->{'command_unknown'},'/',{COMMAND => encode_html($command)});
}
# exec_show()
@@ -79,183 +99,193 @@ sub exec_show($$)
my ($data,$config) = @_;
my $physical = $data->{'physical'};
my $virtual = $data->{'virtual'};
- my $output;
+ my $upper_path = multi_string(upper_path($virtual));
+
+ my $tpl = new Template;
- if(-d $physical)
+ if(-d $physical && not -l $physical)
{
# Create directory listing
+ return error($config->{'errors'}->{'no_dir_access'},$upper_path->{'normal'}) unless(-r $physical && -x $physical);
+
my $direntries = dir_read($physical);
- return error("Reading of directory $virtual failed.",upper_path($virtual)) unless($direntries);
+ return error($config->{'errors'}->{'dir_read_failed'},$upper_path->{'normal'},{DIR => encode_html($virtual)}) unless($direntries);
my $files = $direntries->{'files'};
my $dirs = $direntries->{'dirs'};
- $output .= htmlhead("Directory listing of $virtual");
- $output .= equal_url($config->{'httproot'},$virtual);
- $output .= "\n\n
\n";
+ my $dirlist = '';
+
+ my $count = 0;
+
+ my $filter1 = $data->{'cgi'}->param('filter') || '*'; # The real wildcard
+ my $filter2 = ($filter1 && $filter1 ne '*') ? $filter1 : ''; # Wildcard for output
# Create the link to the upper directory
- # (only if we are not in the root directory)
+ # (only if the current directory is not the root directory)
- unless($virtual eq "/")
+ unless($virtual eq '/')
{
- my $upper = $physical."/..";
- my @stat = stat($upper);
+ $count++;
- $output .= " [SUBDIR] ";
- $output .= strftime("%d.%m.%Y %H:%M",localtime($stat[9]));
- $output .= " " x 10;
- $output .= "../\n";
- }
+ my @stat = stat($physical.'/..');
- # Get the length of the longest file/directory name
+ my $udtpl = new Template;
+ $udtpl->read_file($config->{'templates'}->{'dirlist_up'});
- my $max_name_len = 0;
+ $udtpl->fillin('UPPER_DIR',$upper_path->{'html'});
+ $udtpl->fillin('UPPER_DIR_URL',$upper_path->{'url'});
+ $udtpl->fillin('DATE',encode_html(strftime($config->{'timeformat'},($config->{'use_gmt'}) ? gmtime($stat[9]) : localtime($stat[9]))));
- foreach(@$dirs,@$files)
- {
- my $length = length($_);
- $max_name_len = $length if($length > $max_name_len);
+ $dirlist .= $udtpl->get_template;
}
# Directories
foreach my $dir(@$dirs)
{
- my @stat = stat($physical."/".$dir);
- my $virt_path = encode_entities($virtual.$dir."/");
-
- $output .= " ";
- $output .= "[SUBDIR] ";
- $output .= strftime($config->{'timeformat'},localtime($stat[9]));
- $output .= " " x 10;
- $output .= "".encode_entities($dir)."/";
- $output .= " " x ($max_name_len - length($dir) - 1)."\t (";
- $output .= "Work with directory)\n";
+ next if($config->{'hide_dot_files'} && substr($dir,0,1) eq '.');
+ next unless(dos_wildcard_match($filter1,$dir));
+
+ $count++;
+
+ my $phys_path = $physical.'/'.$dir;
+ my $virt_path = multi_string($virtual.$dir.'/');
+
+ my @stat = stat($phys_path);
+
+ my $dtpl = new Template;
+ $dtpl->read_file($config->{'templates'}->{'dirlist_dir'});
+
+ $dtpl->fillin('DIR',$virt_path->{'html'});
+ $dtpl->fillin('DIR_URL',$virt_path->{'url'});
+ $dtpl->fillin('DIR_NAME',encode_html($dir));
+ $dtpl->fillin('DATE',encode_html(strftime($config->{'timeformat'},($config->{'use_gmt'}) ? gmtime($stat[9]) : localtime($stat[9]))));
+ $dtpl->fillin('URL',equal_url(encode_html($config->{'httproot'}),$virt_path->{'html'}));
+
+ $dtpl->parse_if_block('forbidden',is_forbidden_file($config->{'forbidden'},$virt_path->{'normal'}));
+ $dtpl->parse_if_block('readable',-r $phys_path && -x $phys_path);
+ $dtpl->parse_if_block('users',$users && -o $phys_path);
+ $dtpl->parse_if_block('even',($count % 2) == 0);
+
+ $dirlist .= $dtpl->get_template;
}
# Files
foreach my $file(@$files)
{
- my $phys_path = $physical."/".$file;
- my $virt_path = encode_entities($virtual.$file);
+ next if($config->{'hide_dot_files'} && substr($file,0,1) eq '.');
+ next unless(dos_wildcard_match($filter1,$file));
- my @stat = stat($phys_path);
- my $in_use = $data->{'uselist'}->in_use($virtual.$file);
+ $count++;
- $output .= " " x (10 - length($stat[7]));
- $output .= $stat[7];
- $output .= " ";
- $output .= strftime($config->{'timeformat'},localtime($stat[9]));
- $output .= " " x 10;
- $output .= encode_entities($file);
- $output .= " " x ($max_name_len - length($file))."\t (";
+ my $phys_path = $physical.'/'.$file;
+ my $virt_path = multi_string($virtual.$file);
- # Link "View"
+ my @stat = lstat($phys_path);
+ my $too_large = $config->{'max_file_size'} && $stat[7] > $config->{'max_file_size'};
- if(-r $phys_path && -T $phys_path)
- {
- $output .= "View";
- }
- else
- {
- $output .= 'fillin('FILE',$virt_path->{'html'});
+ $ftpl->fillin('FILE_URL',$virt_path->{'url'});
+ $ftpl->fillin('FILE_NAME',encode_html($file));
+ $ftpl->fillin('FILE_URL',$virt_path->{'url'});
+ $ftpl->fillin('SIZE',$stat[7]);
+ $ftpl->fillin('DATE',encode_html(strftime($config->{'timeformat'},($config->{'use_gmt'}) ? gmtime($stat[9]) : localtime($stat[9]))));
+ $ftpl->fillin('URL',equal_url(encode_html($config->{'httproot'}),$virt_path->{'html'}));
- $output .= '">View';
- }
+ $ftpl->parse_if_block('link',-l $phys_path);
+ $ftpl->parse_if_block('readable',-r $phys_path);
+ $ftpl->parse_if_block('writeable',-w $phys_path);
+ $ftpl->parse_if_block('binary',-B $phys_path);
- $output .= " | ";
+ $ftpl->parse_if_block('forbidden',is_forbidden_file($config->{'forbidden'},$virt_path->{'normal'}));
+ $ftpl->parse_if_block('viewable',(-r $phys_path && -T $phys_path && not $too_large) || -l $phys_path);
+ $ftpl->parse_if_block('editable',(-r $phys_path && -w $phys_path && -T $phys_path && not $too_large) && not -l $phys_path);
- # Link "Edit"
+ $ftpl->parse_if_block('too_large',$config->{'max_file_size'} && $stat[7] > $config->{'max_file_size'});
- if(-w $phys_path && -r $phys_path && -T $phys_path && not $in_use)
- {
- $output .= "Edit";
- }
- else
- {
- $output .= 'parse_if_block('even',($count % 2) == 0);
- $output .= '">Edit';
- }
+ $dirlist .= $ftpl->get_template;
+ }
- # Link "Do other stuff"
+ $tpl->read_file($config->{'templates'}->{'dirlist'});
- $output .= " | Work with file)\n";
- }
+ $tpl->fillin('DIRLIST',$dirlist);
+ $tpl->fillin('DIR',encode_html($virtual));
+ $tpl->fillin('DIR_URL',escape($virtual));
+ $tpl->fillin('SCRIPT',$script);
+ $tpl->fillin('URL',encode_html(equal_url($config->{'httproot'},$virtual)));
- $output .= "
\n\n\n\n";
-
- # Bottom of directory listing
- # (Fields for creating files and directories)
-
- $output .= <
-
-
-
-
-
Create new file:
-
-
-
-
-
-END
- $output .= htmlfoot;
+ $tpl->fillin('FILTER',encode_html($filter2));
+ $tpl->fillin('FILTER_URL',escape($filter2));
+
+ $tpl->parse_if_block('empty',$dirlist eq '');
+ $tpl->parse_if_block('dir_writeable',-w $physical);
+ $tpl->parse_if_block('filter',$filter2);
+ $tpl->parse_if_block('gmt',$config->{'use_gmt'});
+ }
+ elsif(-l $physical)
+ {
+ # Show the target of a symbolic link
+
+ my $link_target = readlink($physical);
+
+ $tpl->read_file($config->{'templates'}->{'viewlink'});
+
+ $tpl->fillin('FILE',encode_html($virtual));
+ $tpl->fillin('DIR',$upper_path->{'html'});
+ $tpl->fillin('DIR_URL',$upper_path->{'url'});
+ $tpl->fillin('URL',encode_html(equal_url($config->{'httproot'},$virtual)));
+ $tpl->fillin('SCRIPT',$script);
+
+ $tpl->fillin('LINK_TARGET',encode_html($link_target));
}
else
{
# View a file
- return error("You have not enough permissions to view this file.",upper_path($virtual)) unless(-r $physical);
+ return error($config->{'errors'}->{'no_view'},$upper_path->{'normal'}) unless(-r $physical);
# Check on binary files
- # We have to do it in this way, or empty files
- # will be recognized as binary files
+ # We have to do it in this way or empty files will be recognized
+ # as binary files
- unless(-T $physical)
- {
- # Binary file
+ return error($config->{'errors'}->{'binary_file'},$upper_path->{'normal'}) unless(-T $physical);
- return error("This editor is not able to view/edit binary files.",upper_path($virtual));
- }
- else
- {
- # Text file
+ # Is the file too large?
- $output = htmlhead("Contents of file ".encode_entities($virtual));
- $output .= equal_url($config->{'httproot'},$virtual);
- $output .= dir_link($virtual);
+ return error($config->{'errors'}->{'file_too_large'},$upper_path->{'normal'},{SIZE => $config->{'max_file_size'}}) if($config->{'max_file_size'} && -s $physical > $config->{'max_file_size'});
- $output .= '
Someone else is currently editing this file. So not all features are available.
\n\n" unless($unused);
-
- $output .= "\n\n";
-
- # Copying of the file is always allowed - but we need read access
-
- if(-r $physical)
+ if(my $uploaded_file = $cgi->param('uploaded_file'))
{
- $output .= <Copy
-
-
+ if($cgi->param('remote_file'))
+ {
+ $uploaded_file = $cgi->param('remote_file');
-
+ $uploaded_file =~ s!/!!g;
+ $uploaded_file =~ s!\\!!g;
+ }
-END
- }
+ # Process file upload
- if($unused)
- {
- # File is not locked
- # Allow renaming and deleting the file
+ my $filename = file_name($uploaded_file);
+ my $file_phys = $physical.'/'.$filename;
+ my $file_virt = encode_html($virtual.$filename);
- $output .= <Move/rename
+ if(-e $file_phys)
+ {
+ return error($config->{'errors'}->{'link_replace'},$virtual) if(-l $file_phys);
+ return error($config->{'errors'}->{'dir_replace'},$virtual) if(-d $file_phys);
+ return error($config->{'errors'}->{'exist_no_write'},$virtual,{FILE => $file_virt}) unless(-w $file_phys);
+ return error($config->{'errors'}->{'file_exists'},$virtual,{FILE => $file_virt}) unless($cgi->param('overwrite'));
+ }
-
+ my $ascii = $cgi->param('ascii');
+ my $handle = $cgi->upload('uploaded_file');
-
+ return error($config->{'errors'}->{'invalid_upload'},$virtual) unless($handle);
-
Delete
+ # Read transferred file and write it to disk
-
Click on the button below to remove the file '$virtual'.
+ read($handle, my $data, -s $handle);
+ $data =~ s/\015\012|\012|\015/\n/g if($ascii); # Replace line separators if transferring in ASCII mode
+ file_save($file_phys,\$data,not $ascii) or return error($config->{'errors'}->{'mkfile_failed'},$virtual,{FILE => $file_virt});
-
-END
+ return devedit_reload({command => 'show', file => $virtual});
}
else
{
- # File is locked
- # Just display a button for unlocking it
+ my $tpl = new Template;
+ $tpl->read_file($config->{'templates'}->{'upload'});
- $output .= <Unlock file
+ $tpl->fillin('DIR',encode_html($virtual));
+ $tpl->fillin('DIR_URL',escape($virtual));
+ $tpl->fillin('URL',encode_html(equal_url($config->{'httproot'},$virtual)));
+ $tpl->fillin('SCRIPT',$script);
-
Someone else is currently editing this file. At least, the file is marked so. Maybe, someone who was editing the file has forgotten to unlock it. In this case (and only in this case) you can unlock the file using this button:
+ my $output = header(-type => 'text/html');
+ $output .= $tpl->get_template;
-
-END
+ return \$output;
}
-
- $output .= "\n";
- $output .= htmlfoot;
-
- return \$output;
}
-# exec_workwithdir()
+# exec_copy()
#
-# Display a form for renaming/deleting a directory
+# Copy a file and return to directory view
#
# Params: 1. Reference to user input hash
# 2. Reference to config hash
#
# Return: Output of the command (Scalar Reference)
-sub exec_workwithdir($$)
+sub exec_copy($$)
{
my ($data,$config) = @_;
my $physical = $data->{'physical'};
my $virtual = $data->{'virtual'};
+ my $dir = upper_path($virtual);
+ my $new_physical = $data->{'new_physical'};
- my $dir = encode_entities(upper_path($virtual));
-
- my $output = htmlhead("Work with directory ".encode_entities($virtual));
- $output .= equal_url($config->{'httproot'},$virtual);
+ return error($config->{'errors'}->{'link_copy'},$dir) if(-l $physical);
+ return error($config->{'errors'}->{'no_copy'},$dir) unless(-r $physical);
- $virtual = encode_entities($virtual);
+ if($new_physical)
+ {
+ my $new_virtual = multi_string($data->{'new_virtual'});
+ my $new_dir = upper_path($new_virtual->{'normal'});
- $output .= dir_link($virtual);
- $output .= "
Note: On UNIX systems, filenames are case-sensitive!