Browse Source

rewrite mimetype detection

euromark 11 years ago
parent
commit
12c48a0c7b

+ 14 - 20
src/Network/Email/Email.php

@@ -289,20 +289,15 @@ class Email extends CakeEmail {
 		return false;
 		return false;
 	}
 	}
 
 
-	/**
-	 * Try to determine the mimetype by filename.
-	 * Uses finfo_open() if availble, otherwise guesses it via file extension.
-	 *
-	 * @param string $filename
-	 * @return string Mimetype
-	 */
-	protected function _getMime($filename) {
-		$mimeType = Utility::getMimeType($filename);
-		if (!$mimeType) {
-			$ext = pathinfo($filename, PATHINFO_EXTENSION);
-			$mimeType = $this->_getMimeByExtension($ext);
+	protected function _getMimeByExtension($ext, $default = 'application/octet-stream') {
+		if (!isset($this->_Mime)) {
+			$this->_Mime = new Mime();
 		}
 		}
-		return $mimeType;
+		$mime = $this->_Mime->getMimeTypeByAlias($ext);
+		if (!$mime) {
+			$mime = $default;
+		}
+		return $mime;
 	}
 	}
 
 
 	/**
 	/**
@@ -312,16 +307,15 @@ class Email extends CakeEmail {
 	 * @param string $defaultMimeType
 	 * @param string $defaultMimeType
 	 * @return string Mimetype (falls back to `application/octet-stream`)
 	 * @return string Mimetype (falls back to `application/octet-stream`)
 	 */
 	 */
-	protected function _getMimeByExtension($ext, $default = 'application/octet-stream') {
-		if (!$ext) {
-			return $default;
-		}
+	protected function _getMime($filename, $default = 'application/octet-stream') {
 		if (!isset($this->_Mime)) {
 		if (!isset($this->_Mime)) {
 			$this->_Mime = new Mime();
 			$this->_Mime = new Mime();
 		}
 		}
-		$mime = $this->_Mime->getMimeType($ext);
-		if (!$mime) {
-			$mime = $default;
+		$mime = $this->_Mime->detectMimeType($filename);
+		// Some environments falsely return the default too fast, better fallback to extension here
+		if (!$mime || $mime === $default) {
+			$ext = pathinfo($filename, PATHINFO_EXTENSION);
+			$mime = $this->_Mime->getMimeTypeByAlias($ext);
 		}
 		}
 		return $mime;
 		return $mime;
 	}
 	}

+ 63 - 29
src/Utility/Mime.php

