آموزش ساخت لینک دانلود غیر مستقیم در PHP ( تغییر و هش لینک فایل )

آموزش ساخت لینک دانلود غیر مستقیم در PHP ( تغییر و هش لینک فایل )

دانلود غیر مستقیم در PHP – با کمک الگوریتمی که در آموزش قبلی یاد گرفتیم مسیر فایل را hash کرده و زمانی که درخواستی برای دانلود از سوی کاربر ارسال می گردد

hash داده شده را رمزگشایی کرده و در صورتی که در مسیر files وجود داشت فایل را برای دانلود ارسال می کنیم همچنین اگر فایل وجود داشت اما در مسیر files نبود باز هم کاربر با پیغام فایل یافت نشد مواجه می شود .


چون نمی خواهیم که کاربر اسکریپت های php داخل هاست را دریافت کند که باگ امنیتی محسوب می شود .


ویدیو آموزشی ساخت لینک دانلود با PHP


شرح کارایی اسکرپیت ها :

  1. hash_file_address.php : ابتدا وارد این فایل می شویم تا مسیری که برای دانلود میخواهیم را hash کنیم .
  2. index.php : لینک hash شده را دریافت کرده و درصورت وجود فایل در مسیر files آن را دریافت می کنیم .
  3. functions.php : شامل توابع مورد نیاز ( مثل هش و آن هش لینک دانلود ، پردازش لینک )
  4. 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);
        }
    }
}


در صورتی که میخواهید لینک دانلود زمان دار بسازید می توانید از این آموزش استفاده کنید .

سورس دانلود غیر مستقیم در PHP

ارسال نظر

جهت استفاده از کد حتما از تگ pre استفاده نمایید .

contact us