# ==================================================================
# Gossamer Threads Module Library - http://gossamer-threads.com/
#
#   GT::MIMETypes
#   Author  : Scott Beck
#   CVS Info : 087,071,086,086,085 
#   $Id: MIMETypes.pm,v 1.30 2012/01/26 00:36:19 brewt Exp $
#
# Copyright (c) 2004 Gossamer Threads Inc.  All Rights Reserved.
# ==================================================================
#
# Description:
#   Provides methods to guess mime types.
#

package GT::MIMETypes;
# ===================================================================
use strict;
use vars qw/%CONTENT_EXT %MIME_EXT %MIME_TYPE/;
use GT::AutoLoader;

$COMPILE{guess_type} = __LINE__ . <<'END_OF_SUB';
sub guess_type {
# -------------------------------------------------------------------
# Makes it's best guess based on input. Returns application/octet-stream
# on failure to guess.
# Possible arguments
#{
#   filename => name of the file
#   filepath => full path to the file
#}
# No arguments are required but you will get application/octet-stream
# with no arguments.
#
    shift if @_ > 1 and UNIVERSAL::isa($_[0], __PACKAGE__);
    my $msg = shift;

    if (!ref $msg) {
        %CONTENT_EXT or content_ext();
        if ($msg =~ /\.([^.]+)$/ and exists $CONTENT_EXT{lc $1}) {
            return $CONTENT_EXT{lc $1};
        }
        else {
            return 'application/octet-stream';
        }
    }

# If we have a filename with an extension use that
    if ($msg->{filename} or $msg->{filepath}) {
        my $f;
        if ($msg->{filename}) {
            $f = $msg->{filename};
        }
        else {
            $f = $msg->{filepath};
        }
        %CONTENT_EXT or content_ext();
        if ($f =~ /\.([^.]+)$/ and exists $CONTENT_EXT{lc $1}) {
            return $CONTENT_EXT{lc $1};
        }
    }
    return 'application/octet-stream';
}
END_OF_SUB

$COMPILE{guess_image} = __LINE__ . <<'END_OF_SUB';
sub guess_image {
# -------------------------------------------------------------------
# Makes it's best guess based on input. Returns unknown.gif
# on failure to guess.
# Possible arguments
#{
#   filename => name of the file
#   filepath => full path to the file
#   type     => mime type
#}
# No arguments are required but you will get unknown.gif
# with no arguments.
#
    shift if @_ > 1 and UNIVERSAL::isa($_[0], __PACKAGE__);
    my $msg = shift;
    my $image;

    if (!ref $msg) {
        if ($msg =~ /\.([^.]+)$/) {
            %MIME_EXT or mime_ext();
            return $MIME_EXT{lc $1} || 'unknown.gif';
        }
        else {
            return 'unknown.gif';
        }
    }
    if ($msg->{filepath} and -d $msg->{filepath}) {
        return 'folder.gif';
    }

# If we have a filename with an extension use that
    my $f;
    if ($msg->{filename} or $msg->{filepath}) {
        if ($msg->{filename}) {
            $f = $msg->{filename};
        }
        else {
            $f = $msg->{filepath};
        }
        %MIME_EXT or mime_ext();
        if ($f =~ /\.([^.]+)$/ and exists $MIME_EXT{lc $1}) {
            return $MIME_EXT{lc $1};
        }
    }

# If a content type was passed in see if we know anything about it
    %MIME_TYPE or mime_type();
    if (exists $MIME_TYPE{$msg->{type} || $msg->{mime_type}}) {
        return $MIME_TYPE{$msg->{type} || $msg->{mime_type}};
    }

# No luck so far, resort to other means
    elsif ($msg->{filepath} and -B $msg->{filepath}) {
        return 'binary.gif';
    }
    elsif ($f and lc($f) =~ /readme/) {
        return 'readme.gif';
    }
    elsif ($msg->{filepath} and -T _) {
        return 'txt.gif';
    }

# Oops nothing
    return 'unknown.gif';
}
END_OF_SUB