@@ -714,7 +714,7 @@ class Mime extends Response {
 	 *
 	 *
 	 * @return array
 	 * @return array
 	 */
 	 */
-	public function getMimeTypes($coreHasPrecedence = false) {
+	public function mimeTypes($coreHasPrecedence = false) {
 		if ($coreHasPrecedence) {
 		if ($coreHasPrecedence) {
 			return $this->_mimeTypes += $this->_mimeTypesExt;
 			return $this->_mimeTypes += $this->_mimeTypesExt;
 		}
 		}
@@ -722,7 +722,7 @@ class Mime extends Response {
 	}
 	}
 
 
 	/**
 	/**
-	 * Returns the primary mime type definition for an alias
+	 * Returns the primary mime type definition for an alias/extension.
 	 *
 	 *
 	 * e.g `getMimeType('pdf'); // returns 'application/pdf'`
 	 * e.g `getMimeType('pdf'); // returns 'application/pdf'`
 	 *
 	 *
@@ -731,9 +731,9 @@ class Mime extends Response {
 	 * @param bool $coreHasPrecedence
 	 * @param bool $coreHasPrecedence
 	 * @return mixed string mapped mime type or false if $alias is not mapped
 	 * @return mixed string mapped mime type or false if $alias is not mapped
 	 */
 	 */
-	public function getMimeType($alias, $primaryOnly = true, $coreHasPrecedence = false) {
+	public function getMimeTypeByAlias($alias, $primaryOnly = true, $coreHasPrecedence = false) {
 		if (empty($this->_mimeTypeTmp)) {
 		if (empty($this->_mimeTypeTmp)) {
-			$this->_mimeTypesTmp = $this->getMimeTypes($coreHasPrecedence);
+			$this->_mimeTypesTmp = $this->mimeTypes($coreHasPrecedence);
 		}
 		}
 		if (!isset($this->_mimeTypesTmp[$alias])) {
 		if (!isset($this->_mimeTypesTmp[$alias])) {
 			return false;
 			return false;
@@ -750,7 +750,7 @@ class Mime extends Response {
 	 *
 	 *
 	 * e.g `mapType('application/pdf'); // returns 'pdf'`
 	 * e.g `mapType('application/pdf'); // returns 'pdf'`
 	 *
 	 *
-	 * @param mixed $ctype Either a string content type to map, or an array of types.
+	 * @param string|array $ctype Either a string content type to map, or an array of types.
 	 * @return mixed Aliases for the types provided.
 	 * @return mixed Aliases for the types provided.
 	 */
 	 */
 	public function mapType($ctype) {
 	public function mapType($ctype) {
@@ -760,19 +760,14 @@ class Mime extends Response {
 	/**
 	/**
 	 * Retrieve the corresponding MIME type, if one exists
 	 * Retrieve the corresponding MIME type, if one exists
 	 *
 	 *
-	 * @param String $file File Name (relative location such as "image_test.jpg" or full "http://site.com/path/to/image_test.jpg")
-	 * @return String MIMEType - The type of the file passed in the argument
+	 * @param string $file File Name (relative location such as "image_test.jpg" or full "http://site.com/path/to/image_test.jpg")
+	 * @return string MIMEType - The type of the file passed in the argument
 	 */
 	 */
-	public function extractMimeType($file = null) {
-		if (!is_file($file)) {
-			return false;
-		}
-		/**
-		* Attempts to retrieve file info from FINFO
-		* If FINFO functions are not available then try to retrieve MIME type from pre-defined MIMEs
-		* If MIME type doesn't exist, then try (as a last resort) to use the (deprecated) mime_content_type function
-		* If all else fails, just return application/octet-stream
-		*/
+	public function detectMimeType($file = null) {
+		// Attempts to retrieve file info from FINFO
+		// If FINFO functions are not available then try to retrieve MIME type from pre-defined MIMEs
+		// If MIME type doesn't exist, then try (as a last resort) to use the (deprecated) mime_content_type function
+		// If all else fails, just return application/octet-stream
 		if (!function_exists("finfo_open")) {
 		if (!function_exists("finfo_open")) {
 			if (function_exists("mime_content_type")) {
 			if (function_exists("mime_content_type")) {
 				$type = mime_content_type($file);
 				$type = mime_content_type($file);
@@ -781,15 +776,57 @@ class Mime extends Response {
 				}
 				}
 			}
 			}
 			$extension = $this->_getExtension($file);
 			$extension = $this->_getExtension($file);
-			if ($mimeType = $this->getMimeType($extension)) {
+			if ($mimeType = $this->getMimeTypeByAlias($extension)) {
 				return $mimeType;
 				return $mimeType;
 			}
 			}
 			return "application/octet-stream";
 			return "application/octet-stream";
 		}
 		}
-		$finfo = finfo_open(FILEINFO_MIME_TYPE);
-		$mimeType = finfo_file($finfo, $file);
-		finfo_close($finfo);
-		return $mimeType;
+		return $this->_detectMimeType($file);
+	}
+
+	/**
+	 * Utility::getMimeType()
+	 *
+	 * @param string $file File
+	 * @return string Mime type
+	 */
+	public static function _detectMimeType($file) {
+		if (!function_exists('finfo_open')) {
+			//throw new InternalErrorException('finfo_open() required - please enable');
+		}
+
+		// Treat non local files differently
+		$pattern = '~^https?://~i';
+		if (preg_match($pattern, $file)) {
+			$headers = @get_headers($file);
+			if (!preg_match("|\b200\b|", $headers[0])) {
+				return '';
+			}
+			foreach ($headers as $header) {
+				if (strpos($header, 'Content-Type:') === 0) {
+					return trim(substr($header, 13));
+				}
+			}
+			return '';
+		}
+
+		if (!is_file($file)) {
+			return '';
+		}
+
+		$finfo = finfo_open(FILEINFO_MIME);
+		$mimetype = finfo_file($finfo, $file);
+		if (($pos = strpos($mimetype, ';')) !== false) {
+			$mimetype = substr($mimetype, 0, $pos);
+		}
+		if ($mimetype) {
+			return $mimetype;
+		}
+		$extension = $this->_getExtension($file);
+		if ($mimeType = $this->getMimeTypeByAlias($extension)) {
+			return $mimeType;
+		}
+		return "application/octet-stream";
 	}
 	}
 
 
 	/**
 	/**
@@ -818,13 +855,10 @@ class Mime extends Response {
 	 * @param String $file The full file name
 	 * @param String $file The full file name
 	 * @return String ext The file extension
 	 * @return String ext The file extension
 	 */
 	 */
-	protected function _getExtension($file = null) {
-		if ($file !== null) {
-			$pieces = explode('.', $file);
-			$ext = strtolower(array_pop($pieces));
-			return $ext;
-		}
-		return false;
+	protected function _getExtension($file) {
+		$pieces = explode('.', $file);
+		$ext = strtolower(array_pop($pieces));
+		return $ext;
 	}
 	}
 
 
 }
 }

+ 1 - 34
src/Utility/Utility.php

@@ -245,40 +245,6 @@ class Utility {
 	}
 	}
 
 
 	/**
 	/**
-	 * Utility::getMimeType()
-	 *
-	 * @param string $file File
-	 * @return string Mime type
-	 */
-	public static function getMimeType($file) {
-		if (!function_exists('finfo_open')) {
-			throw new InternalErrorException('finfo_open() required - please enable');
-		}
-
-		// Treat non local files differently
-		$pattern = '~^https?://~i';
-		if (preg_match($pattern, $file)) {
-			$headers = @get_headers($file);
-			if (!preg_match("|\b200\b|", $headers[0])) {
-				return '';
-			}
-			foreach ($headers as $header) {
-				if (strpos($header, 'Content-Type:') === 0) {
-					return trim(substr($header, 13));
-				}
-			}
-			return '';
-		}
-
-		$finfo = finfo_open(FILEINFO_MIME);
-		$mimetype = finfo_file($finfo, $file);
-		if (($pos = strpos($mimetype, ';')) !== false) {
-			$mimetype = substr($mimetype, 0, $pos);
-		}
-		return $mimetype;
-	}
-
-	/**
 	 * Parse headers from a specific URL content.
 	 * Parse headers from a specific URL content.
 	 *
 	 *
 	 * @param string $url
 	 * @param string $url
@@ -410,6 +376,7 @@ class Utility {
 	 *
 	 *
 	 * @param array
 	 * @param array
 	 * @return bool
 	 * @return bool
+	 * @deprecated Not sure this is useful for CakePHP 3.0
 	 */
 	 */
 	public static function isValidSaveAll($array) {
 	public static function isValidSaveAll($array) {
 		if (empty($array)) {
 		if (empty($array)) {

+ 3 - 2
src/View/Helper/ObfuscateHelper.php

@@ -169,8 +169,9 @@ class ObfuscateHelper extends Helper {
 			if ($replacement !== null) {
 			if ($replacement !== null) {
 				$str = preg_replace("/({$delim})(" . str_replace('\*', '\w*?', preg_quote($badword, '/')) . ")({$delim})/i", "\\1{$replacement}\\3", $str);
 				$str = preg_replace("/({$delim})(" . str_replace('\*', '\w*?', preg_quote($badword, '/')) . ")({$delim})/i", "\\1{$replacement}\\3", $str);
 			} else {
 			} else {
-				$str = preg_replace("/({$delim})(" . str_replace('\*', '\w*?', preg_quote($badword, '/')) . ")({$delim})/ie", "'\\1'.str_repeat('#', strlen('\\2')).'\\3'",
-					$str);
+				$str = preg_replace_callback("/({$delim})(" . str_replace('\*', '\w*?', preg_quote($badword, '/')) . ")({$delim})/i", function($matches) {
+					return $matches[1] . str_repeat('#', strlen($matches[2])). $matches[3];
+				}, $str);
 			}
 			}
 		}
 		}
 
 

+ 1 - 1
tests/TestCase/Network/Email/EmailTest.php

@@ -218,7 +218,7 @@ class EmailTest extends TestCase {
 			//'data' => $content,
 			//'data' => $content,
 			'mimetype' => 'image/jpeg',
 			'mimetype' => 'image/jpeg',
 		);
 		);
-		$this->assertEquals($expected, $res['hotel.gif']);#
+		$this->assertEquals($expected, $res['hotel.gif']);
 		$this->assertSame(2, count($res));
 		$this->assertSame(2, count($res));
 	}
 	}
 
 

+ 29 - 10
tests/TestCase/Utility/MimeTest.php

@@ -4,6 +4,7 @@ namespace Tools\TestCase\Utility;
 use Tools\Utility\Mime;
 use Tools\Utility\Mime;
 use Cake\TestSuite\TestCase;
 use Cake\TestSuite\TestCase;
 use Cake\Network\Response;
 use Cake\Network\Response;
+use Cake\Core\Plugin;
 
 
 class MimeTest extends TestCase {
 class MimeTest extends TestCase {
 
 
@@ -21,37 +22,37 @@ class MimeTest extends TestCase {
 	}
 	}
 
 
 	public function testAll() {
 	public function testAll() {
-		$res = $this->Mime->getMimeTypes();
+		$res = $this->Mime->mimeTypes();
 		$this->assertTrue(is_array($res) && count($res) > 100);
 		$this->assertTrue(is_array($res) && count($res) > 100);
 	}
 	}
 
 
 	public function testSingle() {
 	public function testSingle() {
-		$res = $this->Mime->getMimeType('odxs');
+		$res = $this->Mime->getMimeTypeByAlias('odxs');
 		$this->assertFalse($res);
 		$this->assertFalse($res);
 
 
-		$res = $this->Mime->getMimeType('ods');
+		$res = $this->Mime->getMimeTypeByAlias('ods');
 		$this->assertEquals('application/vnd.oasis.opendocument.spreadsheet', $res);
 		$this->assertEquals('application/vnd.oasis.opendocument.spreadsheet', $res);
 	}
 	}
 
 
 	public function testOverwrite() {
 	public function testOverwrite() {
-		$res = $this->Mime->getMimeType('ics');
+		$res = $this->Mime->getMimeTypeByAlias('ics');
 		$this->assertEquals('application/ics', $res);
 		$this->assertEquals('application/ics', $res);
 	}
 	}
 
 
 	public function testReverseToSingle() {
 	public function testReverseToSingle() {
-		$res = $this->Mime->getMimeType('html');
+		$res = $this->Mime->getMimeTypeByAlias('html');
 		$this->assertEquals('text/html', $res);
 		$this->assertEquals('text/html', $res);
 
 
-		$res = $this->Mime->getMimeType('csv');
+		$res = $this->Mime->getMimeTypeByAlias('csv');
 		$this->assertEquals('text/csv', $res);
 		$this->assertEquals('text/csv', $res);
 	}
 	}
 
 
 	public function testReverseToMultiple() {
 	public function testReverseToMultiple() {
-		$res = $this->Mime->getMimeType('html', false);
+		$res = $this->Mime->getMimeTypeByAlias('html', false);
 		$this->assertTrue(is_array($res));
 		$this->assertTrue(is_array($res));
 		$this->assertSame(2, count($res));
 		$this->assertSame(2, count($res));
 
 
-		$res = $this->Mime->getMimeType('csv', false);
+		$res = $this->Mime->getMimeTypeByAlias('csv', false);
 		$this->assertTrue(is_array($res)); //  && count($res) > 2
 		$this->assertTrue(is_array($res)); //  && count($res) > 2
 		$this->assertSame(2, count($res));
 		$this->assertSame(2, count($res));
 	}
 	}
@@ -61,7 +62,7 @@ class MimeTest extends TestCase {
 	 */
 	 */
 	public function testCorrectFileExtension() {
 	public function testCorrectFileExtension() {
 		file_put_contents(TMP . 'sometest.txt', 'xyz');
 		file_put_contents(TMP . 'sometest.txt', 'xyz');
-		$is = $this->Mime->extractMimeType(TMP . 'sometest.txt');
+		$is = $this->Mime->detectMimeType(TMP . 'sometest.txt');
 		//pr($is);
 		//pr($is);
 		$this->assertEquals($is, 'text/plain');
 		$this->assertEquals($is, 'text/plain');
 	}
 	}
@@ -71,12 +72,30 @@ class MimeTest extends TestCase {
 	 */
 	 */
 	public function testWrongFileExtension() {
 	public function testWrongFileExtension() {
 		file_put_contents(TMP . 'sometest.zip', 'xyz');
 		file_put_contents(TMP . 'sometest.zip', 'xyz');
-		$is = $this->Mime->extractMimeType(TMP . 'sometest.zip');
+		$is = $this->Mime->detectMimeType(TMP . 'sometest.zip');
 		//pr($is);
 		//pr($is);
 		$this->assertEquals($is, 'text/plain');
 		$this->assertEquals($is, 'text/plain');
 		//Test failes? finfo_open not availaible??
 		//Test failes? finfo_open not availaible??
 	}
 	}
 
 
+
+	/**
+	 * testgetMimeTypeByAlias()
+	 *
+	 * @cover detectMimeType
+	 * @return void
+	 */
+	public function testgetMimeTypeByAlias() {
+		$res = $this->Mime->detectMimeType('http://www.spiegel.de/static/sys/v10/icons/home_v2.png');
+		$this->assertEquals('image/png', $res);
+
+		$res = $this->Mime->detectMimeType('http://www.spiegel.de/static/sys/v10/icons/home_v2_inexistent.png');
+		$this->assertEquals('', $res);
+
+		$res = $this->Mime->detectMimeType(Plugin::path('Tools') . 'tests' . DS . 'test_files' . DS . 'img' . DS . 'hotel.jpg');
+		$this->assertEquals('image/jpeg', $res);
+	}
+
 	/**
 	/**
 	 * Test fake files
 	 * Test fake files
 	 */
 	 */

+ 0 - 17
tests/TestCase/Utility/UtilityTest.php

@@ -196,23 +196,6 @@ class UtilityTest extends TestCase {
 	}
 	}
 
 
 	/**
 	/**
-	 * UtilityTest::testGetMimeType()
-	 *
-	 * @covers Utility::getMimeType
-	 * @return void
-	 */
-	public function testGetMimeType() {
-		$res = Utility::getMimeType('http://www.spiegel.de/static/sys/v10/icons/home_v2.png');
-		$this->assertEquals('image/png', $res);
-
-		$res = Utility::getMimeType('http://www.spiegel.de/static/sys/v10/icons/home_v2_inexistent.png');
-		$this->assertEquals('', $res);
-
-		$res = Utility::getMimeType(Plugin::path('Tools') . 'tests' . DS . 'test_files' . DS . 'img' . DS . 'hotel.jpg');
-		$this->assertEquals('image/jpeg', $res);
-	}
-
-	/**
 	 * UtilityTest::testFileExists()
 	 * UtilityTest::testFileExists()
 	 *
 	 *
 	 * @covers Utility::fileExists
 	 * @covers Utility::fileExists