Evidovaný download - Builder.cz - Informacni server o programovani

Odběr fotomagazínu

Fotografický magazín "iZIN IDIF" každý týden ve Vašem e-mailu.
Co nového ve světě fotografie!

 

Zadejte Vaši e-mailovou adresu:

Kamarád fotí rád?

Přihlas ho k odběru fotomagazínu!

 

Zadejte e-mailovou adresu kamaráda:



PHP

Evidovaný download

php

30. září 2002, 00.00 | Nejednoho tvůrce zajímá kdo a kdy, je stahuje jeho soubory. Tento článek věnuji tématu, jak sledovat download souborů. Navíc
jakým způsobem povolit či zamítnout download souborů nechtěným uživatelům.

Asi každý má na svých stránkách nějaké soubory ke stažení. Často se jedná o soubory vlastní tvorby a určitě nejednoho tvůrce by zajímalo kdo a kdy, je stahuje. Tento článek věnuji právě tomuto tématu. Navíc ozřejmím, jakým způsobem lze soubory schovat, aby je bylo možné downloadovat pouze přes Váš skript, který např. může od dat uříznout všechny neregistrované uživatele apod.

Téma první — ochrana dat

Skript pro download souborů je sice dobrá věc, ale když budete neopatrní, může se stát obrovskou dírou pro hackery. Už při tvorbě databáze je nutné to vzít vpodaz. Příklad: skript, který downloaduje vaše soubory, může stejně dobře stahovat PHP či konfigurační soubory přímo z vašeho serveru a to v původní podobě.

Můj návrh spočívá asi v nejbezpečnější variantě, kterou je, že všechny soubory, které lze downloadovat jsou uloženy v databázi (jen jejich adresy). Mimo každý soubor má svůj label, který se může absolutně lišit od pravého jména souboru.

#
# Struktura tabulky `files`
#

CREATE TABLE files (
  label varchar(255) NOT NULL default '',
  filename varchar(255) NOT NULL default '',
  UNIQUE KEY label (label),
  KEY filename (filename)
) TYPE=MyISAM;

Další částí do databáze bude tabulka downloads, což bude prostý log. Do něj budeme zapisovat podrobnosti o downloadu jako čas, downloadovaný soubor, ip adresu a url toho, kdo ho požaduje a samozřejmě od koho k nám přišel např. http://www.download.com/.

#
# Struktura tabulky `downloads`
#

CREATE TABLE downloads (
  id int(11) NOT NULL auto_increment,
  time timestamp(14) NOT NULL default '',
  referer varchar(50) NOT NULL default '',
  ip varchar(136) NOT NULL default '',
  addr varchar(255) NOT NULL default '',
  file varchar(20) NOT NULL default '',
  PRIMARY KEY (id),
  KEY referer (referer,file)
) TYPE=MyISAM;

Téma druhé — vlastní skript

První co je nutné říci je, že skript bude umístěný v souboru download.php a požadovaný soubor tj. label se mu bude předávat přes parameter file. V případě, že bude parameter file obsahovat chybný label (neobsažený v databázi) či ho nebude obsahovat vůbec, provede se prosté přesměrování na index celého webu.

// soubor download.php
<?
$web_url = 'http://www.svecpetr.com/';

