How to get a file extension from a file name without extension? - php

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.

Related

Prevent uploading .sh files to server uisng php [duplicate]

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

Find Mime type of file or url using php for all file format

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!

How do I detect MIME type via a file handle in PHP?

I'm on 5.4 and looking to detect a mime type from my file handle. I know I can save off a file and then use functions by passing strings, but we want to avoid using strings. So is there a way without any strings?
Instead of passing a file handle or a string, pass an SplFileObject. Using this, you get OO access to the file without directly calling file system functions. Functions that require a pathname can still by used by calling ->getRealPath() on the object.
$finfo = new finfo(FILEINFO_MIME_TYPE);
$mime_type = $finfo->file( $fileObject->getRealPath() );
If your PHP installation supports Fileinfo:
$finfo = new finfo;
$mime = $finfo->file($file, FILEINFO_MIME);
finfo_close($finfo);
Where $file would be the full path to the file. $mime will then contain it's MIME type, for example 'image/jpeg' for a JPG image or 'text/x-php' for a PHP script.
Use fileinfo
$fileinfo = finfo_file($finfo, $file, FILEINFO_MIME);
finfo_close($finfo);
Or, you could do it the object-oriented way:
$finfo = new finfo();
$file = '/path/to/file/';
$fileinfo = $finfo->file($file, FILEINFO_MIME);
Use stream_get_meta_data to extract uri
$mime = mime_content_type(
stream_get_meta_data($fh)['uri']
);
Where $fh is our filehandle
AFAIK there's nothing inside a file content bytes that specifically tell the mime type. You have two options:
Detect the contents inspecting the bytes (actually I don't think this should be considered an option, given the difficulty and the performance implications involved).
Detect the mime type inspecting the file extension (if such extension exists): this method isn't error-proof, but is the accepted way of doing this (IMO). If the file haven't any extension, then you have a problem that can't be easily solved.

How to find out extension of a file through its url?

I am trying to find out what extensions a particular url has, Here is what I am trying to do:
$pathinfo = pathinfo('http://imgur.com/9P54j');
$extension = $pathinfo['extension'];
echo $extension;
The url 'http://imgur.com/9P54j' is actually a url having 9P54j.gif image, and its not evident in the url, how do I extract the extension .gif of the the file '9P54j' ?
That URL is not a URL to the .gf image, but a page that contains the image in its HTML. You will want to parse the HTML for the URL to the image. Try: rightclick on the image in the link you provided above, and click "open image" or "view image" to see the full URL.
Even that URL may not have an extension because the data may be streamed to the user bia PHP. If that's the case, just check the Content-Type header to find out what the extension is.
You can use a regex to extract it, something like this:
$url = 'http://imgur.com/9P54j';
$content = file_get_contents($url);
$explode = explode('/', $url);
preg_match('/http:\/\/i\.imgur\.com\/' . array_pop($explode) . '(\.[A-z]{1,4})/', $content, $matches);
$ext = $matches[1]; // '.gif'
My answer assumes that would like to grab the file's extension from urls that have no extensions in the url itself.
Using pathinfo() will not work as it retrieves the extension using text procession and in the url there is just no extension.
An approach would be to use lower level http functionality that allows to send a http request to the url and fetch the response headers. The response headers should regulary contain the 'Content-Type:' header that shows us the mimetype of the content.
Once having the 'Content-Type' header you could use a translation table and translation mimetype to file extension. This list of supported extensions would of course be limited und there are mimetypes that can translate to more than one extension. In such cases you would have to do further investigations on the files content itself.
As a real php programm would be too large for this answer I'll give just a pseudo code:
<?php
function get_extension_from_mimetype($url) {
// static translation table. to be extended
static $translationTable = array (
'image/jpeg' => 'jpg',
'text/xml' => 'xml',
'text/html' => 'html'
);
$defaultExtension = 'dat';
// you'll have to write this method
$mimetype = get_mimetype_by_url($url);
if(isset($translationTable[$mimetype])) {
$extension = $translationTable[$mimetype];
} else {
$extension = $defaultExtension;
}
return $extension;
}

PHP's FILEINFO_MIME option returns empty string

I'm trying to check the MIME type of an uploaded file in my PHP application. I upload the file, then do this, where $file is the path to my file:
$finfo = new finfo(FILEINFO_MIME);
$mimetype = $finfo->file($file);
In this situation, $mimetype is always an empty string. I've tested on several file types (.jpg, .doc, .txt, .pdf) and it's always empty. It's supposed to return something like "image/jpeg".
I was debugging and changed the first line so that the code snippet is now this:
$finfo = new finfo(FILEINFO_NONE);
$info = $finfo->file($file);
In this situation, when I uploaded a jpg, $info was this: JPEG image data, JFIF standard 1.02. So now I know it's getting to the file correctly, but passing in FILEINFO_MIME doesn't give me back the correct mime string.
This only happens on my staging server. On my local server, I get the correct mime type. Does anyone have any ideas why my staging server returns an empty string for mime type?
I'm wondering if the magic file is correctly placed on your server.
magic_file
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.
Since you can specify your own file Via the last argument
$finfo = new finfo(FILEINFO_MIME, "/usr/share/misc/magic");
Try this:
<?php
$fi = new finfo(FILEINFO_MIME,'/usr/share/file/magic');
$mime_type = $fi->buffer(file_get_contents($file));
?>
Did you try the example from the manual:
<?php
$finfo = finfo_open(FILEINFO_MIME_TYPE); // return mime type ala mimetype extension
echo finfo_file($finfo, $filename) . "\n";
finfo_close($finfo);
?>

Categories