$COMPILE{mime_ext} = __LINE__ . <<'END_OF_SUB';
sub mime_ext {
# -------------------------------------------------------------------
# Map file extension to image file
#
    %MIME_EXT = (
        css         => 'html.gif',
        htm         => 'html.gif',
        html        => 'html.gif',
        shtm        => 'html.gif',
        shtml       => 'html.gif',
        c           => 'source.gif',
        cc          => 'source.gif',
        'c++'       => 'source.gif',
        cpp         => 'source.gif',
        h           => 'source.gif',
        pl          => 'source.gif',
        pm          => 'source.gif',
        cgi         => 'source.gif',
        txt         => 'txt.gif',
        text        => 'txt.gif',
        diff        => 'txt.gif',
        patch       => 'txt.gif',
        eml         => 'email.gif',
        email       => 'email.gif',
        mime        => 'email.gif',
        java        => 'source.gif',
        el          => 'source.gif',
        pdf         => 'pdf.gif',
        dvi         => 'dvi.gif',
        eds         => 'postscript.gif',
        ai          => 'postscript.gif',
        ps          => 'postscript.gif',
        tex         => 'tex.gif',
        texinfo     => 'tex.gif',
        tar         => 'tar.gif',
        ustar       => 'tar.gif',
        tgz         => 'tgz.gif',
        gz          => 'tgz.gif',
        snd         => 'sound.gif',
        au          => 'sound.gif',
        aifc        => 'sound.gif',
        aif         => 'sound.gif',
        aiff        => 'sound.gif',
        wav         => 'sound.gif',
        mp3         => 'sound.gif',
        ogg         => 'sound.gif',
        bmp         => 'image.gif',
        gif         => 'image.gif',
        ief         => 'image.gif',
        jfif        => 'image.gif',
        'jfif-tbnl' => 'image.gif',
        jpe         => 'image.gif',
        jpg         => 'image.gif',
        jpeg        => 'image.gif',
        tif         => 'image.gif',
        tiff        => 'image.gif',
        fpx         => 'image.gif',
        fpix        => 'image.gif',
        ras         => 'image.gif',
        pnm         => 'image.gif',
        pbn         => 'image.gif',
        pgm         => 'image.gif',
        ppm         => 'image.gif',
        rgb         => 'image.gif',
        xbm         => 'image.gif',
        xpm         => 'image.gif',
        xwd         => 'image.gif',
        png         => 'image.gif',
        mpg         => 'video.gif',
        mpe         => 'video.gif',
        mpeg        => 'video.gif',
        mov         => 'video.gif',
        qt          => 'video.gif',
        avi         => 'video.gif',
        asf         => 'video.gif',
        movie       => 'video.gif',
        mv          => 'video.gif',
        ogv         => 'video.gif',
        mp4         => 'video.gif',
        webm        => 'video.gif',
        wmv         => 'wvideo.gif',
        wma         => 'wvideo.gif',
        sh          => 'shellscript.gif',
        rpm         => 'rpm.gif',
        ttf         => 'font_true.gif',
        doc         => 'doc.gif',
        docx        => 'doc.gif',
        xls         => 'excel.gif',
        xlsx        => 'excel.gif',
        ppt         => 'ppt.gif',
        pptx        => 'ppt.gif',
        zip         => 'zip.gif'
    ) unless keys %MIME_EXT;

    %MIME_EXT;
}
END_OF_SUB

