\n";
+ my $dir_writeable = -w $physical;
+
+ my $dirlist = '';
+
+ 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);
+ my @stat = stat($physical.'/..');
- $output .= " [SUBDIR] ";
- $output .= strftime("%d.%m.%Y %H:%M",localtime($stat[9]));
- $output .= " " x 10;
- $output .= "../\n";
- }
-
- # 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);
+ $udtpl->fillin('DATE',encode_entities(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 unless(dos_wildcard_match($filter1,$dir));
+
+ my $phys_path = $physical.'/'.$dir;
+ my $virt_path = encode_entities($virtual.$dir.'/');
+
+ my @stat = stat($phys_path);
+
+ my $dtpl = new Template;
+ $dtpl->read_file($config->{'templates'}->{'dirlist_dir'});
+
+ $dtpl->fillin('DIR',$virt_path);
+ $dtpl->fillin('DIR_NAME',encode_entities($dir));
+ $dtpl->fillin('DATE',encode_entities(strftime($config->{'timeformat'},($config->{'use_gmt'}) ? gmtime($stat[9]) : localtime($stat[9]))));
+ $dtpl->fillin('URL',equal_url(encode_entities($config->{'httproot'}),$virt_path));
+
+ $dtpl->parse_if_block('readable',-r $phys_path && -x $phys_path);
+ $dtpl->parse_if_block('users',$users && -o $phys_path);
+
+ $dirlist .= $dtpl->get_template;
}
# Files
foreach my $file(@$files)
{
- my $phys_path = $physical."/".$file;
+ next unless(dos_wildcard_match($filter1,$file));
+
+ my $phys_path = $physical.'/'.$file;
my $virt_path = encode_entities($virtual.$file);
- my @stat = stat($phys_path);
- my $in_use = $data->{'uselist'}->in_use($virtual.$file);
+ my @stat = lstat($phys_path);
+ my $in_use = $uselist->in_use($virtual.$file);
+ my $too_large = $config->{'max_file_size'} && $stat[7] > $config->{'max_file_size'};
- $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 $ftpl = new Template;
+ $ftpl->read_file($config->{'templates'}->{'dirlist_file'});
- # Link "View"
+ $ftpl->fillin('FILE',$virt_path);
+ $ftpl->fillin('FILE_NAME',encode_entities($file));
+ $ftpl->fillin('SIZE',$stat[7]);
+ $ftpl->fillin('DATE',encode_entities(strftime($config->{'timeformat'},($config->{'use_gmt'}) ? gmtime($stat[9]) : localtime($stat[9]))));
+ $ftpl->fillin('URL',equal_url(encode_entities($config->{'httproot'}),$virt_path));
- if(-r $phys_path && -T $phys_path)
- {
- $output .= "View";
- }
- else
- {
- $output .= '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 $in_use) && not -l $phys_path);
- $output .= '">View';
- }
+ $ftpl->parse_if_block('in_use',$in_use);
+ $ftpl->parse_if_block('unused',not $in_use);
- $output .= " | ";
+ $ftpl->parse_if_block('too_large',$config->{'max_file_size'} && $stat[7] > $config->{'max_file_size'});
- # Link "Edit"
+ $ftpl->parse_if_block('users',$users && -o $phys_path);
- if(-w $phys_path && -r $phys_path && -T $phys_path && not $in_use)
- {
- $output .= "Edit";
- }
- else
- {
- $output .= 'read_file($config->{'templates'}->{'dirlist'});
- $output .= '">Edit';
- }
+ $tpl->fillin('DIRLIST',$dirlist);
+ $tpl->fillin('DIR',encode_entities($virtual));
+ $tpl->fillin('SCRIPT',$script);
+ $tpl->fillin('URL',encode_entities(equal_url($config->{'httproot'},$virtual)));
- # Link "Do other stuff"
+ $tpl->fillin('FILTER',encode_entities($filter2));
+ $tpl->fillin('FILTER_URL',escape($filter2));
- $output .= " | Work with file)\n";
- }
+ $tpl->parse_if_block('dir_writeable',$dir_writeable);
+ $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'});
- $output .= "
\n\n\n\n";
-
- # Bottom of directory listing
- # (Fields for creating files and directories)
-
- $output .= <
-
-
-
-
-
Create new file:
-
-
-
-
-
-END
- $output .= htmlfoot;
+ $tpl->fillin('FILE',encode_entities($virtual));
+ $tpl->fillin('DIR',$upper_path);
+ $tpl->fillin('URL',encode_entities(equal_url($config->{'httproot'},$virtual)));
+ $tpl->fillin('SCRIPT',$script);
+
+ $tpl->fillin('LINK_TARGET',encode_entities($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) 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'},$upper_path) 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,{SIZE => $config->{'max_file_size'}}) if($config->{'max_file_size'} && -s $physical > $config->{'max_file_size'});
- $output .= '
";
+ # View the file
- $output .= htmlfoot;
- }
+ my $content = file_read($physical);
+ $$content =~ s/\015\012|\012|\015/\n/g;
+
+ $tpl->read_file($config->{'templates'}->{'viewfile'});
+
+ $tpl->fillin('FILE',encode_entities($virtual));
+ $tpl->fillin('DIR',$upper_path);
+ $tpl->fillin('URL',encode_entities(equal_url($config->{'httproot'},$virtual)));
+ $tpl->fillin('SCRIPT',$script);
+
+ $tpl->parse_if_block('editable',-w $physical && $uselist->unused($virtual));
+
+ $tpl->fillin('CONTENT',encode_entities($$content));
}
+ my $output = header(-type => 'text/html');
+ $output .= $tpl->get_template;
+
return \$output;
}
@@ -273,70 +279,65 @@ sub exec_beginedit($$)
my ($data,$config) = @_;
my $physical = $data->{'physical'};
my $virtual = $data->{'virtual'};
+ my $dir = upper_path($virtual);
my $uselist = $data->{'uselist'};
- return error("You cannot edit directories.",upper_path($virtual)) if(-d $physical);
- return error_in_use($virtual) if($uselist->in_use($virtual));
- return error("You have not enough permissions to edit this file.",upper_path($virtual)) unless(-r $physical && -w $physical);
+ return error($config->{'errors'}->{'link_edit'},$dir) if(-l $physical);
+ return error($config->{'errors'}->{'dir_edit'}, $dir) if(-d $physical);
+ return error($config->{'errors'}->{'in_use'}, $dir,{FILE => $virtual}) if($uselist->in_use($virtual));
+ return error($config->{'errors'}->{'no_edit'}, $dir) unless(-r $physical && -w $physical);
# Check on binary files
- unless(-T $physical)
- {
- # Binary file
+ return error($config->{'errors'}->{'binary'},$dir) 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?
- $uselist->add_file($virtual);
- $uselist->save;
+ return error($config->{'errors'}->{'file_too_large'},$dir,{SIZE => $config->{'max_file_size'}}) if($config->{'max_file_size'} && -s $physical > $config->{'max_file_size'});
- my $dir = upper_path($virtual);
- my $content = encode_entities(${file_read($physical)});
+ # Lock the file...
- my $equal_url = equal_url($config->{'httproot'},$virtual);
+ ($uselist->add_file($virtual) and
+ $uselist->save) or return error($config->{'errors'}->{'ul_add_failed'},$dir,{FILE => $virtual});
- $virtual = encode_entities($virtual);
+ # ... and show the editing form
- my $output = htmlhead("Edit file $virtual");
- $output .= $equal_url;
- $output .= <Caution! This file is locked for other users while you are editing it. To unlock it, click Save and exit or Exit WITHOUT saving. Please don't click the Reload button in your browser! This will confuse the editor.
+ my $content = file_read($physical);
+ $$content =~ s/\015\012|\012|\015/\n/g;
-
+ my $tpl = new Template;
+ $tpl->read_file($config->{'templates'}->{'editfile'});
-
-END
+ return \$output;
+}
- $output .= htmlfoot;
+# exec_canceledit()
+#
+# Abort file editing
+#
+# Params: 1. Reference to user input hash
+# 2. Reference to config hash
+#
+# Return: Output of the command (Scalar Reference)
- return \$output;
- }
+sub exec_canceledit($$)
+{
+ my ($data,$config) = @_;
+ my $virtual = $data->{'virtual'};
+ my $dir = upper_path($virtual);
+ my $uselist = $data->{'uselist'};
+
+ file_unlock($uselist,$virtual) or return error($config->{'errors'}->{'ul_rm_failed'},$dir,{FILE => $virtual, USELIST => $uselist->{'listfile'}});
+ return devedit_reload({command => 'show', file => $dir});
}
# exec_endedit()
@@ -353,10 +354,16 @@ sub exec_endedit($$)
my ($data,$config) = @_;
my $physical = $data->{'physical'};
my $virtual = $data->{'virtual'};
+ my $dir = upper_path($virtual);
my $content = $data->{'cgi'}->param('filecontent');
+ my $uselist = $data->{'uselist'};
+
+ # We already unlock the file at the beginning of the subroutine,
+ # because if we have to abort this routine, the file keeps locked.
+ # No other user of Dev-Editor will access the file during this
+ # routine because of the concept of File::UseList.
- return error("You cannot edit directories.") if(-d $physical);
- return error("You have not enough permissions to edit this file.",upper_path($virtual)) unless(-r $physical && -w $physical);
+ file_unlock($uselist,$virtual) or return error($config->{'errors'}->{'ul_rm_failed'},$dir,{FILE => $virtual, USELIST => $uselist->{'listfile'}});
# Normalize newlines
@@ -369,23 +376,32 @@ sub exec_endedit($$)
$content = encode_entities($content,"\200-\377");
}
- if($data->{'cgi'}->param('saveas'))
+ if($data->{'cgi'}->param('saveas') && $data->{'new_physical'} ne '' && $data->{'new_virtual'} ne '')
{
# Create the new filename
$physical = $data->{'new_physical'};
$virtual = $data->{'new_virtual'};
+
+ # Check if someone else is editing the new file
+
+ return error($config->{'errors'}->{'in_use'},$dir,{FILE => $virtual}) if($uselist->in_use($virtual));
}
+ return error($config->{'errors'}->{'link_edit'},$dir) if(-l $physical);
+ return error($config->{'errors'}->{'dir_edit'},$dir) if(-d $physical);
+ return error($config->{'errors'}->{'no_edit'},$dir) if(-e $physical && !(-r $physical && -w $physical));
+ return error($config->{'errors'}->{'text_to_binary'},$dir) unless(-T $physical);
+
if(file_save($physical,\$content))
{
- # Saving of the file was successful - so unlock it!
+ # The file was successfully saved!
- return exec_unlock($data,$config);
+ return devedit_reload({command => 'show', file => $dir});
}
else
{
- return error("Saving of file '".encode_entities($virtual)."' failed'.",upper_path($virtual));
+ return error($config->{'errors'}->{'edit_failed'},$dir,{FILE => $virtual});
}
}
@@ -406,10 +422,26 @@ sub exec_mkfile($$)
my $dir = upper_path($new_virtual);
$new_virtual = encode_entities($new_virtual);
- return error("A file or directory called '$new_virtual' already exists.",$dir) if(-e $new_physical);
+ if($new_physical)
+ {
+ return error($config->{'errors'}->{'file_exists'},$dir,{FILE => $new_virtual}) if(-e $new_physical);
- file_create($new_physical) or return error("Could not create file '$new_virtual'.",$dir);
- return devedit_reload({command => 'show', file => $dir});
+ file_create($new_physical) or return error($config->{'errors'}->{'mkfile_failed'},$dir,{FILE => $new_virtual});
+ return devedit_reload({command => 'show', file => $dir});
+ }
+ else
+ {
+ my $tpl = new Template;
+ $tpl->read_file($config->{'templates'}->{'mkfile'});
+
+ $tpl->fillin('DIR','/');
+ $tpl->fillin('SCRIPT',$script);
+
+ my $output = header(-type => 'text/html');
+ $output .= $tpl->get_template;
+
+ return \$output;
+ }
}
# exec_mkdir()
@@ -429,194 +461,168 @@ sub exec_mkdir($$)
my $dir = upper_path($new_virtual);
$new_virtual = encode_entities($new_virtual);
- return error("A file or directory called '$new_virtual' already exists.",$dir) if(-e $new_physical);
+ if($new_physical)
+ {
+ return error($config->{'errors'}->{'file_exists'},$dir,{FILE => $new_virtual}) if(-e $new_physical);
- mkdir($new_physical,0777) or return error("Could not create directory '$new_virtual'.",$dir);
- return devedit_reload({command => 'show', file => $dir});
+ mkdir($new_physical,0777) or return error($config->{'errors'}->{'mkdir_failed'},$dir,{DIR => $new_virtual});
+ return devedit_reload({command => 'show', file => $dir});
+ }
+ else
+ {
+ my $tpl = new Template;
+ $tpl->read_file($config->{'templates'}->{'mkdir'});
+
+ $tpl->fillin('DIR','/');
+ $tpl->fillin('SCRIPT',$script);
+
+ my $output = header(-type => 'text/html');
+ $output .= $tpl->get_template;
+
+ return \$output;
+ }
}
-# exec_workwithfile()
+# exec_upload()
#
-# Display a form for renaming/copying/deleting/unlocking a file
+# Process a file upload
#
# Params: 1. Reference to user input hash
# 2. Reference to config hash
#
# Return: Output of the command (Scalar Reference)
-sub exec_workwithfile($$)
+sub exec_upload($$)
{
my ($data,$config) = @_;
my $physical = $data->{'physical'};
my $virtual = $data->{'virtual'};
- my $unused = $data->{'uselist'}->unused($virtual);
-
- my $dir = encode_entities(upper_path($virtual));
+ my $cgi = $data->{'cgi'};
- my $output = htmlhead("Work with file ".encode_entities($virtual));
- $output .= equal_url($config->{'httproot'},$virtual);
+ return error($config->{'errors'}->{'no_directory'},upper_path($virtual),{FILE => $virtual}) unless(-d $physical && not -l $physical);
+ return error($config->{'errors'}->{'dir_no_create'},$virtual,{DIR => $virtual}) unless(-w $physical);
- $virtual = encode_entities($virtual);
-
- $output .= dir_link($virtual);
- $output .= "
Note: On UNIX systems, filenames are case-sensitive!
\n\n";
-
- $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
-
-
+ # Process file upload
-
+ my $filename = file_name($uploaded_file);
+ my $file_phys = $physical.'/'.$filename;
+ my $file_virt = $virtual.$filename;
-END
- }
+ return error($config->{'errors'}->{'in_use'},$virtual,{FILE => $file_virt}) if($data->{'uselist'}->in_use($file_virt));
- if($unused)
- {
- # File is not locked
- # Allow renaming and deleting the file
-
- $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',$virtual);
+ $tpl->fillin('URL',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 = encode_entities(upper_path($virtual));
-
- my $output = htmlhead("Work with directory ".encode_entities($virtual));
- $output .= equal_url($config->{'httproot'},$virtual);
-
- $virtual = encode_entities($virtual);
-
- $output .= dir_link($virtual);
- $output .= "
Note: On UNIX systems, filenames are case-sensitive!