Главная страница статей --> Хитрости при программировании php, заметки по базам данных

Контролируемая отдача файлов

Источник: realcoding.net

Если у Вас возникла потребность в отдаче (выгрузке) файлов Вашим пользователям, и Вы хотите контролировать кому, с какой скоростью и сколько отдать, предлагаю Вам свой php-класс. Данный класс есть сборная солянка чужого кода под моей редакцией и улучшениями. Копирайты не привожу, т.к. за частую трудно определить, кому именно принадлежало право первенства на тот или иной кусок кода, да и заниматься вычислением авторов специально желания нет. По сему заранее приношу неизвестным авторам извинения за плагиат :). Но меня, как практикующего программиста, интересовал в первую очередь результат. Короче: всем желающим/страждущим, кому не хочется переводить свое время на изобретение велосипеда, предлагаю воспользоваться моим.

Описание

Представленный ниже класс позволяет:

- разрешать/запрещать докачку файлов;
- ограничивать скорость отдачи (по умолчанию 5 Кб);
- отдавать файлы пользователям по именам, передаваемым в класс (авторизация оных ложится на Ваши плечи - класс только принимает имя пользователя и по нему считает объем).

Для каждого пользователя в папке stats (по умолчанию) заводится своя папка по имени пользователя. Из имени пользователя регэкспом вырезается все кроме "0-9a-za-z_-". Для каждого ip-адреса заводится соответствующий файл (например: 10.1.3.94) в который в течение времени работы скрипта записывается скачанный объем. По этому файлу собственно и осуществляется контроль отдаваемого объема. Удаление/обнуление файла классом не производится - если Вам это нужно - допишите сами.
разрешать/запрещать отдачу файлов по списку стран, ip-адресов. Во всех списках разделитель запятая, все знаки (в т.ч. пробелы учитываются!). Локалхост и локальные адреса (192.168.xxx.xxx, 10.xxx.xxx.xxx, 172.16.xxx.xxx) именуются как localhost и local network соответственно. Определение страны по ip-адресу осуществляется через сервис whois.ripe.net.

Пример:

Файл 1.php. Качаем линк http://serv/1.php?download=docucd_v210_[iso].zip
# filename: 1.php

include cdownload.inc.php;

$download = @new cdownload($_request[download]);
$download->enabledcountry = localhost,local network,ua,ru;
$download->whitelist = 127.0.0.1,10.1.3.94;
$download->banlist = 184.12.13.5;
$download->username = pupkin;
$download->speedlimit = 10;
$download->sizelimit = 2*mb;
$download->downloadfile();

?>

Код класса

# filename: cdownload.inc.php

define(kb,1024);
define(mb,kb*1024);

