I'm on 5.3.1 and after reading the docs, I see that fileinfo is included and that pecl is no longer required. I an however getting:
finfo_file(): File or path not found
I'm not sure what it's looking for. I've enabled the extension in the ini file and attempted to run the example from the PHP site:
$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);
Can someone tell me what file I need?
I've just discovered from my hosting company that the path to the elusive magic.mime file is to be found when running phpinfo(): look for the entry "mime_magic.magicfile". If it's not listed, contact your hosting company and explain you need this file and path for PHP finfo(). Worked for me.
You need to either configure your environment so PHP knows where the "magic database file" is, or, as another possibility, when calling fileinfo_open, you need to specify the path to the magic database file (quoting) :
Name of a magic database file, usually
something like /path/to/magic.mime. If
not specified, the MAGIC environment
variable is used. If this variable is
not set either, /usr/share/misc/magic
is used by default. A .mime and/or
.mgc suffix is added if needed.
See the example given on the manual page of fileinfo_open, for instance (quoting) :
$finfo = finfo_open(FILEINFO_MIME, "/usr/share/misc/magic"); // return mime type ala mimetype extension
if (!$finfo) {
echo "Opening fileinfo database failed";
exit();
}
/* get mime-type for a specific file */
$filename = "/usr/local/something.txt";
echo finfo_file($finfo, $filename);
/* close connection */
finfo_close($finfo);
Of course, up to you to find where that file is on your system...
Related
I have tried both the options:
mime_content_type function
echo mime_content_type($img_path);
finfo function
$finfo = finfo_open(FILEINFO_MIME_TYPE);
echo finfo_file($finfo, $img_path);
finfo_close($finfo);
But I am getting error for both the cases
"Warning: finfo_file(): Failed identify data 0:no magic files loaded"
I am not getting what is the issue in this?
For people wondering in the future, the original poster probably had an external URL set as the path - both the "mime_content_type" & "finfo" functions can only be ran on local paths and not external URLS.
Example:
// Local file path
echo mime_content_type("image.gif");
Will return: image/gif
// External file path
echo mime_content_type("http://localhost/image.gif");
Will return "Warning: mime_content_type(): Failed identify data 0:no magic files loaded"
Fallback versions and more information on usage of these functions can be found in the manual on PHP.net:
mime_content_type:
http://php.net/manual/en/function.mime-content-type.php
finfo functions: http://php.net/manual/en/book.fileinfo.php
looks like $img_path is not containing any file or wrong file path.
Ok here is my code for uploading files
$ext_whitelist = array('pdf','doc','doc','mkv','mp4','mpg','mpeg','avi','flv','wma','ogg');
if(in_array($ext, $ext_whitelist))
{
$uniqid_file = uniqid('', true)."_".$file['name'];
$lokacija = $folder . "/" . $uniqid_file;
$encoded_uniqid_file = base64_encode($uniqid_file);
move_uploaded_file($file['tmp_name'], $lokacija);
$base_url= base_url("forms/fdownload/$encoded_uniqid_file/$path");
$form_data[$key] = "$uniqid_file ";
}
This checks file extension, so easy some could rename file, can someone help me to check file type proper?
Insted of a comment, I'll write a bit more as an answer.
Mimetype checking is a good thing if you want to know the type of the file, but it's not secure if you want to allow/deny the files at upload, because it's very easy to fake the mimetype.
Just try it, you can change it with a proxy or you can create a simple image, then add some php code at the end and rename it to .php. If you only check the mimetype, you can upload this .php file and run it on the server.
If you upload .jpg with php code in it, it's okay, the server won't push it through the php parser. (Except when you change the default configuration. (Apache: AddType, nginx: AddHandler )
There are some "secure" ways to check the uploaded files:
1. Check the extension and compare it to a whitelist.
This is the example in the question, but I'd like to write a complete solution. (A common mistake to check only the first think after the ., because there could be file names like: something.txt.php so always check the last postfix.)
$ext = array_pop(explode(".", $fileName));
$whitelist = array('pdf','doc','doc','mkv','mp4','mpg','mpeg','avi','flv','wma','ogg');
if (in_array($ext, $whitelist) {
//OK the extension is good, handle the upload.
} else {
//Wrong type, add error message.
}
If you use something like this, be careful and never allow extensions like .php and anything wich is in the server config.
2. Rename the file and drop the extension.
This is an another good way, but maybe you want to keep the original file name, the extension and the mimetype. You can store them in a database!
For this solution just take the original filename, add some random data (because if you upload into a single folder and you trie to upload something.jpg 2 time that would be a bad idea), then store this.
For example:
$newName = sha1($fileName.time());
move_uploaded_file($file['tmp_name'], $uploadPath . $newName);
Because the file doesn't have an extension, the server wont try to run it. (But if it's for example an image it'll work in the browsers, because they use the mimetype to determine the type and we didn't changed that.)
You can use
perl-file-mimeinfo
Ex:-
$file_path = '/tmp/temp.jpg';
$mimetype = trim(shell_exec("/usr/bin/mimetype -bi ".escapeshellarg($file_path)));
$info = null;
if(strpos($mimetype, "video/")===0 || strpos($mimetype, 'x-flash-video') > 0){
$info = 'video';
}elseif(strpos($mimetype, "audio/")===0){
$info = 'audio';
}elseif(strpos($mimetype, "image/")===0){
$info = 'image';
}
I have a file called 94bf663a100e848fb599209af8cdc2b5.wmv. I know pathinfo will not give me the extension if I just use the name 94bf663a100e848fb599209af8cdc2b5. I believe glob is only for checking if a file exists. So is it possible to get a file extension just knowing the file name (94bf663a100e848fb599209af8cdc2b5)?
As the example on the php glob manual page suggests, glob does not simply check if the file exists, it returns every file that matches the expression.
Here's a modification of the example on that page for your needs:
$name = "94bf663a100e848fb599209af8cdc2b5";
$matching = glob($name . ".*");
$info = pathinfo($matching[0]);
$ext = $info['extension'];
This assumes there is one (and only one) file with that name (with any extension), but you should be able to modify it if the file might not exist, or there might be multiple files with the same name, and different extensions.
The finfo_file() function will inspect the byte signature of a file to return its mimetype. From there, you can mostly deduce the correct file extension.
// Adapted from the PHP docs
$finfo = finfo_open(FILEINFO_MIME_TYPE); // return mime type ala mimetype extension
echo finfo_file($finfo, $filename);
finfo_close($finfo);
The first few characters of the file (binary) will usually give you some kind of hint about what the file type is.
Try it out by opening some binary files (rar, zip, mp3 etc.) in Notepad.
Try filetype() or mime_content_type() function in php...
pass the file path it returns the file type.
Is there a way to detect the mime type of a file without actually having an actual file, for example when you're generating the file and serving it as a download?
I'm currently using file extension sniffing from here:
http://www.php.net/manual/en/function.mime-content-type.php#87856
I was just wondering if there was another way short of actually creating the file on the server and using FileInfo, mime_content_type(), or file
Try the Fileinfo finfo_buffer() function:
$filename = 'image.jpg';
$contents = file_get_contents($filename);
$finfo = finfo_open(FILEINFO_MIME_TYPE);
var_dump( finfo_buffer($finfo, $contents) ); // string(10) "image/jpeg"
You do say "short of actually creating the file," so this seems to meet your requirements even though it uses Fileinfo.
Have you tried writing it to a ramdisk - shouldn't have a significant speed penalty and you can use the standard functions
You might want to pipe it as such:
$type = `echo $FILE_CONTENTS | file -bi -`
READ: This is a bad idea. Do not do this. 'Command line injection' (thanks to Andrew Moore for point this out.)
If you know the type of file you're generating, just consult an array of known mime types and apply as appropriate.
you can check this :
$filename = 'image.jpg';
$filename2 = 'file.php';
echo mime_content_type($filename) . "<br>";
echo mime_content_type($filename2);
I have a .doc file and I renamed named it to give it a .jpg extension. When I process the renamed file with my function it accepts the file as having a .jpg although the file is not really a JPEG. What's the best way to find the actual file type? Here is my current code:
function getExtension($str) {
$i = strrpos($str,".");
if (!$i) { return ""; }
$l = strlen($str) - $i;
$ext = substr($str,$i+1,$l);
return $ext;
}
What's the best way to check the file's type without depending on the extension?
You can use PHP's Fileinfo to detect file types based on their contents; however, it is only available in PHP 5.3.0 or if you have access to install PECL extensions.
It returns a file's mime-type, such as text/html, image/gif, or application/vnd.ms-excel which should be more accurate (accounts for contents possibly having multiple common extensions, such as: jpg, jpe, jpeg).
This is the one I use and it has never failed me.
function getExtension($str)
{
$i = explode('.', $str);
return strtolower(end($i));
}
I don't know if you can check the actual original file extension if someone has renamed it, you would have to have the spec of every file type you were checking for I'm not sure how easy it is to tell. But you could verify something was an image like this:
function isImage($file)
{
if(#getimagesize($file) == false)
return false;
else
return true;
}
Summing up
if(isImage($file) && getExtention($file) == "jpg")
{
//Process, it's a valid image
}
Firstly, with respect to file extension, on't reinvent the wheel. Use PHP's pathinfo() function:
$extension = pathinfo($filename, PATHINFO_EXTENSION);
Secondly, you're quite right: the file extension tells you nothing about it's contents.
Third, you should where possible determine the contents of the file yourself rather than relying on either the file extension or the MIME type (from file uploads). Both are arbitrary and simply specified by the client.
Images are fairly easy because you can load the file with the GD library. It'll fail if its not an image and you can interrogate it for size, etc.
Word documents are harder. If you're running on Windows, you can make a call to the system to load the file and see if it does load. I'm not aware of any native PHP library that can do this.
If you just want to get the file extension, you could use pathinfo:
function getExtension($str)
{
$info = pathinfo($str)
return $info['extension'];
}
However, it sounds like you want to check if the file you're given is a valid image. To do that, you can do something similar with the getimagesize() function:
function getMimeType($str)
{
$info = #getimagesize($str)
if (!$info)
{
// Uh oh, this wasn't a valid image -- do some error handling
return NULL;
}
return $info['mime'];
}
Using this, you can check the MIME type of the image ("image/jpeg", etc.), and validate if the given file is really the type of image you think it is.
You can use explode(".", $sFileName) and take the last item of the array to do this, but that one fails when you have something like filename.tar.gz, when you want the last two array items, or filename.class.php, when, after you have implemented the last-two-array-items-thing, you just want the last one.
The best way of doing this is, in my opinion, pathinfo($sFileName). This returns an array with the keys dirname, basename, extension (if any), and filename.
If you want the file type, though, you'll have to use something like PHP 5.3's built-in Fileinfo to get the file's MIME-type. (getimagesize() returns the MIME-type too, but this only works on images!)
function file_extension($filename) {
$path_info = pathinfo($filename);
return $path_info['extension'];
}