setup your server to properly recognize the types you want to
support.
uploads: false to disable uploading files with notices (true by default).
-filecommand: The required MIME_Type library may need to use the 'file'
- command. It tries the one in the Web server's path, but if
- you're having problems with uploads, try setting this to the
- correct value. Note: 'file' must accept '-b' and '-i' options.
For quotas, be sure you've set the upload_max_filesize and post_max_size
in php.ini to be large enough to handle your upload. In httpd.conf
main path + '/file/'.
ssl: whether to use HTTPS for file URLs. Defaults to null, meaning to
guess based on other SSL settings.
-filecommand: command to use for determining the type of a file. May be
- skipped if fileinfo extension is installed. Defaults to
- '/usr/bin/file'.
sslserver: if specified, this server will be used when creating HTTPS
URLs. Otherwise, the site SSL server will be used, with /file/ path.
sslpath: if this and the sslserver are specified, this path will be used
'sslserver' => null,
'sslpath' => null,
'ssl' => null,
- 'supported' => array('image/png',
- 'image/jpeg',
- 'image/gif',
- 'image/svg+xml',
- 'audio/mpeg',
- 'audio/x-speex',
- 'application/ogg',
- 'application/pdf',
- 'application/vnd.oasis.opendocument.text',
- 'application/vnd.oasis.opendocument.text-template',
- 'application/vnd.oasis.opendocument.graphics',
- 'application/vnd.oasis.opendocument.graphics-template',
- 'application/vnd.oasis.opendocument.presentation',
- 'application/vnd.oasis.opendocument.presentation-template',
- 'application/vnd.oasis.opendocument.spreadsheet',
- 'application/vnd.oasis.opendocument.spreadsheet-template',
- 'application/vnd.oasis.opendocument.chart',
- 'application/vnd.oasis.opendocument.chart-template',
- 'application/vnd.oasis.opendocument.image',
- 'application/vnd.oasis.opendocument.image-template',
- 'application/vnd.oasis.opendocument.formula',
- 'application/vnd.oasis.opendocument.formula-template',
- 'application/vnd.oasis.opendocument.text-master',
- 'application/vnd.oasis.opendocument.text-web',
- 'application/x-zip',
- 'application/zip',
- 'text/plain',
- 'video/mpeg',
- 'video/mp4',
- 'video/quicktime',
- 'video/webm'),
+ 'supported' => array(
+ 'application/vnd.oasis.opendocument.chart' => 'odc',
+ 'application/vnd.oasis.opendocument.formula' => 'odf',
+ 'application/vnd.oasis.opendocument.graphics' => 'odg',
+ 'application/vnd.oasis.opendocument.graphics-template' => 'otg',
+ 'application/vnd.oasis.opendocument.image' => 'odi',
+ 'application/vnd.oasis.opendocument.presentation' => 'odp',
+ 'application/vnd.oasis.opendocument.presentation-template' => 'otp',
+ 'application/vnd.oasis.opendocument.spreadsheet' => 'ods',
+ 'application/vnd.oasis.opendocument.spreadsheet-template' => 'ots',
+ 'application/vnd.oasis.opendocument.text' => 'odt',
+ 'application/vnd.oasis.opendocument.text-master' => 'odm',
+ 'application/vnd.oasis.opendocument.text-template' => 'ott',
+ 'application/vnd.oasis.opendocument.text-web' => 'oth',
+ 'application/pdf' => 'pdf',
+ 'application/zip' => 'zip',
+ 'image/png' => 'png',
+ 'image/jpeg' => 'jpg',
+ 'image/gif' => 'gif',
+ 'image/svg+xml' => 'svg',
+ 'image/vnd.microsoft.icon' => 'ico',
+ 'audio/ogg' => 'ogg',
+ 'audio/mpeg' => 'mpg',
+ 'audio/x-speex' => 'spx',
+ 'application/ogg' => 'ogx',
+ 'text/plain' => 'txt',
+ 'video/mpeg' => 'mpeg',
+ 'video/mp4' => 'mp4',
+ 'video/ogg' => 'ogv',
+ 'video/quicktime' => 'mov',
+ 'video/webm' => 'webm',
+ ),
'file_quota' => 5000000,
'user_quota' => 50000000,
'monthly_quota' => 15000000,
'uploads' => true,
- 'filecommand' => '/usr/bin/file',
'show_thumbs' => true, // show thumbnails in notice lists for uploaded images, and photos and videos linked remotely that provide oEmbed info
'thumb_width' => 100,
'thumb_height' => 75,
// Throws exception if additional size does not respect quota
File::respectsQuota($scoped, $_FILES[$param]['size']);
- $mimetype = MediaFile::getUploadedFileType($_FILES[$param]['tmp_name'],
+ $mimetype = self::getUploadedMimeType($_FILES[$param]['tmp_name'],
$_FILES[$param]['name']);
$basename = basename($_FILES[$param]['name']);
File::respectsQuota($scoped, filesize($stream['uri']));
- $mimetype = MediaFile::getUploadedFileType($stream['uri']);
+ $mimetype = self::getUploadedMimeType($stream['uri']);
$filename = File::filename($scoped, "email", $mimetype);
/**
* Attempt to identify the content type of a given file.
*
- * @param mixed $f file handle resource, or filesystem path as string
+ * @param string $filepath filesystem path as string (file must exist)
* @param string $originalFilename (optional) for extension-based detection
* @return string
*
- * @fixme is this an internal or public method? It's called from GetFileAction
* @fixme this seems to tie a front-end error message in, kinda confusing
- * @fixme this looks like it could return a PEAR_Error in some cases, if
- * type can't be identified and $config['attachments']['supported'] is true
*
* @throws ClientException if type is known, but not supported for local uploads
*/
- static function getUploadedFileType($f, $originalFilename=false) {
- global $_PEAR;
-
- require_once 'MIME/Type.php';
- require_once 'MIME/Type/Extension.php';
-
- // We have to disable auto handling of PEAR errors
- $_PEAR->staticPushErrorHandling(PEAR_ERROR_RETURN);
- $mte = new MIME_Type_Extension();
-
- $cmd = &$_PEAR->getStaticProperty('MIME_Type', 'fileCmd');
- $cmd = common_config('attachments', 'filecommand');
-
- $filetype = null;
-
- // If we couldn't get a clear type from the file extension,
- // we'll go ahead and try checking the content. Content checks
- // are unambiguous for most image files, but nearly useless
- // for office document formats.
-
+ static function getUploadedMimeType($filepath, $originalFilename=false) {
// We only accept filenames to existing files
- $filetype = MIME_Type::autoDetect($f);
+ $mimelookup = new finfo(FILEINFO_MIME_TYPE);
+ $mimetype = $mimelookup->file($filepath);
- // The content-based sources for MIME_Type::autoDetect()
- // are wildly unreliable for office-type documents. If we've
- // gotten an unclear reponse back or just couldn't identify it,
- // we'll try detecting a type from its extension...
+ // Unclear types are such that we can't really tell by the auto
+ // detect what they are (.bin, .exe etc. are just "octet-stream")
$unclearTypes = array('application/octet-stream',
'application/vnd.ms-office',
'application/zip',
// TODO: for XML we could do better content-based sniffing too
'text/xml');
- if ($originalFilename && (!$filetype || in_array($filetype, $unclearTypes))) {
- $type = $mte->getMIMEType($originalFilename);
- if (is_string($type)) {
- $filetype = $type;
+ $supported = common_config('attachments', 'supported');
+
+ // If we didn't match, or it is an unclear match
+ if ($originalFilename && (!$mimetype || in_array($mimetype, $unclearTypes))) {
+ $type = common_supported_ext_to_mime($originalFilename);
+ if (!empty($type)) {
+ return $type;
}
}
- $supported = common_config('attachments', 'supported');
- if ($supported === true || in_array($filetype, $supported)) {
- // Restore PEAR error handlers for our DB code...
- $_PEAR->staticPopErrorHandling();
- return $filetype;
+ // If $config['attachments']['supported'] equals boolean true, accept any mimetype
+ if ($supported === true || array_key_exists($mimetype, $supported)) {
+ // FIXME: Don't know if it always has a mimetype here because
+ // finfo->file CAN return false on error: http://php.net/finfo_file
+ // so if $supported === true, this may return something unexpected.
+ return $mimetype;
}
- $media = MIME_Type::getMedia($filetype);
+
+ // We can conclude that we have failed to get the MIME type
+ $media = common_get_mime_media($mimetype);
if ('application' !== $media) {
// TRANS: Client exception thrown trying to upload a forbidden MIME type.
// TRANS: %1$s is the file type that was denied, %2$s is the application part of
// TRANS: the MIME type that was denied.
$hint = sprintf(_('"%1$s" is not a supported file type on this server. ' .
- 'Try using another %2$s format.'), $filetype, $media);
+ 'Try using another %2$s format.'), $mimetype, $media);
} else {
// TRANS: Client exception thrown trying to upload a forbidden MIME type.
// TRANS: %s is the file type that was denied.
- $hint = sprintf(_('"%s" is not a supported file type on this server.'), $filetype);
+ $hint = sprintf(_('"%s" is not a supported file type on this server.'), $mimetype);
}
- // Restore PEAR error handlers for our DB code...
- $_PEAR->staticPopErrorHandling();
throw new ClientException($hint);
}
}
return $prefs;
}
+// Match by our supported file extensions
+function common_supported_ext_to_mime($fileext)
+{
+ // Accept a filename and take out the extension
+ if (strpos($fileext, '.') !== false) {
+ $fileext = substr(strrchr($fileext, '.'), 1);
+ }
+
+ $supported = common_config('attachments', 'supported');
+ foreach($supported as $type => $ext) {
+ if ($ext === $fileext) {
+ return $type;
+ }
+ }
+
+ return false;
+}
+
+// The MIME "media" is the part before the slash (video in video/webm)
+function common_get_mime_media($type)
+{
+ $tmp = explode('/', $type);
+ return strtolower($tmp[0]);
+}
+
function common_mime_type_match($type, $avail)
{
if(array_key_exists($type, $avail)) {
* @dataProvider fileTypeCases
*
*/
- public function testFileType($filename, $expectedType)
+ public function testMimeType($filename, $expectedType)
{
if (!file_exists($filename)) {
throw new Exception("WTF? $filename test file missing");
}
- $type = MediaFile::getUploadedFileType($filename, basename($filename));
+ $type = MediaFile::getUploadedMimeType($filename, basename($filename));
$this->assertEquals($expectedType, $type);
}
* @dataProvider fileTypeCases
*
*/
- public function testUploadedFileType($filename, $expectedType)
+ public function testUploadedMimeType($filename, $expectedType)
{
if (!file_exists($filename)) {
throw new Exception("WTF? $filename test file missing");
fwrite($tmp, file_get_contents($filename));
$tmp_metadata = stream_get_meta_data($tmp);
- $type = MediaFile::getUploadedFileType($tmp_metadata['uri'], basename($filename));
+ $type = MediaFile::getUploadedMimeType($tmp_metadata['uri'], basename($filename));
$this->assertEquals($expectedType, $type);
}