$COMPILE{content_ext} = __LINE__ . <<'END_OF_SUB';
sub content_ext {
# -------------------------------------------------------------------
# To guess the content-type for files by extension
#
    %CONTENT_EXT = (
        doc         => 'application/msword',
        docx        => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
        ppt         => 'application/vnd.ms-powerpoint',
        pptx        => 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
        xls         => 'application/vnd.ms-excel',
        xlsx        => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
        oda         => 'application/oda',
        pdf         => 'application/pdf',
        eds         => 'application/postscript',
        ai          => 'application/postscript',
        ps          => 'application/postscript',
        rtf         => 'application/rtf',
        dvi         => 'application/x-dvi',
        hdf         => 'application/x-hdf',
        latex       => 'application/x-latex',
        nc          => 'application/x-netcdf',
        cdf         => 'application/x-netcdf',
        tex         => 'application/x-tex',
        texinfo     => 'application/x-texinfo',
        texi        => 'application/x-texinfo',
        t           => 'application/x-troff',
        tr          => 'application/x-troff',
        roff        => 'application/x-troff',
        man         => 'application/x-troff-man',
        me          => 'application/x-troff-me',
        ms          => 'application/x-troff-ms',
        src         => 'application/x-wais-source',
        wsrc        => 'application/x-wais-source',
        zip         => 'application/zip',
        bcpio       => 'application/x-bcpio',
        cpio        => 'application/x-cpio',
        gtar        => 'application/x-gtar',
        sh          => 'application/x-shar',
        shar        => 'application/x-shar',
        sv4cpio     => 'application/x-sv4cpio',
        sv4crc      => 'application/x-sv4crc',
        tar         => 'application/x-tar',
        ustar       => 'application/x-ustar',
        snd         => 'audio/basic',
        au          => 'audio/basic',
        aifc        => 'audio/x-aiff',
        aif         => 'audio/x-aiff',
        aiff        => 'audio/x-aiff',
        wav         => 'audio/x-wav',
        mp3         => 'audio/mpeg',
        ogg         => 'application/ogg',
        bmp         => 'image/bmp',
        gif         => 'image/gif',
        ief         => 'image/ief',
        jfif        => 'image/jpeg',
        'jfif-tbnl' => 'image/jpeg',
        jpe         => 'image/jpeg',
        jpg         => 'image/jpeg',
        jpeg        => 'image/jpeg',
        tif         => 'image/tiff',
        tiff        => 'image/tiff',
        fpx         => 'image/vnd.fpx',
        fpix        => 'image/vnd.fpx',
        ras         => 'image/x-cmu-rast',
        pnm         => 'image/x-portable-anymap',
        pbn         => 'image/x-portable-bitmap',
        pgm         => 'image/x-portable-graymap',
        ppm         => 'image/x-portable-pixmap',
        rgb         => 'image/x-rgb',
        xbm         => 'image/x-xbitmap',
        xpm         => 'image/x-xbitmap',
        xwd         => 'image/x-xwindowdump',
        png         => 'image/png',
        css         => 'text/css',
        htm         => 'text/html',
        html        => 'text/html',
        shtml       => 'text/html',
        text        => 'text/plain',
        c           => 'text/plain',
        cc          => 'text/plain',
        'c++'       => 'text/plain',
        h           => 'text/plain',
        pl          => 'text/plain',
        pm          => 'text/plain',
        cgi         => 'text/plain',
        txt         => 'text/plain',
        java        => 'text/plain',
        el          => 'text/plain',
        diff        => 'text/plain',
        patch       => 'text/plain',
        tsv         => 'text/tab-separated-values',
        etx         => 'text/x-setext',
        ogv         => 'video/ogg',
        mp4         => 'video/mp4',
        webm        => 'video/webm',
        mpg         => 'video/mpeg',
        mpe         => 'video/mpeg',
        mpeg        => 'video/mpeg',
        mov         => 'video/quicktime',
        qt          => 'video/quicktime',
        avi         => 'application/x-troff-msvideo',
        asf         => 'video/x-ms-asf',
        movie       => 'video/x-sgi-movie',
        mv          => 'video/x-sgi-movie',
        wmv         => 'video/x-ms-wmv',
        wma         => 'audio/x-ms-wma',
        mime        => 'message/rfc822',
        eml         => 'message/rfc822',
        xml         => 'application/xml'
    ) unless keys %CONTENT_EXT;

    %CONTENT_EXT;
}
END_OF_SUB

