رتبه موضوع:
  • 0 رای - 0 میانگین
  • 1
  • 2
  • 3
  • 4
  • 5
کلاس EUP (آسان آپلود پرنس)
#1
Big Grin 
سلام دوستان وقت بخیر
مدتی پیش کلاسی برای آپلود نوشته بودم و در آن انجمن کذایی هم قرار داده بودم Big Grin
الان این کلاس رو به ورژن 1.4 ارتقا دادم که کمی در ساختار اون تغییرات ایجاد شده ، بهینه تر و سریع تر شده و در نهایت چند امکان بهش اضافه شده .

امکانات کلاس :
  • امکان آپلود به صورت تکی و چندتایی
  • امکان بررسی فرمت فایل و mimetype فایل
  • امکان ایجاد محدودیت برای حجم فایل (حداقل و حداکثر حجم فایل)
  • امکان تولید اسم تصادفی برای فایل
  • یونیکه سازی خودکار اسم فایل در صورت وجود فایل
  • خروجی آپلود به صورت آرایه همراه با ارور
موارد امنیتی آپلود رو هم داخل کلاس کاملا رعایت کردیم ، خیالتون راحت باشه  Cool

این هم کلاس :
class EUP {
	/**
	 * in the name of allah
	 * Easy Upload Prans
	 * @author Mahdi Sorkhabi
	 * @version 1.4
	 * @author website http://prans.info
	 * @author weblog http://sorkhabi.net
	 * The followings are the available columns in table 'agents':
	 * @property string $dir
	 * @property string $domin
	 * @property boolean $randomName
	 * @property integer $minSize
	 * @property integer $maxSize
	 * @property array $format
	 * @property array $log
	 * @property array $result
	 */
	private $_attributes = array(
		'dir',
		'domin',
		'randomName',
		'minSize',
		'maxSize',
		'format',
		'log' => array (),
		'result' => array(),
	);
	public function __construct ($dir,$domin,$format = array ('pdf'=> 'application/pdf'),$randomName = false,$minSize = 1024,$maxSize = 1048576)
	{
		$this->_attributes ['domin'] = $domin;
		$this->_attributes ['dir'] = $dir;
		$this->_attributes ['format'] = $format;
		$this->_attributes ['randomName'] = $randomName;
		$this->_attributes ['minSize'] = $minSize;
		$this->_attributes ['maxSize'] = $maxSize;
	}
	/**
	 * Magic Getter method
	 * @param string $fileName The name of attribute
	 *
	 * @return mixed The value of attribute
	 */
	public function __GET($fileName)
	{
		if(isset($this->_attributes)) {
			return $this->_attributes[$fileName];
		}
	}
	/**
	 * Magic setter method
	 * @param string $fileName The name of attribute
	 * @param mixed $value The value of attribute
	 */
	public function __SET($fileName, $value)
	{
		if(isset($this->_attributes)) {
			$this->_attributes[$fileName] = $value;
		}
	}
	/**
	 * Check the size
	 * @param integer $size The size to check
	 *
	 * @return boolean Whether the size is valid
	 */
	private function checkMaxSize($size)
	{
		return ($size <= $this->maxSize);
	}
	/**
	 * Check the size
	 * @param integer $size The size to check
	 *
	 * @return boolean Whether the size is valid
	 */
	private function checkMinSize($size)
	{
		return ($size >= $this->minSize);
	}
	/**
	 * Get the file extension
	 * @param string $fileName The filename
	 * @param boolean $lower Whether to return the extension in lowercase
	 *
	 * @return string The file extension
	 */
	private function getExtension($fileName)
	{
		mb_internal_encoding('utf-8');
		return mb_substr($fileName, mb_strrpos($fileName, '.') + 1);
	}
	private function checkFormat($fileName,$fileType)
	{
		$extension = $this->getExtension ($fileName);
		foreach ($this->_attributes ['format'] as $format => $MIME){
			if ($extension === $format and $fileType === $MIME){
				return true;
			}
		}
		return false;
	}
	/**
	 * Get the safe filename based on the original name
	 * @param string $fileName The original filename
	 *
	 * @return string The new filename
	 */
	private function newFileName($fileName)
	{
		$extension = '.' . $this->getExtension($fileName);
		if ($this->_attributes ['randomName']){
			return md5(rand(100000, 999999) . $fileName . rand(100000, 999999)) . $extension;
		}else{
			return str_replace('.', '-', basename($fileName,'.' . $this->getExtension ($fileName))) . $extension;
		}
	}
	/**
	 * Create a unique name
	 * @param string $fileName The original filename
	 *
	 * @return string The new filename
	 */
	private function uniqueName($fileName)
	{
		$baseName = basename($fileName,'.' . $this->getExtension ($fileName));
		$extension = '.' . $this->getExtension($fileName);
		$counter = 2;
		while(file_exists($this->dir . $fileName)) {
			$fileName = $baseName . '-' . $counter . $extension;
			$counter++;
		}
		return $fileName;
	}
	/**
	 * Add log
	 * @param string $log The log to add
	 */
	private function addLog($log)
	{
		$this->_attributes ['log'] = $log;
	}
	/**
	 * Do the real upload process
	 * @param array $element The file element (an element of $_FILES array)
	 *
	 * @return boolean|false The uploaded file URL on success, false otherwise
	 */
	private function uploadFile ($element,$key = false){
		$this->_attributes ['log'] = '';
		if ($key === false){
			list($name, $tempName, $error, $size, $mimeType) = array($element['name'], $element['tmp_name'], $element['error'], $element['size'], $element['type']);
		}else{
			list($name, $tempName, $error, $size, $mimeType) = array($element['name'][$key], $element['tmp_name'][$key], $element['error'][$key], $element['size'][$key], $element['type'][$key]);
		}
		if (trim ($name) !== '') {
			if ($error == 0) {
				if($this->checkFormat ($name,$mimeType)) {
					if($this->checkMinSize($size)) {
					   if($this->checkMaxSize($size)) {
							$newName = $this->newFileName($name);
							$newName = $this->uniqueName($newName);
							if(move_uploaded_file($tempName, $this->dir . $newName)) {
								$this->addLog ('فایل "' . $name . '" با موفقیت آپلود شد');
								$file = $this->domin . $newName;
							}
							else {
								$this->addLog('مشکلی در اجرای عملیات رخ داد (آپلود فایل "' . $name . '")');
							}
						}
						else {
							$this->addLog('سایز فایل "' . $name . '" بیش از اندازه مجاز می باشد');
						}
					}
					else{
						$this->addLog('سایز فایل "' . $name . '" کم تر از حجم مجاز می باشد');
					}
				}
				else {
					$this->addLog('پسوند فایل "' . $name . '" مجاز نیست');
				}
			}
			else{
				 $this->addLog('مشکلی در اجرای عملیات رخ داد (آپلود فایل "' . $name . '")');
			}
			if(isset ($file)){
				return array (
					'result' => true,
					'url' => $file,
					'log' => $this->_attributes ['log'],
					'fileName' => $name,
					);
			}else{
				return array (
					'result' => false,
					'url' => '',
					'log' => $this->_attributes ['log'],
					'fileName' => $name,
					);
			}
		}
		return false;
	}
	/**
	 * Execute the upload process
	 * @param array $element (an element of $_FILES array)
	 *
	 * @return array|string The upload result in single mode or an array of results in multiple mode
	 */
	public function upload($element,$multiple = false) {
		if (!is_dir ($this->_attributes ['dir'])){
			mkdir ($this->_attributes ['dir']);
		}
		if($multiple) {
			if(isset ($element ['name'])){
				$count = count ($element ['name']);
				for ($key = 0;$key < $count; $key++) {
					$result = $this->uploadFile($element,$key);
					if ($result){
						$this->_attributes ['result'][$key] = $result;
					}
				}
				return $this->_attributes ['result'];
			}
		}else{
			$result = $this->uploadFile($element,false);
			if ($result){
					$this->_attributes ['result'][0] = $result;
			}
			return $this->_attributes ['result'];
		}
	}
	public function checkUpload ($uploadResult){
		return (isset ($uploadResult ['0']) ? true : false);
	}
}
?>

