Jump to content


Photo

Extract file extension from an uploaded file


  • Please log in to reply
15 replies to this topic

#1 jo.nova

jo.nova
  • Members
  • PipPip
  • Member
  • 27 posts

Posted 13 July 2006 - 04:39 PM

I'm trying to isolate the file extension of  uploaded files so that I can check them for validity.  For example, say I want to only accept ".zip" files:

Let's say the value of $_FILES['somefile']['name'] is "afile.zip"; I want to put just the extension in a variable and check it against a predefined set of strings.  I can setup the string filtering, but I don't know how to tell PHP to look at just the last three characters in a file name.

Any help?

#2 kenrbnsn

kenrbnsn
  • Staff Alumni
  • Advanced Member
  • 8,235 posts
  • LocationHillsborough, NJ, USA

Posted 13 July 2006 - 04:42 PM

Use the function pathinfo()  http://www.php.net/m...on.pathinfo.php
<?php
$pi = pathinfo($_FILES['somefile']['name']);
echo '<pre>' . print_r($pi,true) . '</pre>';
?>

Ken

#3 akitchin

akitchin
  • Staff Alumni
  • Advanced Member
  • 2,516 posts
  • LocationCalgary, AB, Canada

Posted 13 July 2006 - 04:44 PM

another easy way of doing this is to use strrchr:

<?php
$filename = 'something.zip';
$extension = strrchr($filename, '.');
?>

would yield '.zip' in $extension.  use substr() if you want to remove the period as well.

#4 kenrbnsn

kenrbnsn
  • Staff Alumni
  • Advanced Member
  • 8,235 posts
  • LocationHillsborough, NJ, USA

Posted 13 July 2006 - 04:46 PM

That solution will only work for files with exactly one dot in them. It would break on files named, for example, something.ver.1.2.3.zip

Ken

#5 pixy

pixy
  • Members
  • PipPipPip
  • Advanced Member
  • 295 posts

Posted 13 July 2006 - 04:47 PM

