Jump to content

File upload restrictions


jarvis

Recommended Posts

Hi all,

 

hope someone can kindly assist. I've the following form:

		for ($i = 0; $i < MAX_IMAGE_UPLOADS; $i++)
		{
			echo '<tr>
				<td><p><b>File '.($i + 1).':</b> <input type="file" name="upload' . $i . '" /></p></td>
				<td><p><b>Image Description:</b> <textarea name="image_description' . $i . '" cols="25" rows="3"></textarea></p></td>
			</tr>';
		}

Which allows a set number of upload fields as defined by MAX_IMAGE_UPLOADS. The script then does it's thing using the following script to process the images:

				$article_insert_id =  mysql_insert_id();

				$image_path = 'uploads/'.$article_insert_id;

				if(isset($message))
					die ($message);

				// CREATE NEW DIRECTORY TO STORE IMAGES
				if(!file_exists($image_path))
				{

					if(mkdir($image_path))
					{

						// MAKE NEW IMAGE DIRECTORY WRITABLE
						if(chmod($image_path, 0777))

						{

							// HANDLE EACH UPLOADED FILE.
							for ($i = 0; $i < MAX_IMAGE_UPLOADS; $i++)
							{
								#echo $i;
								// Create index names to refer to the proper upload and description.
								$filename = 'upload' . $i;
								$image_description = 'image_description' . $i;

								// Check for a file.
								if (isset($_FILES[$filename]) && ($_FILES[$filename]['error'] != 4))
								{
									// Check for a description (not required).
									if (!empty($_POST[$image_description]))
									{
										$d = "'" . escape_data($_POST[$image_description]) . "'";
									} else {
										$d = 'NULL';
									}
									/*
										if (!empty($_POST['$image_description'])) {
											$d = escape_data($_POST['$image_description']);
										} else {
											$d = 'NULL';
										}*/

									// Add the record to the database										
									$query = "INSERT INTO uploads (article_id, file_name, file_size, file_type, image_description) VALUES (".$article_insert_id.", '{$_FILES[$filename]['name']}', {$_FILES[$filename]['size']}, '{$_FILES[$filename]['type']}', $d)";

									$result = mysql_query ($query) or die(mysql_error());

									if($result)
									{

										// Return the upload_id from the database.
										$upload_id = mysql_insert_id();

										// Move the file over.

										if (move_uploaded_file($_FILES[$filename]['tmp_name'], $image_path.'/'.$_FILES[$filename]['name']))
										{
											saveThumb($article_insert_id,$_FILES[$filename]['name']);
											//hidden as not required
											#echo '<p>File number ' . ($i + 1) . ' has been uploaded!</p>';
											#echo '<p>' . mysql_error() . '<br /><br />Query: ' . $query . '</p>'; // Debugging message.
											//include ('./includes/footer.html');

										} else { // File could not be moved.
											die('couldnt move file');
											echo '<p>File number ' . ($i + 1) . ' could not be moved.</p>';
											include ('./includes/footer.html');

											// Remove the record from the database.
											$query = "DELETE FROM uploads WHERE upload_id = $upload_id";
											$result = mysql_query ($query) or die(mysql_error());

										}


									} else { // If the query did not run OK.
										echo '<p>Your submission could not be processed due to a system error. We apologize for any inconvenience.</p>';
										// Print the query and invoke the mysql_error() function to debug.
									}

								//} else die('ERROR');
								} else die();

							} // End of FOR loop.
						// used for debugging
						} else die('could not chmod the image directory');
					// used for debugging
					} else die('could not make new image directory');
				// used for debugging
				} else die('could not make new image directory, directory exists. Please contact the administrator');

This then calls in the below function to resize and create the thumbnails:

