#! /usr/bin/perl

# 05/08/2k1 - cabextract -v entfernt, leichtsinn

# unp, Version 1.0.3 ; Sun, 29 Jul 2001 23:18:25 +0200
# -----------------------------------------------------------------------
#
# Maintained by Eduard Bloch <edi@ka.linux.de>
# http://www.eduard.bloch.com/edecosi/unp.en.html
#
# Originaly written by Andr Karwath, 1997
# andre.karwath@informatik.tu-chemnitz.de
# http://www.aka-online.de
#
# "unp" runs the correct unpack program depending on the file extension
# of the given parameter.
# 
# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# General Public License for more details.
#
# -----------------------------------------------------------------------
# If you make changes to this script, please feel free to forward the new 
# version to eduard@bloch.com or Andre.Karwath@informatik.tu-chemnitz.de
# -----------------------------------------------------------------------
# You need some archiver and compressor programs for extracting:
# GNU tar, gzip, bzip2, ar, rpm, unrar or rar, unarj, unzip and lha


$not_found=": not found\n";
$not_read=": not readable\n";
$unsup=": unsupported format\n";
$formats="
tar[.gz,.bz2], gz, bz2, Z, ar/deb, rpm, shar, rar, arj, zip, LHa, cab, ace,
tnef, uu (mail, news), mime, hqx, sea
";
$usage="
usage: unp file [file]...
file: compressed file(s) to expand

Use -- to pass arguments to external programs, eg. some tar options:
unp fastgl.tgz xmnt.tgz -- -C /tmp

Special option:
  -u  For Debian packages:
      - extract data.tar.gz after each operation
      - extract control.tar.gz in control/<filename>/
      For other archives:
      - create directory <filename without suffix>/
      - extract contents there

currently supported extensions and formats are".$formats;
$tryfile=" - unknown extension, checking with \"file\"\n";
$testbz2=" contains bzip2-compressed data, determining data type...\n";
$testgz=" contains gzip-compressed data, determining data type...\n";
$skip=" exists allready, skipping...\n";
$is_dir=" is a directory, skipping...\n";

# localisation part (only german at the moment):
if($ENV{'LANG'}=~ "^de"){
$not_found=" wurde nicht gefunden!\n";
$not_read=" konnte nicht gelesen werden!\n";
$unsup=": dieses Format wird nicht untersttzt!\n";
$usage="
Aufruf: unp Datei [Datei] ...
Datei: eine oder mehrere komprimierte Datei(en) zum entpacken

Optionen:
  -u  Fr Debian-Pakete:
      - Nach jeder Operation data.tar.gz entpacken
      - control.tar.gz nach control/<Achiv-Name>/
      Fr andere Archive:
      - Verzeichniss <Archivename ohne Endung>/ erstellen
      - Archiv dort entpacken

Optionen nach -- werden an externe Programme bergeben, z.B. tar-Optionen:
unp fastgl.tgz xmnt.tgz -- -C /tmp

Derzeit untersttzte Erweiterungen und Formate:".$formats;
$tryfile=" - Endung unbekannt, berprfe mit \"file\"...
";
$testbz2=" enthlt bzip2-komprimierte Daten, berprfe den Datentyp...\n";
$testgz=" enthlt gzip-komprimierte Daten, berprfe den Datentyp...\n";
$skip=" existiert bereits, berspringe...\n";
$is_dir=" ist ein Verzeichnis\n";
}