نمونه کد برای آپلود به صورت تکی :
<?php
if(isset ($_POST ['one_ok'])){
	$eup = new EUP ('test/','http://site.com/test/');
	$result = $eup->upload ($_FILES ['one']);
	// نمایش فایل های آپلود شده
	if ($eup->checkUpload ($result)){
		if ($result [0]['result']){
			echo $result [0]['log'] . '<br />آدرس فایل : <br />'.$result [0]['url'];
		}else{
			echo $re ['log'] . '<br />';
		}
	}
}
?>
<meta charset="UTF-8">
<body dir="rtl">
<form method="post" enctype="multipart/form-data">
	<table>
			<tr><td>فایل :</td><td><input type="file" name="one"></td></tr></tr>
	
			<tr><td></td><td><input type="submit" name="one_ok" value="آپلود بفرما !!!"></td></tr></tr>
	</table>
</form>
</body>

نمونه کد برای آپلود چند تایی :
<?php
if(isset ($_POST ['multi_ok'])){
	$eup = new EUP ('test/','http://site.com/test/');
	$result = $eup->upload ($_FILES ['multi'],true);
	// نمایش فایل های آپلود شده
	if ($eup->checkUpload ($result)){
		foreach ($result as $re){
			if ($re['result']){
				echo $re ['log'] . '<br />آدرس فایل : <br />'.$re ['url'] . '<br />';
			}else{
				echo $re ['log'] . '<br />';
			}
		}
	}
}
?>
<meta charset="UTF-8">
<body dir="rtl">
<form method="post" enctype="multipart/form-data">
	<table>
			<tr><td>فایل :</td><td><input type="file" name="multi[]"></td></tr></tr>
			<tr><td>فایل :</td><td><input type="file" name="multi[]"></td></tr></tr>
			<tr><td>فایل :</td><td><input type="file" name="multi[]"></td></tr></tr>
			<tr><td>فایل :</td><td><input type="file" name="multi[]"></td></tr></tr>
			<tr><td></td><td><input type="submit" name="multi_ok" value="آپلود بفرما !!!"></td></tr></tr>
	</table>
