آموزش ساخت لینک دانلود غیر مستقیم در PHP ( تغییر و هش لینک فایل )
دانلود غیر مستقیم در PHP – با کمک الگوریتمی که در آموزش قبلی یاد گرفتیم مسیر فایل را hash کرده و زمانی که درخواستی برای دانلود از سوی کاربر ارسال می گردد
hash داده شده را رمزگشایی کرده و در صورتی که در مسیر files وجود داشت فایل را برای دانلود ارسال می کنیم همچنین اگر فایل وجود داشت اما در مسیر files نبود باز هم کاربر با پیغام فایل یافت نشد مواجه می شود .
چون نمی خواهیم که کاربر اسکریپت های php داخل هاست را دریافت کند که باگ امنیتی محسوب می شود .
ویدیو آموزشی ساخت لینک دانلود با PHP
شرح کارایی اسکرپیت ها :
- hash_file_address.php : ابتدا وارد این فایل می شویم تا مسیری که برای دانلود میخواهیم را hash کنیم .
- index.php : لینک hash شده را دریافت کرده و درصورت وجود فایل در مسیر files آن را دریافت می کنیم .
- functions.php : شامل توابع مورد نیاز ( مثل هش و آن هش لینک دانلود ، پردازش لینک )
- download.php : کلاس ساخت لینک دانلود با قابلیت resume
1- اسکریپت hash_file_address.php
<?php require_once "inc/functions.php"; $str = @$_GET['file']; if($str){ $hashed_str = hash_str($str, function ($chr_int) { return $chr_int + 255; }); echo $hashed_str; }
2- اسکریپت index.php
<?php require_once "inc/functions.php"; $hashed_str = @$_GET['file_hash']; if ($hashed_str) { $un_hashed_str = (un_hash_str($hashed_str, function ($chr_int) { return is_numeric($chr_int) ? $chr_int - 255 : 0; })); download_file($un_hashed_str); }
3- اسکریپت functions.php
<?php function hash_str($str, $func = null) { $chr_list = str_split($str); $int_chr_list = []; foreach ($chr_list as $element) { $int_chr = ord($element); $int_chr_list[] = $func ? $func($int_chr) : $int_chr; } $int_chr_list_base64 = base64_encode(join(",", $int_chr_list)); return $int_chr_list_base64; } function un_hash_str($int_chr_list_base64, $func = null) { $list_chr_list = explode(",", base64_decode($int_chr_list_base64)); $str = ""; foreach ($list_chr_list as $chr_int) { $chr_int = $func ? $func($chr_int) : $chr_int; $str .= chr($chr_int); } return $str; } function download_file($filename) { set_time_limit(300); // for 5 minutes open download channel require_once __DIR__ . "/class/download.php"; $download = new Download($filename, 10000); $download->process(); }
4- اسکریپت download.php
<?php class Download { private $file; private $name; private $boundary; private $delay = 0; private $size = 0; function __construct($file, $delay = 0) { // explode -> فقط فایل های پوشه files قابل دانلود باشد تا از دانلود اسکریپت های هاست جلوگیری گردد $search_res = explode("/" , $file); if (! is_file($file) || @$search_res[0] != "files") { header("HTTP/1.1 400 Invalid Request"); die("<h3>فایل مورد نظر یافت نشد</h3>"); } $this->size = filesize($file); $this->file = fopen($file, "r"); $this->boundary = md5($file); $this->delay = $delay; $this->name = basename($file); } public function process() { $ranges = NULL; $t = 0; if ($_SERVER['REQUEST_METHOD'] == 'GET' && isset($_SERVER['HTTP_RANGE']) && $range = stristr(trim($_SERVER['HTTP_RANGE']), 'bytes=')) { $range = substr($range, 6); $ranges = explode(',', $range); $t = count($ranges); } header("Accept-Ranges: bytes"); header("Content-Type: application/octet-stream"); header("Content-Transfer-Encoding: binary"); header(sprintf('Content-Disposition: attachment; filename="%s"', $this->name)); if ($t > 0) { header("HTTP/1.1 206 Partial content"); $t === 1 ? $this->pushSingle($range) : $this->pushMulti($ranges); } else { header("Content-Length: " . $this->size); $this->readFile(); } flush(); } private function pushSingle($range) { $start = $end = 0; $this->getRange($range, $start, $end); header("Content-Length: " . ($end - $start + 1)); header(sprintf("Content-Range: bytes %d-%d/%d", $start, $end, $this->size)); fseek($this->file, $start); $this->readBuffer($end - $start + 1); $this->readFile(); } private function pushMulti($ranges) { $length = $start = $end = 0; $output = ""; $tl = "Content-type: application/octet-stream\r\n"; $formatRange = "Content-range: bytes %d-%d/%d\r\n\r\n"; foreach ( $ranges as $range ) { $this->getRange($range, $start, $end); $length += strlen("\r\n--$this->boundary\r\n"); $length += strlen($tl); $length += strlen(sprintf($formatRange, $start, $end, $this->size)); $length += $end - $start + 1; } $length += strlen("\r\n--$this->boundary--\r\n"); header("Content-Length: $length"); header("Content-Type: multipart/x-byteranges; boundary=$this->boundary"); foreach ( $ranges as $range ) { $this->getRange($range, $start, $end); echo "\r\n--$this->boundary\r\n"; echo $tl; echo sprintf($formatRange, $start, $end, $this->size); fseek($this->file, $start); $this->readBuffer($end - $start + 1); } echo "\r\n--$this->boundary--\r\n"; } private function getRange($range, &$start, &$end) { list($start, $end) = explode('-', $range); $fileSize = $this->size; if ($start == '') { $tmp = $end; $end = $fileSize - 1; $start = $fileSize - $tmp; if ($start < 0) $start = 0; } else { if ($end == '' || $end > $fileSize - 1) $end = $fileSize - 1; } if ($start > $end) { header("Status: 416 Requested range not satisfiable"); header("Content-Range: */" . $fileSize); exit(); } return array( $start, $end ); } private function readFile() { while ( ! feof($this->file) ) { echo fgets($this->file); flush(); usleep($this->delay); } } private function readBuffer($bytes, $size = 1024) { $bytesLeft = $bytes; while ( $bytesLeft > 0 && ! feof($this->file) ) { $bytesLeft > $size ? $bytesRead = $size : $bytesRead = $bytesLeft; $bytesLeft -= $bytesRead; echo fread($this->file, $bytesRead); flush(); usleep($this->delay); } } }
در صورتی که میخواهید لینک دانلود زمان دار بسازید می توانید از این آموزش استفاده کنید .
ارسال نظر