return;
}
- $mimetype = MediaFile::getUploadedFileType($_FILES[$param]['tmp_name']);
+ $mimetype = MediaFile::getUploadedFileType($_FILES[$param]['tmp_name'],
+ $_FILES[$param]['name']);
$filename = null;
return new MediaFile($user, $filename, $mimetype);
}
- static function getUploadedFileType($f) {
+ /**
+ * Attempt to identify the content type of a given file.
+ *
+ * @param mixed $f file handle resource, or filesystem path as string
+ * @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) {
require_once 'MIME/Type.php';
+ require_once 'MIME/Type/Extension.php';
+ $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.
+
if (is_string($f)) {
// assuming a filename
$filetype = MIME_Type::autoDetect($f);
+
} else {
// assuming a filehandle
$filetype = MIME_Type::autoDetect($stream['uri']);
}
- if (common_config('attachments', 'supported') === true || in_array($filetype, common_config('attachments', 'supported'))) {
+ // 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...
+ $unclearTypes = array('application/octet-stream',
+ 'application/vnd.ms-office',
+ 'application/zip');
+
+ if ($originalFilename && (!$filetype || in_array($filetype, $unclearTypes))) {
+ $type = $mte->getMIMEType($originalFilename);
+ if (is_string($type)) {
+ $filetype = $type;
+ }
+ }
+
+ $supported = common_config('attachments', 'supported');
+ if (is_array($supported)) {
+ // Normalize extensions to mime types
+ foreach ($supported as $i => $entry) {
+ if (strpos($entry, '/') === false) {
+ common_log(LOG_INFO, "sample.$entry");
+ $supported[$i] = $mte->getMIMEType("sample.$entry");
+ }
+ }
+ }
+ if ($supported === true || in_array($filetype, $supported)) {
return $filetype;
}
$media = MIME_Type::getMedia($filetype);
if (!file_exists($filename)) {
throw new Exception("WTF? $filename test file missing");
}
- $this->assertEquals($expectedType, MediaFile::getUploadedFileType($filename));
+
+ $type = MediaFile::getUploadedFileType($filename, basename($filename));
+ $this->assertEquals($expectedType, $type);
+ }
+
+ /**
+ * @dataProvider fileTypeCases
+ *
+ */
+ public function testUploadedFileType($filename, $expectedType)
+ {
+ if (!file_exists($filename)) {
+ throw new Exception("WTF? $filename test file missing");
+ }
+ $tmp = tmpfile();
+ fwrite($tmp, file_get_contents($filename));
+
+ $type = MediaFile::getUploadedFileType($tmp, basename($filename));
+ $this->assertEquals($expectedType, $type);
}
static public function fileTypeCases()
{
$base = dirname(__FILE__);
$dir = "$base/sample-uploads";
- return array(
- array("$dir/office.pdf", "application/pdf"),
+ $files = array(
+ "image.png" => "image/png",
+ "image.gif" => "image/gif",
+ "image.jpg" => "image/jpeg",
+ "image.jpeg" => "image/jpeg",
+
+ "office.pdf" => "application/pdf",
- array("$dir/wordproc.odt", "application/vnd.oasis.opendocument.text"),
- array("$dir/wordproc.ott", "application/vnd.oasis.opendocument.text-template"),
- array("$dir/wordproc.doc", "application/msword"),
- array("$dir/wordproc.docx",
- "application/vnd.openxmlformats-officedocument.wordprocessingml.document"),
- array("$dir/wordproc.rtf", "text/rtf"),
+ "wordproc.odt" => "application/vnd.oasis.opendocument.text",
+ "wordproc.ott" => "application/vnd.oasis.opendocument.text-template",
+ "wordproc.doc" => "application/msword",
+ "wordproc.docx" => "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
+ "wordproc.rtf" => "text/rtf",
- array("$dir/spreadsheet.ods",
- "application/vnd.oasis.opendocument.spreadsheet"),
- array("$dir/spreadsheet.ots",
- "application/vnd.oasis.opendocument.spreadsheet-template"),
- array("$dir/spreadsheet.xls", "application/vnd.ms-excel"),
- array("$dir/spreadsheet.xlt", "application/vnd.ms-excel"),
- array("$dir/spreadsheet.xlsx",
- "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"),
+ "spreadsheet.ods" => "application/vnd.oasis.opendocument.spreadsheet",
+ "spreadsheet.ots" => "application/vnd.oasis.opendocument.spreadsheet-template",
+ "spreadsheet.xls" => "application/vnd.ms-excel",
+ "spreadsheet.xlt" => "application/vnd.ms-excel",
+ "spreadsheet.xlsx" => "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
- array("$dir/presentation.odp",
- "application/vnd.oasis-opendocument.presentation"),
- array("$dir/presentation.otp",
- "application/vnd.oasis-opendocument.presentation-template"),
- array("$dir/presentation.ppt",
- "application/vnd.ms-powerpoint"),
- array("$dir/presentation.pot",
- "application/vnd.ms-powerpoint"),
- array("$dir/presentation.pptx",
- "application/vnd.openxmlformats-officedocument.presentationml.presentation"),
+ "presentation.odp" => "application/vnd.oasis.opendocument.presentation",
+ "presentation.otp" => "application/vnd.oasis.opendocument.presentation-template",
+ "presentation.ppt" => "application/vnd.ms-powerpoint",
+ "presentation.pptx" => "application/vnd.openxmlformats-officedocument.presentationml.presentation",
);
+
+ $dataset = array();
+ foreach ($files as $file => $type) {
+ $dataset[] = array("$dir/$file", $type);
+ }
+ return $dataset;
}
}