if (isset($_REQUEST["file"]) && $_REQUEST["file"] != '') { // otestuj, zda je zadán
soubor
 require 'db_conn.php'; // připojení k DB
// check file  $_REQUEST["file"] = strtolower($_REQUEST["file"]);
 $query = "SELECT filename FROM `files` WHERE label = '$_REQUEST[file]' LIMIT 1";
 $data = MySQL_Query($query) or die(mysql_error().'<br>'.$query.'<br>');
 $entry = MySQL_Fetch_Array($data);
 if ($entry["filename"] == '') { // file not found > redivert
  $location = $web_url;
  Header("Location: $location"); // přesměruj prohlížeč
  require "download_html.php";
  exit;
 } else $location = $entry["filename"];

V první fázi můžete krásně vidět připojení k databázi s následným ověřením, zda existuje label a případnému přesměrování na index webu (definovaný jako $web_url).

 $ip = $_SERVER["REMOTE_ADDR"]; // vše, co lze o čtenáři zjistit odděleno | (adresy uživatelů za proxy ap.)
 if (isset($_SERVER["HTTP_X_FORWARDED_FOR"])) $ip .= '|'.$_SERVER["HTTP_X_FORWARDED_FOR"];
 if (isset($_SERVER["HTTP_FORWARDED"])) $ip .= '|'.$_SERVER["HTTP_FORWARDED"];
 if (isset($_SERVER["HTTP_CLIENT_IP"])) $ip .= '|'.$_SERVER["HTTP_CLIENT_IP"];
 if (isset($_SERVER["X_HTTP_FORWARDED_FOR"])) $ip .= '|'.$_SERVER["X_HTTP_FORWARDED_FOR"];
 if (isset($_SERVER["X_FORWARDED_FOR"])) $ip .= '|'.$_SERVER["X_FORWARDED_FOR"];
 $referer = $_SERVER["HTTP_REFERER"];
 $ip_addr = gethostbyaddr($_SERVER["REMOTE_ADDR"]);

Možná jste si všimli, že IP adresa je VARCHAR(136) a nevěděli proč. Je to jednoduché. Zaprvné je to navrženo pro IPv6. Za druhé snažím se rozlišovat, pokud je to možné, proxy servery od skutečného uživatele. Takže ve finále zde může být několik podobných IP adres, které se postupně konkretizují.

 $query = "INSERT INTO `downloads` VALUES (null, null, '$referer', '$ip', '$ip_addr', '$_REQUEST[file]');";
 @MySQL_Query($query) or die(mysql_error().'<br>'.$query.'<br>');
 MySQL_Close();

Zapsání do databáze. Co dodat? A teď to hlavní.

// WAY #1 - read (may failure, but secure)
 $filename = substr($location, strlen($web_url));
 set_time_limit(600); // Limits the maximum execution time
 Header("Accept-Ranges: bytes");
 Header("Content-Length: ".filesize($filename));
 Header("Content-Type: application/octet-stream");
 Header("Content-Disposition: filename=\"$_REQUEST[file]\"");
 @readfile($filename);
 exit;

První způsob downloadu souboru spočívá v bezpečnější cestě. Protože uživatel, ani kdyby se zabýval HTTP hlavičkami, nezjistí cestu souboru či jaké jeho pravé jméno. Ale musí vzít v potaz, že se celý soubor musí odesílat přes PHP na výstup, což by u velkých souborů mohlo vést k tomu, že se překročí standardní doba 30 sekund pro běh skriptu. Proto ihned nastavuji nový limit na 600 sekund. Potlačil jsem i vypsání chybové hlášky, kdyby nebyl nazelezen soubor, aby se neprozradila jeho pravá cesta.

// WAY #2 - redivert
 Header("Location: $location"); // přesměruj prohlížeč
 require "download_html.php";
 exit;

Cesta druhá — aneb klasické přesměrování na fyzický soubor.

} else { // unknown > redivert to index
         $location = $web_url;
         Header("Location: $location"); // přesměruj prohlížeč
         require "download_html.php";
         exit;
        }
?>

A skript končí poslední variantou. A to, že nebyl zadán parameter file. Opět se provede přesměrování na index webu.

To je ode mně vše. Zdrojové kódy, včetně SQL. Budete si muset opravit soubor db_conn.php a proměnou $web_url v souboru download.php.

Tématické zařazení:

 » Rubriky  » PHP  

 » Rubriky  » Web  

 » Rubriky  » HTML  

 

 

 

Nejčtenější články
Nejlépe hodnocené články

 

Přihlášení k mému účtu

Uživatelské jméno:

Heslo: