timeformat    = %d.%m.%Y %H:%M
 use_gmt       = 0
 
-uselist_file  = uselist
-lock_file     = uselist.lock
-lock_timeout  = 10
-
-error_file    = errors.dat
-template_file = templates.dat
+error_file    = errors.conf
+template_file = templates.conf
 
 # End of configuration file
\ No newline at end of file
 
 # Dev-Editor's main program
 #
 # Author:        Patrick Canterino <patrick@patshaping.de>
-# Last modified: 2005-02-19
+# Last modified: 2005-04-09
 #
 
 use strict;
 
 use CGI;
 use Config::DevEdit;
-use File::UseList;
 
 use Command;
 use Output;
 # Path to configuration file
 # Change if necessary!
 
-use constant CONFIGFILE => 'devedit.dat';
+use constant CONFIGFILE => 'devedit.conf';
 
 # Read the configuration file
 
 
  unless(($new_physical,$new_virtual) = check_path($config->{'fileroot'},$dir))
  {
-  abort($config->{'errors'}->{'create_ar'},'/');
+  abort($config->{'errors'}->{'create_above_root'},'/');
  }
 
  # Check if we have enough permissions to create a file
 {
  if(my ($physical,$virtual) = check_path($config->{'fileroot'},$file))
  {
-  # Create a File::UseList object and load the list
-
-  my $uselist = new File::UseList(listfile => $config->{'uselist_file'},
-                                  lockfile => $config->{'lock_file'},
-                                  timeout  => $config->{'lock_timeout'});
-
-  $uselist->lock or abort($config->{'errors'}->{'lock_failed'},undef,{USELIST => $uselist->{'listfile'}, LOCK_FILE => $uselist->{'lockfile'}});
-  $uselist->load;
-
   # Create a hash containing data submitted by the user
   # (some other necessary information are also included)
 
               virtual      => $virtual,
               new_physical => $new_physical,
               new_virtual  => $new_virtual,
-              uselist      => $uselist,
               cgi          => $cgi,
               version      => $VERSION,
               configfile   => CONFIGFILE);
 
   my $output = exec_command($command,\%data,$config);
 
-  # ... unlock the list with files in use and show the output of the command
+  # ... and show the output of the command
 
-  $uselist->unlock or abort($config->{'errors'}->{'unlock_failed'},undef,{USELIST => $uselist->{'listfile'}, LOCK_FILE => $uselist->{'lockfile'}});
   print $$output;
  }
  else
 }
 else
 {
- abort($config->{'errors'}->{'not_exist'},'/');
+ abort($config->{'errors'}->{'not_found'},'/');
 }
 
 #
 
--- /dev/null
+# This file contains the error messages of Dev-Editor
+
+above_root        = Accessing files and directories above the virtual root directory is forbidden.
+binary_file       = This editor is not able to view/edit binary files.
+chprop_link       = You are not allowed to change the properties of a symbolic link.
+chprop_root       = You are not allowed to change the properties of the root directory.
+command_unknown   = Unknown command: '{COMMAND}'
+copy_failed       = Could not copy '{FILE}' to '{NEW_FILE}'.
+create_above_root = You are not allowed to create files and directories above the virtual root directory.
+delete_failed     = Could not delete file '{FILE}'.
+dir_copy          = This editor is not able to copy directories.
+dir_edit          = You cannot edit directories.
+dir_no_create     = You have not enough permissions to create a file in directory '{DIR}'.
+dir_not_exist     = The directory where you want to create this file or directory does not exist.
+dir_read_fail     = Reading of directory '{DIR}' failed.
+dir_replace       = You are not allowed to replace a directory.
+edit_failed       = Saving of file '{FILE}' failed. The file could be damaged, please check its integrity.
+edit_file_changed = The file you want to edit changed meanwhile. Now, it looks like this: <a href="{SCRIPT}?command=show&file={FILE}">{FILE}</a>. Please try to merge these two versions together of the file or save this file using a different name.
+exist_no_write    = The target file '{FILE}' already exists and you have not enough permissions to replace it.
+file_exists       = A file or directory called '{FILE}' already exists.
+file_too_large    = The file you want to view or edit is too large (max. {SIZE} Bytes).
+invalid_group     = '{GROUP}' seems to be an invalid group name. Please check it and try again.
+invalid_upload    = It seems that something is wrong with the file upload you want to submit.
+link_copy         = Copying symbolic links does not work.
+link_edit         = For security reasons, you cannot edit the target file of a symbolic link.
+link_replace      = You are not allowed to overwrite symbolic links.
+mkdir_failed      = Could not create directory '{DIR}'.
+mkfile_failed     = Could not create file '{FILE}'.
+no_copy           = You have not enough permissions to copy this file.
+no_delete         = You have not enough permissions to delete this file.
+no_dir_access     = You have not enough permissions to access this directory.
+no_directory      = '{FILE}' is not a directory.
+no_edit           = You have not enough permissions to edit this file.
+no_rename         = You have not enough permissions to move/rename this file.
+no_root_access    = You have not enough permissions to access the root directory.
+no_root_dir       = The root directory does not exist or is not a directory.
+no_users          = It seems that your system does not support users and groups.
+no_view           = You have not enough permissions to view this file.
+not_found         = File/directory does not exist.
+not_owner         = You are not the owner of '{FILE}', so you are not allowed to change its mode and its group.
+remove_root       = You are not allowed to remove the root directory.
+rename_failed     = Could not move/rename '{FILE}' to '{NEW_FILE}'.
+rename_root       = You are not allowed to move/rename the root directory.
+text_to_binary    = You are not allowed to write text data into a binary file.
+
+# End of configuration file
\ No newline at end of file
 
