# $Id: wwwmailcap.pl,v 1.1 1994/08/01 13:30:11 fielding Exp $ # --------------------------------------------------------------------------- # wwwmailcap.pl: This library implements routines for parsing a # MIME mailcap file and executing commands based on # a file's MIME Content-type # # This package has been developed by Brooks Cutter . # It is distributed under the Artistic License (included with your Perl # distribution files and with the standard distribution of this package). # # 26 Jul 1994 (BBC): Initial version # 31 Jul 1994 (RTF): Reformatted a bit (and new name) for inclusion in # standard libwww-perl distribution. # # If you have any suggestions, bug reports, fixes, or enhancements, # send them to the libwww-perl mailing list at . # --------------------------------------------------------------------------- # # The MIME mailcap file is defined in the (Work in progress) mailcap draft: # ftp://venera.isi.edu/internet-drafts/draft-borenstein-mailcap-00.ps # ftp://venera.isi.edu/internet-drafts/draft-borenstein-mailcap-00.txt # # This package currently parses mailcap lines, and uses the test field # to determine if the mailcap line should be used. It will save the # 'view' command associated with each MIME Content-type. # # Public/External routines: # # &exists_handler($mime_type,$cmd) - is a mime type handler defined? # Returns 1 if there exists a definition for $mime_type in mailcap # Returns 0 if there is no handler for the specified $mime_type # $mime_type is of the form "type/subtype" like "text/html" # $cmd is optional, and defaults to 'view' if not specified # # &view($mime_type,$fn) - exec view program for $mime_type # $mime_type is of the form "type/subtype" like "text/html" # $fn is the name of the file to pass to the program # # Private/Internal routines: # - You don't need to call (or know about) these routines. # the first time you call &view or &exists_handler, &init # is called and parses the mailcap files.. # # &init - load defaults and search for mailcap files # &load_mailcap_default - load mailcap from internal defaults # &load_mailcap_file - local mailcap from external file # &parse_mailcap(@_) - parse mailcap lines intro internal assoc array # #---------------------------------------------------------------------- # Todo: # This package recognizes the 'view' and 'test' fields, however there # are a number of other fields that should be recognized, and the values # (if any) should be saved and accessible through the library API. # # The following key/value fields or flags are not currently recognized: # # key/value fields: compose, composetyped, edit, print, description, # textualnewlines, x11bitmap, nametemplate # flags: needsterminal, copiousoutput, needsx11 # # Also needs to be done: # - rewrite parse_mailcap so it recognizes lines that end with \ (backslash) # - recognize attribute/variable quoting and pass other needed MIME headers. #---------------------------------------------------------------------- package wwwmailcap; # =========================================================================== # This is Mosaic's default mailcap ... $gl_default_mailcap = <<'EOF'; audio/*; showaudio %s image/xwd; xwud -in %s image/x-xwd; xwud -in %s image/x-xwindowdump; xwud -in %s image/*; xv %s video/mpeg; mpeg_play %s application/postscript; ghostview %s application/x-dvi; xdvi %d message/rfc822; xterm -e metamail %s EOF # =========================================================================== # As defined in draft-bornstein-mailcap-00.txt 5/94 # If Environment variable MAILCAPS isn't set, use the default search path $gl_mailcap_path = $ENV{'MAILCAPS'} || "$ENV{'HOME'}/.mailcap:/etc/mailcap:/usr/etc/mailcap:/usr/local/etc/mailcap"; # =========================================================================== # =========================================================================== # exists_handler(): returns 1 if there is a "handler" for $mime_type (1st arg) # otherwise returns 0 # $cmd indicates the MIME mailcap command to execute # if $cmd isn't specified, it defaults to 'view' # # $ok = &exists_handler($mime_type,$cmd); # # WHERE, # # $ok: 1 if there is a mailcap entry for $mime_type and command $cmd # # $mime_type: A MIME Content-type, like "text/html" # # $cmd: Either null (defaults to 'view') or a MIME command # Currently the only supported command is 'view' # # Example # # $url = 'http://www.host.dom/dir/file.html'; # $response = &www'request('GET',$url,*headers,*content,$timeout); # if ($headers{'content-type'} =~ m!^text/(plain|html)$!i) { # print $content; # display it on the screen # } elsif (&wwwmailcap'exists_handler($headers{'content-type'},'view')) { # local($fn) = "/tmp/file.$$.".time; # open(OUT,">$fn"); print OUT $content; close(OUT); # &wwwmailcap'view($headers{'content-type'},$fn); # } else { # print "Unable to handle MIME type $headers{'content-type'}\n"; # } # sub exists_handler { local($mime_type, $cmd) = @_; &init unless (%gl_mailcap); local($type, $subtype) = split(/\//,$mime_type,2); $cmd = 'view' unless(@_); if (($gl_mailcap{$type,$subtype,$cmd}) || ($gl_mailcap{$type,'*',$cmd}) || ($gl_mailcap{'*','*',$cmd})) { return(1); } return(0); } # =========================================================================== # view(): select the 'view' program for $mime_type and execute with $fn # # &exists_handler($mime_type,$fn) # # WHERE, # # $mime_type: A MIME Content-type, like "text/html" # # $fn: The name of the file to pass to the MIME mailcap 'view' program # # Note: For an example including &view, see &exists_handler # sub view { local($mime_type, $fn) = @_; &init unless (%gl_mailcap); # %s - replace with name of file (otherwise pass data by stdin) # %t - replace with content-type (type/subtype) local($type,$subtype) = split(/\//,$mime_type,2); local($cmd) = $gl_mailcap{$type,$subtype,'view'} || $gl_mailcap{$type,'*','view'} || $gl_mailcap{'*','*','view'}; return unless($cmd); # exit rather than return since already forked return if (fork); if ($cmd =~ /%s/) { $cmd =~ s/%s/$fn/g; if ($cmd =~ /%t/) { $cmd =~ s!%t!$type/$subtype!g; } exec "$cmd ; rm -f $fn"; # calls sh -c .. } else { exec "cat $fn | $cmd ; rm -f $fn"; # calls sh -c .. } exit; } # =========================================================================== # init(): load mailcap files and default mailcap # # &init (no arguments) # sub init { return if (%gl_mailcap); local($_); for (split(/:/,$gl_mailcap_path)) { next unless(-f $_); &load_mailcap_file($_); } &load_mailcap_default; } # =========================================================================== # load_mailcap_default(): load defaults from global var $gl_default_mailcap # # &load_mailcap_default (no arguments) # sub load_mailcap_default { return(-1) unless($gl_default_mailcap); &parse_mailcap(split(/\n/,$gl_default_mailcap)); return(0); } # =========================================================================== # load_mailcap_file(): load mailcap data from external file $fn # # &load_mailcap_file($fn) # # WHERE, # # $fn: Name of mailcap file to load # sub load_mailcap_file { local($fn) = @_; open(IN,$fn) || return(-1); &parse_mailcap(); close(IN); return(0); } # =========================================================================== # parse_mailcap(): parse mailcap lines and store in var $gl_default_mailcap # # &parse_mailcap(@mailcap_lines) # # WHERE, # # @mailcap_lines: One or more mailcap lines. Each element of @mailcap_lines # is a complete entry and has any newlines and/or backslashes # stripped out. # sub parse_mailcap { local($_,$type,$view,@types,$line,$key,$val,$types,$subtype); for (@_) { tr/\x00-\x1f\x7f-\xff//d; @types = split(/\s*;\s*/); $types = shift(@types); ($type, $subtype) = split(/\//,$types,2); $view = shift(@types); for $line (@types) { $line =~ s/^\s+//; $line =~ s/\s+$//; ($key,$val) = split(/\s*=\s*/,$line,2); $key =~ tr/A-Z/a-z/; if (($key eq 'test') && ($val)) { local(@ret) = `sh -c '$val'`; local($ret) = ($? >> 8); # value returned by exec'ing $val.. # if test field returns a non-zero value, ignore the entry next if ($ret); } } if (($view) && (!$gl_mailcap{$type,$subtype,'view'})) { $gl_mailcap{$type,$subtype,'view'} = $view; } } } # =========================================================================== 1;