reimplement r73652 having actually read coding conventions this time
[lhc/web/wiklou.git] / includes / MimeMagic.php
index 8c939e0..cde30bc 100644 (file)
@@ -1,9 +1,12 @@
 <?php
-/** Module defining helper functions for detecting and dealing with mime types.
+/**
+ * Module defining helper functions for detecting and dealing with mime types.
  *
+ * @file
  */
 
- /** Defines a set of well known mime types
+/**
+ * Defines a set of well known mime types
  * This is used as a fallback to mime.types files.
  * An extensive list of well known mime types is provided by
  * the file mime.types in the includes directory.
@@ -50,7 +53,8 @@ video/mpeg mpg mpeg
 END_STRING
 );
 
- /** Defines a set of well known mime info entries
+/**
+ * Defines a set of well known mime info entries
  * This is used as a fallback to mime.info files.
  * An extensive list of well known mime types is provided by
  * the file mime.info in the includes directory.
@@ -405,18 +409,73 @@ class MimeMagic {
                return in_array( strtolower( $extension ), $types );
        }
 
+       /** improves a mime type using the file extension. Some file formats are very generic,
+       * so their mime type is not very meaningful. A more useful mime type can be derived 
+       * by looking at the file extension. Typically, this method would be called on the 
+       * result of guessMimeType().
+       * 
+       * Currently, this method does the following:
+       *
+       * If $mime is "unknown/unknown" and isRecognizableExtension( $ext ) returns false,
+       * return the result of guessTypesForExtension($ext). 
+       *
+       * If $mime is "application/x-opc+zip" and isMatchingExtension( $ext, $mime )
+       * gives true, return the result of guessTypesForExtension($ext). 
+       *
+       * @param $mime String: the mime type, typically guessed from a file's content.
+       * @param $ext String: the file extension, as taken from the file name
+       *
+       * @return string the mime type
+       */
+       function improveTypeFromExtension( $mime, $ext ) {
+               if ( $mime === "unknown/unknown" ) {
+                       if( $this->isRecognizableExtension( $ext ) ) {
+                               wfDebug( __METHOD__. ": refusing to guess mime type for .$ext file, " .
+                                       "we should have recognized it\n" );
+                       } else {
+                               /* Not something we can detect, so simply 
+                               * trust the file extension */
+                               $mime = $this->guessTypesForExtension( $ext );
+                       }
+               }
+               else if ( $mime === "application/x-opc+zip" ) {
+                       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 {
+                               wfDebug( __METHOD__. ": refusing to guess better type for $mime file, " . 
+                                       ".$ext is not a known OPC extension.\n" );
+                               $mime = "application/zip";
+                       }
+               }
+
+               if ( isset( $this->mMimeTypeAliases[$mime] ) ) {
+                       $mime = $this->mMimeTypeAliases[$mime];
+               }
+
+               wfDebug(__METHOD__.": improved mime type for .$ext: $mime\n");
+               return $mime;
+       }
 
        /** mime type detection. This uses detectMimeType to detect the mime type of the file,
        * 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).
+       * or misinterpreter by the default mime detection (namely XML based formats like XHTML or SVG,
+       * as well as ZIP based formats like OPC/ODF files).
        *
        * @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.
+       * @param $ext Mixed: the file extension, or true (default) to extract it from the filename.
+       *             Set it to false to ignore the extension. DEPRECATED! Set to false, use 
+       *             improveTypeFromExtension($mime, $ext) later to improve mime type.
        *
        * @return string the mime type of $file
        */
        function guessMimeType( $file, $ext = true ) {
+               if( $ext ) { # TODO: make $ext default to false. Or better, remove it.
+                       wfDebug( __METHOD__.": WARNING: use of the \$ext parameter is deprecated. " .
+                               "Use improveTypeFromExtension(\$mime, \$ext) instead.\n" );
+               }
+
                $mime = $this->doGuessMimeType( $file, $ext );
 
                if( !$mime ) {
@@ -428,11 +487,11 @@ class MimeMagic {
                        $mime = $this->mMimeTypeAliases[$mime];
                }
 
-               wfDebug(__METHOD__.": final mime type of $file: $mime\n");
+               wfDebug(__METHOD__.": guessed mime type of $file: $mime\n");
                return $mime;
        }
 
-       function doGuessMimeType( $file, $ext = true ) {
+       private function doGuessMimeType( $file, $ext ) { # TODO: remove $ext param
                // Read a chunk of the file
                wfSuppressWarnings();
                $f = fopen( $file, "rt" );
@@ -443,6 +502,8 @@ class MimeMagic {
                $tail = fread( $f, 65558 ); // 65558 = maximum size of a zip EOCDR
                fclose( $f );
 
+               wfDebug( __METHOD__ . ": analyzing head and tail of $file for magic numbers.\n" );
+
                // Hardcode a few magic number checks...
                $headers = array(
                        // Multimedia...
@@ -598,11 +659,17 @@ class MimeMagic {
         * @param $header String: some reasonably-sized chunk of file header
         * @param $tail   String: the tail of the file
         * @param $ext Mixed: the file extension, or true to extract it from the filename.
-        *             Set it to false to ignore the extension.
+        *             Set it to false (default) to ignore the extension. DEPRECATED! Set to false, 
+        *             use improveTypeFromExtension($mime, $ext) later to improve mime type.
         *
         * @return string
         */
        function detectZipType( $header, $tail = null, $ext = false ) {
+               if( $ext ) { # TODO: remove $ext param
+                       wfDebug( __METHOD__.": WARNING: use of the \$ext parameter is deprecated. " .
+                               "Use improveTypeFromExtension(\$mime, \$ext) instead.\n" );
+               }
+
                $mime = 'application/zip';
                $opendocTypes = array(
                        'chart-template',
@@ -633,7 +700,8 @@ class MimeMagic {
                        wfDebug( __METHOD__.": detected $mime from ZIP archive\n" );
                } elseif( preg_match( $openxmlRegex, substr( $header, 30 ) ) ) {
                        $mime = "application/x-opc+zip";
-                       if( $ext !== true && $ext !== false ) {
+                       # TODO: remove the block below, as soon as improveTypeFromExtension is used everywhere 
+                       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
@@ -691,15 +759,20 @@ class MimeMagic {
        * If no mime type can be determined, this function returns "unknown/unknown".
        *
        * @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.
+       * @param $ext Mixed: the file extension, or true (default) to extract it from the filename.
+       *             Set it to false to ignore the extension. DEPRECATED! Set to false, use 
+       *             improveTypeFromExtension($mime, $ext) later to improve mime type.
        *
        * @return string the mime type of $file
        * @access private
        */
-       function detectMimeType( $file, $ext = true ) {
+       private function detectMimeType( $file, $ext = true ) {
                global $wgMimeDetectorCommand;
 
+               if( $ext ) { # TODO:  make $ext default to false. Or better, remove it.
+                       wfDebug( __METHOD__.": WARNING: use of the \$ext parameter is deprecated. Use improveTypeFromExtension(\$mime, \$ext) instead.\n" );
+               }
+
                $m = null;
                if ( $wgMimeDetectorCommand ) {
                        $fn = wfEscapeShellArg( $file );