+ return error($config->{'errors'}->{'invalid_upload'},$virtual) unless($handle);
-
+ # Read transferred file and write it to disk
-
Delete
+ 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
{
- $output .= <Unlock file
+ my $tpl = new Template;
+ $tpl->read_file($config->{'templates'}->{'upload'});
-
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:
+ $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);
-
-END
- }
+ my $output = header(-type => 'text/html');
+ $output .= $tpl->get_template;
- $output .= "\n";
- $output .= htmlfoot;
-
- return \$output;
+ return \$output;
+ }
}
# exec_copy()
@@ -404,7 +633,99 @@ END
sub exec_copy($$)
{
- 1;
+ my ($data,$config) = @_;
+ my $physical = $data->{'physical'};
+ my $virtual = $data->{'virtual'};
+ my $dir = upper_path($virtual);
+ my $new_physical = $data->{'new_physical'};
+
+ return error($config->{'errors'}->{'link_copy'},$dir) if(-l $physical);
+ return error($config->{'errors'}->{'no_copy'},$dir) unless(-r $physical);
+
+ if($new_physical)
+ {
+ my $new_virtual = multi_string($data->{'new_virtual'});
+ my $new_dir = upper_path($new_virtual->{'normal'});
+
+ if(-d $physical)
+ {
+ return error($config->{'errors'}->{'no_copy'},$dir) unless(-x $physical);
+ return error($config->{'errors'}->{'file_exists'},$dir,{FILE => $new_virtual->{'html'}}) if(-e $new_physical);
+ return error($config->{'errors'}->{'dir_copy_self'},$dir) if(index($new_virtual->{'normal'},$virtual) == 0);
+
+ dir_copy($physical,$new_physical) or return error($config->{'errors'}->{'copy_failed'},$dir,{FILE => encode_html($virtual), NEW_FILE => $new_virtual->{'html'}});
+ return devedit_reload({command => 'show', file => $new_dir});
+ }
+ else
+ {
+ if(-e $new_physical)
+ {
+ return error($config->{'errors'}->{'link_replace'},$new_dir) if(-l $new_physical);
+ return error($config->{'errors'}->{'dir_replace'},$new_dir) if(-d $new_physical);
+ return error($config->{'errors'}->{'exist_no_write'},$new_dir,{FILE => $new_virtual->{'html'}}) unless(-w $new_physical);
+
+ if(not $data->{'cgi'}->param('confirmed'))
+ {
+ my $tpl = new Template;
+ $tpl->read_file($config->{'templates'}->{'confirm_replace'});
+
+ $tpl->fillin('FILE',encode_html($virtual));
+ $tpl->fillin('NEW_FILE',$new_virtual->{'html'});
+ $tpl->fillin('NEW_FILENAME',file_name($new_virtual->{'html'}));
+ $tpl->fillin('NEW_DIR',encode_html($new_dir));
+ $tpl->fillin('DIR',encode_html($dir));
+ $tpl->fillin('DIR_URL',escape($dir));
+
+ $tpl->fillin('COMMAND','copy');
+ $tpl->fillin('URL',encode_html(equal_url($config->{'httproot'},$virtual)));
+ $tpl->fillin('SCRIPT',$script);
+
+ my $output = header(-type => 'text/html');
+ $output .= $tpl->get_template;
+
+ return \$output;
+ }
+ }
+
+ copy($physical,$new_physical) or return error($config->{'errors'}->{'copy_failed'},$dir,{FILE => encode_html($virtual), NEW_FILE => $new_virtual->{'html'}});
+ return devedit_reload({command => 'show', file => $new_dir});
+ }
+ }
+ else
+ {
+ if(-d $physical)
+ {
+ my $tpl = new Template;
+ $tpl->read_file($config->{'templates'}->{'copydir'});
+
+ $tpl->fillin('FILE',encode_html($virtual));
+ $tpl->fillin('DIR',encode_html($dir));
+ $tpl->fillin('DIR_URL',escape($dir));
+ $tpl->fillin('URL',encode_html(equal_url($config->{'httproot'},$virtual)));
+ $tpl->fillin('SCRIPT',$script);
+
+ my $output = header(-type => 'text/html');
+ $output .= $tpl->get_template;
+
+ return \$output;
+ }
+ else
+ {
+ my $tpl = new Template;
+ $tpl->read_file($config->{'templates'}->{'copyfile'});
+
+ $tpl->fillin('FILE',encode_html($virtual));
+ $tpl->fillin('DIR',encode_html($dir));
+ $tpl->fillin('DIR_URL',escape($dir));
+ $tpl->fillin('URL',encode_html(equal_url($config->{'httproot'},$virtual)));
+ $tpl->fillin('SCRIPT',$script);
+
+ my $output = header(-type => 'text/html');
+ $output .= $tpl->get_template;
+
+ return \$output;
+ }
+ }
}
# exec_rename()
@@ -418,12 +739,71 @@ sub exec_copy($$)
sub exec_rename($$)
{
- 1;
+ my ($data,$config) = @_;
+ my $physical = $data->{'physical'};
+ my $virtual = $data->{'virtual'};
+ my $dir = upper_path($virtual);
+ my $new_physical = $data->{'new_physical'};
+
+ return error($config->{'errors'}->{'rename_root'},'/') if($virtual eq '/');
+ return error($config->{'errors'}->{'no_rename'},$dir) unless(-w upper_path($physical));
+
+ if($new_physical)
+ {
+ my $new_virtual = multi_string($data->{'new_virtual'});
+ my $new_dir = upper_path($new_virtual->{'normal'});
+
+ if(-e $new_physical)
+ {
+ return error($config->{'errors'}->{'dir_replace'},$new_dir) if(-d $new_physical && not -l $new_physical);
+ return error($config->{'errors'}->{'exist_no_write'},$new_dir,{FILE => $new_virtual}) unless(-w $new_physical);
+
+ if(not $data->{'cgi'}->param('confirmed'))
+ {
+ my $tpl = new Template;
+ $tpl->read_file($config->{'templates'}->{'confirm_replace'});
+
+ $tpl->fillin('FILE',encode_html($virtual));
+ $tpl->fillin('NEW_FILE',$new_virtual->{'html'});
+ $tpl->fillin('NEW_FILENAME',file_name($new_virtual->{'html'}));
+ $tpl->fillin('NEW_DIR',encode_html($new_dir));
+ $tpl->fillin('DIR',encode_html($dir));
+
+ $tpl->fillin('COMMAND','rename');
+ $tpl->fillin('URL',encode_html(equal_url($config->{'httproot'},$virtual)));
+ $tpl->fillin('SCRIPT',$script);
+
+ my $output = header(-type => 'text/html');
+ $output .= $tpl->get_template;
+
+ return \$output;
+ }
+ }
+
+ move($physical,$new_physical) or return error($config->{'errors'}->{'rename_failed'},$dir,{FILE => encode_html($virtual), NEW_FILE => $new_virtual->{'html'}});
+ return devedit_reload({command => 'show', file => $new_dir});
+ }
+ else
+ {
+ my $tpl = new Template;
+ $tpl->read_file($config->{'templates'}->{'renamefile'});
+
+ $tpl->fillin('FILE',encode_html($virtual));
+ $tpl->fillin('DIR',encode_html($dir));
+ $tpl->fillin('DIR_URL',escape($dir));
+ $tpl->fillin('URL',encode_html(equal_url($config->{'httproot'},$virtual)));
+ $tpl->fillin('SCRIPT',$script);
+
+ my $output = header(-type => 'text/html');
+ $output .= $tpl->get_template;
+
+ return \$output;
+ }
}
# exec_remove()
#
-# Remove a file and return to directory view
+# Remove a file or a directory and return to directory view
#
# Params: 1. Reference to user input hash
# 2. Reference to config hash
@@ -435,40 +815,417 @@ sub exec_remove($$)
my ($data,$config) = @_;
my $physical = $data->{'physical'};
my $virtual = $data->{'virtual'};
+ my $dir = upper_path($virtual);
- return error_in_use($virtual) if($data->{'uselist'}->in_use($virtual));
+ return error($config->{'errors'}->{'remove_root'},'/') if($virtual eq '/');
+ return error($config->{'errors'}->{'no_delete'},$dir) unless(-w upper_path($physical));
- my $dir = upper_path($virtual);
+ if(-d $physical && not -l $physical)
+ {
+ # Remove a directory
- unlink($physical);
+ if($data->{'cgi'}->param('confirmed'))
+ {
+ rmtree($physical);
+ return devedit_reload({command => 'show', file => $dir});
+ }
+ else
+ {
+ my $tpl = new Template;
+ $tpl->read_file($config->{'templates'}->{'confirm_rmdir'});
- my $output = redirect("http://$ENV{'HTTP_HOST'}$script?command=show&file=$dir");
- return \$output;
+ $tpl->fillin('DIR',encode_html($virtual));
+ $tpl->fillin('DIR_URL',escape($virtual));
+ $tpl->fillin('UPPER_DIR',encode_html($dir));
+ $tpl->fillin('UPPER_DIR_URL',escape($dir));
+ $tpl->fillin('URL',encode_html(equal_url($config->{'httproot'},$virtual)));
+ $tpl->fillin('SCRIPT',$script);
+
+ my $output = header(-type => 'text/html');
+ $output .= $tpl->get_template;
+
+ return \$output;
+ }
+ }
+ else
+ {
+ # Remove a file
+
+ if($data->{'cgi'}->param('confirmed'))
+ {
+ unlink($physical) or return error($config->{'errors'}->{'delete_failed'},$dir,{FILE => $virtual});
+ return devedit_reload({command => 'show', file => $dir});
+ }
+ else
+ {
+ my $tpl = new Template;
+ $tpl->read_file($config->{'templates'}->{'confirm_rmfile'});
+
+ $tpl->fillin('FILE',encode_html($virtual));
+ $tpl->fillin('FILE_URL',escape($virtual));
+ $tpl->fillin('DIR',encode_html($dir));
+ $tpl->fillin('DIR_URL',escape($dir));
+ $tpl->fillin('URL',encode_html(equal_url($config->{'httproot'},$virtual)));
+ $tpl->fillin('SCRIPT',$script);
+
+ my $output = header(-type => 'text/html');
+ $output .= $tpl->get_template;
+
+ return \$output;
+ }
+ }
}
-# exec_unlock()
+# exec_remove_multi()
#
-# Remove a file from the list of used files and
-# return to directory view
+# Remove a file or a directory 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_unlock($$)
+sub exec_remove_multi($$)
{
my ($data,$config) = @_;
my $physical = $data->{'physical'};
my $virtual = $data->{'virtual'};
- my $uselist = $data->{'uselist'};
+ my $cgi = $data->{'cgi'};
+
+ my @files = $cgi->param('files');#
+ my @new_files;
- my $dir = upper_path($virtual);
+ if(@files)
+ {
+ foreach my $file(@files)
+ {
+ # Filter out some "bad" files (e.g. files going up in the
+ # directory hierarchy or files containing slashes (it's too
+ # dangerous...)
+
+ next if($file =~ m!^\.+$!);
+ next if($file =~ m!/!);
+ next if($file =~ m!\\!);
+
+ push(@new_files,$file);
+ }
+ }
+
+ if(@new_files)
+ {
+ if($cgi->param('confirmed'))
+ {
+ my @success;
+ my @failed;
+
+ foreach my $file(@new_files)
+ {
+ my $file_path = clean_path($physical.'/'.$file);
+
+ if(-e $file_path)
+ {
+ if(-d $file_path && not -l $file_path)
+ {
+ # Remove a directory
+
+ if(rmtree($file_path))
+ {
+ push(@success,clean_path($file));
+ }
+ else
+ {
+ push(@failed,clean_path($file));
+ }
+ }
+ else
+ {
+ # Remove a file
+
+ if(unlink($file_path))
+ {
+ push(@success,clean_path($file));
+ }
+ else
+ {
+ push(@failed,clean_path($file));
+ }
+ }
+ }
+ else
+ {
+ push(@failed,clean_path($file));
+ }
+ }
+
+ my $tpl = new Template;
+ $tpl->read_file($config->{'templates'}->{'rmmulti'});
+
+ if(scalar(@success) > 0)
+ {
+ if(scalar(@success) == scalar(@new_files) && scalar(@failed) == 0)
+ {
+ return devedit_reload({command => 'show', file => $virtual});
+ }
+ else
+ {
+ $tpl->parse_if_block('success',1);
+
+ foreach my $file_success(@success)
+ {
+ $tpl->add_loop_data('SUCCESS',{FILE => encode_html($file_success),
+ FILE_PATH => encode_html(clean_path($virtual.'/'.$file_success))});
+ }
+
+ $tpl->parse_loop('SUCCESS');
+ }
+ }
+ else
+ {
+ $tpl->parse_if_block('success',0);
+ }
+
+ if(scalar(@failed) > 0)
+ {
+ $tpl->parse_if_block('failed',1);
+
+ foreach my $file_failed(@failed)
+ {
+ $tpl->add_loop_data('FAILED',{FILE => encode_html($file_failed),
+ FILE_PATH => encode_html(clean_path($virtual.'/'.$file_failed))});
+ }
+
+ $tpl->parse_loop('FAILED');
+ }
+ else
+ {
+ $tpl->parse_if_block('failed',0);
+ }
+
+
+ $tpl->fillin('DIR',encode_html($virtual));
+ $tpl->fillin('SCRIPT',$script);
+
+ my $output = header(-type => 'text/html');
+ $output .= $tpl->get_template;
+
+ return \$output;
+ }
+ else
+ {
+ my $tpl = new Template;
+ $tpl->read_file($config->{'templates'}->{'confirm_rmmulti'});
+
+ foreach my $file(@new_files)
+ {
+ $tpl->add_loop_data('FILES',{FILE => encode_html($file),
+ FILE_PATH => encode_html(clean_path($virtual.'/'.$file))});
+ }
+
+ $tpl->parse_loop('FILES');
+
+ $tpl->fillin('COUNT',scalar(@new_files));
+
+ $tpl->fillin('DIR',encode_html($virtual));
+ $tpl->fillin('SCRIPT',$script);
+
+ my $output = header(-type => 'text/html');
+ $output .= $tpl->get_template;
+
+ return \$output;
+ }
+ }
+ else
+ {
+ return devedit_reload({command => 'show', file => $virtual});
+ }
+}
+
+# exec_chprop()
+#
+# Change the mode and the group of a file or a directory
+#
+# Params: 1. Reference to user input hash
+# 2. Reference to config hash
+#
+# Return: Output of the command (Scalar Reference)
+
+sub exec_chprop($$)
+{
+ my ($data,$config) = @_;
+ my $physical = $data->{'physical'};
+ my $virtual = $data->{'virtual'};
+ my $dir = upper_path($virtual);
+
+ return error($config->{'errors'}->{'no_users'},$dir,{FILE => encode_html($virtual)}) unless($users);
+ return error($config->{'errors'}->{'chprop_root'},'/') if($virtual eq '/');
+ return error($config->{'errors'}->{'not_owner'},$dir,{FILE => encode_html($virtual)}) unless(-o $physical);
+ return error($config->{'errors'}->{'chprop_link'},$dir) if(-l $physical);
+
+ my $cgi = $data->{'cgi'};
+ my $mode = $cgi->param('mode');
+ my $group = $cgi->param('group');
+
+ if($mode || $group)
+ {
+ if($mode)
+ {
+ # Change the mode
+
+ return error($config->{'errors'}->{'invalid_mode'},$dir) unless($mode =~ /^[0-7]{3,}$/);
+ chmod(oct($mode),$physical);
+ }
+
+ if($group)
+ {
+ # Change the group using the `chgrp` system command
+
+ return error($config->{'errors'}->{'invalid_group'},$dir,{GROUP => encode_html($group)}) unless($group =~ /^[a-z0-9_]+[a-z0-9_-]*$/i);
+ system('chgrp',$group,$physical);
+ }
+
+ return devedit_reload({command => 'show', file => $dir});
+ }
+ else
+ {
+ # Display the form
+
+ my @stat = stat($physical);
+ my $mode = $stat[2];
+ my $gid = $stat[5];
+
+ my $tpl = new Template;
+ $tpl->read_file($config->{'templates'}->{'chprop'});
+
+ # Insert file properties into the template
+
+ $tpl->fillin('MODE_OCTAL',substr(sprintf('%04o',$mode),-4));
+ $tpl->fillin('MODE_STRING',mode_string($mode));
+ $tpl->fillin('GID',$gid);
+
+ if(my $group = getgrgid($gid))
+ {
+ $tpl->fillin('GROUP',encode_html($group));
+ $tpl->parse_if_block('group_detected',1);
+ }
+ else
+ {
+ $tpl->parse_if_block('group_detected',0);
+ }
+
+ # Insert other information
+
+ $tpl->fillin('FILE',encode_html($virtual));
+ $tpl->fillin('FILE_URL',escape($virtual));
+ $tpl->fillin('DIR',encode_html($dir));
+ $tpl->fillin('DIR_URL',escape($dir));
+ $tpl->fillin('URL',encode_html(equal_url($config->{'httproot'},$virtual)));
+ $tpl->fillin('SCRIPT',$script);
+
+ my $output = header(-type => 'text/html');
+ $output .= $tpl->get_template;
+
+ return \$output;
+ }
+}
+
+# exec_about()
+#
+# Display some information about Dev-Editor
+#
+# Params: 1. Reference to user input hash
+# 2. Reference to config hash
+#
+# Return: Output of the command (Scalar Reference)
+
+sub exec_about($$)
+{
+ my ($data,$config) = @_;
+
+ my $tpl = new Template;
+ $tpl->read_file($config->{'templates'}->{'about'});
+
+ $tpl->fillin('SCRIPT',$script);
+
+ # Dev-Editor's version number
+
+ $tpl->fillin('VERSION',$data->{'version'});
+
+ # Some path information
+
+ $tpl->fillin('SCRIPT_PHYS',encode_html($ENV{'SCRIPT_FILENAME'}));
+ $tpl->fillin('CONFIG_PATH',encode_html($data->{'configfile'}));
+ $tpl->fillin('FILE_ROOT', encode_html($config->{'fileroot'}));
+ $tpl->fillin('HTTP_ROOT', encode_html($config->{'httproot'}));
+
+ # Perl
+
+ $tpl->fillin('PERL_PROG',encode_html($^X));
+ $tpl->fillin('PERL_VER', sprintf('%vd',$^V));
+
+ # Information about the server
+
+ $tpl->fillin('HTTPD',encode_html($ENV{'SERVER_SOFTWARE'}));
+ $tpl->fillin('OS', encode_html($^O));
+ $tpl->fillin('TIME', encode_html(strftime($config->{'timeformat'},($config->{'use_gmt'}) ? gmtime : localtime)));
+
+ $tpl->parse_if_block('gmt',$config->{'use_gmt'});
+
+ # Process information
+
+ $tpl->fillin('PID',$$);
+
+ # The following information is only available on systems supporting
+ # users and groups
+
+ if($users)
+ {
+ # Dev-Editor is running on a system which allows users and groups
+ # So we display the user and the group of our process
+
+ my $uid = POSIX::getuid;
+ my $gid = POSIX::getgid;
+
+ $tpl->parse_if_block('users',1);
+
+ # IDs of user and group
+
+ $tpl->fillin('UID',$uid);
+ $tpl->fillin('GID',$gid);
+
+ # Names of user and group
+
+ if(my $user = getpwuid($uid))
+ {
+ $tpl->fillin('USER',encode_html($user));
+ $tpl->parse_if_block('user_detected',1);
+ }
+ else
+ {
+ $tpl->parse_if_block('user_detected',0);
+ }
+
+ if(my $group = getgrgid($gid))
+ {
+ $tpl->fillin('GROUP',encode_html($group));
+ $tpl->parse_if_block('group_detected',1);
+ }
+ else
+ {
+ $tpl->parse_if_block('group_detected',0);
+ }
+
+ # Process umask
+
+ $tpl->fillin('UMASK',sprintf('%04o',umask));
+ }
+ else
+ {
+ $tpl->parse_if_block('users',0);
+ }
- $uselist->remove_file($virtual);
- $uselist->save;
+ my $output = header(-type => 'text/html');
+ $output .= $tpl->get_template;
- my $output = redirect("http://$ENV{'HTTP_HOST'}$script?command=show&file=$dir");
return \$output;
}