Suppress warnings
[lhc/web/wiklou.git] / includes / MimeMagic.php
index 58a9cbe..18fc9e7 100644 (file)
@@ -9,7 +9,7 @@
  * the file mime.types in the includes directory.
  */
 define('MM_WELL_KNOWN_MIME_TYPES',<<<END_STRING
-application/ogg ogg ogm ogv
+application/ogg ogx ogg ogm ogv oga spx
 application/pdf pdf
 application/vnd.oasis.opendocument.chart odc
 application/vnd.oasis.opendocument.chart-template otc
@@ -33,7 +33,7 @@ audio/midi mid midi kar
 audio/mpeg mpga mpa mp2 mp3
 audio/x-aiff aif aiff aifc
 audio/x-wav wav
-audio/ogg ogg
+audio/ogg oga spx ogg
 image/x-bmp bmp
 image/gif gif
 image/jpeg jpeg jpg jpe
@@ -45,7 +45,7 @@ image/x-portable-pixmap ppm
 image/x-xcf xcf
 text/plain txt
 text/html html htm
-video/ogg ogm ogg ogv
+video/ogg ogv ogm ogg
 video/mpeg mpg mpeg
 END_STRING
 );
@@ -80,7 +80,7 @@ audio/x-aiff [AUDIO]
 audio/x-wav [AUDIO]
 audio/mp3 audio/mpeg [AUDIO]
 application/ogg audio/ogg video/ogg [MULTIMEDIA]
-image/x-bmp image/bmp [BITMAP]
+image/x-bmp image/x-ms-bmp image/bmp [BITMAP]
 image/gif [BITMAP]
 image/jpeg [BITMAP]
 image/png [BITMAP]
@@ -102,7 +102,7 @@ END_STRING
 global $wgLoadFileinfoExtension;
 
 if ($wgLoadFileinfoExtension) {
-       if(!extension_loaded('fileinfo')) dl('fileinfo.' . PHP_SHLIB_SUFFIX);
+       wfDl( 'fileinfo' );
 }
 
 /**
@@ -118,19 +118,23 @@ class MimeMagic {
        * Mapping of media types to arrays of mime types.
        * This is used by findMediaType and getMediaType, respectively
        */
-       var $mMediaTypes= NULL;
+       var $mMediaTypes= null;
 
        /** Map of mime type aliases
        */
-       var $mMimeTypeAliases= NULL;
+       var $mMimeTypeAliases= null;
 
        /** map of mime types to file extensions (as a space seprarated list)
        */
-       var $mMimeToExt= NULL;
+       var $mMimeToExt= null;
 
        /** map of file extensions types to mime types (as a space seprarated list)
        */
-       var $mExtToMime= NULL;
+       var $mExtToMime= null;
+
+       /** IEContentAnalyzer instance
+        */
+       var $mIEAnalyzer;
 
        /** The singleton instance
         */
