It works but needs a lot of fine tuning.
                 'mkdir'        => \&exec_mkdir,
                 'mkfile'       => \&exec_mkfile,
                 'upload'       => \&exec_upload,
+                'unpack'       => \&exec_unpack,
                 'copy'         => \&exec_copy,
                 'rename'       => \&exec_rename,
                 'remove'       => \&exec_remove,
 
    $ftpl->parse_if_block('users',$users && -o $phys_path);
 
+   $ftpl->parse_if_block('archive',$File::Access::has_archive_extract && is_archive($file));
+
    $ftpl->parse_if_block('even',($count % 2) == 0);
 
    $dirlist .= $ftpl->get_template;
   return error($config->{'errors'}->{'file_exists'},$dir,{FILE => $new_virtual}) if(-e $new_physical);
 
   file_create($new_physical) or return error($config->{'errors'}->{'mkfile_failed'},$dir,{FILE => $new_virtual});
-  
+
   if($data->{'cgi'}->param('edit'))
   {
    return devedit_reload({command => 'beginedit', file => $new_virtual});
  }
 }
 
+# exec_unpack()
+#
+# Unpack an archive
+#
+# Params: 1. Reference to user input hash
+#         2. Reference to config hash
+#
+# Return: Output of the command (Scalar Reference)
+
+sub exec_unpack($$)
+{
+ my ($data,$config) = @_;
+ my $physical       = $data->{'physical'};
+ my $virtual        = $data->{'virtual'};
+ my $dir            = upper_path($virtual);
+ my $new_physical   = $data->{'new_physical'};
+ my $new_virtual    = $data->{'new_virtual'};
+ my $cgi            = $data->{'cgi'};
+
+ if($new_physical)
+ {
+  archive_unpack($physical,$new_physical);
+  return devedit_reload({command => 'show', file => $new_virtual});
+ }
+ else
+ {
+  my $tpl = new Template;
+  $tpl->read_file($config->{'templates'}->{'unpack'});
+
+  $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_copy()
 #
 # Copy a file and return to directory view
 
 # using only one command
 #
 # Author:        Patrick Canterino <patrick@patshaping.de>
-# Last modified: 2005-08-01
+# Last modified: 2010-12-27
 #
 # Copyright (C) 1999-2000 Roland Bluethgen, Frank Schoenmann
 # Copyright (C) 2003-2009 Patrick Canterino
 use strict;
 
 use vars qw(@EXPORT
-            $has_flock);
+            $has_flock
+            $has_archive_extract);
 
 use Fcntl qw(:DEFAULT
              :flock);
 
 use base qw(Exporter);
 
-@EXPORT = qw(dir_copy
+@EXPORT = qw(archive_unpack
+             dir_copy
              dir_read
              file_create
              file_lock
 
 $has_flock = eval { local $SIG{'__DIE__'}; flock(STDOUT,0); 1 };
 
+# Check if Archive::Extract is available
+
+$has_archive_extract = eval { local $SIG{'__DIE__'}; require Archive::Extract; 1 };
+
 # Predeclaration of dir_copy()
 
 sub dir_copy($$);
 
+# archive_unpack()
+#
+# Unpack an archive
+# (archive type must be supported by Archive::Extract)
+#
+# Params: 1. Archive path
+#         2. Path to extract (optional)
+#
+# Return: - Status code (Boolean)
+#         - undef if Archive::Extract is not available
+
+sub archive_unpack($;$)
+{
+ my ($archive,$path) = @_;
+
+ return undef unless($has_archive_extract);
+
+ return unless(-f $archive);
+ return if($path && not -d $path);
+
+ my $ae = Archive::Extract->new(archive => $archive);
+ return unless($ae);
+
+ if($path)
+ {
+  return $ae->extract(to => $path);
+ }
+ else
+ {
+  return $ae->extract;
+ }
+}
+
 # dir_copy()
 #
 # Copy a directory
 
              encode_html
              equal_url
              file_name
+             is_archive
              in_array
              is_disabled_command
              is_forbidden_file
              mode_string
              multi_string
              upper_path);
+             
+my @archive_exts = ('.zip', 'tar.gz', 'tar.bz2');
 
 # check_path()
 #
  return;
 }
 
+# is_archive()
+#
+# Check if a file is an archive
+# (currently only by file extension)
+#
+# Params: Archive file name
+#
+# Return: Status code (Boolean)
+
+sub is_archive($)
+{
+ my $file = shift;
+ 
+ foreach my $ext(@archive_exts)
+ {
+  return 1 if(lc(substr($file,length($file)-length($ext),length($ext))) eq lc($ext));
+ }
+ 
+ return;
+}
+
 # is_disabled_command()
 #
 # Check if a command is disabled
 
 mkfile          = templates/mkfile.htm
 renamefile      = templates/renamefile.htm
 rmmulti         = templates/rmmulti.htm
+unpack          = templates/unpack.htm
 upload          = templates/upload.htm
 viewfile        = templates/viewfile.htm
 viewlink        = templates/viewlink.htm
 
 <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;">{IF forbidden}<span title="File access forbidden by Dev-Editor's configuration">{FILE_NAME}</span>{ELSE}{FILE_NAME}{ENDIF}</td>
-<td style="padding-left:15pt;white-space:nowrap;">({IF !forbidden}{IF viewable}<a href="{SCRIPT}?command=show&file={FILE_URL}">View</a>{ELSE}<span title="{IF !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_URL}">Edit</a>{ELSE}<span title="{IF link}Symbolic link{ELSE}{IF !readable}Not readable{ELSE}{IF !writeable}Read only{ELSE}{IF binary}Binary file{ELSE}{IF too_large}File too large{ENDIF}{ENDIF}{ENDIF}{ENDIF}{ENDIF}">Edit</span>{ENDIF}{IF !link}{IF readable}| <a href="{SCRIPT}?command=download&file={FILE_URL}">Download</a> | <a href="{SCRIPT}?command=copy&file={FILE_URL}">Copy</a>{ENDIF}{ENDIF}{IF dir_writeable} | <a href="{SCRIPT}?command=rename&file={FILE_URL}">Rename</a> | <a href="{SCRIPT}?command=remove&file={FILE_URL}">Delete</a>{ENDIF} |{IF !link}{IF users} <a href="{SCRIPT}?command=chprop&file={FILE_URL}">Chmod/Chgrp</a> |{ENDIF}{ENDIF} {ENDIF}<a href="{URL}" target="_blank">View in Browser</a>)</td>
+<td style="padding-left:15pt;white-space:nowrap;">({IF !forbidden}{IF viewable}<a href="{SCRIPT}?command=show&file={FILE_URL}">View</a>{ELSE}<span title="{IF !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_URL}">Edit</a>{ELSE}<span title="{IF link}Symbolic link{ELSE}{IF !readable}Not readable{ELSE}{IF !writeable}Read only{ELSE}{IF binary}Binary file{ELSE}{IF too_large}File too large{ENDIF}{ENDIF}{ENDIF}{ENDIF}{ENDIF}">Edit</span>{ENDIF}{IF !link}{IF readable}| <a href="{SCRIPT}?command=download&file={FILE_URL}">Download</a> {IF archive}| <a href="{SCRIPT}?command=unpack&file={FILE_URL}">Unpack</a> {ENDIF}| <a href="{SCRIPT}?command=copy&file={FILE_URL}">Copy</a>{ENDIF}{ENDIF}{IF dir_writeable} | <a href="{SCRIPT}?command=rename&file={FILE_URL}">Rename</a> | <a href="{SCRIPT}?command=remove&file={FILE_URL}">Delete</a>{ENDIF} |{IF !link}{IF users} <a href="{SCRIPT}?command=chprop&file={FILE_URL}">Chmod/Chgrp</a> |{ENDIF}{ENDIF} {ENDIF}<a href="{URL}" target="_blank">View in Browser</a>)</td>
 </tr>
 
--- /dev/null
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+"http://www.w3.org/TR/html4/loose.dtd">
+
+<html>
+<head>
+<title>Unpack file {FILE}</title>
+<meta http-equiv="content-type" content="text/html; charset=iso-8859-1">
+</head>
+<body bgcolor="#FFFFFF" text="#000000" link="#0000FF" vlink="#800080" alink="#FF0000">
+
+<h1>Unpack file {FILE}</h1>
+
+<p>(equals <a href="{URL}" target="_blank">{URL}</a>)</p>
+
+<p><a href="{SCRIPT}?command=show&file={DIR_URL}">Back to {DIR}</a></p>
+
+<hr>
+
+<form action="{SCRIPT}" method="post">
+<input type="hidden" name="command" value="unpack">
+<input type="hidden" name="file" value="{FILE}">
+
+<p>Unpack file '{FILE}' to:<br>
+<input type="text" name="newfile" value="{DIR}"><!-- <input type="checkbox" name="confirmed" id="overwrite"><label for="overwrite">Overwrite existing file</label> --></p>
+
+<p><input type="submit" value="Unpack file!"></p>
+</form>
+
+<hr>
+
+<p align="right"><a href="{SCRIPT}?command=about" target="_blank"><i>About Dev-Editor</i></a></p>
+</body>
+</html>
\ No newline at end of file