+++ /dev/null
-# This file contains the error messages of Dev-Editor
-
-above_root     = Accessing files and directories above the virtual root directory is forbidden.
-binary         = This editor is not able to view/edit binary files.
-chprop_link    = You are not allowed to change the properties of a symbolic link.
-chprop_root    = You are not allowed to change the properties of the root directory.
-cmd_unknown    = Unknown command: '{COMMAND}'
-copy_failed    = Could not copy '{FILE}' to '{NEW_FILE}'.
-create_ar      = You are not allowed to create files and directories above the virtual root directory.
-delete_failed  = Could not delete file '{FILE}'.
-dir_copy       = This editor is not able to copy directories.
-dir_edit       = You cannot edit directories.
-dir_no_create  = You have not enough permissions to create a file in directory '{DIR}'.
-dir_not_exist  = The directory where you want to create this file or directory does not exist.
-dir_read_fail  = Reading of directory '{DIR}' failed.
-dir_replace    = You are not allowed to replace a directory.
-edit_failed    = Saving of file '{FILE}' failed. The file could be damaged, please check its integrity.
-exist_edited   = The target file '{FILE}' already exists and is edited by someone else.
-exist_no_write = The target file '{FILE}' already exists and you have not enough permissions to replace it.
-file_exists    = A file or directory called '{FILE}' already exists.
-file_too_large = The file you want to view or edit is too large (max. {SIZE} Bytes).
-in_use         = The file '{FILE}' is currently edited by someone else.
-invalid_group  = '{GROUP}' seems to be an invalid group name. Please check it and try again.
-invalid_upload = It seems that something is wrong with the file upload you want to submit.
-link_copy      = Copying symbolic links does not work.
-link_edit      = For security reasons, you cannot edit the target file of a symbolic link.
-link_replace   = You are not allowed to overwrite symbolic links.
-lock_failed    = Locking of '{USELIST}' failed. Try it again in a moment. If the problem persists, ask the administrator to check the lock file ('{LOCK_FILE}') and to recreate it if necessary.
-mkdir_failed   = Could not create directory '{DIR}'.
-mkfile_failed  = Could not create file '{FILE}'.
-no_copy        = You have not enough permissions to copy this file.
-no_delete      = You have not enough permissions to delete this file.
-no_dir_access  = You have not enough permissions to access this directory.
-no_directory   = '{FILE}' is not a directory.
-no_edit        = You have not enough permissions to edit this file.
-no_rename      = You have not enough permissions to move/rename this file.
-no_root_access = You have not enough permissions to access the root directory.
-no_root_dir    = The root directory does not exist or is not a directory.
-no_users       = It seems that your system does not support users and groups.
-no_view        = You have not enough permissions to view this file.
-not_exist      = File/directory does not exist.
-not_owner      = You are not the owner of '{FILE}', so you are not allowed to change its mode and its group.
-remove_root    = You are not allowed to remove the root directory.
-rename_failed  = Could not move/rename '{FILE}' to '{NEW_FILE}'.
-rename_root    = You are not allowed to move/rename the root directory.
-text_to_binary = You are not allowed to write text data into a binary file.
-ul_add_failed  = Could not add '{FILE}' to the list of files in use.
-ul_rm_failed   = Could not remove '{FILE}' from the list of files in use. Try it again using the 'unlock' command of Dev-Editor or by removing the file manually from '{USELIST}'.
-unlock_failed  = Unlocking of '{USELIST}' failed. Ask the administrator to check the lock file ('{LOCK_FILE}') and to recreate it if necessary.
-
-# End of configuration file
\ No newline at end of file
 
 # Execute Dev-Editor's commands
 #
 # Author:        Patrick Canterino <patrick@patshaping.de>