@@ -324,7 +328,7 @@ class MimeMagic {
        */
        function guessTypesForExtension( $ext ) {
                $m = $this->getTypesForExtension( $ext );
-               if ( is_null( $m ) ) return NULL;
+               if ( is_null( $m ) ) return null;
 
                $m = trim( $m );
                $m = preg_replace( '/\s.*$/', '', $m );
@@ -341,7 +345,7 @@ class MimeMagic {
                $ext = $this->getExtensionsForType( $mime );
 
                if ( !$ext ) {
-                       return NULL;  //unknown
+                       return null;  //unknown
                }
 
                $ext = explode( ' ', $ext );
@@ -392,7 +396,7 @@ class MimeMagic {
                        'xbm',
 
                        // Formats we recognize magic numbers for
-                       'djvu', 'ogg', 'ogv', 'mid', 'pdf', 'wmf', 'xcf',
+                       'djvu', 'ogx', 'ogg', 'ogv', 'oga', 'spx', 'mid', 'pdf', 'wmf', 'xcf',
 
                        // XML formats we sure hope we recognize reliably
                        'svg',
@@ -405,9 +409,9 @@ class MimeMagic {
        * but applies additional checks to determine some well known file formats that may be missed
        * or misinterpreter by the default mime detection (namely xml based formats like XHTML or SVG).
        *
-       * @param string $file The file to check
-       * @param mixed $ext The file extension, or true to extract it from the filename.
-       *                   Set it to false to ignore the extension.
+       * @param $file String: the file to check
+       * @param $ext Mixed: the file extension, or true to extract it from the filename.
+       *             Set it to false to ignore the extension.
        *
        * @return string the mime type of $file
        */
@@ -465,16 +469,18 @@ class MimeMagic {
                }
 
                /*
-                * look for PHP
-                * Check for this before HTML/XML...
-                * Warning: this is a heuristic, and won't match a file with a lot of non-PHP before.
-                * It will also match text files which could be PHP. :)
+                * Look for PHP.  Check for this before HTML/XML...  Warning: this is a
+                * heuristic, and won't match a file with a lot of non-PHP before.  It
+                * will also match text files which could be PHP. :)
+                *
+                * FIXME: For this reason, the check is probably useless -- an attacker
+                * could almost certainly just pad the file with a lot of nonsense to
+                * circumvent the check in any case where it would be a security
+                * problem.  On the other hand, it causes harmful false positives (bug
+                * 16583).  The heuristic has been cut down to exclude three-character
+                * strings like "<? ", but should it be axed completely?
                 */
                if( ( strpos( $head, '<?php' ) !== false ) ||
-                   ( strpos( $head, '<? ' ) !== false ) ||
-                   ( strpos( $head, "<?\n" ) !== false ) ||
-                   ( strpos( $head, "<?\t" ) !== false ) ||
-                   ( strpos( $head, "<?=" ) !== false ) ||
 
                    ( strpos( $head, "<\x00?\x00p\x00h\x00p" ) !== false ) ||
                    ( strpos( $head, "<\x00?\x00 " ) !== false ) ||
@@ -502,7 +508,7 @@ class MimeMagic {
                /*
                 * look for shell scripts
                 */
-               $script_type = NULL;
+               $script_type = null;
 
                # detect by shebang
                if ( substr( $head, 0, 2) == "#!" ) {
@@ -542,7 +548,7 @@ class MimeMagic {
                // Check for ZIP (before getimagesize)
                if ( strpos( $tail, "PK\x05\x06" ) !== false ) {
                        wfDebug( __METHOD__.": ZIP header present at end of $file\n" );
-                       return $this->detectZipType( $head );
+                       return $this->detectZipType( $head, $ext );
                }
 
                wfSuppressWarnings();
@@ -570,41 +576,63 @@ class MimeMagic {
         * header data.  Currently works for OpenDocument types...
         * If can't tell, returns 'application/zip'.
         *
-        * @param string $header Some reasonably-sized chunk of file header
+        * @param $header String: some reasonably-sized chunk of file header
+        * @param $ext Mixed: the file extension, or true to extract it from the filename.
+        *             Set it to false to ignore the extension.
+        *
         * @return string
         */
-       function detectZipType( $header ) {
+       function detectZipType( $header, $ext = false ) {
+               $mime = 'application/zip';
                $opendocTypes = array(
-                       'chart',
                        'chart-template',
-                       'formula',
+                       'chart',
                        'formula-template',
-                       'graphics',
+                       'formula',
                        'graphics-template',
-                       'image',
+                       'graphics',
                        'image-template',
-                       'presentation',
+                       'image',
                        'presentation-template',
-                       'spreadsheet',
+                       'presentation',
                        'spreadsheet-template',
-                       'text',
+                       'spreadsheet',
                        'text-template',
                        'text-master',
-                       'text-web' );
+                       'text-web',
+                       'text' );
 
                // http://lists.oasis-open.org/archives/office/200505/msg00006.html
                $types = '(?:' . implode( '|', $opendocTypes ) . ')';
                $opendocRegex = "/^mimetype(application\/vnd\.oasis\.opendocument\.$types)/";
                wfDebug( __METHOD__.": $opendocRegex\n" );
+
+               $openxmlRegex = "/^\[Content_Types\].xml/";
                
                if( preg_match( $opendocRegex, substr( $header, 30 ), $matches ) ) {
                        $mime = $matches[1];
                        wfDebug( __METHOD__.": detected $mime from ZIP archive\n" );
-                       return $mime;
+               } elseif( preg_match( $openxmlRegex, substr( $header, 30 ), $matches ) ) {
+                       $mime = "application/x-opc+zip";
+                       if( $ext !== true && $ext !== false ) {
+                               /** This is the mode used by getPropsFromPath
+                               * These mime's are stored in the database, where we don't really want
+                               * x-opc+zip, because we use it only for internal purposes
+                               */
+                               if( $this->isMatchingExtension( $ext, $mime) ) {
+                                       /* A known file extension for an OPC file,
+                                       * find the proper mime type for that file extension */
+                                       $mime = $this->guessTypesForExtension( $ext );
+                               } else {
+                                       $mime = 'application/zip';
+                               }
+                               
+                       }
+                       wfDebug( __METHOD__.": detected an Open Packaging Conventions archive: $mime\n" );
                } else {
                        wfDebug( __METHOD__.": unable to identify type of ZIP archive\n" );
-                       return 'application/zip';
                }
+               return $mime;
        }
 
        /** Internal mime type detection, please use guessMimeType() for application code instead.
@@ -615,9 +643,9 @@ class MimeMagic {
        * If the mime type is still unknown, getimagesize is used to detect the mime type if the file is an image.
        * If no mime type can be determined, this function returns "unknown/unknown".
        *
-       * @param string $file The file to check
-       * @param mixed $ext The file extension, or true to extract it from the filename.
-       *                   Set it to false to ignore the extension.
+       * @param $file String: the file to check
+       * @param $ext Mixed: the file extension, or true to extract it from the filename.
+       *             Set it to false to ignore the extension.
        *
        * @return string the mime type of $file
        * @access private
@@ -625,7 +653,7 @@ class MimeMagic {
        function detectMimeType( $file, $ext = true ) {
                global $wgMimeDetectorCommand;
 
-               $m = NULL;
+               $m = null;
                if ( $wgMimeDetectorCommand ) {
                        $fn = wfEscapeShellArg( $file );
                        $m = `$wgMimeDetectorCommand $fn`;
@@ -672,7 +700,7 @@ class MimeMagic {
                        $m = strtolower( $m );
 
                        if ( strpos( $m, 'unknown' ) !== false ) {
-                               $m = NULL;
+                               $m = null;
                        } else {
                                wfDebug( __METHOD__.": magic mime type of $file: $m\n" );
                                return $m;
@@ -711,13 +739,13 @@ class MimeMagic {
        * @todo analyse file if need be
        * @todo look at multiple extension, separately and together.
        *
-       * @param string $path full path to the image file, in case we have to look at the contents
+       * @param $path String: full path to the image file, in case we have to look at the contents
        *        (if null, only the mime type is used to determine the media type code).
-       * @param string $mime mime type. If null it will be guessed using guessMimeType.
+       * @param $mime String: mime type. If null it will be guessed using guessMimeType.
        *
        * @return (int?string?) a value to be used with the MEDIATYPE_xxx constants.
        */
-       function getMediaType( $path = NULL, $mime = NULL ) {
+       function getMediaType( $path = null, $mime = null ) {
                if( !$mime && !$path ) return MEDIATYPE_UNKNOWN;
 
                # If mime type is unknown, guess it
@@ -750,7 +778,7 @@ class MimeMagic {
                }
 
                # Check for entry for file extension
-               $e = NULL;
+               $e = null;
                if ( $path ) {
                        $i = strrpos( $path, '.' );
                        $e = strtolower( $i ? substr( $path, $i + 1 ) : '' );
@@ -810,411 +838,25 @@ class MimeMagic {
        }
 
        /**
-        * Get the MIME type from ieMimeFromData(), but convert the result from IE's 
-        * idiosyncratic private types into something MediaWiki will understand.
+        * Get the MIME types that various versions of Internet Explorer would 
+        * detect from a chunk of the content.
         *
-        * @param string $fileName The file name (unused at present)
-        * @param string $chunk The first 256 bytes of the file
-        * @param string $proposed The MIME type proposed by the server
+        * @param $fileName String: the file name (unused at present)
+        * @param $chunk String: the first 256 bytes of the file
+        * @param $proposed String: the MIME type proposed by the server
         */
-       public function getIEMimeType( $fileName, $chunk, $proposed ) {
-               static $table = array(
-                       'image/pjpeg' => 'image/jpeg',
-                       'image/x-png' => 'image/png',
-                       'image/x-wmf' => 'application/x-msmetafile',
-                       'image/bmp' => 'image/x-bmp',
-                       'application/x-zip-compressed' => 'application/zip',
-                       'application/x-compressed' => 'application/x-compress',
-                       'application/x-gzip-compressed' => 'application/x-gzip',
-                       'audio/mid' => 'audio/midi',
-               );
-
-               $type = $this->ieMimeFromData( $fileName, $chunk, $proposed );
-               if ( isset( $table[$type] ) ) {
-                       $type = $table[$type];
-               }
-               return $type;
+       public function getIEMimeTypes( $fileName, $chunk, $proposed ) {
+               $ca = $this->getIEContentAnalyzer();
+               return $ca->getRealMimesFromData( $fileName, $chunk, $proposed );
        }
 
        /**
-        * Do a MIME type check similar to IE's FindMimeFromData(). This is used to 
-        * ensure that a file won't be detected as a blacklisted type such as text/html,
-        * thus opening up an XSS vulnerability. 
-        *
-        * Based on a disassembly of urlmon.dll from IE 7.
-        *
-        * @param string $fileName The file name (unused at present)
-        * @param string $chunk The first 256 bytes of the file
-        * @param string $proposed The MIME type proposed by the server
+        * Get a cached instance of IEContentAnalyzer
         */
-       public function ieMimeFromData( $fileName, $chunk, $proposed ) {
-               // IE puts a null character at byte 255 (the 256th byte)
-               $chunk = substr( $chunk, 0, 255 );
-               
-               $types = array(
-                       'ambiguous' /*1*/ => array(
-                               'text/plain', 
-                               'application/octet-stream', 
-                               'application/x-netcdf', // [sic]
-                               'unknown/unknown', // for MediaWiki
-                       ),
-                       'text' /*3*/ => array(
-                               'text/richtext', 'image/x-bitmap', 'application/postscript', 'application/base64',
-                               'application/macbinhex40', 'application/x-cdf', 'text/scriptlet', 'text/xml', 
-                               'application/xml',
-                               
-                       ),
-                       'binary' /*4*/ => array(
-                               'application/pdf', 'audio/x-aiff', 'audio/basic', 'audio/wav', 'image/gif',
-                               'image/pjpeg', 'image/jpeg', 'image/tiff', 'image/x-png', 'image/png', 'image/bmp', 
-                               'image/x-jg', 'image/x-art', 'image/x-emf', 'image/x-wmf', 'video/avi', 
-                               'video/x-msvideo', 'video/mpeg', 'application/x-compressed',
-                               'application/x-zip-compressed', 'application/x-gzip-compressed', 'application/java',
-                               'application/x-msdownload'
-                       ),
-                       'html' /*5*/ => array( 'text/html' ),
-               );
-
-               if ( in_array( $proposed, $types['text'] ) ) {
-                       return $proposedType;
-               }
-               if ( !in_array( $proposed, $types['binary'] )
-                       && !in_array( $proposed, $types['ambiguous'] ) 
-                       && !in_array( $proposed, $types['html'] ) )
-               {
-                       // Unknown
-                       return $proposed;
-               }
-
-               // CContentAnalyzer::SampleData
-               $found = array();
-               $numControl = 0;
-               $numHigh = 0;
-               $numLow = 0;
-               $numLF = 0;
-               $numCR = 0;
-               $numFF = 0;
-               $htmlTags = array(
-                       'html',
-                       'head',
-                       'title',
-                       'body',
-                       'script',
-                       'a href',
-                       'pre',
-                       'img',
-                       'plaintext',
-                       'table'
-               );
-               $rdfUrl = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#';
-               $rdfPurl = 'http://purl.org/rss/1.0/';
-               $xbmMagic1 = '#define';
-               $xbmMagic2 = '_width';
-               $xbmMagic3 = '_bits';
-               $binhexMagic = 'converted with BinHex';
-
-               for ( $offset = 0; $offset < strlen( $chunk ); $offset++ ) {
-                       $curChar = $chunk[$offset];
-                       if ( $curChar == "\x0a" ) {
-                               $numLF++;
-                               continue;
-                       } elseif ( $curChar == "\x0d" ) {
-                               $numCR++;
-                               continue;
-                       } elseif ( $curChar == "\x0c" ) {
-                               $numFF++;
-                               continue;
-                       } elseif ( $curChar == "\t" ) {
-                               $numLow++;
-                               continue;
-                       } elseif ( ord( $curChar ) < 32 ) {
-                               $numControl++;
-                               continue;
-                       } elseif ( ord( $curChar ) >= 128 ) {
-                               $numHigh++;
-                               continue;
-                       }
-
-                       $numLow++;
-                       if ( $curChar == '<' ) {
-                               // XML
-                               $remainder = substr( $chunk, $offset + 1 );
-                               if ( !strncasecmp( $remainder, '?XML', 4 ) ) {
-                                       $nextChar = substr( $chunk, $offset + 5, 1 );
-                                       if ( $nextChar == ':' || $nextChar == ' ' || $nextChar == "\t" ) {
-                                               $found['xml'] = true;
-                                       }
-                               }
-                               // Scriptlet (JSP)
-                               if ( !strncasecmp( $remainder, 'SCRIPTLET', 9 ) ) {
-                                       $found['scriptlet'] = true;
-                                       break;
-                               }
-                               // HTML
-                               foreach ( $htmlTags as $tag ) {
-                                       if ( !strncasecmp( $remainder, $tag, strlen( $tag ) ) ) {
-                                               $found['html'] = true;
-                                       }
-                               }
-                               // Skip broken check for additional tags (HR etc.)
-
-                               // RSS
-                               if ( !strncasecmp( $remainder, 'RSS', 3 ) ) {
-                                       $found['rss'] = true;
-                                       break; // return from SampleData
-                               }
-                               if ( !strncasecmp( $remainder, 'rdf:RDF', 7 ) ) {
-                                       $found['rdf-tag'] = true;
-                                       // no break
-                               }
-                               if ( !strncasecmp( $remainder, 'FEED', 4 ) ) {
-                                       $found['feed'] = true;
-                                       break;
-                               }
-                               continue;
-                       }
-                       // Skip broken check for -->
-
-                       // RSS URL checks
-                       // For some reason both URLs must appear before a break is triggered
-                       $remainder = substr( $chunk, $offset );
-                       if ( !strncasecmp( $remainder, $rdfUrl, strlen( $rdfUrl ) ) ) {
-                               $found['rdf-url'] = true;
-                               if ( isset( $found['rdf-tag'] )
-                                       && isset( $found['rdf-purl'] ) ) // [sic]
-                               {
-                                       break;
-                               }
-                               continue;
-                       }
-
-                       if ( !strncasecmp( $remainder, $rdfPurl, strlen( $rdfPurl ) ) ) {
-                               if ( isset( $found['rdf-tag'] ) 
-                                       && isset( $found['rdf-url'] ) ) // [sic]
-                               {
-                                       break;
-                               }
-                               continue;
-                       }
-
-                       // XBM checks
-                       if ( !strncasecmp( $remainder, $xbmMagic1, strlen( $xbmMagic1 ) ) ) {
-                               $found['xbm1'] = true;
-                               continue;
-                       }
-                       if ( $curChar == '_' ) {
-                               if ( isset( $found['xbm2'] ) ) {
-                                       if ( !strncasecmp( $remainder, $xbmMagic3, strlen( $xbmMagic3 ) ) ) {
-                                               $found['xbm'] = true;
-                                               break;
-                                       }
-                               } elseif ( isset( $found['xbm1'] ) ) {
-                                       if ( !strncasecmp( $remainder, $xbmMagic2, strlen( $xbmMagic2 ) ) ) {
-                                               $found['xbm2'] = true;
-                                       }
-                               }
-                       }
-
-                       // BinHex
-                       if ( !strncasecmp( $remainder, $binhexMagic, strlen( $binhexMagic ) ) ) {
-                               $found['binhex'] = true;
-                       }
-               } // end main loop
-               
-               // CContentAnalyzer::FindMimeFromData
-               
-               // IE does the Check*Headers() calls last, and instead does the following image 
-               // type checksby directly looking for the magic numbers. What I do here should 
-               // have the same effect since the magic number checks are identical in both cases.
-               $binaryType = $this->ieCheckBinaryHeaders( $chunk );
-               $textType = $this->ieCheckTextHeaders( $chunk );
-
-               if ( $proposed == 'text/html' && isset( $found['html'] ) ) {
-                       return 'text/html';
-               }
-               if ( $proposed == 'image/gif' && $binaryType == 'image/gif' ) {
-                       return 'image/gif';
-               }
-               if ( ( $proposed == 'image/pjpeg' || $proposed == 'image/jpeg' )
-                       && $binaryType == 'image/pjpeg' ) 
-               {
-                       return $proposed;
-               }
-               if ( ( $proposed == 'image/x-png' || $proposed == 'image/png' )
-                       && $binaryType == 'image/x-png' )
-               {
-                       return $proposed;
-               }
-
-               if ( isset( $found['rss'] ) ) {
-                       return 'application/rss+xml';
-               }
-               if ( isset( $found['rdf-tag'] )
-                       && isset( $found['rdf-url'] )
-                       && isset( $found['rdf-purl'] ) )
-               {
-                       return 'application/rss+xml';
-               }
-               // Skip apparently unimplemented atom flag
-               if ( isset( $found['xml'] ) ) {
-                       // Skip check for proposed MIME type
-                       // IE may continue on here to further checks if a feature is enabled
-                       // and if the server proposes something other than text/html or text/xml
-                       return 'text/xml';
-               }
-               if ( isset( $found['html'] ) ) {
-                       // Skip complex XML-related check
-                       return 'text/html';
-               }
-               if ( isset( $found['xbm'] ) ) {
-                       return 'image/x-bitmap';
-               }
-               if ( isset( $found['binhex'] ) ) {
-                       return 'application/macbinhex40';
-               }
-               if ( isset( $found['scriptlet'] ) ) {
-                       // Skip complex HTML-related check
-                       return 'text/scriptlet';
-               }
-
-               // Freaky heuristics to determine check order
-               // Probably doesn't matter since the checks appear to be orthogonal
-               // The heuristic is of course broken for non-ASCII text
-               if ( $numControl != 0 && ( $numFF + $numLow ) < ( $numControl + $numHigh ) * 16 ) {
-                       $kindOfBinary = true;
-                       $type = $binaryType ? $binaryType : $textType;
-               } else {
-                       $kindOfBinary = false;
-                       $type = $textType ? $textType : $binaryType;
-               }
-               if ( $type !== false ) {
-                       return $type;
-               }
-
-               // FormatAgreesWithData()
-               if ( in_array( $proposed, $types['text'] ) && !$kindOfBinary ) {
-                       return $proposed;
-               }
-               if ( in_array( $proposed, $types['binary'] ) && $kindOfBinary ) {
-                       return $proposed;
-               }
-               if ( in_array( $proposed, $types['html'] ) ) {
-                       return $proposed;
-               }
-
-               // TODO: extension checks
-               return $proposed;
-       }
-
-       private function ieCheckTextHeaders( $chunk ) {
-               $chunk2 = substr( $chunk, 0, 2 );
-               $chunk4 = substr( $chunk, 0, 4 );
-               $chunk5 = substr( $chunk, 0, 5 );
-               if ( $chunk4 == '%PDF' ) {
-                       return 'application/pdf';
-               }
-               if ( $chunk2 == '%!' ) {
-                       return 'application/postscript';
+       protected function getIEContentAnalyzer() {
+               if ( is_null( $this->mIEAnalyzer ) ) {
+                       $this->mIEAnalyzer = new IEContentAnalyzer;
                }
-               if ( $chunk5 == '{\\rtf' ) {
-                       return 'text/richtext';
-               }
-               if ( $chunk5 == 'begin' ) {
-                       return 'application/base64';
-               }
-               return false;
+               return $this->mIEAnalyzer;
        }
-
-       private function ieCheckBinaryHeaders( $chunk ) {
-               $chunk2 = substr( $chunk, 0, 2 );
-               $chunk3 = substr( $chunk, 0, 3 );
-               $chunk4 = substr( $chunk, 0, 4 );
-               $chunk5 = substr( $chunk, 0, 5 );
-               $chunk8 = substr( $chunk, 0, 8 );
-               if ( $chunk5 == 'GIF87' || $chunk5 == 'GIF89' ) {
-                       return 'image/gif';
-               }
-               if ( $chunk2 == "\xff\xd8" ) {
-                       return 'image/pjpeg'; // actually plain JPEG but this is what IE returns
-               }
-               if ( $chunk2 == 'BM' 
-                       && substr( $chunk, 6, 2 ) == "\000\000"
-                       && substr( $chunk, 8, 2 ) != "\000\000" )
-               {
-                       return 'image/bmp'; // another non-standard MIME
-               }
-               if ( $chunk4 == 'RIFF' 
-                       && substr( $chunk, 8, 4 ) == 'WAVE' )
-               {
-                       return 'audio/wav';
-               }
-               // These were integer literals in IE
-               // Perhaps the author was not sure what the target endianness was
-               if ( $chunk4 == ".sd\000"
-                       || $chunk4 == ".snd"
-                       || $chunk4 == "\000ds."
-                       || $chunk4 == "dns." )
-               {
-                       return 'audio/basic';
-               }
-               if ( $chunk3 == "MM\000" ) {
-                       return 'image/tiff';
-               }
-               if ( $chunk2 == 'MZ' ) {
-                       return 'application/x-msdownload';
-               }
-               if ( $chunk8 == "\x89PNG\x0d\x0a\x1a\x0a" ) {
-                       return 'image/x-png'; // [sic]
-               }
-               if ( strlen( $chunk ) >= 5 ) {
-                       $byte2 = ord( $chunk[2] );
-                       $byte4 = ord( $chunk[4] );
-                       if ( $byte2 >= 3 && $byte2 <= 31 && $byte4 == 0 && $chunk2 == 'JG' ) {
-                               return 'image/x-jg';
-                       }
-               }
-               // More endian confusion
-               if ( $chunk4 == 'MROF' ) {
-                       return 'audio/x-aiff';
-               }
-               $chunk4_8 = substr( $chunk, 8, 4 );
-               if ( $chunk4 == 'FORM' && ( $chunk4_8 == 'AIFF' || $chunk4_8 == 'AIFC' ) ) {
-                       return 'audio/x-aiff';
-               }
-               if ( $chunk4 == 'RIFF' && $chunk4_8 == 'AVI ' ) {
-                       return 'video/avi';
-               }
-               if ( $chunk4 == "\x00\x00\x01\xb3" || $chunk4 == "\x00\x00\x01\xba" ) {
-                       return 'video/mpeg';
-               }
-               if ( $chunk4 == "\001\000\000\000"
-                       && substr( $chunk, 40, 4 ) == ' EMF' )
-               {
-                       return 'image/x-emf';
-               }
-               if ( $chunk4 == "\xd7\xcd\xc6\x9a" ) {
-                       return 'image/x-wmf';
-               }
-               if ( $chunk4 == "\xca\xfe\xba\xbe" ) {
-                       return 'application/java';
-               }
-               if ( $chunk2 == 'PK' ) {
-                       return 'application/x-zip-compressed';
-               }
-               if ( $chunk2 == "\x1f\x9d" ) {
-                       return 'application/x-compressed';
-               }
-               if ( $chunk2 == "\x1f\x8b" ) {
-                       return 'application/x-gzip-compressed';
-               }
-               // Skip redundant check for ZIP
-               if ( $chunk5 == "MThd\000" ) {
-                       return 'audio/mid';
-               }
-               if ( $chunk4 == '%PDF' ) {
-                       return 'application/pdf';
-               }
-               return false;
-       }
-       
 }