View Full Version : validating file extensions
deletedUser2352352
July 4th, 2006, 11:18 AM
how can i use ereg to validate file extensions.
eg: .jpeg .jpg .gif .png .swf .zip
i have this code and i want to adapt it
function validateFile($thefile,$description = ''){
$result = ereg ("^[A-Za-z0-9\ ]+$", $thefile );
if ($result){
return true;
}else{
$this->errors[] = $description;
return false;
}
}
deletedUser2352352
July 4th, 2006, 11:55 AM
i solved it but using a different method
function validateFile($thefile,$description = ''){
$allowed_ext = "jpg, gif";
$extension = @pathinfo($thefile);
$extension = $extension[extension];
$allowed_paths = @explode(", ", $allowed_ext);
for($i = 0; $i < @count($allowed_paths); $i++) {
if ($allowed_paths[$i] == "$extension") {
return true;
}else{
$this->errors[] = $description;
return false;
}
}
}
Could any of you check to see if it could be made more efficient. before my head burns :red:
deletedUser2352352
July 4th, 2006, 12:11 PM
Ok this works up to a certain poit but wont validate anything other then a jpg it says all over are invalid even though i've specified them.
Any ideas?
function validateFile($thefile,$description = ''){
$allowed_ext = "jpg, gif, png, pdf, swf, zip";
$extension = @pathinfo($thefile);
$extension = $extension[extension];
$allowed_paths = @explode(", ", $allowed_ext);
for($i = 0; $i < @count($allowed_paths); $i++) {
if ($allowed_paths[$i] == "$extension") {
return true;
}else{
$this->errors[] = $description;
return false;
}
}
}
SlowRoasted
July 4th, 2006, 12:37 PM
Why aren't you useing $_FILES?
deletedUser2352352
July 4th, 2006, 12:42 PM
as that will be passed in via the function "$thefile" when called.
It works on the first file type in the list so if swf is first it will pick it up and say valid but it ignore the rest.
Jeff Wheeler
July 4th, 2006, 12:49 PM
<?php
function validate_extension ($filename, $description)
{
$valid_extensions = array( 'jpg', 'gif', 'png', 'pdf', 'swf', 'zip' );
preg_match( '/\.([a-zA-Z]+)$/', $filename, $file_matches );
if ( in_array( $file_matches[1], $valid_extensions ) )
{
// Valid
echo 'Valid';
}
else
{
// Invalid
echo 'Invalid';
}
}
validate_extension( 'file.gasd', 'uh' );
?>
deletedUser2352352
July 4th, 2006, 01:03 PM
bingo mate cheers for that makes sense now. doh on me.
This is how i used it :)
function validateFile($filename,$description = ''){
// array of allowed extensions
$valid_extensions = array( 'jpg', 'gif', 'png', 'pdf', 'swf', 'zip' );
// searches subject for a match to the regular expression given in pattern
preg_match( '/\.([a-zA-Z]+)$/', $filename, $file_matches );
// checks to see if the file has the allowed extensions
if ( in_array( $file_matches[1], $valid_extensions ) ){
return true; // if so return true
}else{
$this->errors[] = $description; // Extension not valid! Add error description to list of errors
return false;
}
}
Jeff Wheeler
July 4th, 2006, 01:07 PM
If you use PHP5, I recommend you check out exceptions (http://www.php.net/manual/en/language.exceptions.php):
<?php
function validate_extension ($filename, $description)
{
$valid_extensions = array( 'jpg', 'gif', 'png', 'pdf', 'swf', 'zip' );
preg_match( '/[a-zA-Z]+$/', $filename, $file_matches );
if ( in_array( $file_matches[0], $valid_extensions ) )
{
// Valid
return true;
}
else
{
// Invalid
return false;
}
}
validate_extension( 'file.gif', 'uh' );
?>
I also changed the regex and if, to be a tad shorter.
Edit: I've decided this is really not an appropriate use to throw an exception. It's a validation function, and it should return true or false, not true or die.
Edited the script
deletedUser2352352
July 4th, 2006, 01:09 PM
Cheers thanks for that i don't use php5 but i'll store that code when i move up.
Thanks for the help
Jeff Wheeler
July 4th, 2006, 01:11 PM
I edited my post… I figure since this is a validation function, it should not throw anything if the input is invalid.
Still, exception handling is important.
deletedUser2352352
July 4th, 2006, 01:21 PM
:)
deletedUser2352352
July 4th, 2006, 01:31 PM
just a thought is there anyway we can make it case sensitive so JPG works as well as jpg?
Jeff Wheeler
July 4th, 2006, 01:34 PM
Sure, just transform their input to all-lowercase:
function validate_extension ($filename, $description)
{
$valid_extensions = array( 'jpg', 'gif', 'png', 'pdf', 'swf', 'zip' );
preg_match( '/[a-zA-Z]+$/', $filename, $file_matches );
if ( in_array( strtolower( $file_matches[0] ), $valid_extensions ) )
{
// Valid
return true;
}
else
{
// Invalid
$this->errors[] = $description;
return false;
}
}
ramie
July 4th, 2006, 02:01 PM
would it not be better to validate the actual file type rather than the file extension? checking just the extension seems redundant and wrong to me, but im not sure what context your looking to use this, is it a file uploader?
Jeff Wheeler
July 5th, 2006, 12:15 AM
You mean checking the mime-type?
deletedUser2352352
July 5th, 2006, 03:50 AM
how would you check the mime type?
ramie
July 5th, 2006, 05:32 AM
$_FILES[$var]['type'] (http://uk.php.net/features.file-upload) is what you want to check,
so something like
if($_FILES[$var]['type'] == "image/gif"){
#valid
}else{
#invalid
}
http://www.phpfreaks.com/mimetypes.php for a list of MIME Types
deletedUser2352352
July 5th, 2006, 05:45 AM
hmm i'm all confused now.
What i want it to do is check if its of a certain file type and then uploaded it to a folder and store the url of that file in a database.
I've done this before but i'm trying out another way using the system i've posted above
When the file is called it will be place between <img /> if its an image <a></a> if its a file such as zip, txt, php etc to download.
So what system is best?
ramie
July 5th, 2006, 05:56 AM
MIME checking would still be better, a user could just change the file extension and upload anything causing all types of trouble, you can still act on the file if it's an image, zip or whatever, but you can have more assurance it is what it's supposed to be.
deletedUser2352352
July 5th, 2006, 05:59 AM
i see.
I'm just looking at that if else statment and thinking wow that will be a lot of code. Could yu store the mime-types in an array and then loop through them to check?
If so how could i do that?
ramie
July 5th, 2006, 06:23 AM
Link (5th post down) (http://www.sitepoint.com/forums/showthread.php?t=397566) is a good example of what you want.
deletedUser2352352
July 5th, 2006, 07:23 AM
aghh i can't get it to work!!!
this is what i have now
function validateFile($filename,$description = ''){
$imageTypes = array('image/pjpeg' => 'jpeg','image/jpeg' => 'jpeg','image/gif' => 'gif','image/x-png' => 'png','image/png' => 'png');
if (in_array($filename, $this->$imageTypes)){
return true;
}else{
// File is not an image of one of our types
$this->errors[] = $description; // Extension not valid! Add error description to list of errors
return false;
}
}
//call the function
validateFile($_FILES['file']['type'],'invalid file extensions');
it throws up this error
Warning: in_array(): Wrong datatype for second argument in /
deletedUser2352352
July 5th, 2006, 08:19 AM
Weird i've got it working now
Could someone just check to make sure its doing the right thing?
// validates file by mime-type
function validateFile($filename,$description = ''){
$imageTypes = array(
'image/jpeg' => jpeg,
'image/gif' => gif,
'image/x-png' => png,
'image/png' => png,
'application/x-shockwave-flash' =>flash,
'application/pdf' => pdf,
'application/x-pdf' => pdf,
'application/acrobat' =>pdf
);
if (array_key_exists($filename, $imageTypes)){
return true;
}else{
// File is not an image of one of our types
$this->errors[] = $description; // Extension not valid! Add error description to list of errors
return false;
}
}
Jeff Wheeler
July 5th, 2006, 12:31 PM
The PHP documentation states that we should not use mime-types defined by the browser:
The mime type of the file, if the browser provided this information. An example would be "image/gif". This mime type is however not checked on the PHP side and therefore don't take its value for granted.
SlowRoasted
July 5th, 2006, 01:06 PM
$_FILES[$var]['type'] is what you want to check,
Yeah, I wrote an upload script using that and it worked fine.
deletedUser2352352
July 5th, 2006, 01:13 PM
its working sweet as well.
ramie
July 5th, 2006, 01:44 PM
The PHP documentation states that we should not use mime-types defined by the browser:
It dosent state that, it states that you not take it's value for granted, which is sensible advice, good validation should always be a two or even 3 tier process.
However bluffing the MIME type is a lot harder for the casual user than changing the file extension, and what about OS that dont even rely on file extensions such as linux.
deletedUser2352352
July 5th, 2006, 01:58 PM
Well this upload code is behind a secure area where the users arn't very web savvy.
But for further reference what would your two/three tier approach be ramie?
mime-type validation
extension-type validation
maybe?
ramie
July 5th, 2006, 02:10 PM
I would validate the mime type on the client site after submission to the upload script (if I was really paranoid I would also do a quick file extension check at this stage), once the file has uploaded I would then do some server side checking on the file to make sure it is what it's supposed to be, before I move it to it's final destination.
Never assume when it comes to a web application, assuming they are not web savvy is asking for it, this kind of thinking may also filter through everything you do and the entire application, so you may leave bigger holes elsewhere. I've seen databases being hacked with a simple email form so always assume the worst when users are involved.
deletedUser2352352
July 5th, 2006, 02:12 PM
ok so could you check my mime-type validator and see if there is any errors in it that could be slipped past?
ramie
July 5th, 2006, 02:23 PM
It looks fine so far, add 'image/pjpeg' => jpeg for progressive jpg's
I would also check the filesize, make sure it's not 0 and make sure it does not exceed the maximum size limits.
$_FILES[$var]['size'] provides you the file size information.
deletedUser2352352
July 5th, 2006, 02:34 PM
yeah i've already built in a file size validator that check to see if it goes over or is 0. i'll add image/preg as well.
I'll use the file extension validator as well that was posted previous just be careful.
Would this work as well for none image files such as swf's and xml files?
Also how do you hack a file to change its mime-type so i can check it properly?
Thanks for all the help as well
ramie
July 5th, 2006, 02:51 PM
The easy way to test it is to create a txt file, rename that to testfile.gif and try and upload it, it should fail.
To try some hardcore mime type spoofing you should Google it, there is lots of info out there on this, browser vulnerabilities and lots of ways to avoid it, posting links to it may not be so smart in an open forum.
You already test for swf 'application/x-shockwave-flash' =>flash, xml is just a plain text file, MIME checking will work for anything that has a MIME type.
http://www.phpfreaks.com/mimetypes.php
deletedUser2352352
July 5th, 2006, 02:56 PM
i've tried that with a text file and renaming it .gif instead and it still uploads.
But is that cause i'm running OS X?
But when i check these files after uploading them nothing comes up on screen.
ramie
July 5th, 2006, 03:07 PM
It's more likely that its a txt file and it's allowed, what browser are you using on the mac, also try renaming somethng like a .doc to .gif and upload that
deletedUser2352352
July 5th, 2006, 03:09 PM
i'm using safari at the min
i'll try that with a doc then
deletedUser2352352
July 5th, 2006, 03:12 PM
nope still uploaded i tried a power point press changed it to .jpg
am i missing something?
ramie
July 5th, 2006, 03:12 PM
I think safari has some issues with MIME types, perhaps a mac user can answer that one better.
Test with the target browser, how many of your end users are likely to be on a mac and using safari.
deletedUser2352352
July 5th, 2006, 03:15 PM
true i'll try netscape, firefox and IE
deletedUser2352352
July 5th, 2006, 03:21 PM
nope its not being picked up on those browsers as well.
It wont allow uploading of files that haven't got the right extension with that code though so its doing something if not what i want
ramie
July 5th, 2006, 03:25 PM
Try this File Handler Component (http://cakeforge.org/snippet/detail.php?type=snippet&id=36)
deletedUser2352352
July 5th, 2006, 03:29 PM
thanks i'll take a look see what i can figure out.
I just wonder whats going wrong in my code.
Jeff Wheeler
July 5th, 2006, 06:28 PM
I'm pretty sure most browsers (maybe this is because of the OS) will base the mime-type on the extension.
Also, rather than giving specific mime-types, you could use the type, first, such as just 'text/', with any value afterwards (for example, xml would be text/xml, plain-text would be text/plain, etc).
deletedUser2352352
July 6th, 2006, 03:45 AM
could you explain a little further please?
deletedUser2352352
July 6th, 2006, 06:03 AM
Ok so how now got it working and its working well.
It only works on files that have been uploaded so if it see that the file is not of the correct type it unlinks it and aborts the save to the database(thats in another part of the code but you get the idea.
Could someone check this to make sure i haven't opened up any holes?
function validateFile($filename,$description = ''){
if (!function_exists('mime_content_type')){
$filetype = system(trim('file -bi ' . escapeshellarg ($filename)));
}else{
$filetype = mime_content_type($file);
}
$imageTypes = array(
'image/jpeg' => jpeg,
'image/pjpeg' => jpeg,
'image/gif' => gif,
'image/x-png' => png,
'image/png' => png,
'application/x-shockwave-flash' =>flash,
'application/pdf' => pdf,
'application/x-pdf' => pdf,
'application/acrobat' =>pdf
);
if (array_key_exists($filetype, $imageTypes)){
return true;
}else{
// File is not an image of one of our types
$this->errors[] = $description; // Extension not valid! Add error description to list of errors
return false;
}
}
ramie
July 6th, 2006, 06:49 AM
At a glance that looks fine, but if you really want to test it properly have a look at unit testing.
http://www.lastcraft.com/first_test_tutorial.php
http://www.google.co.uk/search?q=php+unit+testing&start=0&ie=utf-8&oe=utf-8
Test driven development is the ticket, at the start it seems convoluted, but once you get used to it you will save loads of time and have more peace of mind with your applications.
deletedUser2352352
July 6th, 2006, 07:37 AM
thanks for that and cheers for all your help
Powered by vBulletin® Version 4.1.10 Copyright © 2012 vBulletin Solutions, Inc. All rights reserved.