&print_usage if ($#ARGV<0 || $ARGV[0] eq "-h");

sub testfile {
   print $file.$tryfile;
   $filestr=`file \"$file\"`;
   if ($filestr =~ /(gzip)/gi){
      print $file.$testgz;
      $file=~/([^\/]*)$/i; $target="$1.unp";
      if (-f $target){ print $target.$skip; next LOOP;} # mgl. fall:.unp existiert, ist aber doch ein tar.gz! -> nachher fixen
      $command=(`zcat \"$file\" | file -`=~/tar/i) ? "zcat \"$file\" | tar -xvf - $ARGS" : "zcat < \"$file\" > $target";
   };
   
   if ($filestr =~ /(bzip2)/gi){
      print $file.$testbz2; 
      $file=~/([^\/]*)$/i; $target="$1.unp";
      if (-f $target){ print $target.$skip; next LOOP;}
      $command=(`bzcat \"$file\" | file -`=~/tar/i) ? "bzcat \"$file\" | tar -xvf - $ARGS" : "bzcat < \"$file\" > $target";
   };
   
   if ($filestr =~ /RAR.*archive/i) { $command="rar x $ARGS \"$file\" || unrar x $ARGS \"$file\""; }
   if ($filestr =~ /tar.*archive/i) { $command="tar -xvf \"$file\" $ARGS"; }
   if ($filestr =~ /(Debian binary package|\ ar.*archive)/i) { $command="ar xv \"$file\" $ARGS"; }
   if ($filestr =~ /LHa.*archive/i) { $command="lha x $ARGS \"$file\""; }
   if ($filestr =~ /ARJ.*archive/i) { $command="unarj x \"$file\""; }
   if ($filestr =~ /CAB file/i) { $command="cabextract \"$file\""; }
   if ($filestr =~ /Zip.*archive/i) { $command="unzip $ARGS \"$file\""; }
   if ($filestr =~ /shell.*archive/i) { $command="unshar $ARGS \"$file\""; }
   if ($filestr =~ /Transport Neutral Encapsulation Format/i) { $command="tnef -v $ARGS \"$file\""; }
   if ($filestr =~ /uuencoded/i) { $command="uudecode $ARGS \"$file\""; }
   if ($filestr =~ /(mail text)|news/i) { $command="cat \"$file\" | formail -s munpack"; }
   if ($filestr =~ /RPM/) { $command="rpm2cpio < \"$file\" | cpio -i -d	--verbose $ARGS";}
   # RAR can also create executables
   if ($filestr =~ /executable/i){$command="unzip \"$file\" || unrar x \"$file\" || rar x \"$file\" || unarj x \"$file\" || lha x \"$file\"";}
   if ($filestr =~ /BinHex/i) {$command="a=`hexbin -v \"$file\" 2>&1`; bla=`echo \$a | sed -e 's/.* name=\"\\(.*\\)\".*/\\1/'`; macunpack -v \$bla.bin;"}

   # if still nothing could be found, print an error message
   if ($command eq "") {
      print $file.$unsup;
      next LOOP;
   }
}

arglabel: foreach $arg (@ARGV){
	if("$arg" eq "-u"){$dataunp=1 ; next arglabel};
	if("$arg" eq "--"){$argvalue=1; next arglabel};
	if($argvalue){
		$ARGS="$ARGS $arg";
	}else{
		push(@FILES,$arg);
	}
}

LOOP: foreach $file (@FILES) {
  if (!-e $file) {
     print $file.$not_found;
     if ($file == "-") 
       {$stdin=1}
     else
       {next LOOP;}
  }

  if ((!-r $file) && (!$stdin)) {
     print $file.$not_read;
     next LOOP;
  }
  
	if (-d $file) {
     print $file.$is_dir;
     next LOOP;
  }
	undef $command;

  # not just gunzip, create new file with uncompressed data in the current
	# directory, same for bz2
	if ($file =~ /([^\/]*)\.(gz|Z)$/i) {if (-f $1){ print $1.$skip; next LOOP;};
			$command="gunzip < \"$file\" > $1"; }
  if ($file =~ /([^\/]*)\.(bz2$)/i) {if (-f $1){ print $1.$skip; next LOOP;};
			$command="bunzip2 < \"$file\" > $1"; }
	
	# check also for _tar, because of broken filenames
  if ($file =~ /(\.|_)tar$/i) { $command="tar -xvf \"$file\" $ARGS"; }
	if ($file =~ /(\.|_)rpm$/i) { $command="rpm2cpio < \"$file\" | cpio -i -d	--verbose $ARGS";}
	if ($file =~ /(\.|_)tar\.gz$/i) { $command="tar -xvzf \"$file\" $ARGS"; }
  if ($file =~ /(\.|_)tar\.bz2$/i) { $command="bunzip2 -c \"$file\" | tar -xvf - $ARGS"; }
	
	if ($file =~ /\.tgz$/i) { $command="tar -xvzf \"$file\" $ARGS"; }
  if ($file =~ /\.rar$/i) { $command="rar x \"$file\" $ARGS || unrar x \"$file\" $ARGS"; }
  if ($file =~ /\.(ar|deb)$/i) { $command="ar xv \"$file\" $ARGS"; }
  if ($file =~ /\.l(ha|zh)$/i) { $command="lha x $ARGS \"$file\""; }
  if ($file =~ /\.arj$/i) { $command="unarj x \"$file\""; }
  if ($file =~ /\.zip$/i) { $command="unzip $ARGS \"$file\""; }
  if ($file =~ /\.cab$/i) { $command="cabextract \"$file\""; }
  if ($file =~ /\.ace$/i) { $command="unace e $ARGS \"$file\""; }
  if ($file =~ /\.dat$/i) { $command="tnef -v $ARGS \"$file\""; }
  if ($file =~ /\.(sea|sea\.bin)$/i) { $command="macutils -v $ARGS \"$file\""; }
  if ($file =~ /\.uu$/i) { $command="uudecode $ARGS \"$file\""; }
	
	# assume that exe is just an arcive with executable header and try
	# some programs
	if ($file =~ /\.exe$/i) { $command="unzip \"$file\" || unrar x \"$file\" || rar x \"$file\" || unarj x \"$file\" || lha x \"$file\"";}

  if ($command eq "") {testfile};
	if ($dataunp){
#print "binda\n$command\n$1";
	  if($file =~ /([^\/]*)\.deb$/i) {
      &doit;
      system ("tar zxvf data.tar.gz; mkdir -p control/$1; cd control/$1; tar zxvf ../../control.tar.gz");
    }
   else {
      $file =~ /([^\/]+)\.(\w)+$/i;
      $newdir=$1;
      if(!$file =~ /^\//) { # wenn der pfad nicht absolut ist
        $file = `pwd`."/".$file;
      }
      mkdir $newdir;
      chdir $newdir;
      system ($0, $file);
   }
	}
  else {
    &doit;
  }
}

sub doit {
   #print "binda\n$command\n$1";
  if(system ($command)) {
  # if execution failed, try file
    testfile;
    #    system($command);
    system($command);
  };
}

die "\n";

# -----------------------------------------------------------------------------
sub print_usage {
  print $usage;
	die "\n";
}
# -----------------------------------------------------------------------------