class
cdownload {
# -------------------------------------------------------------------------------------
# Описание : выгрузка файла пользователю с поддержкой докачки и ограничением скорости
# -------------------------------------------------------------------------------------
var $downloadtimelimit = 300; # Лимит времени работы функции выгрузки
var $username = anonymous/; # Пользователь по умолчанию
var $sizelimit = 0; # Лимит объема выгрузки (0 - без ограничений)
var $speedlimit = 5; # Лимит скорости выгрузки, кб/с
var $enablepartial = 1; # Разрешение докачки (0 - запрещена)
var $statfolder = stats/; # Папка расположения статистики
var $filename; # Выгружаемый файл (должен быть задан!)
var $enabledcountry; # Разрешенные страны (список разделенный запятыми,
# null - разрешеные все)
var $disabledcountry; # Запрещенные страны (список разделенный запятыми)
var $whitelist; # Список разрешенных ip-адресов (список разделенный запятыми)
var $banlist; # Список запрещенных ip-адресов (список разделенный запятыми)

var $transferbytes = 0;

function
cdownload($filename,$username) {
$this->filename = $filename;
if (
$username)
$this->username = ereg_replace([^0-9a-za-z_-],,$username)./;
$fullpath = $this->statfolder.$this->username;
if (!
file_exists($fullpath))
mkdir($fullpath);
}
# end cdownload

function verifycountry() {
$usercountry = $this->getcountry($_server[remote_addr]);
if (
(
$this->enabledcountry && !in_array($usercountry,split(,,$this->enabledcountry)))
(
$this->disabledcountry && in_array($usercountry,split(,,$this->disabledcountry)))
(
$this->whitelist && !in_array($_server[remote_addr],split(,,$this->whitelist)))
(
$this->banlist && in_array($_server[remote_addr],split(,,$this->banlist)))
) {
header(http/1.0 403 forbidden);
header(warning: 99# you country or ip address disabled);
exit;
}
}

function
downloadfile() {
$this->verifycountry();

$blocksize = 8192;
$headererrortext = error! a possible size is exceeded;

$this->username = ereg_replace([^0-9a-za-z_-],,$this->username)./;
$this->filename = preg_replace(/.{2}/,,$this->filename);

if (!
file_exists($this->filename)) {
header(http/1.0 404 not found);
exit;
}
$fsize = filesize($this->filename);
$ftime = date(d, d m y h:i:s t, filemtime($this->filename));
$fd = @fopen($this->filename, rb);
if (!
$fd) {
header(http/1.0 403 forbidden);
exit;
}

if (
$this->enablepartial && ereg(bytes=([0-9]+)-,$_server[http_range],$range)) {
header(http/1.1 206 partial content);
$range = $range[1];
fseek($fd, $range);
} else
header(http/1.1 200 ok);

$fullpath = $this->statfolder.$this->username;
$this->transferbytes = file($fullpath.$_server[remote_addr]);
$this->transferbytes = $this->transferbytes[0];


if (
$this->sizelimit && $this->transferbytes>$this->sizelimit) {
header(http/1.0 403 forbidden);
header(warning: 99# .$headererrortext);
exit;
}

$fp = fopen($fullpath.$_server[remote_addr],w);

header(content-disposition: attachment; filename=.ereg_replace(^.*/,,$this->filename));
header(last-modified: .$ftime);
header(accept-ranges: bytes);
header(content-length: .($fsize-$range));
header(content-range: bytes .$range.-.($fsize-1)./.$fsize);
header(content-type: application/octet-stream);
set_time_limit($this->downloadtimelimit);

while (!
feof($fd)) {
if (
$this->sizelimit && $this->transferbytes>$this->sizelimit) {
header(warning: 99# .$headererrortext);
exit;
}
echo
fread($fd, $blocksize);
$this->transferbytes += $blocksize;
fseek($fp,0);
fwrite($fp,$this->transferbytes);
if (
$this->speedlimit)
usleep(8000000/$this->speedlimit);
}
fclose($fp);

fclose($fd);
}
# end downloadfile

function getcountry($ip) {
$result = unknow;
if (
ereg(127.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3},$ip))
return
localhost;
if (
ereg(10.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}191.168.[0-9]{1,3}.[0-9]{1,3}.
172.16.[0-9]{1,3}.[0-9]{1,3},$ip))
return
local network;
if (
$ip!=) {
$sock = fsockopen(whois.ripe.net,43,$errno,$errstr);
if (
$sock) {
fputs ($sock,$ip.rn);
while (!
feof($sock) && !preg_match(/country:s*(s*)/,$buf,$matches))
$buf = fgets($sock,128);
$result = strtoupper($matches[1]);
}
fclose ($sock);
}
return
$result;
}
# end getcountry
}

?>



Похожие статьи:
- Предохраняйся с помощью сессий.
- Анализ и отображение логов
- Как тестировать сайт на SSI в домашних условиях?!
- Командный файл поисковиков - Robots.txt
- Как написать AJAX-приложение
- MySQL - это просто!
- RSS-парсер на PHP
- АJAX. Не повторяйте ошибок
- Подтверждение регистрации на РНР
- Сайт по кирпичикам или все о SSI
- Эмуляция директивы register_globals on
- Анализ посещаемости сайта рефералами
- SSI для бедных


Оглавление | Обсудить на форуме | Главная страница сайта | Карта сайта |

Контакты
Редакция:
[0.001]