This question already has answers here:
Check file extension in upload form in PHP [duplicate]
(10 answers)
Closed 3 years ago.
Currently in my code the extension of the files is checked before it is uploaded to the server. I need to check the content of the files too before uploading it to server. I have used the following code
$FileName = $_FILES[$imageInput]['name'];
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mtype = finfo_file($finfo, $FileName);
$mtype is correctly identified for all image type like .png , .jpg but it doesn't recognised .sh files. How can I check this using php? Some one please help.
You can block various files to be executed via .htaccess. For example you can place this
<FilesMatch "\.(sh|cgi.+)$">
ForceType text/plain
</FilesMatch>
This will ensure files in the folder will return as text/plain
If you want you can detect mime type as you detect for images. Mime type for .sh is
application/x-sh
application/x-csh
text/x-shellscript
In this case, you can try cross-validate between mime type and extension by taking the extension through the following scripts:
$fileExtension= end(explode(".", $_FILES["uploadedFile"]["name"]));
or
$fileName = ($_FILES['uploadedFile']['name']);
$fileExtension = pathinfo($fileName , PATHINFO_EXTENSION);
And later, apply something like:
$finfo = new finfo(FILEINFO_MIME_TYPE);
if (false === $fileExtension = array_search(
$finfo->file($_FILES['uploadedFile']['tmp_name']),
array(
//'sh' => 'text/x-shellscript', //not allowed
'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
'rtf' => 'text/rtf',
'odt' => 'application/vnd.oasis.opendocument.text',
'txt' => 'text/plain',
'pdf' => 'application/pdf',
),
true
)) {
$error .= "<br> The allowed file format file are: \"doc\", \"docx\", \"rtf\", \"odt\", \"txt\", \"pdf\"' ";
}
I had a problem similar to this, but in my case the file was .rtf type.
The FILEINFO_MIME_TYPE function apparently can not capture any type of file extension, this can lead to some validation errors.
Some examples:
The default mime type for .rtf files is application/rtf, but the FILEINFO_MIME_TYPE function displays text/rtf.
I wasted a lot of time trying to solve this bug as I described it here:
In the case of .sh files I noticed that the FILEINFO_MIME_TYPE function can not capture the extension, it returns me a null value
Related
I am trying to create a cross validation of uploaded files through phpmailer using the "extension X mime" file values, the system is working to almost all files that i need to do this, but exceptionally with .rtf files the script isn't working.
The extension just disappear, the script can't get this if the file is .rtf. I'm using this script: https://stackoverflow.com/a/33349901/4623271 with some adaptations.
Bellow in the code, is the variable $ext where i can get the extension of any files allowed by the verification, except .rtf files, when the file is a .rtf, the variable becomes apparently empty.
I tried using $ext = end(explode(".", $_FILES["uploadedFile"]["name"])); but in the same way, when is a .rtf file, the variable becomes empty.
// mime verification
$finfo = new finfo(FILEINFO_MIME_TYPE);
if (false === $ext = array_search(
$finfo->file($_FILES['uploadedFile']['tmp_name']),
array(
'doc' => 'application/msword',
'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
'rtf' => 'application/msword',
'odt' => 'application/vnd.oasis.opendocument.text',
'txt' => 'text/plain',
'pdf' => 'application/pdf',
),
true
)) {
$errorMsg .= "<br> Please, watch that the formats allowed are: \"doc\", \"docx\", \"rtf\", \"odt\", \"txt\", \"pdf\"' ";
}
For the time you spent reading this, thank you.
I have discovered that the problem is in mime value that i was using in array to validate the .rtf file.
The mime type readed by $finfo = new finfo(FILEINFO_MIME_TYPE); is not the usual mime type finded in online tables with this kind of information and that i have used to create the initial array.
After searching for help in a Brazilian PHP Telegram group, I received the hint to analyse the value of the $finfo variable.
When i applied var_dump ($finfo->file($_FILES['uploadedFile']['tmp_name'])); I discovered that to FILEINFO_MIME_TYPE the mime of .rtf files is: text/rtf and not application/rtf, that as i said above, is the most common option of mime type to .rtf files.
Because of this, the validation error was occurring since the script expected text/rtf to associate with .rtffile.
After I change the key value for text/rtf instead application/mswordor application/rtf , the script worked as expected.
Now i´m sending attachments with mime validation using phpmailer.
Thanks to all who tried to help in some way.
PHP: I am uploading image files in a folder with a name of particular format which is like postid_posttype_postserial.ext so that while showing particular blog post I would just use this format based on the post id, post type of that post. But problem here is I dont have extension of that file. So here is the actual question, how do I get the extension of a file of which I just know the name(in name.ext) not the extension.
FYI I searched for this and I found few function which returns extensions but you have to pass a full filename that is with extension to get the info about the file.
In your case, you need to get the mime type of the file then do a switch statement in PHP. You can get the mime type of the file by:
$finfo = finfo_open(FILEINFO_MIME_TYPE); // return mime type ala mimetype extension
$mime_type = finfo_file($finfo, $postid_posttype_postserial_file);
finfo_close($finfo);
$mime_types = array(
'image/gif' => '.gif',
'image/jpeg' => '.jpg',
// etc.
);
$ext = array_key_exists($mime_type, $mime_types) ? $mime_types[$mime_type] : false;
echo $ext;
Learn more: http://www.php.net/manual/en/function.finfo-file.php
Update 2: As pointed out by the comment, replacing switch to array matching is more elegant.
Hi I am looking for best way to find out mime type in php for any local file or url.
I have tried mime_content_type function of php but since it is deprecated I am looking for better solution in php for all file format.
mime_content_type — Detect MIME Content-type for a file ***(deprecated)***
I have already tried below function
echo 'welcome';
if (function_exists('finfo_open')) {
echo 'testing';
$finfo = finfo_open(FILEINFO_MIME);
$mimetype = finfo_file($finfo, "http://4images.in/wp-content/uploads/2013/12/Siberian-Tiger-Running-Through-Snow-Tom-Brakefield-Getty-Images-200353826-001.jpg");
finfo_close($finfo);
echo $mimetype;
}
Above code is not working for me, I am only seeing welcome for output.I am not sure if I am doing something wrong here.
Below code works somehow in my local but it does not work for urls.
$file = './apache_pb2.png';
$file_info = new finfo(FILEINFO_MIME); // object oriented approach!
$mime_type = $file_info->buffer(file_get_contents($file)); // e.g. gives "image/jpeg"
$mime = explode(';', $mime_type);
print $mime[0];
Is there some work around which work for both(url and local).what is the best practice to set mime type for all contents (image, video, file etc.) other than mime_content_type function in php.also is it recommended to use the mime_content_type function in php, Is it best practice in php ?
Make use of file_info in PHP with FILEINFO_MIME_TYPE flag as the parameter.
[Example taken as it is from PHP Manual]
<?php
$finfo = finfo_open(FILEINFO_MIME_TYPE); // return mime type ala mimetype extension
foreach (glob("*") as $filename) {
echo finfo_file($finfo, $filename) . "\n";
}
finfo_close($finfo);
?>
OUTPUT :
text/html
image/gif
application/vnd.ms-excel
EDIT :
You need to enable the extension on your PHP.ini
;extension=php_fileinfo.dll
Remove the semicolon from that line and restart your webserver and you are good to go. Installation Doc.
Found the answer,
To find the extension of the file best way is to use path_info for both local files and url.
$info = pathinfo($filename);
$basename = $info['basename'];
$ext = $info['extension'];
create an array for the mime type
$mimeTypes = array("mp4" => "video/mp4");// --> See Example here and Here
//get the mime type for file
$type = isset($this->mime_types[$ext]) ? $this->mime_types[$ext] : "application/octet-stream";
Above code works for both url and local files.
Note :
Those struggling with CDN mp4 video mime type video/mp4 issue - I had
made a change in my class.s3.php file -> in mime_type[] array and also
cross checked with putObject() function.
Setting of mime type is always done in coding side and not in AWS S3
bucket, We need to use AWS PHP Class file or sdk to do the
manipulation in mime type or make the necessary changes in core class
file (eg. class.s3.php )
$type = image_type_to_mime_type(exif_imagetype($file));
After I tried all these solutions above that's what I use:
$command = "file -i {$filename}";
$mimeTypeArr = shell_exec($command);
This command returns the line below:
filename: mime_type
After I have this I explode and get what I need.
$mimeTypeArr = shell_exec($command);
$mimeTypeArr = explode(':', $mimeTypeArr);
$mimeType = trim($mimeTypeArr[1]);
Hope it helps!
I'm experiencing a very odd upload problem. Here's the relevant view file:
<form action="http://localhost/index.php/temp/upload/" method="post" enctype="multipart/form-data">
<fieldset>
<input type="file" name="userfile"/>
<input type="submit" value="Upload"/>
</fieldset>
</form>
And here's my temp controller's upload() method:
public function upload()
{
$config['upload_path'] = FCPATH . 'uploads' . DIRECTORY_SEPARATOR;
assert(file_exists($config['upload_path']) === TRUE);
$config['allowed_types'] = 'avi|mpg|mpeg|wmv|jpg';
$config['max_size'] = '0';
$this->load->library('upload', $config);
if ($this->upload->do_upload('userfile') === FALSE)
{
// Some error occured
var_dump($this->upload->display_errors('', ''));
var_dump($_FILES);
}
else
{
// Upload successful
var_dump($this->upload->data());
}
}
When I upload an AVI video, everything works fine. When I upload, say, a WMV video, I get the following var dumps:
string 'The filetype you are attempting to upload is not allowed.' (length=57)
array
'userfile' =>
array
'name' => string 'wmv.wmv' (length=7)
'type' => string 'video/x-ms-wmv' (length=14)
'tmp_name' => string 'C:\wamp\tmp\php2333.tmp' (length=23)
'error' => int 0
'size' => int 83914
The "wmv" extension is being interpreted as the MIME type: video/x-ms-wmv. This should be fine since my config/mimes.php has the following:
'wmv' => array('video/x-ms-wmv', 'audio/x-ms-wmv')
It's a similar situation when I try uploading other files. So far, the only one that seems to work is my test AVI video.
Any ideas what might be wrong?
UPDATE 1:
One my machine, only AVI uploads. On another developer's machine, no files upload. On yet another developer's machine, all supported files upload. Are these browser or server issues?
You are using Firefox, aren't you?
You could try looking at system/libraries/Upload.php line 199:
$this->_file_mime_type($_FILES[$field]);
Change that line to:
$this->_file_mime_type($_FILES[$field]); var_dump($this->file_type); die();
Then do upload your .wmv file. It would show something like application/octet-stream or whatever. Add that to your mimes.php. Hope this help =)
Similar answer here
Some links:
CodeIgniter forum's thread
Mimetype corruption in Firefox
Getting around IE’s MIME type mangling
$config["allowed_types"] ="*";
Upload your .wmv file to the server using FTP/SFTP/scp/etc where you run the CodeIgniter application
On the server where you have uploaded the .wmv file, execute the following PHP code
<?php
$file_path = 'CHANGE_THIS_TO_ABSOLUTE_FILE_PATH_THAT_YOU_HAVE_UPLOADED.wmv';
$finfo = finfo_open(FILEINFO_MIME);
$mime = finfo_file($finfo, $file_path);
var_dump($mime);
?>
Save the code as mime.php
Run in the terminal - $ php mime.php
If it dumps any other value than you already have for wmv, append that value into wmv mime types.
Also check PHP_VERSION in other development machines. finfo_open is introduced in PHP 5.3. The development machine where upload is working may have an older version of PHP or it may have right mime type for the wmv.
did you try using mime types instead of extensions in $config['allowed_types']?
write it like this
$config["allowed_types"] = "video/x-msvideo|image/jpeg|video/mpeg|video/x-ms-wmv";
Answer for to Upload .doc file in CodeIgniter
Change this
'doc' => 'application/msword',
With this on line no 95 (application/config/mimes.php file)
'doc' => array('application/vnd.ms-word','application/msword'),
I've recently had some very similar problems with the Codeigniter's Upload Class.
The *allowed_types* doesn't seem to be working. For example, I wanted to allow .PNG images to be uploaded, but it wouldn't allow them through it's filter. I ended up investigating it further. I allowed all file types to be temporarily uploaded, I uploaded a .PNG, and then dumped the upload data ($this->upload->data());). For some reason, it thought the MIME type was text/plain! This might be related to your problem.
There are some solutions to this I found surfing some forums where you can modify/extend the class or core, but they didn't work for me -- sorry. I believe it's a Codeigniter Core bug (I think the issue has already been opened with EllisLabs). I ended up hard-coding the damn thing anyways! Well, I hope this helps you some.
Basic example/work-around,
//replace with your allowed MIME types
if ($_FILES['name_of_form_upload']['type'] != 'image/jpeg' && $_FILES['name_of_form_upload']['type'] != 'image/png' && $_FILES['name_of_form_upload']['type'] != 'image/gif') {
$data['message'] = '<div class="message">That file type is not allowed!</div>';
$this->load->view('home_view', $data);
} else {
//run upload code
}
Edit: Formatting/Grammar
Check your mimes.php file in application/config. It should return an array of mime types e.g return $mimes; at end of file or return array(..... in start of mimes array.
For Codeigniter 3.1.7 if you are providing a custom file name via $config['file_name'] ensure the filename has the file extension as well.
This is actually a bug in the core.. I upgraded to latest version of CI and the bug disappeared.
if you need the simple way to solve this,there is an easy solution for it.
open "system/libraries/Upload.php" file
line no 465
you will see
if ( ! $this->is_allowed_filetype())
{
$this->set_error('upload_invalid_filetype', 'debug');
return FALSE;
}
just make it true
if ( ! $this->is_allowed_filetype())
{
$this->set_error('upload_invalid_filetype', 'debug');
return TRUE;
}
note : it will stop your all file type validation.
Change IN application\config\Mimes.php
I'm developing a simple php upload script, and users can upload only ZIP and RAR files.
What MIME types I should use to check $_FILES[x][type]? (a complete list please)
The answers from freedompeace, Kiyarash and Sam Vloeberghs:
.rar application/vnd.rar, application/x-rar-compressed, application/octet-stream
.zip application/zip, application/octet-stream, application/x-zip-compressed, multipart/x-zip
I would do a check on the file name too. Here is how you could check if the file is a RAR or ZIP file. I tested it by creating a quick command line application.
<?php
if (isRarOrZip($argv[1])) {
echo 'It is probably a RAR or ZIP file.';
} else {
echo 'It is probably not a RAR or ZIP file.';
}
function isRarOrZip($file) {
// get the first 7 bytes
$bytes = file_get_contents($file, FALSE, NULL, 0, 7);
$ext = strtolower(substr($file, - 4));
// RAR magic number: Rar!\x1A\x07\x00
// http://en.wikipedia.org/wiki/RAR
if ($ext == '.rar' and bin2hex($bytes) == '526172211a0700') {
return TRUE;
}
// ZIP magic number: none, though PK\003\004, PK\005\006 (empty archive),
// or PK\007\008 (spanned archive) are common.
// http://en.wikipedia.org/wiki/ZIP_(file_format)
if ($ext == '.zip' and substr($bytes, 0, 2) == 'PK') {
return TRUE;
}
return FALSE;
}
Notice that it still won't be 100% certain, but it is probably good enough.
$ rar.exe l somefile.zip
somefile.zip is not RAR archive
But even WinRAR detects non RAR files as SFX archives:
$ rar.exe l somefile.srr
SFX Volume somefile.srr
For upload:
An official list of mime types can be found at The Internet Assigned Numbers Authority (IANA) . According to their list Content-Type header for zip is application/zip.
The media type for rar files, registered at IANA in 2016, is application/vnd.rar (see https://www.iana.org/assignments/media-types/application/vnd.rar). The mime-type value, application/x-rar-compressed, was used before that and is still commonly used even though it is marked as deprecated in the document above.
application/octet-stream means as much as: "I send you a file stream and the content of this stream is not specified" (so it is true that it can be a zip or rar file as well). The server is supposed to detect what the actual content of the stream is.
Note: For upload it is not safe to rely on the mime type set in the Content-Type header. The header is set on the client and can be set to any random value. Instead you can use the php file info functions to detect the file mime-type on the server.
For download:
If you want to download a zip file and nothing else you should only set one single Accept header value. Any additional values set will be used as a fallback in case the server cannot satisfy your in the Accept header requested mime-type.
According to the WC3 specifications this:
application/zip, application/octet-stream
will be intrepreted as: "I prefer a application/zip mime-type, but if you cannot deliver this an application/octet-stream (a file stream) is also fine".
So only a single:
application/zip
Will guarantee you a zip file (or a 406 - Not Acceptable response in case the server is unable to satisfy your request).
You should not trust $_FILES['upfile']['mime'], check MIME type by yourself. For that purpose, you may use fileinfo extension, enabled by default as of PHP 5.3.0.
$fileInfo = new finfo(FILEINFO_MIME_TYPE);
$fileMime = $fileInfo->file($_FILES['upfile']['tmp_name']);
$validMimes = array(
'zip' => 'application/zip',
'rar' => 'application/x-rar',
);
$fileExt = array_search($fileMime, $validMimes, true);
if($fileExt != 'zip' && $fileExt != 'rar')
throw new RuntimeException('Invalid file format.');
NOTE: Don't forget to enable the extension in your php.ini and restart your server:
extension=php_fileinfo.dll
I see many answer reporting for zip and rar the Media Types application/zip and application/x-rar-compressed, respectively.
While the former matching is correct, for the latter IANA reports here https://www.iana.org/assignments/media-types/application/vnd.rar that for rar application/x-rar-compressed is a deprecated alias name and instead application/vnd.rar is the official one.
So, right Media Types from IANA in 2020 are:
zip: application/zip
rar: application/vnd.rar
In a linked question, there's some Objective-C code to get the mime type for a file URL. I've created a Swift extension based on that Objective-C code to get the mime type:
import Foundation
import MobileCoreServices
extension URL {
var mimeType: String? {
guard self.pathExtension.count != 0 else {
return nil
}
let pathExtension = self.pathExtension as CFString
if let preferredIdentifier = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, pathExtension, nil) {
guard let mimeType = UTTypeCopyPreferredTagWithClass(preferredIdentifier.takeRetainedValue(), kUTTagClassMIMEType) else {
return nil
}
return mimeType.takeRetainedValue() as String
}
return nil
}
}
As extension might contain more or less that three characters the following will test for an extension regardless of the length of it.
Try this:
$allowedExtensions = array( 'mkv', 'mp3', 'flac' );
$temp = explode(".", $_FILES[$file]["name"]);
$extension = strtolower(end($temp));
if( in_array( $extension, $allowedExtensions ) ) { ///
to check for all characters after the last '.'