Forum Moderators: coopster

Message Too Old, No Replies

how would you test if a jpg was uploaded?

         

jatar_k

11:12 pm on Jun 5, 2006 (gmt 0)

WebmasterWorld Administrator 10+ Year Member



was just contemplating this today and figured I would ask and maybe we could figure out the best way.

I have done a bunch of things but let's what other members think

I was looking at something that uses the old lame extension test, which made me start looking through code to see what might be the best.

eelixduppy

11:19 pm on Jun 5, 2006 (gmt 0)



Hmmm...how about mime_content_type [us2.php.net]? The file extensions can be found here [duke.edu]

jatar_k

11:49 pm on Jun 5, 2006 (gmt 0)

WebmasterWorld Administrator 10+ Year Member



you could also read exif headers [ca3.php.net] and look at exif_imagetype [ca3.php.net]

coopster

11:59 am on Jun 6, 2006 (gmt 0)

WebmasterWorld Administrator 10+ Year Member



I still check the extension because I want it to have the correct extension after upload. But I also check the mime-type and meta data (as described in the Peer Code Review [webmasterworld.com]).

whoisgregg

1:31 pm on Jun 6, 2006 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



If I am expecting a jpeg I would run it through imagecreatefromjpeg [php.net] then output it with imagejpeg [php.net] as a "filter" of sorts.

imagecreatefromjpeg will fail if the source is not a jpeg and, if it is a jpeg but has some other payload, the processing and output should remove any extraneous crap. (If it doesn't I'd be surprised.)

dreamcatcher

1:41 pm on Jun 6, 2006 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Checking the extension is good, but you have to be careful of hackers who use files with a .php.jpg extension to exploit vulnerabilities.

dc

henry0

5:44 pm on Jun 6, 2006 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



whoisgreg is right on the money, many systems that I performed a "Post Mortem" on do figure that type of check.

Further
using is_uploaded_file()
PHP upload a file in a temp so we can check it there:
<?
$filename= $_FILES['attachment']['tmp_name']';
if (is_uploaded_file($filename) )
{
\\$_FILES['attachment']['tmp_name']
}
?>

then by the same token use
move_uploaded_file() to move it in its final destination

jatar_k

5:47 pm on Jun 6, 2006 (gmt 0)

WebmasterWorld Administrator 10+ Year Member



do you find you get image degradation using that filter method?

henry0

6:01 pm on Jun 6, 2006 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



You can create a dup and use that dup for checking purpose, then del the dup and work with the original.

jatar_k

6:08 pm on Jun 6, 2006 (gmt 0)

WebmasterWorld Administrator 10+ Year Member



anyone use just getimagesize [php.net]?

it tells you filetype and mime and returns false on a non image

sample return I am looking at

Array 
(
[0] => 308
[1] => 401
[2] => 2
[3] => width="308" height="401"
[bits] => 8
[channels] => 3
[mime] => image/jpeg
)

henry0

6:27 pm on Jun 6, 2006 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



I get info directly from the S G $_FILES
<<<
<?php
require_once ("../clean.inc.php"); // security function

// Get the details of "imagefile"
$filename = $_FILES['imagefile']['name'];echo"$filename<br>";

// slashed not needed here code
else
{
$temporary_name = $_FILES['imagefile']['tmp_name'];echo"$temporary_name<br>";
$mimetype = $_FILES['imagefile']['type'];echo"$mimetype<br>";
$filesize = $_FILES['imagefile']['size'];echo"$filesize<br>";

$path_img="img/$filename";
$path_thumb="img/thumbs/t_$filename";

$title=Clean($_POST['title']);
$alt_tag=Clean($_POST['alt_tag']);
$description=Clean($_POST['description']);
// etc....
?>

jatar_k

8:34 pm on Jun 6, 2006 (gmt 0)

WebmasterWorld Administrator 10+ Year Member



this is what I ended up playing around with today, stand alone, not using an uploaded image, seems to work

$imgfile_name = 'something.jpg';
$uperror = '';
$maxwidth = 400; // max allowed width for image
$maxheight = 600; // max allowed height for image

$imginfo = getimagesize($imgfile_name);

if ($imginfo[2]!= 2 ¦¦!$imginfo) {
$uperror = "<p>don't be an idiot, that isn't an image or it isn't a jpeg both of which are necessary";
} else if ($imginfo[0] < 1 ¦¦ $imginfo[0] < 1) {
$uperror = "<p>your image to have a width or height of 0, that's not going to work";
} else if ($imginfo[0] > $maxwidth) {
$uperror = "<p>your image is too wide, the max allowed is " . $maxwidth;
} else if ($imginfo[1] > $maxheight) {
$uperror = "<p>your image is too high, the max allowed is " . $maxheight;
}

if ($uperror!= '') {
echo '<p>You screwed up and here is why:<br>',$uperror;
unlink($imgfile);
die();
}

you could always add more checks for other things you may require, I was just playing

NOTE: replace ¦ chars with real pipe characters

whoisgregg

8:41 pm on Jun 6, 2006 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



For JPEGs I tend to prefer a quality level from 80-85 anyway as an acceptable compression level, so the filter is handy in reducing submitted photos at insane 90+ levels. So, yes, I do see degradation but I consider it acceptable and desirable.

Apologies, I got a bit confused and jumped to the punchline. :) I actually do use getimagesize to determine the filetype (precisely because it rolls a couple different functions into one), then whatever type it returns dictates the appropriate imagecreatefrom* and image* function to filter through.

I didn't know about the exif functions [php.net], those look handy.

coopster

11:31 pm on Jun 9, 2006 (gmt 0)

WebmasterWorld Administrator 10+ Year Member



I didn't realize that the getimagesize() [php.net] function does not require the GD image library. As jatar_k pointed out to me, this would obviously make it a bit more portable as opposed to the exif_imagetype() [php.net] function as it returns in index 2 the same value as exif_imagetype(). On the flip side, the manual states that exif_imagetype() is much faster. I ran quite a few tests on a smaller image (73 KB) and it is indeed faster, and much faster, but not when you see where. We are talking down into the ten-thousands of a second here. I tried it on a larger image (2155 KB) and still in the ten-thousands of a second difference. I'm sold on getimagesize() myself ;) thanks jatar_k