steveosoule
5/9/2017 - 4:17 PM

File Upload

File Upload

<?php

/**
 * ------------------------
 * Handle Uploaded File
 * ------------------------
 * This file take a posted $_FILE and save it to an uploads directory.
 * It will put it into a folder based on the user's Miva basket-id cookie.
 * It will return JSON describing the result/status of the upload and paths to the uploaded file
 */


/**
 * Constants
 */

// Store Settings
define('STORE_CODE', 'ABC');
define('STORE_BASKET_SESSION_ID', $_COOKIE['mm5-'.STORE_CODE.'-basket-id']);
define('STORE_EMAIL', 'contact@example.com');

// Upload Path
define('UPLOAD_FOLDER', 'uploads/');
define('DESTINATION_FOLDER', UPLOAD_FOLDER.STORE_BASKET_SESSION_ID.'/');
define('URL_BASE', $_SERVER['HTTP_ORIGIN'].dirname($_SERVER['SCRIPT_NAME']).'/' );

// File Size Helpers
define('KB', 1024);
define('MB', 1048576);
define('GB', 1073741824);
define('TB', 1099511627776);



/**
 * Functions
 */


function is_valid_md5($md5 ='') {
	return strlen($md5) == 32 && ctype_xdigit($md5);
}
function slugify($string)
{
	return str_replace('’', '', strtolower(preg_replace('/[^A-Za-z0-9-_]+/', '-', trim($string))));
}

function make_upload_directory(){
	if( !is_dir(DESTINATION_FOLDER) ){
		if( !mkdir(DESTINATION_FOLDER) ) {
			throw new RuntimeException('Error: Could not make upload directory. '.DESTINATION_FOLDER);
		}
		chmod(DESTINATION_FOLDER, 0775);
	}
}


/**
 * Main Upload Process
 */

header('Content-Type: application/json; charset=utf-8');

try
{

	// Validate Session & Basket ID Cookie Value
	if( !is_valid_md5(STORE_BASKET_SESSION_ID) )
	{
		throw new RuntimeException('Error: Invalid session.');
	}

	// Undefined | Multiple Files | $_FILES Corruption Attack
	// If this request falls under any of them, treat it invalid.
	if ( !isset($_FILES['file']['error']) || is_array($_FILES['file']['error'])	) {
		throw new RuntimeException('Error: Invalid parameters.');
	}

	// Check $_FILES['file']['error'] value.
	switch ($_FILES['file']['error']) {
		case UPLOAD_ERR_OK:
			break;
		case UPLOAD_ERR_NO_FILE:
			throw new RuntimeException('Error: No file sent.');
		case UPLOAD_ERR_INI_SIZE:
		case UPLOAD_ERR_FORM_SIZE:
			throw new RuntimeException('Error: Exceeded filesize limit.');
		default:
			throw new RuntimeException('Error: Unknown errors.');
	}

	// You should also check filesize here.
	if ($_FILES['file']['size'] > 5*MB) {
		throw new RuntimeException('Uploaded file exceeded file-size limit. Please contact '.STORE_EMAIL.' for assistance if the issue persists.');
	}

	// DO NOT TRUST $_FILES['file']['mime'] VALUE
	// Check MIME Type by yourself.
	$finfo = new finfo(FILEINFO_MIME_TYPE);
	if (false === $ext = array_search(
		$finfo->file($_FILES['file']['tmp_name']),
		array(
			'gif'	=> 'image/gif',
			'jpeg'	=> 'image/jpeg',
			'jpg'	=> 'image/jpeg',
			'png'	=> 'image/png'
			// 'ai'	=> 'application/illustrator',
			// 'bmp'	=> 'image/bmp',
			// 'eps'	=> 'application/postscript',
			// 'pdf'	=> 'application/pdf',
			// 'tiff'	=> 'image/tiff'
		),
		true
	)) {
		throw new RuntimeException('Uplodated file-type format is not allowed. Please only upload: gif, jpeg, or png files. Please contact '.STORE_EMAIL.' for assistance if the issue persists.');
	}

	// You should name it uniquely too.
	// DO NOT USE $_FILES['file']['name'] WITHOUT ANY VALIDATION !!

	// $safe_filename = 'upload_'.md5($_FILES['file']['name']).'.'.$ext;
	$safe_filename = 'upload_'.date('Y-m-d_H-i-s').'.'.$ext;
	$destination_file = DESTINATION_FOLDER.$safe_filename;
	$destination_url = URL_BASE.$destination_file;

	make_upload_directory();

	if (move_uploaded_file($_FILES['file']['tmp_name'], $destination_file) ) {
		chmod($destination_file, 0775);
		$result = array(
			'uploaded' => true,
			'message' => 'success',
			'description' => 'File successfully uploaded!',
			'file' => $destination_file,
			'url' => $destination_url
		);
		echo json_encode($result);
	} else {
		throw new RuntimeException('Error: Failed to move uploaded file. Please contact '.STORE_EMAIL.' for assistance if the issue persists.');
	}
}
catch (RuntimeException $e)
{
	// Error Message Display
	$result = array(
		'uploaded' => false,
		'message' => 'error',
		'description' => $e->getMessage()
	);
	echo json_encode($result);
}

?>
<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Uploader</title>
</head>
<body>
	<form action="upload.php" method="POST" enctype="multipart/form-data">
		File to Upload: <input type="file" name="file">
		<button>Submit</button>
	</form>
</body>
</html>