<?php
function saveThumb($gal,$fn) {
  define("MAX_XY", 250); // maximum width or height of thumbnail image
$fpath = "uploads/$gal/$fn";
//print $fpath."\n";
/* GetImageSize returns an array:
 * $info[0] - horizontal size of image in pixels
 * $info[1] - vertical size of image in pixels
 * $info[2] - type of image (1=GIF, 2=JPEG, 3=PNG)
*/
$info = GetImageSize("$fpath");
//print_r($info);

// do we need to resize image?
if ($info[0] > MAX_XY || $info[1] > MAX_XY) {
	// is image landscape?
	if ($info[0] >= $info[1]) {
		$width = MAX_XY;
		$height = $info[1]*MAX_XY/$info[0];
	// or portrait?
	} else {
		$height = MAX_XY;
		$width = $info[0]*MAX_XY/$info[1];
	}
} else {
	// use original dimensions
	$width = $info[0];
	$height = $info[1];
}

// create new thumbnail image
//echo "<br>$width - $height<br>";
$im = ImageCreateTrueColor($width, $height);

/* determine image type and load original image. Notice new tests for image
 * types. The GD extension has changed a lot over the years, dropping GIFs
 * and adding PNG support. By testing, we avoid trying to process an image
 * PHP can't deal with
*/
$im_big = ""; // default is no image
switch ($info[2]) {
	case 1 :
		if (ImageTypes() & IMG_GIF) // test for GIF support 
			$im_big = ImageCreateFromGIF("$fpath");
		break;
	case 2 :
		if (ImageTypes() & IMG_JPG) // test for JPEG support 
			$im_big = ImageCreateFromJPEG("$fpath");
		break;
	case 3 :
		if (ImageTypes() & IMG_PNG) // test for PNG support  
			$im_big = ImageCreateFromPNG("$fpath");
		break;
	case 4 :
		if (ImageTypes() & IMG_BMP) // test for BMP support  
			$im_big = ImageCreateFromBMP("$fpath");
		break;			
}

if ($im_big) {
	/* resize original image into thumbnail - see PHP Manual for details on
	 * the arguements ImageCopyResized takes
	*/
	ImageCopyResized($im,$im_big,0,0,0,0,$width,$height,$info[0],$info[1]);
} else {
	// couldn't load original image, so generate 'no thumbnail' image instead
	$width = 100;
	$height = 100;
      	$im = ImageCreate($width, $height); // create a blank image
      	$bgc = ImageColorAllocate($im, 0, 0, 0); // background color = black
      	$tc  = ImageColorAllocate($im, 255, 255, 255); // text color = white
      	ImageFilledRectangle($im, 0, 0, $width, $height, $bgc); // draw rectangle
      	ImageString($im, 3, 9, 36, "No thumbnail", $tc); // add text
		ImageString($im, 3, 17, 48, "available", $tc);  
  	}

/* save our image in thumb directory - if the second argument is left out,
 * the image gets sent to the browser, as in thumbnail.php
*/
ImageJPEG($im, "uploads/".$gal."/t_".$fn);

// clean up our working images
ImageDestroy($im_big);
ImageDestroy($im);
  }

?>

How and where is the best way to only allow for certain file types and to stop the script with a 'wrong file type' error message?

 

Thank you in advanced!

Link to comment
Share on other sites

Oh I see, thank you! I did the following although not sure if its 'ideal':

Changed

if (isset($_FILES[$filename]) && ($_FILES[$filename]['error'] != 4))	

To

if (isset($_FILES[$filename]) && ($_FILES[$filename]['error'] != 4) && ($_FILES["file"]["type"] == "image/gif") || ($_FILES["file"]["type"] == "image/jpeg") || ($_FILES["file"]["type"] == "image/pjpeg") || ($_FILES["file"]["type"] == "image/bmp") ) 

Is that acceptable?

 

Thanks all!

Link to comment
Share on other sites

There is multiple ways to do the file extension checks.. this is what I have always used for it...

<?php
$extension = end(explode('.', $_FILES['tmp_name'])); 
$allowed = array('gif', 'jpg', 'jpeg');
if (in_array($extension, $allowed))
{
    // Allowed extension..
}
else
{
    // Not allowed extension..
} 

Link to comment
Share on other sites

File type can easily be spoofed so you should check file extension.

 

 

You can either use explode() and check the last element to do that, or you can use fileinfo().

 