-# Last modified: 2005-03-18
+# Last modified: 2005-04-09
 #
 
 use strict;
 
 use vars qw(@EXPORT);
 
+use Fcntl;
 use File::Access;
 use File::Copy;
 use File::Path;
 
+use Digest::MD5 qw(md5_hex);
 use POSIX qw(strftime);
 use Tool;
 
 use Output;
 use Template;
 
+use Data::Dumper;
+
 my $script = encode_entities($ENV{'SCRIPT_NAME'});
 my $users  = eval('getpwuid(0)') && eval('getgrgid(0)');
 
 my %dispatch = ('show'       => \&exec_show,
                 'beginedit'  => \&exec_beginedit,
-                'canceledit' => \&exec_canceledit,
                 'endedit'    => \&exec_endedit,
                 'mkdir'      => \&exec_mkdir,
                 'mkfile'     => \&exec_mkfile,
                 'rename'     => \&exec_rename,
                 'remove'     => \&exec_remove,
                 'chprop'     => \&exec_chprop,
-                'unlock'     => \&exec_unlock,
                 'about'      => \&exec_about
                );
 
   }
  }
 
- return error($config->{'errors'}->{'cmd_unknown'},'/',{COMMAND => encode_entities($command)});
+ return error($config->{'errors'}->{'command_unknown'},'/',{COMMAND => encode_entities($command)});
 }
 
 # exec_show()
  my $physical       = $data->{'physical'};
  my $virtual        = $data->{'virtual'};
  my $upper_path     = encode_entities(upper_path($virtual));
- my $uselist        = $data->{'uselist'};
 
  my $tpl = new Template;
 
    my $virt_path = encode_entities($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'};
 
    my $ftpl = new Template;
    $ftpl->parse_if_block('link',-l $phys_path);
    $ftpl->parse_if_block('no_link',not -l $phys_path);
    $ftpl->parse_if_block('not_readable',not -r $phys_path);
-   $ftpl->parse_if_block('binary',-B $phys_path);
+   $ftpl->parse_if_block('binary_file',-B $phys_path);
    $ftpl->parse_if_block('readonly',not -w $phys_path);
 
    $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 $in_use) && not -l $phys_path);
-
-   $ftpl->parse_if_block('in_use',$in_use);
-   $ftpl->parse_if_block('unused',not $in_use);
+   $ftpl->parse_if_block('editable',(-r $phys_path && -w $phys_path && -T $phys_path && not $too_large) && not -l $phys_path);
 
    $ftpl->parse_if_block('too_large',$config->{'max_file_size'} && $stat[7] > $config->{'max_file_size'});
 
   # We have to do it in this way or empty files will be recognized
   # as binary files
 
-  return error($config->{'errors'}->{'binary'},$upper_path) unless(-T $physical);
+  return error($config->{'errors'}->{'binary_file'},$upper_path) unless(-T $physical);
 
   # Is the file too large?
 
   $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->parse_if_block('editable',-w $physical);
 
   $tpl->fillin('CONTENT',encode_entities($$content));
  }
  my $physical       = $data->{'physical'};
  my $virtual        = $data->{'virtual'};
  my $dir            = upper_path($virtual);
- my $uselist        = $data->{'uselist'};
+ my $cgi            = $data->{'cgi'};
 