</form>
</body>
از جناب شهرکی برای داکیومنت سازی و مرتب سازی کد در ورژن 1.3 تشکر می نماییم !!! Dodgy
پاسخ
تشکر شده توسط: php , Renegad , meysam1366
#2
سلام. چه نیازی هستش نام دامنه در constructor وارد بشه؟!
امکان آپـلود از URL رو هم میتونید بهش اضافه کنید؟
پاسخ
تشکر شده توسط: sorkhabi
#3
نام دامنه برای اینکه وقتی آدرس فایل رو که بهتون تحویل میده یک آدرس درست باشه .
فرضا :
http://prans.info/upload/1.png
خب شاید بگید چرا اینو از SERVER_NAME نمیگیریم و در نهایتش DIR رو بهش اضافه نمی کنیم ؟
در بعضی موارد ممکنه آدرس اصلی فایل با آدرسی که میشه بهش دسترسی پیدا کرد متفاوت باشه .

به احتمال زیاد اضافه خواهد شد و مثل حالت فعلی امکان آپلود به صورت تکی و مولتی رو خواهد داشت !
پاسخ
تشکر شده توسط: php , meysam1366
#4
سلام
آیا جلوگیری از آپلود شل در این کلاس بررسی شده .
به این آدرس برید
http://barnamenevis.org/showthread.php?4...8%A2%D9%86
اگه فیلمو ببینید متوجه میشید چقد راحت شل رو آپلود میکنن.
مرسی
پاسخ
تشکر شده توسط: sorkhabi
#5
یکی از موارد مهم امنیتی یعنی جلوگیری از آپلود شل بجای تصویر با کمک GD رعایت نشده تا اینجا که دیدم.
پاسخ
تشکر شده توسط: meysam1366 , sorkhabi
#6
وقتی تایپ و فرمت بررسی بشه و تایپ و فرمت درست وارد بشه چطوری شل اجرا میشه ؟
فکر نکنم بشه شل آپلود کردن چون هم تایپ چک میشه هم فرمت پس وقتی تایپ image/png هست دیگه چیز دیگه اجرا نمیشه ...
به هر حال بررسی می کنم ...
پاسخ
تشکر شده توسط:
#7
متاسفانه به راحتی میتوان شل رو آپلود کرد ، برای رفع این مشکل چه تغییراتی باید در کلاس صورت بگیرد ؟
پاسخ
تشکر شده توسط:




کاربران در حال بازدید این موضوع: 2 مهمان