$COMPILE{mime_type} = __LINE__ . <<'END_OF_SUB';
sub mime_type {
# -------------------------------------------------------------------
# Map content-type to image file
#
    %MIME_TYPE = (
        'text/css'                      => 'html.gif',
        'text/html'                     => 'html.gif',
        'text/plain'                    => 'txt.gif',
        'application/pdf'               => 'pdf.gif',
        'application/dvi'               => 'dvi.gif',
        'application/postscript'        => 'postscript.gif',
        'application/x-tex'             => 'tex.gif',
        'application/x-texinfo'         => 'tex.gif',
        'application/gtar'              => 'tar.gif',
        'application/x-tar'             => 'tar.gif',
        'application/x-ustar'           => 'tar.gif',
        'application/zip'               => 'zip.gif',
        'application/powerpoint'        => 'ppt.gif',
        'application/mspowerpoint'      => 'ppt.gif',
        'application/vnd.ms-powerpoint' => 'ppt.gif',
        'application/x-mspowerpoint'    => 'ppt.gif',
        'application/vnd.openxmlformats-officedocument.presentationml.presentation' => 'ppt.gif',
        'application/msword'            => 'doc.gif',
        'application/vnd.openxmlformats-officedocument.wordprocessingml.document'   => 'doc.gif',
        'application/excel'             => 'excel.gif',
        'application/msexcel'           => 'excel.gif',
        'application/vnd.ms-excel'      => 'excel.gif',
        'application/x-msexcel'         => 'excel.gif',
        'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',        => 'excel.gif',
        'message/rfc822'                => 'email.gif',
        'message/external-body'         => 'email.gif',
        'multipart/alternative'         => 'email.gif',
        'multipart/appledouble'         => 'email.gif',
        'multipart/digest'              => 'email.gif',
        'multipart/mixed'               => 'email.gif',
        'multipart/voice-message'       => 'sound.gif',
        'audio/basic'                   => 'sound.gif',
        'audio/x-aiff'                  => 'sound.gif',
        'audio/x-wav'                   => 'sound.gif',
        'audio/mpeg'                    => 'sound.gif',
        'application/ogg'               => 'sound.gif',
        'image/gif'                     => 'image.gif',
        'image/ief'                     => 'image.gif',
        'image/jpeg'                    => 'image.gif',
        'image/tiff'                    => 'image.gif',
        'image/vnd.fpx'                 => 'image.gif',
        'image/x-cmu-rast'              => 'image.gif',
        'image/x-portable-anymap'       => 'image.gif',
        'image/x-portable-bitmap'       => 'image.gif',
        'image/x-portable-graymap'      => 'image.gif',
        'image/x-portable-pixmap'       => 'image.gif',
        'image/x-rgb'                   => 'image.gif',
        'image/x-xbitmap'               => 'image.gif',
        'image/x-xwindowdump'           => 'image.gif',
        'image/png'                     => 'image.gif',
        'image/bmp'                     => 'image.gif',
        'video/ogg'                     => 'video.gif',
        'video/mp4'                     => 'video.gif',
        'video/webm'                    => 'video.gif',
        'video/mpeg'                    => 'video.gif',
        'video/quicktime'               => 'video.gif',
        'video/x-ms-asf'                => 'video.gif',
        'application/x-troff-msvideo'   => 'video.gif',
        'video/x-sgi-movie'             => 'video.gif',
        'video/x-ms-wmv'                => 'wvideo.gif',
        'video/x-ms-wma'                => 'wvideo.gif',
        'audio/x-ms-wma'                => 'wvideo.gif',
    ) unless keys %MIME_TYPE;

    %MIME_TYPE;
}
END_OF_SUB

1;

__END__

=head1 NAME

GT::MIMETypes - Methods to guess MIME Types of files.

=head1 SYNOPSIS

    use GT::MIMETypes;

    my $file = '/foo/bar/abc.doc';
    my $mime = GT::MIMETypes::guess_type($file);
    my $img  = GT::MIMETypes::guess_image($file);

=head1 DESCRIPTION

GT::MIMETypes provides two simple methods C<guess_type> and C<guess_image>.
They take either a filename or a hash reference.

C<guess_type> returns the MIME type of the file, and guess_image returns an
image name that represents the file.

=head1 COPYRIGHT

Copyright (c) 2004 Gossamer Threads Inc.  All Rights Reserved.
http://www.gossamer-threads.com/

=head1 VERSION

Revision: $Id: MIMETypes.pm,v 1.30 2012/01/26 00:36:19 brewt Exp $

=cut

