diff --git a/src/Symfony/Component/HttpFoundation/File/File.php b/src/Symfony/Component/HttpFoundation/File/File.php
index 729d870cfc..9002b51085 100644
--- a/src/Symfony/Component/HttpFoundation/File/File.php
+++ b/src/Symfony/Component/HttpFoundation/File/File.php
@@ -49,9 +49,15 @@ class File extends \SplFileInfo
*
* If the mime type is unknown, returns null.
*
+ * This method uses the mime type as guessed by getMimeType()
+ * to guess the file extension.
+ *
* @return string|null The guessed extension or null if it cannot be guessed
*
* @api
+ *
+ * @see ExtensionGuesser
+ * @see getMimeType()
*/
public function guessExtension()
{
@@ -64,12 +70,14 @@ class File extends \SplFileInfo
/**
* Returns the mime type of the file.
*
- * The mime type is guessed using the functions finfo(), mime_content_type()
- * and the system binary "file" (in this order), depending on which of those
- * is available on the current operating system.
+ * The mime type is guessed using a MimeTypeGuesser instance, which uses finfo(),
+ * mime_content_type() and the system binary "file" (in this order), depending on
+ * which of those are available.
*
* @return string|null The guessed mime type (i.e. "application/pdf")
*
+ * @see MimeTypeGuesser
+ *
* @api
*/
public function getMimeType()
diff --git a/src/Symfony/Component/HttpFoundation/File/MimeType/ExtensionGuesser.php b/src/Symfony/Component/HttpFoundation/File/MimeType/ExtensionGuesser.php
index d5715f6f55..cc646180c8 100644
--- a/src/Symfony/Component/HttpFoundation/File/MimeType/ExtensionGuesser.php
+++ b/src/Symfony/Component/HttpFoundation/File/MimeType/ExtensionGuesser.php
@@ -16,15 +16,12 @@ namespace Symfony\Component\HttpFoundation\File\MimeType;
*
* A default guesser is provided.
* You can register custom guessers by calling the register()
- * method on the singleton instance.
+ * method on the singleton instance:
*
- *
- * $guesser = ExtensionGuesser::getInstance();
- * $guesser->register(new MyCustomExtensionGuesser());
- *
+ * $guesser = ExtensionGuesser::getInstance();
+ * $guesser->register(new MyCustomExtensionGuesser());
*
* The last registered guesser is preferred over previously registered ones.
- *
*/
class ExtensionGuesser implements ExtensionGuesserInterface
{
diff --git a/src/Symfony/Component/HttpFoundation/File/MimeType/FileinfoMimeTypeGuesser.php b/src/Symfony/Component/HttpFoundation/File/MimeType/FileinfoMimeTypeGuesser.php
index 09a0d7ed19..a6950df2cd 100644
--- a/src/Symfony/Component/HttpFoundation/File/MimeType/FileinfoMimeTypeGuesser.php
+++ b/src/Symfony/Component/HttpFoundation/File/MimeType/FileinfoMimeTypeGuesser.php
@@ -15,12 +15,26 @@ use Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException;
use Symfony\Component\HttpFoundation\File\Exception\AccessDeniedException;
/**
- * Guesses the mime type using the PECL extension FileInfo
+ * Guesses the mime type using the PECL extension FileInfo.
*
* @author Bernhard Schussek
*/
class FileinfoMimeTypeGuesser implements MimeTypeGuesserInterface
{
+ private $magicFile;
+
+ /**
+ * Constructor.
+ *
+ * @param string $magicFile A magic file to use with the finfo instance
+ *
+ * @link http://www.php.net/manual/en/function.finfo-open.php
+ */
+ public function __construct($magicFile = null)
+ {
+ $this->magicFile = $magicFile;
+ }
+
/**
* Returns whether this guesser is supported on the current OS/PHP setup
*
@@ -48,7 +62,7 @@ class FileinfoMimeTypeGuesser implements MimeTypeGuesserInterface
return null;
}
- if (!$finfo = new \finfo(FILEINFO_MIME_TYPE)) {
+ if (!$finfo = new \finfo(FILEINFO_MIME_TYPE, $this->magicFile)) {
return null;
}
diff --git a/src/Symfony/Component/HttpFoundation/File/MimeType/MimeTypeExtensionGuesser.php b/src/Symfony/Component/HttpFoundation/File/MimeType/MimeTypeExtensionGuesser.php
index 13fe4a2fdc..42e7b77af0 100644
--- a/src/Symfony/Component/HttpFoundation/File/MimeType/MimeTypeExtensionGuesser.php
+++ b/src/Symfony/Component/HttpFoundation/File/MimeType/MimeTypeExtensionGuesser.php
@@ -20,6 +20,7 @@ class MimeTypeExtensionGuesser implements ExtensionGuesserInterface
* A map of mime types and their default extensions.
*
* This list has been placed under the public domain by the Apache HTTPD project.
+ * This list has been updated from upstream on 2013-04-23.
*
* @see http://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types
*
@@ -39,6 +40,7 @@ class MimeTypeExtensionGuesser implements ExtensionGuesserInterface
'application/cdmi-queue' => 'cdmiq',
'application/cu-seeme' => 'cu',
'application/davmount+xml' => 'davmount',
+ 'application/docbook+xml' => 'dbk',
'application/dssc+der' => 'dssc',
'application/dssc+xml' => 'xdssc',
'application/ecmascript' => 'ecma',
@@ -46,6 +48,9 @@ class MimeTypeExtensionGuesser implements ExtensionGuesserInterface
'application/epub+zip' => 'epub',
'application/exi' => 'exi',
'application/font-tdpfr' => 'pfr',
+ 'application/gml+xml' => 'gml',
+ 'application/gpx+xml' => 'gpx',
+ 'application/gxf' => 'gxf',
'application/hyperstudio' => 'stk',
'application/inkml+xml' => 'ink',
'application/ipfix' => 'ipfix',
@@ -54,6 +59,7 @@ class MimeTypeExtensionGuesser implements ExtensionGuesserInterface
'application/java-vm' => 'class',
'application/javascript' => 'js',
'application/json' => 'json',
+ 'application/jsonml+json' => 'jsonml',
'application/lost+xml' => 'lostxml',
'application/mac-binhex40' => 'hqx',
'application/mac-compactpro' => 'cpt',
@@ -64,6 +70,7 @@ class MimeTypeExtensionGuesser implements ExtensionGuesserInterface
'application/mathml+xml' => 'mathml',
'application/mbox' => 'mbox',
'application/mediaservercontrol+xml' => 'mscml',
+ 'application/metalink+xml' => 'metalink',
'application/metalink4+xml' => 'meta4',
'application/mets+xml' => 'mets',
'application/mods+xml' => 'mods',
@@ -75,6 +82,7 @@ class MimeTypeExtensionGuesser implements ExtensionGuesserInterface
'application/oda' => 'oda',
'application/oebps-package+xml' => 'opf',
'application/ogg' => 'ogx',
+ 'application/omdoc+xml' => 'omdoc',
'application/onenote' => 'onetoc',
'application/oxps' => 'oxps',
'application/patch-ops-error+xml' => 'xer',
@@ -122,6 +130,7 @@ class MimeTypeExtensionGuesser implements ExtensionGuesserInterface
'application/srgs' => 'gram',
'application/srgs+xml' => 'grxml',
'application/sru+xml' => 'sru',
+ 'application/ssdl+xml' => 'ssdl',
'application/ssml+xml' => 'ssml',
'application/tei+xml' => 'tei',
'application/thraud+xml' => 'tfi',
@@ -136,6 +145,7 @@ class MimeTypeExtensionGuesser implements ExtensionGuesserInterface
'application/vnd.acucobol' => 'acu',
'application/vnd.acucorp' => 'atc',
'application/vnd.adobe.air-application-installer-package+zip' => 'air',
+ 'application/vnd.adobe.formscentral.fcdt' => 'fcdt',
'application/vnd.adobe.fxp' => 'fxp',
'application/vnd.adobe.xdp+xml' => 'xdp',
'application/vnd.adobe.xfdf' => 'xfdf',
@@ -178,6 +188,7 @@ class MimeTypeExtensionGuesser implements ExtensionGuesserInterface
'application/vnd.cups-ppd' => 'ppd',
'application/vnd.curl.car' => 'car',
'application/vnd.curl.pcurl' => 'pcurl',
+ 'application/vnd.dart' => 'dart',
'application/vnd.data-vision.rdz' => 'rdz',
'application/vnd.dece.data' => 'uvf',
'application/vnd.dece.ttml+xml' => 'uvt',
@@ -188,6 +199,7 @@ class MimeTypeExtensionGuesser implements ExtensionGuesserInterface
'application/vnd.dolby.mlp' => 'mlp',
'application/vnd.dpgraph' => 'dpg',
'application/vnd.dreamfactory' => 'dfac',
+ 'application/vnd.ds-keypoint' => 'kpxx',
'application/vnd.dvb.ait' => 'ait',
'application/vnd.dvb.service' => 'svc',
'application/vnd.dynageo' => 'geo',
@@ -248,7 +260,6 @@ class MimeTypeExtensionGuesser implements ExtensionGuesserInterface
'application/vnd.hp-pcl' => 'pcl',
'application/vnd.hp-pclxl' => 'pclxl',
'application/vnd.hydrostatix.sof-data' => 'sfd-hdstx',
- 'application/vnd.hzn-3d-crossword' => 'x3d',
'application/vnd.ibm.minipay' => 'mpy',
'application/vnd.ibm.modcap' => 'afp',
'application/vnd.ibm.rights-management' => 'irm',
@@ -344,6 +355,7 @@ class MimeTypeExtensionGuesser implements ExtensionGuesserInterface
'application/vnd.muvee.style' => 'msty',
'application/vnd.mynfc' => 'taglet',
'application/vnd.neurolanguage.nlu' => 'nlu',
+ 'application/vnd.nitf' => 'ntf',
'application/vnd.noblenet-directory' => 'nnd',
'application/vnd.noblenet-sealer' => 'nns',
'application/vnd.noblenet-web' => 'nnw',
@@ -384,6 +396,7 @@ class MimeTypeExtensionGuesser implements ExtensionGuesserInterface
'application/vnd.openxmlformats-officedocument.wordprocessingml.template' => 'dotx',
'application/vnd.osgeo.mapguide.package' => 'mgp',
'application/vnd.osgi.dp' => 'dp',
+ 'application/vnd.osgi.subsystem' => 'esa',
'application/vnd.palm' => 'pdb',
'application/vnd.pawaafile' => 'paw',
'application/vnd.pg.format' => 'str',
@@ -403,6 +416,7 @@ class MimeTypeExtensionGuesser implements ExtensionGuesserInterface
'application/vnd.rig.cryptonote' => 'cryptonote',
'application/vnd.rim.cod' => 'cod',
'application/vnd.rn-realmedia' => 'rm',
+ 'application/vnd.rn-realmedia-vbr' => 'rmvb',
'application/vnd.route66.link66+xml' => 'link66',
'application/vnd.sailingtracker.track' => 'st',
'application/vnd.seemail' => 'see',
@@ -486,25 +500,33 @@ class MimeTypeExtensionGuesser implements ExtensionGuesserInterface
'application/x-7z-compressed' => '7z',
'application/x-abiword' => 'abw',
'application/x-ace-compressed' => 'ace',
+ 'application/x-apple-diskimage' => 'dmg',
'application/x-authorware-bin' => 'aab',
'application/x-authorware-map' => 'aam',
'application/x-authorware-seg' => 'aas',
'application/x-bcpio' => 'bcpio',
'application/x-bittorrent' => 'torrent',
+ 'application/x-blorb' => 'blb',
'application/x-bzip' => 'bz',
'application/x-bzip2' => 'bz2',
+ 'application/x-cbr' => 'cbr',
'application/x-cdlink' => 'vcd',
+ 'application/x-cfs-compressed' => 'cfs',
'application/x-chat' => 'chat',
'application/x-chess-pgn' => 'pgn',
+ 'application/x-conference' => 'nsc',
'application/x-cpio' => 'cpio',
'application/x-csh' => 'csh',
'application/x-debian-package' => 'deb',
+ 'application/x-dgc-compressed' => 'dgc',
'application/x-director' => 'dir',
'application/x-doom' => 'wad',
'application/x-dtbncx+xml' => 'ncx',
'application/x-dtbook+xml' => 'dtb',
'application/x-dtbresource+xml' => 'res',
'application/x-dvi' => 'dvi',
+ 'application/x-envoy' => 'evy',
+ 'application/x-eva' => 'eva',
'application/x-font-bdf' => 'bdf',
'application/x-font-ghostscript' => 'gsf',
'application/x-font-linux-psf' => 'psf',
@@ -514,14 +536,23 @@ class MimeTypeExtensionGuesser implements ExtensionGuesserInterface
'application/x-font-ttf' => 'ttf',
'application/x-font-type1' => 'pfa',
'application/x-font-woff' => 'woff',
+ 'application/x-freearc' => 'arc',
'application/x-futuresplash' => 'spl',
+ 'application/x-gca-compressed' => 'gca',
+ 'application/x-glulx' => 'ulx',
'application/x-gnumeric' => 'gnumeric',
+ 'application/x-gramps-xml' => 'gramps',
'application/x-gtar' => 'gtar',
'application/x-hdf' => 'hdf',
+ 'application/x-install-instructions' => 'install',
+ 'application/x-iso9660-image' => 'iso',
'application/x-java-jnlp-file' => 'jnlp',
'application/x-latex' => 'latex',
+ 'application/x-lzh-compressed' => 'lzh',
+ 'application/x-mie' => 'mie',
'application/x-mobipocket-ebook' => 'prc',
'application/x-ms-application' => 'application',
+ 'application/x-ms-shortcut' => 'lnk',
'application/x-ms-wmd' => 'wmd',
'application/x-ms-wmz' => 'wmz',
'application/x-ms-xbap' => 'xbap',
@@ -538,35 +569,47 @@ class MimeTypeExtensionGuesser implements ExtensionGuesserInterface
'application/x-msterminal' => 'trm',
'application/x-mswrite' => 'wri',
'application/x-netcdf' => 'nc',
+ 'application/x-nzb' => 'nzb',
'application/x-pkcs12' => 'p12',
'application/x-pkcs7-certificates' => 'p7b',
'application/x-pkcs7-certreqresp' => 'p7r',
'application/x-rar-compressed' => 'rar',
'application/x-rar' => 'rar',
+ 'application/x-research-info-systems' => 'ris',
'application/x-sh' => 'sh',
'application/x-shar' => 'shar',
'application/x-shockwave-flash' => 'swf',
'application/x-silverlight-app' => 'xap',
+ 'application/x-sql' => 'sql',
'application/x-stuffit' => 'sit',
'application/x-stuffitx' => 'sitx',
+ 'application/x-subrip' => 'srt',
'application/x-sv4cpio' => 'sv4cpio',
'application/x-sv4crc' => 'sv4crc',
+ 'application/x-t3vm-image' => 't3',
+ 'application/x-tads' => 'gam',
'application/x-tar' => 'tar',
'application/x-tcl' => 'tcl',
'application/x-tex' => 'tex',
'application/x-tex-tfm' => 'tfm',
'application/x-texinfo' => 'texinfo',
+ 'application/x-tgif' => 'obj',
'application/x-ustar' => 'ustar',
'application/x-wais-source' => 'src',
'application/x-x509-ca-cert' => 'der',
'application/x-xfig' => 'fig',
+ 'application/x-xliff+xml' => 'xlf',
'application/x-xpinstall' => 'xpi',
+ 'application/x-xz' => 'xz',
+ 'application/x-zmachine' => 'z1',
+ 'application/xaml+xml' => 'xaml',
'application/xcap-diff+xml' => 'xdf',
'application/xenc+xml' => 'xenc',
'application/xhtml+xml' => 'xhtml',
'application/xml' => 'xml',
'application/xml-dtd' => 'dtd',
'application/xop+xml' => 'xop',
+ 'application/xproc+xml' => 'xpl',
'application/xslt+xml' => 'xslt',
'application/xspf+xml' => 'xspf',
'application/xv+xml' => 'mxml',
@@ -579,6 +622,8 @@ class MimeTypeExtensionGuesser implements ExtensionGuesserInterface
'audio/mp4' => 'mp4a',
'audio/mpeg' => 'mpga',
'audio/ogg' => 'oga',
+ 'audio/s3m' => 's3m',
+ 'audio/silk' => 'sil',
'audio/vnd.dece.audio' => 'uva',
'audio/vnd.digital-winds' => 'eol',
'audio/vnd.dra' => 'dra',
@@ -593,12 +638,16 @@ class MimeTypeExtensionGuesser implements ExtensionGuesserInterface
'audio/webm' => 'weba',
'audio/x-aac' => 'aac',
'audio/x-aiff' => 'aif',
+ 'audio/x-caf' => 'caf',
+ 'audio/x-flac' => 'flac',
+ 'audio/x-matroska' => 'mka',
'audio/x-mpegurl' => 'm3u',
'audio/x-ms-wax' => 'wax',
'audio/x-ms-wma' => 'wma',
'audio/x-pn-realaudio' => 'ram',
'audio/x-pn-realaudio-plugin' => 'rmp',
'audio/x-wav' => 'wav',
+ 'audio/xm' => 'xm',
'chemical/x-cdx' => 'cdx',
'chemical/x-cif' => 'cif',
'chemical/x-cmdf' => 'cmdf',
@@ -614,6 +663,7 @@ class MimeTypeExtensionGuesser implements ExtensionGuesserInterface
'image/ktx' => 'ktx',
'image/png' => 'png',
'image/prs.btif' => 'btif',
+ 'image/sgi' => 'sgi',
'image/svg+xml' => 'svg',
'image/tiff' => 'tiff',
'image/vnd.adobe.photoshop' => 'psd',
@@ -628,14 +678,17 @@ class MimeTypeExtensionGuesser implements ExtensionGuesserInterface
'image/vnd.fujixerox.edmics-mmr' => 'mmr',
'image/vnd.fujixerox.edmics-rlc' => 'rlc',
'image/vnd.ms-modi' => 'mdi',
+ 'image/vnd.ms-photo' => 'wdp',
'image/vnd.net-fpx' => 'npx',
'image/vnd.wap.wbmp' => 'wbmp',
'image/vnd.xiff' => 'xif',
'image/webp' => 'webp',
+ 'image/x-3ds' => '3ds',
'image/x-cmu-raster' => 'ras',
'image/x-cmx' => 'cmx',
'image/x-freehand' => 'fh',
'image/x-icon' => 'ico',
+ 'image/x-mrsid-image' => 'sid',
'image/x-pcx' => 'pcx',
'image/x-pict' => 'pic',
'image/x-portable-anymap' => 'pnm',
@@ -643,6 +696,7 @@ class MimeTypeExtensionGuesser implements ExtensionGuesserInterface
'image/x-portable-graymap' => 'pgm',
'image/x-portable-pixmap' => 'ppm',
'image/x-rgb' => 'rgb',
+ 'image/x-tga' => 'tga',
'image/x-xbitmap' => 'xbm',
'image/x-xpixmap' => 'xpm',
'image/x-xwindowdump' => 'xwd',
@@ -656,6 +710,10 @@ class MimeTypeExtensionGuesser implements ExtensionGuesserInterface
'model/vnd.mts' => 'mts',
'model/vnd.vtu' => 'vtu',
'model/vrml' => 'wrl',
+ 'model/x3d+binary' => 'x3db',
+ 'model/x3d+vrml' => 'x3dv',
+ 'model/x3d+xml' => 'x3d',
+ 'text/cache-manifest' => 'appcache',
'text/calendar' => 'ics',
'text/css' => 'css',
'text/csv' => 'csv',
@@ -688,7 +746,10 @@ class MimeTypeExtensionGuesser implements ExtensionGuesserInterface
'text/x-fortran' => 'f',
'text/x-pascal' => 'p',
'text/x-java-source' => 'java',
+ 'text/x-opml' => 'opml',
+ 'text/x-nfo' => 'nfo',
'text/x-setext' => 'etx',
+ 'text/x-sfv' => 'sfv',
'text/x-uuencode' => 'uu',
'text/x-vcalendar' => 'vcs',
'text/x-vcard' => 'vcf',
@@ -720,13 +781,17 @@ class MimeTypeExtensionGuesser implements ExtensionGuesserInterface
'video/x-fli' => 'fli',
'video/x-flv' => 'flv',
'video/x-m4v' => 'm4v',
+ 'video/x-matroska' => 'mkv',
+ 'video/x-mng' => 'mng',
'video/x-ms-asf' => 'asf',
+ 'video/x-ms-vob' => 'vob',
'video/x-ms-wm' => 'wm',
'video/x-ms-wmv' => 'wmv',
'video/x-ms-wmx' => 'wmx',
'video/x-ms-wvx' => 'wvx',
'video/x-msvideo' => 'avi',
'video/x-sgi-movie' => 'movie',
+ 'video/x-smv' => 'smv',
'x-conference/x-cooltalk' => 'ice',
);
diff --git a/src/Symfony/Component/HttpFoundation/File/MimeType/MimeTypeGuesser.php b/src/Symfony/Component/HttpFoundation/File/MimeType/MimeTypeGuesser.php
index 59ddc077be..f6bf2cd39d 100644
--- a/src/Symfony/Component/HttpFoundation/File/MimeType/MimeTypeGuesser.php
+++ b/src/Symfony/Component/HttpFoundation/File/MimeType/MimeTypeGuesser.php
@@ -18,15 +18,22 @@ use Symfony\Component\HttpFoundation\File\Exception\AccessDeniedException;
* A singleton mime type guesser.
*
* By default, all mime type guessers provided by the framework are installed
- * (if available on the current OS/PHP setup). You can register custom
- * guessers by calling the register() method on the singleton instance.
+ * (if available on the current OS/PHP setup).
*
- *
- * $guesser = MimeTypeGuesser::getInstance();
- * $guesser->register(new MyCustomMimeTypeGuesser());
- *
+ * You can register custom guessers by calling the register() method on the
+ * singleton instance. Custom guessers are always called before any default ones.
*
- * The last registered guesser is preferred over previously registered ones.
+ * $guesser = MimeTypeGuesser::getInstance();
+ * $guesser->register(new MyCustomMimeTypeGuesser());
+ *
+ * If you want to change the order of the default guessers, just re-register your
+ * preferred one as a custom one. The last registered guesser is preferred over
+ * previously registered ones.
+ *
+ * Re-registering a built-in guesser also allows you to configure it:
+ *
+ * $guesser = MimeTypeGuesser::getInstance();
+ * $guesser->register(new FileinfoMimeTypeGuesser('/path/to/magic/file'));
*
* @author Bernhard Schussek
*/
diff --git a/src/Symfony/Component/HttpFoundation/File/UploadedFile.php b/src/Symfony/Component/HttpFoundation/File/UploadedFile.php
index f08bccd4dd..bd7ebec52e 100644
--- a/src/Symfony/Component/HttpFoundation/File/UploadedFile.php
+++ b/src/Symfony/Component/HttpFoundation/File/UploadedFile.php
@@ -134,11 +134,16 @@ class UploadedFile extends File
/**
* Returns the file mime type.
*
- * It is extracted from the request from which the file has been uploaded.
- * Then is should not be considered as a safe value.
+ * The client mime type is extracted from the request from which the file
+ * was uploaded, so it should not be considered as a safe value.
+ *
+ * For a trusted mime type, use getMimeType() instead (which guesses the mime
+ * type based on the file content).
*
* @return string|null The mime type
*
+ * @see getMimeType
+ *
* @api
*/
public function getClientMimeType()
@@ -146,6 +151,31 @@ class UploadedFile extends File
return $this->mimeType;
}
+ /**
+ * Returns the extension based on the client mime type.
+ *
+ * If the mime type is unknown, returns null.
+ *
+ * This method uses the mime type as guessed by getClientMimeType()
+ * to guess the file extension. As such, the extension returned
+ * by this method cannot be trusted.
+ *
+ * For a trusted extension, use guessExtension() instead (which guesses
+ * the extension based on the guessed mime type for the file).
+ *
+ * @return string|null The guessed extension or null if it cannot be guessed
+ *
+ * @see guessExtension()
+ * @see getClientMimeType()
+ */
+ public function guessClientExtension()
+ {
+ $type = $this->getMimeType();
+ $guesser = ExtensionGuesser::getInstance();
+
+ return $guesser->guess($type);
+ }
+
/**
* Returns the file size.
*