- 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);
+ 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) unless(-r $physical && -w $physical);
 
  # Check on binary files
 
- return error($config->{'errors'}->{'binary'},$dir) unless(-T $physical);
+ return error($config->{'errors'}->{'binary_file'},$dir) unless(-T $physical);
 
  # Is the file too large?
 
  return error($config->{'errors'}->{'file_too_large'},$dir,{SIZE => $config->{'max_file_size'}}) if($config->{'max_file_size'} && -s $physical > $config->{'max_file_size'});
 
- # Lock the file...
-
- ($uselist->add_file($virtual) and
-  $uselist->save)              or return error($config->{'errors'}->{'ul_add_failed'},$dir,{FILE => $virtual});
-
  # ... and show the editing form
 
- my $content =  file_read($physical);
+ my $content =  file_read($physical,1);
+ my $md5sum  =  md5_hex($$content);
  $$content   =~ s/\015\012|\012|\015/\n/g;
 
  my $tpl = new Template;
  $tpl->fillin('DIR',$dir);
  $tpl->fillin('URL',equal_url($config->{'httproot'},$virtual));
  $tpl->fillin('SCRIPT',$script);
+ $tpl->fillin('MD5SUM',$md5sum);
  $tpl->fillin('CONTENT',encode_entities($$content));
 
+ $tpl->parse_if_block('error',0);
+
  my $output = header(-type => 'text/html');
  $output   .= $tpl->get_template;
 
  return \$output;
 }
 
-# exec_canceledit()
-#
-# Abort file editing
-#
-# Params: 1. Reference to user input hash
-#         2. Reference to config hash
-#
-# Return: Output of the command (Scalar Reference)
-
-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()
 #
 # Save a file, unlock it and return to directory view
  my $physical       = $data->{'physical'};
  my $virtual        = $data->{'virtual'};
  my $dir            = upper_path($virtual);
- my $content        = $data->{'cgi'}->param('filecontent');
- my $uselist        = $data->{'uselist'};
+ my $cgi            = $data->{'cgi'};
+ my $content        = $cgi->param('filecontent');
+ my $md5sum         = $cgi->param('md5sum');
+ my $output;
+
+ if($content && $md5sum)
+ {
+  # Normalize newlines
 
- # 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.
+  $content =~ s/\015\012|\012|\015/\n/g;
 
- file_unlock($uselist,$virtual) or return error($config->{'errors'}->{'ul_rm_failed'},$dir,{FILE => $virtual, USELIST => $uselist->{'listfile'}});
+  if($cgi->param('saveas') && $data->{'new_physical'} ne '' && $data->{'new_virtual'} ne '')
+  {
+   # Create the new filename
 
- # Normalize newlines
+   $physical = $data->{'new_physical'};
+   $virtual  = $data->{'new_virtual'};
+  }
 
- $content =~ s/\015\012|\012|\015/\n/g;
+  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) if(-e $physical && not -T $physical);
 
- if($data->{'cgi'}->param('encode_iso'))
- {
-  # Encode all ISO-8859-1 special chars
+  # For technical reasons, we can't use file_save() for
+  # saving the file...
 
-  $content = encode_entities($content,"\200-\377");
- }
+  local *FILE;
 
- if($data->{'cgi'}->param('saveas') && $data->{'new_physical'} ne '' && $data->{'new_virtual'} ne '')
- {
-  # Create the new filename
+  sysopen(FILE,$physical,O_RDWR | O_CREAT) or return error($config->{'errors'}->{'edit_failed'},$dir,{FILE => $virtual});
+  file_lock(FILE,LOCK_EX)                  or do { close(FILE); return error($config->{'errors'}->{'edit_failed'},$dir,{FILE => $virtual}) };
+  binmode(FILE);
 
-  $physical = $data->{'new_physical'};
-  $virtual  = $data->{'new_virtual'};
+  my $md5 = new Digest::MD5;
+  $md5->addfile(*FILE);
 
-  # Check if someone else is editing the new file
+  my $md5_new = $md5->hexdigest;
 
-  return error($config->{'errors'}->{'in_use'},$dir,{FILE => $virtual}) if($uselist->in_use($virtual));
- }
+  if($md5_new ne $md5sum && not $cgi->param('saveas'))
+  {
+   # The file changed meanwhile
 
- 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) if(-e $physical && not -T $physical);
+   my $tpl = new Template;
+   $tpl->read_file($config->{'templates'}->{'editfile'});
 
