File Coverage

blib/lib/HTTP/Proxy/Selective.pm
Criterion Covered Total %
statement 92 110 83.6
branch 19 34 55.8
condition 1 2 50.0
subroutine 14 16 87.5
pod 2 2 100.0
total 128 164 78.0


line stmt bran cond sub pod time code
1             package HTTP::Proxy::Selective;
2              
3 6     6   190407 use base qw( HTTP::Proxy::HeaderFilter );
  6         17  
  6         6794  
4 6     6   2332 use strict;
  6         17  
  6         182  
5 6     6   34 use warnings;
  6         16  
  6         185  
6 6     6   30 use Carp ();
  6         12  
  6         102  
7              
8 6     6   8934 use Path::Class::File;
  6         539127  
  6         217  
9 6     6   6766 use File::Slurp;
  6         115853  
  6         502  
10 6     6   66 use File::stat;
  6         11  
  6         56  
11              
12 6     6   19915 use HTTP::Response;
  6         299116  
  6         15332  
13              
14             our $VERSION = '0.004';
15              
16             sub new {
17 1     1 1 750 my ($class, $filter, $debug) = @_;
18 1         10 my $self = $class->SUPER::new();
19 1         16 my $overrides = delete $filter->{mime_overrides};
20 1   50     9 $overrides ||= {};
21 1         3 my %mime_types = (_initial_mime_types(), %$overrides);
22 1         31 $self->{_mime_types} = \%mime_types;
23 1         5 $self->{_myfilter} = _generate_matches_from_config(%$filter);
24 1 50       7 if ($debug) {
25 0         0 $self->{_debug} = 1;
26 0         0 warn("Debugging mode ON\nPaths this proxy will divert:\n");
27 0         0 foreach my $host (keys %{ $self->{_myfilter} }) {
  0         0  
28 0         0 foreach my $array ( @{ $self->{_myfilter}{$host} } ) {
  0         0  
29 0         0 warn($host . $array->[0] . "\n");
30             }
31             }
32 0         0 warn("\n");
33             }
34            
35 1         3 return $self;
36             }
37              
38             sub _generate_matches_from_config {
39 2     2   34 my (%filter) = @_;
40              
41 2         7 foreach my $site (keys %filter) {
42             # Ensure all filter paths have a leading /
43 4         6 foreach my $key (keys %{$filter{$site}}) {
  4         14  
44 10 100       34 next if ($key =~ m|^/|);
45 3         7 my $path = delete $filter{$site}->{$key};
46 3         10 $filter{$site}->{"/$key"} = $path;
47             }
48             # Re-shuffle into an array, with the longest (most specific) paths first.
49 4         10 my @keys = sort { length $b <=> length $a } keys %{$filter{$site}};
  7         21  
  4         17  
50 4         7 my $new_filter = [ map { [$_, $filter{$site}->{$_} ] } @keys ];
  10         35  
51 4         13 $filter{$site} = $new_filter;
52             }
53 2         10 return \%filter;
54             }
55              
56             sub filter {
57 5     5 1 10837 my ( $self, $headers, $message ) = @_;
58 5         36 my $uri = $message->uri;
59 5 100       323 unless ($self->{_myfilter}{$uri->host}) {
60 1         69 return;
61 0 0       0 warn("Did not match host " . $uri->host . " from config.\n") if $self->{_debug};
62             }
63 4         223 my $path = $uri->path;
64 4 50       206 warn("Trying to match request path: $path\n") if $self->{_debug};
65 4         8 foreach my $myfilter (@{ $self->{_myfilter}{$uri->host} }) {
  4         22  
66 5         201 my ($match_path, $on_disk) = @$myfilter;
67 5 100       28 if ($self->_filter_applies($myfilter, $path)) {
68 2         287 warn("Matched $match_path with path $path\n");
69 2         9 my $path_remainder = substr($path, length($match_path));
70 2         17 my $fn = Path::Class::File->new($on_disk, $path_remainder)->stringify;
71 2         498 $fn =~ s/[\\\/]$//;
72 2         49 my $res = $self->_serve_local($headers, $fn);
73 2         209 $self->proxy->response($res);
74 2         208 return;
75             }
76             else {
77 3 50       186 warn("Did not match $match_path with path $path\n") if $self->{_debug};
78             }
79             }
80 2 50       6 warn("No paths matched - sending request to original server.\n") if $self->{_debug};
81 2         6 return;
82             }
83              
84             sub __file_exists {
85 0     0   0 my $fn = shift;
86 0         0 return -f $fn;
87             }
88              
89             sub _serve_local {
90 3     3   26957 my ($self, $req_headers, $fn) = @_;
91 3         23 my $res = HTTP::Response->new();
92 3 100       167 if ( __file_exists($fn) ) {
93 2 50       17 warn("File exists at $fn, serving from local disk\n") if $self->{_debug};
94 2         8 my $stat = stat($fn);
95 2 100       30 if ($req_headers->header('If-Modified-Since') ) {
96 1 50       94 if ( $req_headers->if_modified_since == $stat->mtime ) {
97 1         114 $res->code(304); # Not modified
98 1         10 return $res;
99             }
100             }
101 1         84 $res->code(200);
102 1         13 $res->headers->content_type($self->_mimetype($fn));
103 1         84 $res->headers->content_length( $stat->size );
104 1         98 $res->headers->last_modified( $stat->mtime );
105 1         17669 my $content = read_file($fn, binmode => ':raw');
106 1         12 $res->content($content);
107             }
108             else {
109 1 50       13 warn("File $fn does not exist on local disk\n") if $self->{_debug};
110 1         4 $res->code(404);
111 1         14 $res->headers->content_type('text/html');
112 1         29 $res->content('Not found

Not found at ' . $fn . '

');
113             }
114 2         52 return $res;
115             }
116              
117             sub _filter_applies {
118 4     4   21 my ($self, $myfilter, $path) = @_;
119 4         9 my $match_path = @$myfilter[0];
120 4 100       26 return 1 if (index($path, $match_path) == 0); # Match at the beginning only
121 2         9 return;
122             }
123              
124             sub _mimetype {
125 0     0   0 my ($self, $fn) = @_;
126 0 0       0 if ($fn) {
127 0 0       0 if ($fn =~ /\.([^.]+)$/) {
128 0         0 my $ext = lc($1);
129 0 0       0 if ($self->{_mime_types}->{$ext}) {
130 0         0 return $self->{_mime_types}->{$ext}
131             }
132             }
133             }
134 0         0 return 'application/octet-stream';
135             }
136              
137             sub _initial_mime_types {(
138 1     1   368 ez => "application/andrew-inset",
139             atom => "application/atom",
140             atomcat => "application/atomcat+xml",
141             atomsrv => "application/atomserv+xml",
142             cap => "application/cap",
143             pcap => "application/cap",
144             cu => "application/cu-seeme",
145             tsp => "application/dsptype",
146             spl => "application/futuresplash",
147             hta => "application/hta",
148             jar => "application/java-archive",
149             ser => "application/java-serialized-object",
150             class => "application/java-vm",
151             hqx => "application/mac-binhex40",
152             cpt => "application/mac-compactpro",
153             nb => "application/mathematica",
154             mdb => "application/msaccess",
155             doc => "application/msword",
156             dot => "application/msword",
157             bin => "application/octet-stream",
158             oda => "application/oda",
159             ogg => "application/ogg",
160             ogx => "application/ogg",
161             pdf => "application/pdf",
162             key => "application/pgp-keys",
163             pgp => "application/pgp-signature",
164             prf => "application/pics-rules",
165             ps => "application/postscript",
166             ai => "application/postscript",
167             eps => "application/postscript",
168             rar => "application/rar",
169             rdf => "application/rdf+xml",
170             rss => "application/rss+xml",
171             rtf => "application/rtf",
172             smi => "application/smil",
173             smil => "application/smil",
174             wpd => "application/wordperfect",
175             wp5 => "application/wordperfect5.1",
176             xhtml => "application/xhtml+xml",
177             xht => "application/xhtml+xml",
178             xml => "application/xml",
179             xsl => "application/xml",
180             zip => "application/zip",
181             cdy => "application/vnd.cinderella",
182             kml => "application/vnd.google-earth.kml+xml",
183             kmz => "application/vnd.google-earth.kmz",
184             xul => "application/vnd.mozilla.xul+xml",
185             xls => "application/vnd.ms-excel",
186             xlb => "application/vnd.ms-excel",
187             xlt => "application/vnd.ms-excel",
188             cat => "application/vnd.ms-pki.seccat",
189             stl => "application/vnd.ms-pki.stl",
190             ppt => "application/vnd.ms-powerpoint",
191             pps => "application/vnd.ms-powerpoint",
192             odc => "application/vnd.oasis.opendocument.chart",
193             odb => "application/vnd.oasis.opendocument.databas",
194             odf => "application/vnd.oasis.opendocument.formula",
195             odg => "application/vnd.oasis.opendocument.graphics",
196             otg => "application/vnd.oasis.opendocument.graphics-template",
197             odi => "application/vnd.oasis.opendocument.image",
198             odp => "application/vnd.oasis.opendocument.presentation",
199             otp => "application/vnd.oasis.opendocument.presentation-template",
200             ods => "application/vnd.oasis.opendocument.spreadsheet",
201             ots => "application/vnd.oasis.opendocument.spreadsheet-template",
202             odt => "application/vnd.oasis.opendocument.text",
203             odm => "application/vnd.oasis.opendocument.text-master",
204             ott => "application/vnd.oasis.opendocument.text-template",
205             oth => "application/vnd.oasis.opendocument.text-web",
206             cod => "application/vnd.rim.cod",
207             mmf => "application/vnd.smaf",
208             sdc => "application/vnd.stardivision.calc",
209             sds => "application/vnd.stardivision.chart",
210             sda => "application/vnd.stardivision.draw",
211             sdd => "application/vnd.stardivision.impress",
212             sdf => "application/vnd.stardivision.math",
213             sdw => "application/vnd.stardivision.writer",
214             sgl => "application/vnd.stardivision.writer-global",
215             sxc => "application/vnd.sun.xml.calc",
216             stc => "application/vnd.sun.xml.calc.template",
217             sxd => "application/vnd.sun.xml.draw",
218             std => "application/vnd.sun.xml.draw.template",
219             sxi => "application/vnd.sun.xml.impress",
220             sti => "application/vnd.sun.xml.impress.template",
221             sxm => "application/vnd.sun.xml.math",
222             sxw => "application/vnd.sun.xml.writer",
223             sxg => "application/vnd.sun.xml.writer.global",
224             stw => "application/vnd.sun.xml.writer.template",
225             sis => "application/vnd.symbian.install",
226             vsd => "application/vnd.visio",
227             wbxml => "application/vnd.wap.wbxml",
228             wmlc => "application/vnd.wap.wmlc",
229             wmlsc => "application/vnd.wap.wmlscriptc",
230             wk => "application/x-123",
231             '7z' => "application/x-7z-compressed",
232             abw => "application/x-abiword",
233             dmg => "application/x-apple-diskimage",
234             bcpio => "application/x-bcpio",
235             torrent => "application/x-bittorrent",
236             cab => "application/x-cab",
237             cbr => "application/x-cbr",
238             cbz => "application/x-cbz",
239             cdf => "application/x-cdf",
240             vcd => "application/x-cdlink",
241             pgn => "application/x-chess-pgn",
242             cpio => "application/x-cpio",
243             csh => "application/x-csh",
244             deb => "application/x-debian-package",
245             udeb => "application/x-debian-package",
246             dcr => "application/x-director",
247             dir => "application/x-director",
248             dxr => "application/x-director",
249             dms => "application/x-dms",
250             wad => "application/x-doom",
251             dvi => "application/x-dvi",
252             rhtml => "application/x-httpd-eruby",
253             flac => "application/x-flac",
254             pfa => "application/x-font",
255             pfb => "application/x-font",
256             gsf => "application/x-font",
257             pcf => "application/x-font",
258             'pcf.Z' => "application/x-font",
259             mm => "application/x-freemind",
260             spl => "application/x-futuresplash",
261             gnumeric => "application/x-gnumeric",
262             sgf => "application/x-go-sgf",
263             gcf => "application/x-graphing-calculator",
264             gtar => "application/x-gtar",
265             tgz => "application/x-gtar",
266             taz => "application/x-gtar",
267             hdf => "application/x-hdf",
268             phtml => "application/x-httpd-php",
269             pht => "application/x-httpd-php",
270             php => "application/x-httpd-php",
271             phps => "application/x-httpd-php-source",
272             php3 => "application/x-httpd-php3",
273             php3p => "application/x-httpd-php3-preprocessed",
274             php4 => "application/x-httpd-php4",
275             ica => "application/x-ica",
276             ins => "application/x-internet-signup",
277             isp => "application/x-internet-signup",
278             iii => "application/x-iphone",
279             iso => "application/x-iso9660-image",
280             jnlp => "application/x-java-jnlp-file",
281             js => "application/x-javascript",
282             jmz => "application/x-jmol",
283             chrt => "application/x-kchart",
284             kil => "application/x-killustrator",
285             skp => "application/x-koan",
286             skd => "application/x-koan",
287             skt => "application/x-koan",
288             skm => "application/x-koan",
289             kpr => "application/x-kpresenter",
290             kpt => "application/x-kpresenter",
291             ksp => "application/x-kspread",
292             kwd => "application/x-kword",
293             kwt => "application/x-kword",
294             latex => "application/x-latex",
295             lha => "application/x-lha",
296             lyx => "application/x-lyx",
297             lzh => "application/x-lzh",
298             lzx => "application/x-lzx",
299             frm => "application/x-maker",
300             maker => "application/x-maker",
301             frame => "application/x-maker",
302             fm => "application/x-maker",
303             fb => "application/x-maker",
304             book => "application/x-maker",
305             fbdoc => "application/x-maker",
306             mif => "application/x-mif",
307             wmd => "application/x-ms-wmd",
308             wmz => "application/x-ms-wmz",
309             com => "application/x-msdos-program",
310             exe => "application/x-msdos-program",
311             bat => "application/x-msdos-program",
312             dll => "application/x-msdos-program",
313             msi => "application/x-msi",
314             nc => "application/x-netcdf",
315             pac => "application/x-ns-proxy-autoconfig",
316             nwc => "application/x-nwc",
317             o => "application/x-object",
318             oza => "application/x-oz-application",
319             p7r => "application/x-pkcs7-certreqresp",
320             crl => "application/x-pkcs7-crl",
321             pyc => "application/x-python-code",
322             pyo => "application/x-python-code",
323             qtl => "application/x-quicktimeplayer",
324             rpm => "application/x-redhat-package-manager",
325             sh => "application/x-sh",
326             shar => "application/x-shar",
327             swf => "application/x-shockwave-flash",
328             swfl => "application/x-shockwave-flash",
329             sit => "application/x-stuffit",
330             sitx => "application/x-stuffit",
331             sv4cpio => "application/x-sv4cpio",
332             sv4crc => "application/x-sv4crc",
333             tar => "application/x-tar",
334             tcl => "application/x-tcl",
335             gf => "application/x-tex-gf",
336             pk => "application/x-tex-pk",
337             texinfo => "application/x-texinfo",
338             texi => "application/x-texinfo",
339             bak => "application/x-trash",
340             old => "application/x-trash",
341             sik => "application/x-trash",
342             t => "application/x-troff",
343             tr => "application/x-troff",
344             roff => "application/x-troff",
345             man => "application/x-troff-man",
346             me => "application/x-troff-me",
347             ms => "application/x-troff-ms",
348             ustar => "application/x-ustar",
349             src => "application/x-wais-source",
350             wz => "application/x-wingz",
351             crt => "application/x-x509-ca-cert",
352             xcf => "application/x-xcf",
353             fig => "application/x-xfig",
354             xpi => "application/x-xpinstall",
355             au => "audio/basic",
356             snd => "audio/basic",
357             mid => "audio/midi",
358             midi => "audio/midi",
359             kar => "audio/midi",
360             mpga => "audio/mpeg",
361             mpega => "audio/mpeg",
362             mp2 => "audio/mpeg",
363             mp3 => "audio/mpeg",
364             m4a => "audio/mpeg",
365             m3u => "audio/mpegurl",
366             oga => "audio/ogg",
367             spx => "audio/ogg",
368             sid => "audio/prs.sid",
369             aif => "audio/x-aiff",
370             aiff => "audio/x-aiff",
371             aifc => "audio/x-aiff",
372             gsm => "audio/x-gsm",
373             m3u => "audio/x-mpegurl",
374             wma => "audio/x-ms-wma",
375             wax => "audio/x-ms-wax",
376             ra => "audio/x-pn-realaudio",
377             rm => "audio/x-pn-realaudio",
378             ram => "audio/x-pn-realaudio",
379             ra => "audio/x-realaudio",
380             pls => "audio/x-scpls",
381             sd2 => "audio/x-sd2",
382             wav => "audio/x-wav",
383             alc => "chemical/x-alchemy",
384             cac => "chemical/x-cache",
385             cache => "chemical/x-cache",
386             csf => "chemical/x-cache-csf",
387             cbin => "chemical/x-cactvs-binary",
388             cascii => "chemical/x-cactvs-binary",
389             ctab => "chemical/x-cactvs-binary",
390             cdx => "chemical/x-cdx",
391             cer => "chemical/x-cerius",
392             c3d => "chemical/x-chem3d",
393             chm => "chemical/x-chemdraw",
394             cif => "chemical/x-cif",
395             cmdf => "chemical/x-cmdf",
396             cml => "chemical/x-cml",
397             cpa => "chemical/x-compass",
398             bsd => "chemical/x-crossfire",
399             csml => "chemical/x-csml",
400             csm => "chemical/x-csml",
401             ctx => "chemical/x-ctx",
402             cxf => "chemical/x-cxf",
403             cef => "chemical/x-cxf",
404             emb => "chemical/x-embl-dl-nucleotide",
405             embl => "chemical/x-embl-dl-nucleotide",
406             spc => "chemical/x-galactic-spc",
407             inp => "chemical/x-gamess-input",
408             gam => "chemical/x-gamess-input",
409             gamin => "chemical/x-gamess-input",
410             fch => "chemical/x-gaussian-checkpoint",
411             fchk => "chemical/x-gaussian-checkpoint",
412             cub => "chemical/x-gaussian-cube",
413             gau => "chemical/x-gaussian-input",
414             gjc => "chemical/x-gaussian-input",
415             gjf => "chemical/x-gaussian-input",
416             gal => "chemical/x-gaussian-log",
417             gcg => "chemical/x-gcg8-sequence",
418             gen => "chemical/x-genbank",
419             hin => "chemical/x-hin",
420             istr => "chemical/x-isostar",
421             ist => "chemical/x-isostar",
422             jdx => "chemical/x-jcamp-dx",
423             dx => "chemical/x-jcamp-dx",
424             kin => "chemical/x-kinemage",
425             mcm => "chemical/x-macmolecule",
426             mmd => "chemical/x-macromodel-input",
427             mmod => "chemical/x-macromodel-input",
428             mol => "chemical/x-mdl-molfile",
429             rd => "chemical/x-mdl-rdfile",
430             rxn => "chemical/x-mdl-rxnfile",
431             sd => "chemical/x-mdl-sdfile",
432             sdf => "chemical/x-mdl-sdfile",
433             tgf => "chemical/x-mdl-tgf",
434             mcif => "chemical/x-mmcif",
435             mol2 => "chemical/x-mol2",
436             b => "chemical/x-molconn-Z",
437             gpt => "chemical/x-mopac-graph",
438             mop => "chemical/x-mopac-input",
439             mopcrt => "chemical/x-mopac-input",
440             mpc => "chemical/x-mopac-input",
441             dat => "chemical/x-mopac-input",
442             zmt => "chemical/x-mopac-input",
443             moo => "chemical/x-mopac-out",
444             mvb => "chemical/x-mopac-vib",
445             asn => "chemical/x-ncbi-asn1",
446             prt => "chemical/x-ncbi-asn1-ascii",
447             ent => "chemical/x-ncbi-asn1-ascii",
448             val => "chemical/x-ncbi-asn1-binary",
449             aso => "chemical/x-ncbi-asn1-binary",
450             asn => "chemical/x-ncbi-asn1-spec",
451             pdb => "chemical/x-pdb",
452             ent => "chemical/x-pdb",
453             ros => "chemical/x-rosdal",
454             sw => "chemical/x-swissprot",
455             vms => "chemical/x-vamas-iso14976",
456             vmd => "chemical/x-vmd",
457             xtel => "chemical/x-xtel",
458             xyz => "chemical/x-xyz",
459             gif => "image/gif",
460             ief => "image/ief",
461             jpeg => "image/jpeg",
462             jpg => "image/jpeg",
463             jpe => "image/jpeg",
464             pcx => "image/pcx",
465             png => "image/png",
466             svg => "image/svg+xml",
467             svgz => "image/svg+xml",
468             tiff => "image/tiff",
469             tif => "image/tiff",
470             djvu => "image/vnd.djvu",
471             djv => "image/vnd.djvu",
472             wbmp => "image/vnd.wap.wbmp",
473             ras => "image/x-cmu-raster",
474             cdr => "image/x-coreldraw",
475             pat => "image/x-coreldrawpattern",
476             cdt => "image/x-coreldrawtemplate",
477             cpt => "image/x-corelphotopaint",
478             ico => "image/x-icon",
479             art => "image/x-jg",
480             jng => "image/x-jng",
481             bmp => "image/x-ms-bmp",
482             psd => "image/x-photoshop",
483             pnm => "image/x-portable-anymap",
484             pbm => "image/x-portable-bitmap",
485             pgm => "image/x-portable-graymap",
486             ppm => "image/x-portable-pixmap",
487             rgb => "image/x-rgb",
488             xbm => "image/x-xbitmap",
489             xpm => "image/x-xpixmap",
490             xwd => "image/x-xwindowdump",
491             eml => "message/rfc822",
492             igs => "model/iges",
493             iges => "model/iges",
494             msh => "model/mesh",
495             mesh => "model/mesh",
496             silo => "model/mesh",
497             wrl => "model/vrml",
498             vrml => "model/vrml",
499             ics => "text/calendar",
500             icz => "text/calendar",
501             css => "text/css",
502             csv => "text/csv",
503             323 => "text/h323",
504             html => "text/html",
505             htm => "text/html",
506             shtml => "text/html",
507             uls => "text/iuls",
508             mml => "text/mathml",
509             asc => "text/plain",
510             txt => "text/plain",
511             text => "text/plain",
512             pot => "text/plain",
513             rtx => "text/richtext",
514             sct => "text/scriptlet",
515             wsc => "text/scriptlet",
516             tm => "text/texmacs",
517             ts => "text/texmacs",
518             tsv => "text/tab-separated-values",
519             jad => "text/vnd.sun.j2me.app-descriptor",
520             wml => "text/vnd.wap.wml",
521             wmls => "text/vnd.wap.wmlscript",
522             bib => "text/x-bibtex",
523             boo => "text/x-boo",
524             'h++' => "text/x-c++hdr",
525             hpp => "text/x-c++hdr",
526             hxx => "text/x-c++hdr",
527             hh => "text/x-c++hdr",
528             'c++' => "text/x-c++src",
529             cpp => "text/x-c++src",
530             cxx => "text/x-c++src",
531             cc => "text/x-c++src",
532             h => "text/x-chdr",
533             htc => "text/x-component",
534             csh => "text/x-csh",
535             c => "text/x-csrc",
536             d => "text/x-dsrc",
537             diff => "text/x-diff",
538             patch => "text/x-diff",
539             hs => "text/x-haskell",
540             java => "text/x-java",
541             lhs => "text/x-literate-haskell",
542             moc => "text/x-moc",
543             p => "text/x-pascal",
544             pas => "text/x-pascal",
545             gcd => "text/x-pcs-gcd",
546             pl => "text/x-perl",
547             pm => "text/x-perl",
548             py => "text/x-python",
549             etx => "text/x-setext",
550             sh => "text/x-sh",
551             tcl => "text/x-tcl",
552             tk => "text/x-tcl",
553             tex => "text/x-tex",
554             ltx => "text/x-tex",
555             sty => "text/x-tex",
556             cls => "text/x-tex",
557             vcs => "text/x-vcalendar",
558             vcf => "text/x-vcard",
559             '3gp' => "video/3gpp",
560             dl => "video/dl",
561             dif => "video/dv",
562             dv => "video/dv",
563             fli => "video/fli",
564             gl => "video/gl",
565             mpeg => "video/mpeg",
566             mpg => "video/mpeg",
567             mpe => "video/mpeg",
568             mp4 => "video/mp4",
569             ogv => "video/ogg",
570             qt => "video/quicktime",
571             mov => "video/quicktime",
572             mxu => "video/vnd.mpegurl",
573             lsf => "video/x-la-asf",
574             lsx => "video/x-la-asf",
575             mng => "video/x-mng",
576             asf => "video/x-ms-asf",
577             asx => "video/x-ms-asf",
578             wm => "video/x-ms-wm",
579             wmv => "video/x-ms-wmv",
580             wmx => "video/x-ms-wmx",
581             wvx => "video/x-ms-wvx",
582             avi => "video/x-msvideo",
583             movie => "video/x-sgi-movie",
584             ice => "x-conference/x-cooltalk",
585             sisx => "x-epoc/x-sisx-app",
586             vrm => "x-world/x-vrml",
587             vrml => "x-world/x-vrml",
588             wrl => "x-world/x-vrml",
589             )}
590              
591             1;
592              
593             __END__