File extension ain't safe either you could create executable code and rename it to a .jpg. When it opens, it executes the code. Same thing that happens with those higly believable 300 kb large .mp3 files.. A file extension is merely to add a recognition for us humans.

Link to comment
Share on other sites

Thanks all for you replies. So the method I used is not worthy?

 

Is it best to alter the main resize function below rather than altering the scripts for adding and editing images?

<?php
function saveThumb($gal,$fn) {
  define("MAX_XY", 250); // maximum width or height of thumbnail image
$fpath = "uploads/$gal/$fn";
//print $fpath."\n";
/* GetImageSize returns an array:
 * $info[0] - horizontal size of image in pixels
 * $info[1] - vertical size of image in pixels
 * $info[2] - type of image (1=GIF, 2=JPEG, 3=PNG)
*/
$info = GetImageSize("$fpath");
//print_r($info);

// do we need to resize image?
if ($info[0] > MAX_XY || $info[1] > MAX_XY) {
	// is image landscape?
	if ($info[0] >= $info[1]) {
		$width = MAX_XY;
		$height = $info[1]*MAX_XY/$info[0];
	// or portrait?
	} else {
		$height = MAX_XY;
		$width = $info[0]*MAX_XY/$info[1];
	}
} else {
	// use original dimensions
	$width = $info[0];
	$height = $info[1];
}

// create new thumbnail image
//echo "<br>$width - $height<br>";
$im = ImageCreateTrueColor($width, $height);

/* determine image type and load original image. Notice new tests for image
 * types. The GD extension has changed a lot over the years, dropping GIFs
 * and adding PNG support. By testing, we avoid trying to process an image
 * PHP can't deal with
*/
$im_big = ""; // default is no image
switch ($info[2]) {
	case 1 :
		if (ImageTypes() & IMG_GIF) // test for GIF support 
			$im_big = ImageCreateFromGIF("$fpath");
		break;
	case 2 :
		if (ImageTypes() & IMG_JPG) // test for JPEG support 
			$im_big = ImageCreateFromJPEG("$fpath");
		break;
	case 3 :
		if (ImageTypes() & IMG_PNG) // test for PNG support  
			$im_big = ImageCreateFromPNG("$fpath");
		break;
	case 4 :
		if (ImageTypes() & IMG_BMP) // test for BMP support  
			$im_big = ImageCreateFromBMP("$fpath");
		break;			
}

if ($im_big) {
	/* resize original image into thumbnail - see PHP Manual for details on
	 * the arguements ImageCopyResized takes
	*/
	ImageCopyResized($im,$im_big,0,0,0,0,$width,$height,$info[0],$info[1]);
} else {
	// couldn't load original image, so generate 'no thumbnail' image instead
	$width = 100;
	$height = 100;
      	$im = ImageCreate($width, $height); // create a blank image
      	$bgc = ImageColorAllocate($im, 0, 0, 0); // background color = black
      	$tc  = ImageColorAllocate($im, 255, 255, 255); // text color = white
      	ImageFilledRectangle($im, 0, 0, $width, $height, $bgc); // draw rectangle
      	ImageString($im, 3, 9, 36, "No thumbnail", $tc); // add text
		ImageString($im, 3, 17, 48, "available", $tc);  
  	}

/* save our image in thumb directory - if the second argument is left out,
 * the image gets sent to the browser, as in thumbnail.php
*/
ImageJPEG($im, "uploads/".$gal."/t_".$fn);

// clean up our working images
ImageDestroy($im_big);
ImageDestroy($im);
  }

?>

 

All help is very much appreciated! Thank you again

Link to comment
Share on other sites

I made some modifications to your code

 

- define() outisde of the function, it only has to be called once not on each and every call to saveThumb()

- $uploadDirectory is now a global variable and allows you to modify the path to the upload directory and saveThumb() doesn't need to be modified

- added some basic security $gal = basename($gal) which ensures that your function won't load a security file or something ($gal = ../../ $fn = somehighsecurityfile which would result in: uploads/../../somehighsecurityfile

 

