package File::Type;
use strict;
use warnings;

use IO::File;

our $VERSION = "0.22";

sub new {
  my $class = shift;
  my $self = {};
  bless $self, $class;
  return $self;
}

sub mime_type {
  # magically route argument

  my($self, $argument) = @_;

  if (length $argument > 1024 || $argument =~ m/\n/) {
    # assume it's data. Saves a stat call if the data's long
    # also avoids stat warning if there's a newline
    return $self->checktype_contents($argument);
  }
  
  if (-e $argument) {
    if (!-d $argument) {
      return $self->checktype_filename($argument);
    } else {
      return undef; # directories don't have mime types
    }
  }  
  # otherwise, fall back to checking the string as if it's data again
  return $self->checktype_contents($argument);
}

sub checktype_filename {
  # reads in 16k of selected file, or returns undef if can't open,
  # then checks contents

  my($self, $filename) = @_;
  my $fh = IO::File->new($filename) || return undef;
  my $data;
  $fh->read($data, 16*1024);
  $fh->close;
  return $self->checktype_contents($data);
}

sub checktype_contents {
  # checks file contents

  my($self, $data) = @_;
  my $substr;

  # autogenerated code begins

  if ($data =~ m[^TADS]) {
    return q{application/x-tads-game};
  }
  if ($data =~ m[^Core\001]) {
    return q{application/x-executable-file};
  }
  if ($data =~ m[^AMANDA\:\ TAPESTART\ DATE]) {
    return q{application/x-amanda-header};
  }
  if (length $data > 0) {
    $substr = substr($data, 0, 4);
    if (pack('H*', '000003f3') eq $substr ) {
      return q{application/x-executable-file};
    }
  }
  if (length $data > 0) {
    $substr = substr($data, 0, 4);
    if (pack('H*', '000003e7') eq $substr ) {
      return q{application/x-library-file};
    }
  }
  if (length $data > 0) {
    $substr = substr($data, 0, 4);
    if (pack('H*', '000001b3') eq $substr ) {
      return q{video/mpeg};
    }
  }
  if (length $data > 0) {
    $substr = substr($data, 0, 4);
    if (pack('H*', '000001ba') eq $substr ) {
      return q{video/mpeg};
    }
  }
  if (length $data > 0) {
    $substr = substr($data, 0, 2);
    if (pack('H*', 'fff0') eq $substr ) {
      return q{audio/mpeg};
    }
  }
  if ($data =~ m[^MOVI]) {
    return q{video/x-sgi-movie};
  }
  if (length $data > 4) {
    $substr = substr($data, 4, 1024);
    if (defined $substr && $substr =~ m[^moov]) {
      return q{video/quicktime};
    }
  }
  if (length $data > 4) {
    $substr = substr($data, 4, 1024);
    if (defined $substr && $substr =~ m[^mdat]) {
      return q{video/quicktime};
    }
  }
  if (length $data > 8) {
    $substr = substr($data, 8, 1024);
    if (defined $substr && $substr =~ m[^mp42]) {
      return q{video/quicktime};
    }
  }
  if (length $data > 12) {
    $substr = substr($data, 12, 1024);
    if (defined $substr && $substr =~ m[^mdat]) {
      return q{video/quicktime};
    }
  }
  if (length $data > 36) {
    $substr = substr($data, 36, 1024);
    if (defined $substr && $substr =~ m[^mdat]) {
      return q{video/quicktime};
    }
  }
  if (length $data > 0) {
    $substr = substr($data, 0, 4);
    if (pack('H*', '3026b275') eq $substr ) {
      return q{video/x-ms-asf};
    }
  }
  if ($data =~ m[^ASF\ ]) {
    return q{audio/x-ms-asx};
  }
  if ($data =~ m[^\<ASX]) {
    return q{audio/x-ms-asx};
  }
  if ($data =~ m[^\<asx]) {
    return q{audio/x-ms-asx};
  }
  if ($data =~ m[^FiLeStArTfIlEsTaRt]) {
    return q{text/x-apple-binscii};
  }
  if ($data =~ m[^\x0aGL]) {
    return q{application/data};
  }
  if ($data =~ m[^\x76\xff]) {
    return q{application/data};
  }
  if ($data =~ m[^NuFile]) {
    return q{application/data};
  }
  if ($data =~ m[^N\xf5F\xe9l\xe5]) {
    return q{application/data};
  }
  if (length $data > 0) {
    $substr = substr($data, 0, 4);
    if (pack('H*', '00051600') eq $substr ) {
      return q{application/data};
    }
  }
  if (length $data > 0) {
    $substr = substr($data, 0, 4);
    if (pack('H*', '00051607') eq $substr ) {
      return q{application/data};
    }
  }
  if (length $data > 257) {
    $substr = substr($data, 257, 1024);
    if (defined $substr && $substr =~ m[^ustar\0]) {
      return q{application/x-tar};
    }
  }
  if (length $data > 257) {
    $substr = substr($data, 257, 1024);
    if (defined $substr && $substr =~ m[^ustar\040\040\0]) {
      return q{application/x-gtar};
    }
  }
  if ($data =~ m[^070707]) {
    return q{application/x-cpio};
  }
  if ($data =~ m[^070701]) {
    return q{application/x-cpio};
  }
  if ($data =~ m[^070702]) {
    return q{application/x-cpio};
  }
  if ($data =~ m[^\!\<arch\>\ndebian]) {
    return q{application/x-dpkg};
  }
  if ($data =~ m[^\=\<ar\>]) {
    return q{application/x-ar};
  }
  if ($data =~ m[^\!\<arch\>\n__________E]) {
    return q{application/x-ar};
  }
  if ($data =~ m[^\-h\-]) {
    return q{application/data};
  }
  if ($data =~ m[^\!\<arch\>]) {
    return q{application/x-ar};
  }
  if ($data =~ m[^\<ar\>]) {
    return q{application/x-ar};
  }
  if ($data =~ m[^\=\<ar\>]) {
    return q{application/x-ar};
  }
  if (length $data > 0) {
    $substr = substr($data, 0, 4);
    if (pack('H*', '65ff0000') eq $substr ) {
      return q{application/x-ar};
    }
  }
  if (length $data > 0) {
    $substr = substr($data, 0, 4);
    if (pack('H*', '3c61723e') eq $substr ) {
      return q{application/x-ar};
    }
  }
  if ($data =~ m[^\032archive]) {
    return q{application/data};
  }
  if ($data =~ m[^HPAK]) {
    return q{application/data};
  }
  if ($data =~ m[^\351\,\001JAM\	]) {
    return q{application/data};
  }
  if (length $data > 2) {
    $substr = substr($data, 2, 1024);
    if (defined $substr && $substr =~ m[^\-lh0\-]) {
      return q{application/x-lha};
    }
  }
  if (length $data > 2) {
    $substr = substr($data, 2, 1024);
    if (defined $substr && $substr =~ m[^\-lh1\-]) {
      return q{application/x-lha};
    }
  }
  if (length $data > 2) {
    $substr = substr($data, 2, 1024);
    if (defined $substr && $substr =~ m[^\-lz4\-]) {
      return q{application/x-lha};
    }
  }
  if (length $data > 2) {
    $substr = substr($data, 2, 1024);
    if (defined $substr && $substr =~ m[^\-lz5\-]) {
      return q{application/x-lha};
    }
  }
  if (length $data > 2) {
    $substr = substr($data, 2, 1024);
    if (defined $substr && $substr =~ m[^\-lzs\-]) {
      return q{application/x-lha};
    }
  }
  if (length $data > 2) {
    $substr = substr($data, 2, 1024);
    if (defined $substr && $substr =~ m[^\-lh40\-]) {
      return q{application/x-lha};
    }
  }
  if (length $data > 2) {
    $substr = substr($data, 2, 1024);
    if (defined $substr && $substr =~ m[^\-lhd\-]) {
      return q{application/x-lha};
    }
  }
  if (length $data > 2) {
    $substr = substr($data, 2, 1024);
    if (defined $substr && $substr =~ m[^\-lh2\-]) {
      return q{application/x-lha};
    }
  }
  if (length $data > 2) {
    $substr = substr($data, 2, 1024);
    if (defined $substr && $substr =~ m[^\-lh3\-]) {
      return q{application/x-lha};
    }
  }
  if (length $data > 2) {
    $substr = substr($data, 2, 1024);
    if (defined $substr && $substr =~ m[^\-lh4\-]) {
      return q{application/x-lha};
    }
  }
  if (length $data > 2) {
    $substr = substr($data, 2, 1024);
    if (defined $substr && $substr =~ m[^\-lh5\-]) {
      return q{application/x-lha};
    }
  }
  if ($data =~ m[^Rar\!]) {
    return q{application/x-rar};
  }
  if ($data =~ m[^SQSH]) {
    return q{application/data};
  }
  if ($data =~ m[^UC2\x1a]) {
    return q{application/data};
  }
  if ($data =~ m[^PK\003\004]) {
    return q{application/zip};
  }
  if (length $data > 10) {
    $substr = substr($data, 10, 1024);
    if (defined $substr && $substr =~ m[^\#\ This\ is\ a\ shell\ archive]) {
      return q{application/x-shar};
    }
  }
  if ($data =~ m[^\*STA]) {
    return q{application/data};
  }
  if ($data =~ m[^2278]) {
    return q{application/data};
  }
  if ($data =~ m[^\000\004\036\212\200]) {
    return q{application/core};
  }
  if ($data =~ m[^\.snd]) {
    return q{audio/basic};
  }
  if ($data =~ m[^MThd]) {
    return q{audio/midi};
  }
  if ($data =~ m[^CTMF]) {
    return q{audio/x-cmf};
  }
  if ($data =~ m[^SBI]) {
    return q{audio/x-sbi};
  }
  if ($data =~ m[^Creative\ Voice\ File]) {
    return q{audio/x-voc};
  }
  if (length $data > 0) {
    $substr = substr($data, 0, 4);
    if (pack('H*', '4e54524b') eq $substr ) {
      return q{audio/x-multitrack};
    }
  }
  if (length $data > 8) {
    $substr = substr($data, 8, 1024);
    if (defined $substr && $substr =~ m[^AVI]) {
      return q{video/x-msvideo};
    }
  }
  if (length $data > 8) {
    $substr = substr($data, 8, 1024);
    if (defined $substr && $substr =~ m[^WAVE]) {
      return q{audio/x-wav};
    }
  }
  if ($data =~ m[^EMOD]) {
    return q{audio/x-emod};
  }
  if (length $data > 0) {
    $substr = substr($data, 0, 4);
    if (pack('H*', '2e7261fd') eq $substr ) {
      return q{audio/x-pn-realaudio};
    }
  }
  if ($data =~ m[^MTM]) {
    return q{audio/x-multitrack};
  }
  if ($data =~ m[^if]) {
    return q{audio/x-669-mod};
  }
  if ($data =~ m[^FAR]) {
    return q{audio/mod};
  }
  if ($data =~ m[^MAS_U]) {
    return q{audio/x-multimate-mod};
  }
  if (length $data > 0x2c) {
    $substr = substr($data, 0x2c, 1024);
    if (defined $substr && $substr =~ m[^SCRM]) {
      return q{audio/x-st3-mod};
    }
  }
  if ($data =~ m[^GF1PATCH110\0ID\#000002\0]) {
    return q{audio/x-gus-patch};
  }
  if ($data =~ m[^GF1PATCH100\0ID\#000002\0]) {
    return q{audio/x-gus-patch};
  }
  if ($data =~ m[^JN]) {
    return q{audio/x-669-mod};
  }
  if ($data =~ m[^UN05]) {
    return q{audio/x-mikmod-uni};
  }
  if ($data =~ m[^Extended\ Module\:]) {
    return q{audio/x-ft2-mod};
  }
  if (length $data > 21) {
    $substr = substr($data, 21, 1024);
    if (defined $substr && $substr =~ m[^\!SCREAM\!]) {
      return q{audio/x-st2-mod};
    }
  }
  if (length $data > 1080) {
    $substr = substr($data, 1080, 1024);
    if (defined $substr && $substr =~ m[^M\.K\.]) {
      return q{audio/x-protracker-mod};
    }
  }
  if (length $data > 1080) {
    $substr = substr($data, 1080, 1024);
    if (defined $substr && $substr =~ m[^M\!K\!]) {
      return q{audio/x-protracker-mod};
    }
  }
  if (length $data > 1080) {
    $substr = substr($data, 1080, 1024);
    if (defined $substr && $substr =~ m[^FLT4]) {
      return q{audio/x-startracker-mod};
    }
  }
  if (length $data > 1080) {
    $substr = substr($data, 1080, 1024);
    if (defined $substr && $substr =~ m[^4CHN]) {
      return q{audio/x-fasttracker-mod};
    }
  }
  if (length $data > 1080) {
    $substr = substr($data, 1080, 1024);
    if (defined $substr && $substr =~ m[^6CHN]) {
      return q{audio/x-fasttracker-mod};
    }
  }
  if (length $data > 1080) {
    $substr = substr($data, 1080, 1024);
    if (defined $substr && $substr =~ m[^8CHN]) {
      return q{audio/x-fasttracker-mod};
    }
  }
  if (length $data > 1080) {
    $substr = substr($data, 1080, 1024);
    if (defined $substr && $substr =~ m[^CD81]) {
      return q{audio/x-oktalyzer-mod};
    }
  }
  if (length $data > 1080) {
    $substr = substr($data, 1080, 1024);
    if (defined $substr && $substr =~ m[^OKTA]) {
      return q{audio/x-oktalyzer-mod};
    }
  }
  if (length $data > 1080) {
    $substr = substr($data, 1080, 1024);
    if (defined $substr && $substr =~ m[^16CN]) {
      return q{audio/x-taketracker-mod};
    }
  }
  if (length $data > 1080) {
    $substr = substr($data, 1080, 1024);
    if (defined $substr && $substr =~ m[^32CN]) {
      return q{audio/x-taketracker-mod};
    }
  }
  if ($data =~ m[^TOC]) {
    return q{audio/x-toc};
  }
  if (length $data > 0) {
    $substr = substr($data, 0, 2);
    if (pack('H*', 'fffa') eq $substr ) {
      return q{audio/mp3};
    }
  }
  if ($data =~ m[^ID3]) {
    return q{audio/mp3};
  }
  if ($data =~ m[^\/\/]) {
    return q{text/cpp};
  }
  if ($data =~ m[^\\1cw\ ]) {
    return q{application/data};
  }
  if ($data =~ m[^\\1cw]) {
    return q{application/data};
  }
  if (length $data > 0) {
    $substr = substr($data, 0, 4);
    if (pack('H*', '85011400') eq $substr ) {
      return q{application/data};
    }
  }
  if (length $data > 0) {
    $substr = substr($data, 0, 4);
    if (pack('H*', '8501cb00') eq $substr ) {
      return q{application/data};
    }
  }
  if (length $data > 4) {
    $substr = substr($data, 4, 1024);
    if (defined $substr && $substr =~ m[^pipe]) {
      return q{application/data};
    }
  }
  if (length $data > 4) {
    $substr = substr($data, 4, 1024);
    if (defined $substr && $substr =~ m[^prof]) {
      return q{application/data};
    }
  }
  if ($data =~ m[^\:\ shell]) {
    return q{application/data};
  }
  if ($data =~ m[^\#\!\/bin\/sh]) {
    return q{application/x-sh};
  }
  if ($data =~ m[^\#\!\ \/bin\/sh]) {
    return q{application/x-sh};
  }
  if ($data =~ m[^\#\!\	\/bin\/sh]) {
    return q{application/x-sh};
  }
  if ($data =~ m[^\#\!\/bin\/csh]) {
    return q{application/x-csh};
  }
  if ($data =~ m[^\#\!\ \/bin\/csh]) {
    return q{application/x-csh};
  }
  if ($data =~ m[^\#\!\	\/bin\/csh]) {
    return q{application/x-csh};
  }
  if ($data =~ m[^\#\!\/bin\/ksh]) {
    return q{application/x-ksh};
  }
  if ($data =~ m[^\#\!\ \/bin\/ksh]) {
    return q{application/x-ksh};
  }
  if ($data =~ m[^\#\!\	\/bin\/ksh]) {
    return q{application/x-ksh};
  }
  if ($data =~ m[^\#\!\/bin\/tcsh]) {
    return q{application/x-csh};
  }
  if ($data =~ m[^\#\!\ \/bin\/tcsh]) {
    return q{application/x-csh};
  }
  if ($data =~ m[^\#\!\	\/bin\/tcsh]) {
    return q{application/x-csh};
  }
  if ($data =~ m[^\#\!\/usr\/local\/tcsh]) {
    return q{application/x-csh};
  }
  if ($data =~ m[^\#\!\ \/usr\/local\/tcsh]) {
    return q{application/x-csh};
  }
  if ($data =~ m[^\#\!\/usr\/local\/bin\/tcsh]) {
    return q{application/x-csh};
  }
  if ($data =~ m[^\#\!\ \/usr\/local\/bin\/tcsh]) {
    return q{application/x-csh};
  }
  if ($data =~ m[^\#\!\	\/usr\/local\/bin\/tcsh]) {
    return q{application/x-csh};
  }
  if ($data =~ m[^\#\!\/usr\/local\/bin\/zsh]) {
    return q{application/x-zsh};
  }
  if ($data =~ m[^\#\!\ \/usr\/local\/bin\/zsh]) {
    return q{application/x-zsh};
  }
  if ($data =~ m[^\#\!\	\/usr\/local\/bin\/zsh]) {
    return q{application/x-zsh};
  }
  if ($data =~ m[^\#\!\/usr\/local\/bin\/ash]) {
    return q{application/x-sh};
  }
  if ($data =~ m[^\#\!\ \/usr\/local\/bin\/ash]) {
    return q{application/x-zsh};
  }
  if ($data =~ m[^\#\!\	\/usr\/local\/bin\/ash]) {
    return q{application/x-zsh};
  }
  if ($data =~ m[^\#\!\/usr\/local\/bin\/ae]) {
    return q{text/script};
  }
  if ($data =~ m[^\#\!\ \/usr\/local\/bin\/ae]) {
    return q{text/script};
  }
  if ($data =~ m[^\#\!\	\/usr\/local\/bin\/ae]) {
    return q{text/script};
  }
  if ($data =~ m[^\#\!\/bin\/nawk]) {
    return q{application/x-awk};
  }
  if ($data =~ m[^\#\!\ \/bin\/nawk]) {
    return q{application/x-awk};
  }
  if ($data =~ m[^\#\!\	\/bin\/nawk]) {
    return q{application/x-awk};
  }
  if ($data =~ m[^\#\!\/usr\/bin\/nawk]) {
    return q{application/x-awk};
  }
  if ($data =~ m[^\#\!\ \/usr\/bin\/nawk]) {
    return q{application/x-awk};
  }
  if ($data =~ m[^\#\!\	\/usr\/bin\/nawk]) {
    return q{application/x-awk};
  }
  if ($data =~ m[^\#\!\/usr\/local\/bin\/nawk]) {
    return q{application/x-awk};
  }
  if ($data =~ m[^\#\!\ \/usr\/local\/bin\/nawk]) {
    return q{application/x-awk};
  }
  if ($data =~ m[^\#\!\	\/usr\/local\/bin\/nawk]) {
    return q{application/x-awk};
  }
  if ($data =~ m[^\#\!\/bin\/gawk]) {
    return q{application/x-awk};
  }
  if ($data =~ m[^\#\!\ \/bin\/gawk]) {
    return q{application/x-awk};
  }
  if ($data =~ m[^\#\!\	\/bin\/gawk]) {
    return q{application/x-awk};
  }
  if ($data =~ m[^\#\!\/usr\/bin\/gawk]) {
    return q{application/x-awk};
  }
  if ($data =~ m[^\#\!\ \/usr\/bin\/gawk]) {
    return q{application/x-awk};
  }
  if ($data =~ m[^\#\!\	\/usr\/bin\/gawk]) {
    return q{application/x-awk};
  }
  if ($data =~ m[^\#\!\/usr\/local\/bin\/gawk]) {
    return q{application/x-awk};
  }
  if ($data =~ m[^\#\!\ \/usr\/local\/bin\/gawk]) {
    return q{application/x-awk};
  }
  if ($data =~ m[^\#\!\	\/usr\/local\/bin\/gawk]) {
    return q{application/x-awk};
  }
  if ($data =~ m[^\#\!\/bin\/awk]) {
    return q{application/x-awk};
  }
  if ($data =~ m[^\#\!\ \/bin\/awk]) {
    return q{application/x-awk};
  }
  if ($data =~ m[^\#\!\	\/bin\/awk]) {
    return q{application/x-awk};
  }
  if ($data =~ m[^\#\!\/usr\/bin\/awk]) {
    return q{application/x-awk};
  }
  if ($data =~ m[^\#\!\ \/usr\/bin\/awk]) {
    return q{application/x-awk};
  }
  if ($data =~ m[^\#\!\	\/usr\/bin\/awk]) {
    return q{application/x-awk};
  }
  if ($data =~ m[^BEGIN]) {
    return q{application/x-awk};
  }
  if ($data =~ m[^\#\!\/bin\/perl]) {
    return q{application/x-perl};
  }
  if ($data =~ m[^\#\!\ \/bin\/perl]) {
    return q{application/x-perl};
  }
  if ($data =~ m[^\#\!\	\/bin\/perl]) {
    return q{application/x-perl};
  }
  if ($data =~ m[^eval\ \"exec\ \/bin\/perl]) {
    return q{application/x-perl};
  }
  if ($data =~ m[^\#\!\/usr\/bin\/perl]) {
    return q{application/x-perl};
  }
  if ($data =~ m[^\#\!\ \/usr\/bin\/perl]) {
    return q{application/x-perl};
  }
  if ($data =~ m[^\#\!\	\/usr\/bin\/perl]) {
    return q{application/x-perl};
  }
  if ($data =~ m[^eval\ \"exec\ \/usr\/bin\/perl]) {
    return q{application/x-perl};
  }
  if ($data =~ m[^\#\!\/usr\/local\/bin\/perl]) {
    return q{application/x-perl};
  }
  if ($data =~ m[^\#\!\ \/usr\/local\/bin\/perl]) {
    return q{application/x-perl};
  }
  if ($data =~ m[^\#\!\	\/usr\/local\/bin\/perl]) {
    return q{application/x-perl};
  }
  if ($data =~ m[^eval\ \"exec\ \/usr\/local\/bin\/perl]) {
    return q{application/x-perl};
  }
  if ($data =~ m[^\#\!\/bin\/rc]) {
    return q{text/script};
  }
  if ($data =~ m[^\#\!\ \/bin\/rc]) {
    return q{text/script};
  }
  if ($data =~ m[^\#\!\	\/bin\/rc]) {
    return q{text/script};
  }
  if ($data =~ m[^\#\!\/bin\/bash]) {
    return q{application/x-sh};
  }
  if ($data =~ m[^\#\!\ \/bin\/bash]) {
    return q{application/x-sh};
  }
  if ($data =~ m[^\#\!\	\/bin\/bash]) {
    return q{application/x-sh};
  }
  if ($data =~ m[^\#\!\/usr\/local\/bin\/bash]) {
    return q{application/x-sh};
  }
  if ($data =~ m[^\#\!\ \/usr\/local\/bin\/bash]) {
    return q{application/x-sh};
  }
  if ($data =~ m[^\#\!\	\/usr\/local\/bin\/bash]) {
    return q{application/x-sh};
  }
  if ($data =~ m[^\#\!\ \/]) {
    return q{text/script};
  }
  if ($data =~ m[^\#\!\	\/]) {
    return q{text/script};
  }
  if ($data =~ m[^\#\!\/]) {
    return q{text/script};
  }
  if ($data =~ m[^\#\!\ ]) {
    return q{text/script};
  }
  if ($data =~ m[^\037\235]) {
    return q{application/compress};
  }
  if ($data =~ m[^\037\213]) {
    return q{application/x-gzip};
  }
  if ($data =~ m[^\037\036]) {
    return q{application/data};
  }
  if ($data =~ m[^\377\037]) {
    return q{application/data};
  }
  if ($data =~ m[^BZh]) {
    return q{application/x-bzip2};
  }
  if ($data =~ m[^\037\237]) {
    return q{application/data};
  }
  if ($data =~ m[^\037\236]) {
    return q{application/data};
  }
  if ($data =~ m[^\037\240]) {
    return q{application/data};
  }
  if ($data =~ m[^BZ]) {
    return q{application/x-bzip};
  }
  if ($data =~ m[^\x89\x4c\x5a\x4f\x00\x0d\x0a\x1a\x0a]) {
    return q{application/data};
  }
  if (length $data > 0) {
    $substr = substr($data, 0, 4);
    if (pack('H*', '011257') eq $substr ) {
      return q{application/core};
    }
  }
  if (length $data > 0) {
    $substr = substr($data, 0, 4);
    if (pack('H*', '13579ace') eq $substr ) {
      return q{application/x-gdbm};
    }
  }
  if ($data =~ m[^GDBM]) {
    return q{application/x-gdbm};
  }
  if (length $data > 0) {
    $substr = substr($data, 0, 4);
    if (pack('H*', '061561') eq $substr ) {
      return q{application/x-db};
    }
  }
  if (length $data > 0) {
    $substr = substr($data, 0, 4);
    if (pack('H*', '053162') eq $substr ) {
      return q{application/x-db};
    }
  }
  if ($data =~ m[^\=\<list\>\n\<protocol\ bbn\-m]) {
    return q{application/data};
  }
  if ($data =~ m[^diff\ ]) {
    return q{text/x-patch};
  }
  if ($data =~ m[^\*\*\*\ ]) {
    return q{text/x-patch};
  }
  if ($data =~ m[^Only\ in\ ]) {
    return q{text/x-patch};
  }
  if ($data =~ m[^Common\ subdirectories\:\ ]) {
    return q{text/x-patch};
  }
  if ($data =~ m[^\!\<arch\>\n________64E]) {
    return q{application/data};
  }
  if ($data =~ m[^\377\377\177]) {
    return q{application/data};
  }
  if ($data =~ m[^\377\377\174]) {
    return q{application/data};
  }
  if ($data =~ m[^\377\377\176]) {
    return q{application/data};
  }
  if ($data =~ m[^\033c\033]) {
    return q{application/data};
  }
  if ($data =~ m[^\!\<PDF\>\!\n]) {
    return q{application/x-prof};
  }
  if ($data =~ m[^\177ELF]) {
    return q{application/x-executable-file};
  }
  if ($data =~ m[^\366\366\366\366]) {
    return q{application/x-pc-floppy};
  }
  if (length $data > 0774) {
    $substr = substr($data, 0774, 2);
    if (pack('H*', 'dabe') eq $substr ) {
      return q{application/data};
    }
  }
  if ($data =~ m[^\-rom1fs\-\0]) {
    return q{application/x-filesystem};
  }
  if (length $data > 0x18b) {
    $substr = substr($data, 0x18b, 1024);
    if (defined $substr && $substr =~ m[^OS\/2]) {
      return q{application/x-bootable};
    }
  }
  if ($data =~ m[^FONT]) {
    return q{font/x-vfont};
  }
  if ($data =~ m[^\%\!PS\-AdobeFont\-1\.0]) {
    return q{font/type1};
  }
  if (length $data > 6) {
    $substr = substr($data, 6, 1024);
    if (defined $substr && $substr =~ m[^\%\!PS\-AdobeFont\-1\.0]) {
      return q{font/type1};
    }
  }
  if ($data =~ m[^STARTFONT\040]) {
    return q{font/x-bdf};
  }
  if ($data =~ m[^\001fcp]) {
    return q{font/x-pcf};
  }
  if ($data =~ m[^D1\.0\015]) {
    return q{font/x-speedo};
  }
  if ($data =~ m[^flf]) {
    return q{font/x-figlet};
  }
  if ($data =~ m[^flc]) {
    return q{application/x-font};
  }
  if (length $data > 0) {
    $substr = substr($data, 0, 4);
    if (pack('H*', '14025919') eq $substr ) {
      return q{font/x-libgrx};
    }
  }
  if (length $data > 0) {
    $substr = substr($data, 0, 4);
    if (pack('H*', 'ff464f4e') eq $substr ) {
      return q{font/x-dos};
    }
  }
  if (length $data > 7) {
    $substr = substr($data, 7, 4);
    if (pack('H*', '00454741') eq $substr ) {
      return q{font/x-dos};
    }
  }
  if (length $data > 7) {
    $substr = substr($data, 7, 4);
    if (pack('H*', '00564944') eq $substr ) {
      return q{font/x-dos};
    }
  }
  if (length $data > 4098) {
    $substr = substr($data, 4098, 1024);
    if (defined $substr && $substr =~ m[^DOSFONT]) {
      return q{font/x-dos};
    }
  }
  if ($data =~ m[^\<MakerFile]) {
    return q{application/x-framemaker};
  }
  if ($data =~ m[^\<MIFFile]) {
    return q{application/x-framemaker};
  }
  if ($data =~ m[^\<MakerDictionary]) {
    return q{application/x-framemaker};
  }
  if ($data =~ m[^\<MakerScreenFont]) {
    return q{font/x-framemaker};
  }
  if ($data =~ m[^\<MML]) {
    return q{application/x-framemaker};
  }
  if ($data =~ m[^\<BookFile]) {
    return q{application/x-framemaker};
  }
  if ($data =~ m[^\<Maker]) {
    return q{application/x-framemaker};
  }
  if (length $data > 7) {
    $substr = substr($data, 7, 1024);
    if (defined $substr && $substr =~ m[^\357\020\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0]) {
      return q{application/core};
    }
  }
  if ($data =~ m[^GIMP\ Gradient]) {
    return q{application/x-gimp-gradient};
  }
  if ($data =~ m[^gimp\ xcf]) {
    return q{application/x-gimp-image};
  }
  if (length $data > 20) {
    $substr = substr($data, 20, 1024);
    if (defined $substr && $substr =~ m[^GPAT]) {
      return q{application/x-gimp-pattern};
    }
  }
  if (length $data > 20) {
    $substr = substr($data, 20, 1024);
    if (defined $substr && $substr =~ m[^GIMP]) {
      return q{application/x-gimp-brush};
    }
  }
  if ($data =~ m[^\336\224\225]) {
    return q{application/x-locale};
  }
  if ($data =~ m[^\2254\22\336]) {
    return q{application/x-locale};
  }
  if ($data =~ m[^\000\001\000\000\000]) {
    return q{font/ttf};
  }
  if (length $data > 0) {
    $substr = substr($data, 0, 4);
    if (pack('H*', '02100106') eq $substr ) {
      return q{application/x-object-file};
    }
  }
  if (length $data > 0) {
    $substr = substr($data, 0, 4);
    if (pack('H*', '02100107') eq $substr ) {
      return q{application/x-executable-file};
    }
  }
  if (length $data > 0) {
    $substr = substr($data, 0, 4);
    if (pack('H*', '02100108') eq $substr ) {
      return q{application/x-executable-file};
    }
  }
  if (length $data > 0) {
    $substr = substr($data, 0, 4);
    if (pack('H*', '0210010b') eq $substr ) {
      return q{application/x-executable-file};
    }
  }
  if (length $data > 0) {
    $substr = substr($data, 0, 4);
    if (pack('H*', '0210010e') eq $substr ) {
      return q{application/x-library-file};
    }
  }
  if (length $data > 0) {
    $substr = substr($data, 0, 4);
    if (pack('H*', '0210010d') eq $substr ) {
      return q{application/x-library-file};
    }
  }
  if (length $data > 0) {
    $substr = substr($data, 0, 4);
    if (pack('H*', '02140106') eq $substr ) {
      return q{application/x-object-file};
    }
  }
  if (length $data > 0) {
    $substr = substr($data, 0, 4);
    if (pack('H*', '02140107') eq $substr ) {
      return q{application/x-executable-file};
    }
  }
  if (length $data > 0) {
    $substr = substr($data, 0, 4);
    if (pack('H*', '02140108') eq $substr ) {
      return q{application/x-executable-file};
    }
  }
  if (length $data > 0) {
    $substr = substr($data, 0, 4);
    if (pack('H*', '0214010b') eq $substr ) {
      return q{application/x-executable-file};
    }
  }
  if (length $data > 0) {
    $substr = substr($data, 0, 4);
    if (pack('H*', '0214010e') eq $substr ) {
      return q{application/x-library-file};
    }
  }
  if (length $data > 0) {
    $substr = substr($data, 0, 4);
    if (pack('H*', '0214010d') eq $substr ) {
      return q{application/x-object-file};
    }
  }
  if (length $data > 0) {
    $substr = substr($data, 0, 4);
    if (pack('H*', '020b0106') eq $substr ) {
      return q{application/x-object-file};
    }
  }
  if (length $data > 0) {
    $substr = substr($data, 0, 4);
    if (pack('H*', '020b0107') eq $substr ) {
      return q{application/x-executable-file};
    }
  }
  if (length $data > 0) {
    $substr = substr($data, 0, 4);
    if (pack('H*', '020b0108') eq $substr ) {
      return q{application/x-executable-file};
    }
  }
  if (length $data > 0) {
    $substr = substr($data, 0, 4);
    if (pack('H*', '020b010b') eq $substr ) {
      return q{application/x-executable-file};
    }
  }
  if (length $data > 0) {
    $substr = substr($data, 0, 4);
    if (pack('H*', '020b010e') eq $substr ) {
      return q{application/x-library-file};
    }
  }
  if (length $data > 0) {
    $substr = substr($data, 0, 4);
    if (pack('H*', '020b010d') eq $substr ) {
      return q{application/x-library-file};
    }
  }
  if (length $data > 0) {
    $substr = substr($data, 0, 4);
    if (pack('H*', '213c6172') eq $substr ) {
      return q{application/x-ar};
    }
  }
  if (length $data > 0) {
    $substr = substr($data, 0, 4);
    if (pack('H*', '020c0108') eq $substr ) {
      return q{application/x-executable-file};
    }
  }
  if (length $data > 0) {
    $substr = substr($data, 0, 4);
    if (pack('H*', '020c0107') eq $substr ) {
      return q{application/x-executable-file};
    }
  }
  if (length $data > 0) {
    $substr = substr($data, 0, 4);
    if (pack('H*', '020c010b') eq $substr ) {
      return q{application/x-executable-file};
    }
  }
  if (length $data > 0) {
    $substr = substr($data, 0, 4);
    if (pack('H*', '020c0106') eq $substr ) {
      return q{application/x-executable-file};
    }
  }
  if (length $data > 0) {
    $substr = substr($data, 0, 4);
    if (pack('H*', '020a0108') eq $substr ) {
      return q{application/x-executable-file};
    }
  }
  if (length $data > 0) {
    $substr = substr($data, 0, 4);
    if (pack('H*', '020a0107') eq $substr ) {
      return q{application/x-executable-file};
    }
  }
  if (length $data > 0) {
    $substr = substr($data, 0, 4);
    if (pack('H*', '020c010e') eq $substr ) {
      return q{application/x-library-file};
    }
  }
  if (length $data > 0) {
    $substr = substr($data, 0, 4);
    if (pack('H*', '020c010d') eq $substr ) {
      return q{application/x-library-file};
    }
  }
  if ($data =~ m[^Bitmapfile]) {
    return q{image/unknown};
  }
  if ($data =~ m[^IMGfile]) {
    return q{CIS 	image/unknown};
  }
  if ($data =~ m[^msgcat01]) {
    return q{application/x-locale};
  }
  if ($data =~ m[^HPHP48\-]) {
    return q{application/unknown};
  }
  if ($data =~ m[^\%\%HP\:]) {
    return q{text/x-unknown};
  }
  if (length $data > 0) {
    $substr = substr($data, 0, 2);
    if (pack('H*', '01df') eq $substr ) {
      return q{application/executable};
    }
  }
  if (length $data > 0) {
    $substr = substr($data, 0, 2);
    if (pack('H*', '0104') eq $substr ) {
      return q{application/x-shared-library};
    }
  }
  if (length $data > 0) {
    $substr = substr($data, 0, 2);
    if (pack('H*', '0105') eq $substr ) {
      return q{application/data};
    }
  }
  if (length $data > 0) {
    $substr = substr($data, 0, 2);
    if (pack('H*', 'fe04') eq $substr ) {
      return q{application/data};
    }
  }
  if ($data =~ m[^0xabcdef]) {
    return q{application/data};
  }
  if (length $data > 0) {
    $substr = substr($data, 0, 4);
    if (pack('H*', '000001f9') eq $substr ) {
      return q{application/data};
    }
  }
  if ($data =~ m[^\<aiaff\>]) {
    return q{application/x-archive};
  }
  if ($data =~ m[^FORM]) {
    return q{application/data};
  }
  if ($data =~ m[^P1]) {
    return q{image/x-portable-bitmap};
  }
  if ($data =~ m[^P2]) {
    return q{image/x-portable-graymap};
  }
  if ($data =~ m[^P3]) {
    return q{image/x-portable-pixmap};
  }
  if ($data =~ m[^P4]) {
    return q{image/x-portable-bitmap};
  }
  if ($data =~ m[^P5]) {
    return q{image/x-portable-graymap};
  }
  if ($data =~ m[^P6]) {
    return q{image/x-portable-pixmap};
  }
  if ($data =~ m[^IIN1]) {
    return q{image/tiff};
  }
  if ($data =~ m[^MM\x00\x2a]) {
    return q{image/tiff};
  }
  if ($data =~ m[^II\x2a\x00]) {
    return q{image/tiff};
  }
  if ($data =~ m[^\x89PNG]) {
    return q{image/x-png};
  }
  if (length $data > 1) {
    $substr = substr($data, 1, 1024);
    if (defined $substr && $substr =~ m[^PNG]) {
      return q{image/x-png};
    }
  }
  if ($data =~ m[^GIF8]) {
    return q{image/gif};
  }
  if ($data =~ m[^\361\0\100\273]) {
    return q{image/x-cmu-raster};
  }
  if (length $data > 0) {
    $substr = substr($data, 0, 2);
    if (pack('H*', 'ffd8') eq $substr ) {
      return q{image/jpeg};
    }
  }
  if ($data =~ m[^hsi1]) {
    return q{image/x-jpeg-proprietary};
  }
  if ($data =~ m[^BM]) {
    return q{image/x-bmp};
  }
  if ($data =~ m[^IC]) {
    return q{image/x-ico};
  }
  if (length $data > 0) {
    $substr = substr($data, 0, 4);
    if (pack('H*', '59a66a95') eq $substr ) {
      return q{x/x-image-sun-raster};
    }
  }
  if (length $data > 2048) {
    $substr = substr($data, 2048, 1024);
    if (defined $substr && $substr =~ m[^PCD_IPI]) {
      return q{x/x-photo-cd-pack-file};
    }
  }
  if ($data =~ m[^PCD_OPA]) {
    return q{x/x-photo-cd-overfiew-file};
  }
  if ($data =~ m[^\007\001\000]) {
    return q{Linux/i386 object file};
  }
  if (length $data > 4086) {
    $substr = substr($data, 4086, 1024);
    if (defined $substr && $substr =~ m[^SWAP\-SPACE]) {
      return q{Linux/i386 swap file};
    }
  }
  if ($data =~ m[^\;\;]) {
    return q{Lisp/Scheme program text};
  }
  if ($data =~ m[^FFIL]) {
    return q{font/ttf};
  }
  if (length $data > 65) {
    $substr = substr($data, 65, 1024);
    if (defined $substr && $substr =~ m[^FFIL]) {
      return q{font/ttf};
    }
  }
  if ($data =~ m[^LWFN]) {
    return q{font/type1};
  }
  if (length $data > 65) {
    $substr = substr($data, 65, 1024);
    if (defined $substr && $substr =~ m[^LWFN]) {
      return q{font/type1};
    }
  }
  if ($data =~ m[^Return\-Path\:]) {
    return q{message/rfc822};
  }
  if ($data =~ m[^Path\:]) {
    return q{message/news};
  }
  if ($data =~ m[^Xref\:]) {
    return q{message/news};
  }
  if ($data =~ m[^From\:]) {
    return q{message/rfc822};
  }
  if ($data =~ m[^Article]) {
    return q{message/news};
  }
  if ($data =~ m[^BABYL]) {
    return q{message/x-gnu-rmail};
  }
  if ($data =~ m[^Received\:]) {
    return q{message/rfc822};
  }
  if ($data =~ m[^MZ]) {
    return q{application/x-ms-dos-executable};
  }
  if (length $data > 2080) {
    $substr = substr($data, 2080, 1024);
    if (defined $substr && $substr =~ m[^Microsoft\ Word\ 6\.0\ Document]) {
      return q{text/vnd.ms-word};
    }
  }
  if (length $data > 2080) {
    $substr = substr($data, 2080, 1024);
    if (defined $substr && $substr =~ m[^Documento\ Microsoft\ Word\ 6]) {
      return q{text/vnd.ms-word};
    }
  }
  if (length $data > 2112) {
    $substr = substr($data, 2112, 1024);
    if (defined $substr && $substr =~ m[^MSWordDoc]) {
      return q{text/vnd.ms-word};
    }
  }
  if (length $data > 0) {
    $substr = substr($data, 0, 4);
    if (pack('H*', '31be0000') eq $substr ) {
      return q{text/vnd.ms-word};
    }
  }
  if ($data =~ m[^PO\^Q\`]) {
    return q{text/vnd.ms-word};
  }
  if (length $data > 2080) {
    $substr = substr($data, 2080, 1024);
    if (defined $substr && $substr =~ m[^Microsoft\ Excel\ 5\.0\ Worksheet]) {
      return q{application/vnd.ms-excel};
    }
  }
  if (length $data > 2114) {
    $substr = substr($data, 2114, 1024);
    if (defined $substr && $substr =~ m[^Biff5]) {
      return q{application/vnd.ms-excel};
    }
  }
  if ($data =~ m[^\x31\xbe\x00\x00]) {
    return q{application/msword};
  }
  if ($data =~ m[^PO\^Q\`]) {
    return q{application/msword};
  }
  if (length $data > 1) {
    $substr = substr($data, 1, 1024);
    if (defined $substr && $substr =~ m[^WPC]) {
      return q{text/vnd.wordperfect};
    }
  }
  if ($data =~ m[^StartFontMetrics]) {
    return q{font/x-sunos-news};
  }
  if ($data =~ m[^StartFont]) {
    return q{font/x-sunos-news};
  }
  if (length $data > 0) {
    $substr = substr($data, 0, 4);
    if (pack('H*', '137A2944') eq $substr ) {
      return q{font/x-sunos-news};
    }
  }
  if (length $data > 0) {
    $substr = substr($data, 0, 4);
    if (pack('H*', '137A2947') eq $substr ) {
      return q{font/x-sunos-news};
    }
  }
  if (length $data > 0) {
    $substr = substr($data, 0, 4);
    if (pack('H*', '137A2950') eq $substr ) {
      return q{font/x-sunos-news};
    }
  }
  if (length $data > 0) {
    $substr = substr($data, 0, 4);
    if (pack('H*', '137A2951') eq $substr ) {
      return q{font/x-sunos-news};
    }
  }
  if (length $data > 8) {
    $substr = substr($data, 8, 4);
    if (pack('H*', '137A2B45') eq $substr ) {
      return q{font/x-sunos-news};
    }
  }
  if (length $data > 8) {
    $substr = substr($data, 8, 4);
    if (pack('H*', '137A2B48') eq $substr ) {
      return q{font/x-sunos-news};
    }
  }
  if (length $data > 0) {
    $substr = substr($data, 0, 2);
    if (pack('H*', '87CD') eq $substr ) {
      return q{OS9/6809 module:};
    }
  }
  if (length $data > 0) {
    $substr = substr($data, 0, 2);
    if (pack('H*', '4AFC') eq $substr ) {
      return q{OS9/68K module:};
    }
  }
  if ($data =~ m[^\%PDF\-]) {
    return q{application/pdf};
  }
  if ($data =~ m[^\%\!]) {
    return q{application/postscript};
  }
  if ($data =~ m[^\004\%\!]) {
    return q{application/postscript};
  }
  if ($data =~ m[^\033E\033]) {
    return q{image/x-pcl-hp};
  }
  if ($data =~ m[^\<\!DOCTYPE\ HTML]) {
    return q{text/html};
  }
  if ($data =~ m[^\<\!doctype\ html]) {
    return q{text/html};
  }
  if ($data =~ m[^\<HEAD]) {
    return q{text/html};
  }
  if ($data =~ m[^\<head]) {
    return q{text/html};
  }
  if ($data =~ m[^\<TITLE]) {
    return q{text/html};
  }
  if ($data =~ m[^\<title]) {
    return q{text/html};
  }
  if ($data =~ m[^\<html]) {
    return q{text/html};
  }
  if ($data =~ m[^\<HTML]) {
    return q{text/html};
  }
  if ($data =~ m[^\<\!SQ\ A\/E\>]) {
    return q{A/E SGML Document binary};
  }
  if ($data =~ m[^\<\!SQ\ STS\>]) {
    return q{A/E SGML binary styles file};
  }
  if ($data =~ m[^\367\203]) {
    return q{font/x-tex};
  }
  if ($data =~ m[^\367\131]) {
    return q{font/x-tex};
  }
  if ($data =~ m[^\367\312]) {
    return q{font/x-tex};
  }
  if (length $data > 2) {
    $substr = substr($data, 2, 1024);
    if (defined $substr && $substr =~ m[^\000\021]) {
      return q{font/x-tex-tfm};
    }
  }
  if (length $data > 2) {
    $substr = substr($data, 2, 1024);
    if (defined $substr && $substr =~ m[^\000\022]) {
      return q{font/x-tex-tfm};
    }
  }
  if (length $data > 1) {
    $substr = substr($data, 1, 1024);
    if (defined $substr && $substr =~ m[^WPC]) {
      return q{(Corel/WP)};
    }
  }
  if ($data =~ m[^BLENDER]) {
    return q{application/x-blender};
  }

  # autogerated code ends

  # fallback case
  {
    return 'application/octet-stream';
  }
}

1;

__END__

=head1 NAME

File::Type - determine file type using magic

=head1 SYNOPSIS

    my $ft = File::Type->new();
    
    # read in data from file to $data, then
    my $type_from_data = $ft->checktype_contents($data);
    
    # alternatively, check file from disk
    my $type_from_file = $ft->checktype_filename($file);

    # convenient method for checking either a file or data
    my $type_1 = $ft->mime_type($file);
    my $type_2 = $ft->mime_type($data);

=head1 DESCRIPTION

File::Type uses magic numbers (typically at the start of a file) to 
determine the MIME type of that file.

File::Type can use either a filename, or file contents, to determine the
type of a file.

=head1 METHODS

=head2 new

Returns a new File::Type object.

=head2 mime_type($argument)

Takes either data or a filename, determines what it is, and passes the
argument through to the relevant method below. If the argument is a 
directory, returns undef.

=head2 checktype_filename($filename)

Opens $filename (if possible; if not, returns undef) and returns the MIME 
type of the file.

=head2 checktype_contents($data)

Matches $data against the magic database criteria and returns the MIME
type of the file.

=head1 TODO

=over 4

* Add additional magic match criteria

=back

=head1 BUGS

None known.

=head2 NOTES

Some magic definitions in the mime-magic file used in the creation of this 
module vary from those in other apps (eg image/x-png not image/png).

=head1 SEE ALSO

L<File::MMagic> and L<File::MimeInfo> perform the same job, but have a number
of problems that led to the creation of this module.

L<File::MMagic> inlines a copy of the magic database, and uses a DATA
filehandle, which causes problems when running under mod_perl.

L<File::MimeInfo> uses an external magic file, and relies on file extensions
rather than magic to determine the mime type.

As a result, File::Type uses a seperate module and script to create the
code at the core of this module, which means that there is no need to
include a magic database at all, and that it is safe to run under mod_perl.

L<File::Type::Builder>, which generates the code at the heart of this module.

=head1 ACKNOWLEDGMENTS

File::Type is built from a mime-magic file from cleancode.org. The original
can be found at L<http://cleancode.org/cgi-bin/viewcvs.cgi/email/mime-magic.mime?rev=1.1.1.1>.

=head1 AUTHOR

Paul Mison <pmison@fotango.com>

=head1 COPYRIGHT 

Copyright 2003-2004 Fotango Ltd.

=head1 LICENSE

Licensed under the same terms as Perl itself. 

=cut