$allowed = array('image/gif', 'image/jpeg', 'image/png');
if (in_array($_FILES['upload']['type'], $allowed) {
  // Continue to process
}
else {
  // Tell them its bad
}

And replace ['upload'] with whatever the name of the input you use is.

This is a .44 Caliber Loveletter straight through my heart.

Tabulas + Threadless + Hire Me!


#6 akitchin

akitchin
  • Staff Alumni
  • Advanced Member
  • 2,516 posts
  • LocationCalgary, AB, Canada

Posted 13 July 2006 - 05:31 PM

nay ken, strrchr() takes the LAST instance of the needle in the haystack, and returns it from there.  that's what's so handy about the function for this purpose.  you may be thinking of strchr().

#7 kenrbnsn

kenrbnsn
  • Staff Alumni
  • Advanced Member
  • 8,235 posts
  • LocationHillsborough, NJ, USA

Posted 13 July 2006 - 05:33 PM

My mistake, sorry.

Ken

#8 akitchin

akitchin
  • Staff Alumni
  • Advanced Member
  • 2,516 posts
  • LocationCalgary, AB, Canada

Posted 13 July 2006 - 05:43 PM

no need to apologize, the lovely PHP function-namers hardly made it obvious that strrchr is different from strchr.  but that's a beef for another day.

#9 jo.nova

jo.nova
  • Members
  • PipPip
  • Member
  • 27 posts

Posted 13 July 2006 - 06:12 PM

WOW! Thanks, guys.  I go to lunch, and return to find an entire disseratation on my topic.  Much appreciated!  I'm lovin' PHP; way better than my boring-ass C++ class. Thanks!

Now, here's the next part I just realized:

How do I make the match case insenstive?  (Just in case someone happens to have their file extension in caps)

#10 Koobi

Koobi
  • Staff Alumni
  • Advanced Member
  • 419 posts
  • LocationColombo, Sri Lanka | South Asia

Posted 13 July 2006 - 06:20 PM

I'm trying to isolate the file extension of  uploaded files so that I can check them for validity.  For example, say I want to only accept ".zip" files:

Let's say the value of $_FILES['somefile']['name'] is "afile.zip"; I want to put just the extension in a variable and check it against a predefined set of strings.  I can setup the string filtering, but I don't know how to tell PHP to look at just the last three characters in a file name.

Any help?


the thing is, an extension can be more than 3 characters so you wouldn't be doing a thorough job if you looked at the last 3 characters.
also, a file can be a text file and have a ".zip" extension or it could be a malicious exe and have a ".jpg" extension.
and if you plan to upload files such as tar.gz or tar.bz, etc (files with more than one extension - in this example, the file is an archived and compressed file), you would have to have some sort of work around to detect such extensions.


there are two options:
1. maintain an array of files with more than one extension that you permit. and first check if the last two blocks of characters (by a period) are in the array (using in_array()) that you maintain. if not, take the block of characters after the last period and check against that. i used to use this:
echo end(explode('.', $fileName));
but i think akitchin's strrchr() is faster than an explode.

2. match the value of $_FILES['upload']['type'] or mime_content_type() against an array of allowed MIME's and allow or disallow accordingly.



you might find this useful: Almost Every file format in the world!
or you could refer to /etc/mime.types if you're on a linux machine.

#11 jo.nova

jo.nova
  • Members
  • PipPip
  • Member
  • 27 posts

Posted 13 July 2006 - 06:24 PM

Sweet.  Good info, Koobi!  This board is so damn helpful.

#12 jo.nova

jo.nova
  • Members
  • PipPip
  • Member
  • 27 posts

Posted 13 July 2006 - 06:34 PM

So would this work?:

//put filename in a variable before checking file extension
$filetypecheck = ($_FILES['FileName']['name']);

//put file's extension in a variable
$extension = strrchr($filetypecheck, '.');
		
// check to see if a file was entered and if that file is a valid type
if ((!$_FILES['FileName']['name']) || ($extension !== "zip" || "sit" || "jpg" || "pdf" || "tif" || "gif" || "eps" || "psd"))

// if not, add that error to our array
$errors[] = '- Your file to be printed (in one of the acceptable formats)';


Or does it have to be like this?:

//put filename in a variable before checking file extension
$filetypecheck = ($_FILES['FileName']['name']);

//put file's extension in a variable
$extension = strrchr($filetypecheck, '.');
		
// check to see if a file was entered and if that file is a valid type
if ((!$_FILES['FileName']['name']) || ($extension !== "zip") || ($extension !== "sit") || ($extension !== "jpg") || ($extension !== "pdf") || ($extension !== "tif") || ($extension !== "gif") || ($extension !== "eps") || ($extension !== "psd"))

// if not, add that error to our array
$errors[] = '- Your file to be printed (in one of the acceptable formats)';


I'm new, so bear with me!


#13 akitchin

akitchin
  • Staff Alumni
  • Advanced Member
  • 2,516 posts
  • LocationCalgary, AB, Canada

Posted 13 July 2006 - 06:40 PM

it would be the latter format for the if() statement (ie. one condition for every possible extension), but three things:

1.  i would suggest simply putting all of your allowed extensions into an array and checking if the extension is in that array or not using in_array() (check the manual on the syntax).
2.  your logic is flawed.  it will check if the filename isn't set OR the extension isn't zip OR the extension isn't sit, etc.  it can't be both sit and zip at the same time, so it will always fail.  you'll need to change the extension checks to && (and operator).  using an array greatly simplifies this statement.
3.  strrchr() returns the '.' in the extension as well.  either change your allowed extensions to include the period or use substr() to remove the period in the file's extension (see manual for syntax).

#14 jo.nova

jo.nova
  • Members
  • PipPip
  • Member
  • 27 posts

Posted 13 July 2006 - 06:49 PM

Gotcha.  Yeah, you're right about the logic; I just uploaded it and got erros no matter what the file type is.  Thanks for the advice!

#15 Koobi

Koobi
  • Staff Alumni
  • Advanced Member
  • 419 posts
  • LocationColombo, Sri Lanka | South Asia

Posted 13 July 2006 - 06:50 PM

:Edit: akitchin has replied by the time i modified the code and posted it...but i'll post it anyway :)


first you would have to tell me if you intend to upload files that can have two valid extensions like tar.gz, etc.

if not, you would modify your code to this:

//put filename in a variable before checking file extension
$filetypecheck = trim($_FILES['FileName']['name']);

//put file's extension in a variable
$extension = strrchr($filetypecheck, '.');


$validTypes = array('.zip', '.sit', '.jpg', '.pdf', '.tif', '.gif', '.epf', '.psd');



// check to see if a file was entered and if that file is a valid type
if(!empty($filetypecheck) && in_array($extension, $validTypes))
{
	echo 'valid upload format';
}
else
{
	echo 'invalid upload format';
}



there's a bunch of other things you should look into if you want to strictly allow only files of a certain type but it seems like you're not very particular about that so this should work ok as far as i know.

hope that helped :)

#16 jo.nova

jo.nova
  • Members
  • PipPip
  • Member
  • 27 posts

Posted 13 July 2006 - 07:07 PM

akitchin, thanks everything you said worked out great!

Koobi, thanks man, got it working in the meantime.  Here's how I implemented it:

//put filename in a variable before checking file extension
$filetypecheck = ($_FILES['FileName']['name']);
//put file's extension in a variable
$extension = strrchr($filetypecheck, '.');
		
//make an array of allowed extensions
$allowext = array(".zip",".sit",".tif",".jpg",".pdf",".eps",".gif",".psd");
		
// check to see if a file was entered and if that file is a valid type
if ((!$_FILES['FileName']['name']) || (!in_array($extension, $allowext)))
// if not, add that error to our array
$errors[] = '- Your file to be printed (in one of the acceptable formats)';


We're a printshop, so we're probably not gonna get anything like .gz files from customers since almost the entire industry is using Macs.

Thanks guys!  I hope to get as proficient at this so that I can help others someday as well!




0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users