- if(file_save($physical,\$content))
- {
-  # The file was successfully saved!
+   $tpl->fillin('ERROR',$config->{'errors'}->{'edit_file_changed'});
 
-  return devedit_reload({command => 'show', file => $dir});
- }
- else
- {
-  return error($config->{'errors'}->{'edit_failed'},$dir,{FILE => $virtual});
+   $tpl->fillin('FILE',$virtual);
+   $tpl->fillin('DIR',$dir);
+   $tpl->fillin('URL',equal_url($config->{'httproot'},$virtual));
+   $tpl->fillin('SCRIPT',$script);
+   $tpl->fillin('MD5SUM',$md5_new);
+   $tpl->fillin('CONTENT',encode_entities($content));
+
+   $tpl->parse_if_block('error',1);
+
+   my $data = header(-type => 'text/html');
+   $data   .= $tpl->get_template;
+
+   $output  = \$data;
+  }
+  else
+  {
+   # The file was saved successfully!
+
+   seek(FILE,0,0);
+   truncate(FILE,0);
+
+   print FILE $content;
+
+   $output = devedit_reload({command => 'show', file => $dir});
+
+   #return error($config->{'errors'}->{'edit_failed'},$dir,{FILE => $virtual});
+  }
+
+  close(FILE);
+
+  return $output;
  }
+
+ return devedit_reload({command => 'beginedit', file => $virtual});
 }
 
 # exec_mkfile()
   my $file_phys = $physical.'/'.$filename;
   my $file_virt = $virtual.$filename;
 
-  return error($config->{'errors'}->{'in_use'},$virtual,{FILE => $file_virt}) if($data->{'uselist'}->in_use($file_virt));
-
   if(-e $file_phys)
   {
    return error($config->{'errors'}->{'link_replace'},$virtual)                        if(-l $file_phys);
 
   if(-e $new_physical)
   {
-   return error($config->{'errors'}->{'exist_edited'},$new_dir,{FILE => $new_virtual})   if($data->{'uselist'}->in_use($data->{'new_virtual'}));
    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}) unless(-w $new_physical);
 
  return error($config->{'errors'}->{'rename_root'},'/')                if($virtual eq '/');
  return error($config->{'errors'}->{'no_rename'},$dir)                 unless(-w upper_path($physical));