<?php
define('MAX_XY', 250); // maximum width or height of thumbnail image

$uploadDirectory = realpath('uploads');
function saveThumb($gal,$fn) {
global $uploadDirectory;
$gal = basename($gal);
$fn = basename($fn);
$fpath = implode(DIRECTORY_SEPARATOR, array($uploadDirectory, $gal, $fn));
//print $fpath."\n";
/* GetImageSize returns an array:
 * $info[0] - horizontal size of image in pixels
 * $info[1] - vertical size of image in pixels
 * $info[2] - type of image (1=GIF, 2=JPEG, 3=PNG)
 */
$info = getimagesize($fpath);
//print_r($info);

// do we need to resize image?
if ($info[0] > MAX_XY || $info[1] > MAX_XY) {
	// is image landscape?
	if ($info[0] >= $info[1]) {
		$width = MAX_XY;
		$height = $info[1]*MAX_XY/$info[0];
	// or portrait?
	} else {
		$height = MAX_XY;
		$width = $info[0]*MAX_XY/$info[1];
	}
} else {
	// use original dimensions
	$width = $info[0];
	$height = $info[1];
}

// create new thumbnail image
//echo "<br>$width - $height<br>";
$im = ImageCreateTrueColor($width, $height);

/* determine image type and load original image. Notice new tests for image
 * types. The GD extension has changed a lot over the years, dropping GIFs
 * and adding PNG support. By testing, we avoid trying to process an image
 * PHP can't deal with
*/
$im_big = ""; // default is no image
switch ($info[2]) {
	case 1 :
		if (ImageTypes() & IMG_GIF) // test for GIF support 
			$im_big = ImageCreateFromGIF("$fpath");
		break;
	case 2 :
		if (ImageTypes() & IMG_JPG) // test for JPEG support 
			$im_big = ImageCreateFromJPEG("$fpath");
		break;
	case 3 :
		if (ImageTypes() & IMG_PNG) // test for PNG support  
			$im_big = ImageCreateFromPNG("$fpath");
		break;
	case 4 :
		if (ImageTypes() & IMG_BMP) // test for BMP support  
			$im_big = ImageCreateFromBMP("$fpath");
		break;			
}

if ($im_big) {
	/* resize original image into thumbnail - see PHP Manual for details on
	 * the arguements ImageCopyResized takes
	*/
	ImageCopyResized($im,$im_big,0,0,0,0,$width,$height,$info[0],$info[1]);
} else {
	// couldn't load original image, so generate 'no thumbnail' image instead
	$width = 100;
	$height = 100;
      	$im = ImageCreate($width, $height); // create a blank image
      	$bgc = ImageColorAllocate($im, 0, 0, 0); // background color = black
      	$tc  = ImageColorAllocate($im, 255, 255, 255); // text color = white
      	ImageFilledRectangle($im, 0, 0, $width, $height, $bgc); // draw rectangle
      	ImageString($im, 3, 9, 36, "No thumbnail", $tc); // add text
		ImageString($im, 3, 17, 48, "available", $tc);  
  	}

/* save our image in thumb directory - if the second argument is left out,
 * the image gets sent to the browser, as in thumbnail.php
*/
ImageJPEG($im, "uploads/".$gal."/t_".$fn);

// clean up our working images
ImageDestroy($im_big);
ImageDestroy($im);
  }

?>

Link to comment
Share on other sites

Will I need to make any other alterations elsewhere?

 

No, I don't think so. I have only one advice though before you start the resize process (which in itself is intense and may cause your script to timeout). You may want to bump up your memory limit or set the time limit for the execution of the script to 0. This way if the resizing takes longer then required or requires more resources then normal, it can otherwise the user will get an error on-screen telling him maximum execution has been reached. You can however also put a restriction of the maximum width and height. If the image is to large, remove it from the server and tell him he needs to resize it first to width x height before uploading it again. This saves you resources and you don't need to resize the image before you need to resize it again to create a thumbnail. Your visitors will thank you to as you save them bandwidth and they won't have to scroll 5 times because the image posted was in 1600x1200.

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.