- return error($config->{'errors'}->{'in_use'},$dir,{FILE => $virtual}) if($data->{'uselist'}->in_use($virtual));
 
  if($new_physical)
  {
 
   if(-e $new_physical)
   {
-   return error($config->{'errors'}->{'exist_edited'},$new_dir,{FILE => $new_virtual})   if($data->{'uselist'}->in_use($data->{'new_virtual'}));
    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);
 
  {
   # Remove a file
 
-  return error($config->{'errors'}->{'in_use'},$dir,{FILE => $virtual}) if($data->{'uselist'}->in_use($virtual));
-
   if($data->{'cgi'}->param('confirmed'))
   {
    unlink($physical) or return error($config->{'errors'}->{'delete_failed'},$dir,{FILE => $virtual});
  return error($config->{'errors'}->{'chprop_root'},'/')                   if($virtual eq '/');
  return error($config->{'errors'}->{'not_owner'},$dir,{FILE => $virtual}) unless(-o $physical);
  return error($config->{'errors'}->{'chprop_link'},$dir)                  if(-l $physical);
- return error($config->{'errors'}->{'in_use'},$dir,{FILE => $virtual})    if($data->{'uselist'}->in_use($virtual));
 
  my $cgi   = $data->{'cgi'};
  my $mode  = $cgi->param('mode');
  }
 }
 
-# exec_unlock()
-#
-# Remove a file from the list of used files 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($$)
-{
- my ($data,$config) = @_;
- my $virtual        = $data->{'virtual'};
- my $uselist        = $data->{'uselist'};
- my $dir            = upper_path($virtual);
-
- return devedit_reload({command => 'show', file => $dir}) if($uselist->unused($virtual));
-
- if($data->{'cgi'}->param('confirmed'))
- {
-  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});
- }
- else
- {
-  my $tpl = new Template;
-  $tpl->read_file($config->{'templates'}->{'confirm_unlock'});
-
-  $tpl->fillin('FILE',$virtual);
-  $tpl->fillin('DIR',$dir);
-  $tpl->fillin('URL',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
 
 # using only one command
 #
 # Author:        Patrick Canterino <patrick@patshaping.de>
-# Last modified: 2005-02-16
+# Last modified: 2005-04-09
 #
 
 use strict;
              file_lock
              file_read
              file_save
-             file_unlock
 
              LOCK_SH
              LOCK_EX
  return 1;
 }
 
-# file_unlock()
-#
-# Remove a file from the list of files in use
-#
-# Params: 1. File::UseList object
-#         2. File to remove
-#
-# Return: Status code (Boolean)
-
-sub file_unlock($$)
-{
- my ($uselist,$file) = @_;
-
- $uselist->remove_file($file) or return;
- $uselist->save               or return;
-
- return 1;
-}
-
 # it's true, baby ;-)
 
 1;
 
+++ /dev/null
-package File::UseList;
-
-#
-# File::UseList 1.3
-#
-# Run a list with files that are currently in use
-# (bases on Filing::UseList by Roland Bluethgen <calocybe@web.de>)
-#
-# Author:        Patrick Canterino <patrick@patshaping.de>
-# Last modified: 2004-12-03
-#
-
-use strict;
-
-use Carp qw(croak);
-use Fcntl;
-
-# new()
-#
-# Constructor
-#
-# Params: Hash: listfile => File with list of files in use
-#               lockfile => Lock file (Default: List file + .lock)
-#               timeout  => Lock timeout in seconds (Default: 10)
-#
-# Return: File::UseList object (Blessed Reference)
-
-sub new(%)
-{
- my ($class,%args) = @_;
-
- # Check if we got all the necessary information
-
- croak "Missing path to list file"             unless($args{'listfile'});
- $args{'lockfile'} = $args{'listfile'}.".lock" unless($args{'lockfile'}); # Default filename of lock file
- $args{'timeout'}  = 10                        unless($args{'timeout'});  # Default timeout
-
- # Add some other information
-
- $args{'files'}  = [];
- $args{'locked'} = 0;
-
- return bless(\%args,$class);
-}
-
-# lock()
-#
-# Lock list with files
-# (delete lock file)
-#
-# Params: -nothing-
-#
-# Return: Status code (Boolean)
-
-sub lock
-{
- my $self     = shift;
- my $lockfile = $self->{'lockfile'};
- my $timeout  = $self->{'timeout'};
-
- return 1 if($self->{'locked'});
-
- # Try to delete the lock file one time per second
- # until the timeout is reached
-
- for(my $x=$timeout;$x>=0;$x--)
- {
-  if(unlink($lockfile))
-  {
-   $self->{'locked'} = 1;
-   return 1;
-  }
-
-  sleep(1);
- }
-
- # Timeout
-
- return;
-}
-
-# unlock()
-#
-# Unlock list with files, but only if _we_ locked it
-# (create lock file)
-#
-# Params: -nothing-
-#
-# Return: Status code (Boolean)
-
-sub unlock
-{
- my $self     = shift;
- my $lockfile = $self->{'lockfile'};
- local *LOCKFILE;
-
- if($self->{'locked'})
- {
-  sysopen(LOCKFILE,$lockfile,O_WRONLY | O_CREAT | O_TRUNC) or return;
-  close(LOCKFILE)                                          or return;
-
-  $self->{'locked'} = 0;
-  return 1;
- }
-
- # The list wasn't lock by us or it isn't locked at all
-
- return;
-}
-
-# load()
-#
-# Load the list with files from the list file
-#
-# Params: -nothing-
-#
-# Return: Status code (Boolean)
-
-sub load
-{
- my $self = shift;
- my $file = $self->{'listfile'};
- local *FILE;
-
- # Read out the file and split the content line-per-line
-
- sysopen(FILE,$file,O_RDONLY) or return;
- read(FILE, my $content, -s $file);
- close(FILE)                  or return;
-
- my @files = split(/\015\012|\012|\015/,$content);
-
- # Remove useless lines
-
- for(my $x=0;$x<@files;$x++)
- {
-  if($files[$x] eq "" || $files[$x] =~ /^\s+$/)
-  {
-   splice(@files,$x,1);
-   $x--; # <-- very important!
-  }
- }
-
- $self->{'files'} = \@files;
- return 1;
-}
-
-# save()
-#
-# Write the list with files back to the list file
-#
-# Params: -nothing-
-#
-# Return: Status code (Boolean)
-
-sub save
-{
- my $self  = shift;
- my $file  = $self->{'listfile'};
- my $temp  = $file.".temp";
- my $files = $self->{'files'};
- local *FILE;
-
- my $data = (@$files) ? join("\n",@$files) : '';
-
- sysopen(FILE,$temp,O_WRONLY | O_CREAT | O_TRUNC) or return;
- print FILE $data                                 or do { close(FILE); return };
- close(FILE)                                      or return;
-
- rename($temp,$file)                              or return;
-
- return 1;
-}
-
-# add_file()
-#
-# Add a file to the list
-#
-# Params: File
-#
-# Return: Status code (Boolean)
-
-sub add_file($)
-{
- my ($self,$file) = @_;
- my $files = $self->{'files'};
-
- # Check if the file is already in the list
-
- return if($self->in_use($file));
-
- push(@$files,$file);
- return 1;
-}
-
-# remove_file()
-#
-# Remove a file from the list
-#
-# Params: File
-#
-# Return: Status code (Boolean)
-
-sub remove_file($)
-{
- my ($self,$file) = @_;
- my $files = $self->{'files'};
-
- # Check if the file is really in the list
-
- return if($self->unused($file));
-
- # Remove the file from the list
-
- for(my $x=0;$x<@$files;$x++)
- {
-  if($files->[$x] eq $file)
-  {
-   splice(@$files,$x,1);
-   return 1;
-  }
- }
-}
-
-# remove_all()
-#
-# Remove all files from the list
-#
-# Params: -nothing-
-#
-# Return: -nothing-
-
-sub remove_all
-{
- my $self = shift;
-
- $self->{'files'} = [];
-
- return;
-}
-
-# in_use()
-#
-# Check if a file is in the list
-#
-# Params: File to check
-#
-# Return: Status code (Boolean)
-
-sub in_use($)
-{
- my ($self,$file) = @_;
- my $files = $self->{'files'};
-
- foreach(@$files)
- {
-  return 1 if($_ eq $file);
- }
-
- return;
-}
-
-# unused()
-#
-# Check if a file is not in the list
-#
-# Params: File to check
-#
-# Return: Status code (Boolean)
-
-sub unused($)
-{
- return not shift->in_use(shift);
-}
-
-# it's true, baby ;-)
-
-1;
-
-#
-### End ###
\ No newline at end of file
 
 <td align="right" style="white-space:nowrap">{SIZE}</td>
 <td style="padding-left:15pt;white-space:nowrap;">{DATE}{IF gmt} (GMT){ENDIF}</td>
 <td style="padding-left:15pt;white-space:nowrap;">{FILE_NAME}</td>
-<td style="padding-left:15pt;white-space:nowrap;">({IF viewable}<a href="{SCRIPT}?command=show&file={FILE}">View</a>{ELSE}<span style="color:#C0C0C0" title="{IF not_readable}Not readable{ELSE}{IF binary}Binary file{ELSE}{IF too_large}File too large{ENDIF}{ENDIF}{ENDIF}">View</span>{ENDIF} | {IF editable}<a href="{SCRIPT}?command=beginedit&file={FILE}">Edit</a>{ELSE}<span style="color:#C0C0C0" title="{IF link}Symbolic link{ELSE}{IF not_readable}Not readable{ELSE}{IF readonly}Read only{ELSE}{IF binary}Binary file{ELSE}{IF too_large}File too large{ENDIF}{IF in_use}In use{ENDIF}{ENDIF}{ENDIF}{ENDIF}{ENDIF}">Edit</span>{ENDIF}{IF no_link} | <a href="{SCRIPT}?command=copy&file={FILE}">Copy</a>{ENDIF}{IF unused}{IF dir_writeable} | <a href="{SCRIPT}?command=rename&file={FILE}">Rename</a> | <a href="{SCRIPT}?command=remove&file={FILE}">Delete</a>{ENDIF}{ENDIF}{IF no_link}{IF in_use} | <a href="{SCRIPT}?command=unlock&file={FILE}">Unlock</a>{ENDIF} |{IF unused}{IF users} <a href="{SCRIPT}?command=chprop&file={FILE}">Chmod/Chgrp</a> |{ENDIF}{ENDIF}{ELSE} |{ENDIF} <a href="{URL}" target="_blank">View in Browser</a>)</td>
+<td style="padding-left:15pt;white-space:nowrap;">({IF viewable}<a href="{SCRIPT}?command=show&file={FILE}">View</a>{ELSE}<span style="color:#C0C0C0" title="{IF not_readable}Not readable{ELSE}{IF binary}Binary file{ELSE}{IF too_large}File too large{ENDIF}{ENDIF}{ENDIF}">View</span>{ENDIF} | {IF editable}<a href="{SCRIPT}?command=beginedit&file={FILE}">Edit</a>{ELSE}<span style="color:#C0C0C0" title="{IF link}Symbolic link{ELSE}{IF not_readable}Not readable{ELSE}{IF readonly}Read only{ELSE}{IF binary}Binary file{ELSE}{IF too_large}File too large{ENDIF}{ENDIF}{ENDIF}{ENDIF}{ENDIF}">Edit</span>{ENDIF}{IF no_link} | <a href="{SCRIPT}?command=copy&file={FILE}">Copy</a>{ENDIF}{IF dir_writeable} | <a href="{SCRIPT}?command=rename&file={FILE}">Rename</a> | <a href="{SCRIPT}?command=remove&file={FILE}">Delete</a>{ENDIF} |{IF users} <a href="{SCRIPT}?command=chprop&file={FILE}">Chmod/Chgrp</a> |{ENDIF} <a href="{URL}" target="_blank">View in Browser</a>)</td>
 </tr>
 
 
 <p>(equals <a href="{URL}" target="_blank">{URL}</a>)</p>
 
-<p><b style="color:#FF0000">Caution!</b> This file is locked for other users while you are editing it. To unlock it, click <i>Save and exit</i> or <i>Exit WITHOUT saving</i>. Please <b>don't</b> click the <i>Reload</i> button in your browser! This will confuse the editor.</p>
+<p><a href="{SCRIPT}?command=show&file={DIR}">Back to {DIR}</a></p>{IF error}
 
-<form action="{SCRIPT}" method="get">
-<input type="hidden" name="command" value="canceledit">
-<input type="hidden" name="file" value="{FILE}">
-<p><input type="submit" value="Exit WITHOUT saving"></p>
-</form>
+<p>{ERROR}</p>{ENDIF}
 
 <form action="{SCRIPT}" method="post">
 <input type="hidden" name="command" value="endedit">
 <input type="hidden" name="file" value="{FILE}">
+<input type="hidden" name="md5sum" value="{MD5SUM}">
+
+<p><textarea name="filecontent" rows="25" cols="120">{CONTENT}</textarea></p>
+
+<p><input type="checkbox" name="saveas" id="newfile" value="1"><label for="newfile"> Save as new file: {DIR} </label><input type="text" name="newfile" value="" onchange="if(this.form.newfile.value != '') this.form.saveas.checked = true; else this.form.saveas.checked = false;"></p>
 
-<table width="100%" border="1">
-<tr>
-<td width="50%" align="center">
-<input type="checkbox" name="saveas" id="newfile" value="1"><label for="newfile"> Save as new file: {DIR} </label><input type="text" name="newfile" value="" onchange="if(this.form.newfile.value != '') this.form.saveas.checked = true; else this.form.saveas.checked = false;"></td>
-<td width="50%" align="center"><input type="checkbox" name="encode_iso" id="encode_iso" value="1"><label for="encode_iso"> Encode ISO-8859-1 special chars</label></td>
-</tr>
-<tr>
-<td align="center"><input type="reset" value="Reset form"></td>
-<td align="center"><input type="submit" value="Save and exit"></td>
-</tr>
-</table>
-
-<textarea name="filecontent" rows="25" cols="120">{CONTENT}</textarea>
+<p><input type="submit" value="Save file"> <input type="reset" value="Discard changes"></p>
 </form>
 
 </body>