CompZone.Org :: Artykuły :: PHP
Która technologia najbardziej Cię interesuje?
PHP
ASP
AJAX
SQL
JavaScript
Inna
Sonda Wyniki

Add to Google

System download

Dzisiaj zajmiemy się napisaniem skryptu, który zajmie się liczeniem tego, ile dany plik został ściągnięty. Przyznam, że kod (tak mi się wydaje) jest w miarę prosty. No ale nie rozpisuję się już i przechodzę do konkretów.

Cały skrypt z założenia nie ma być trudny i skomplikowany. Nadaję się na małe jak i duże systemy, ale takie raczej nie przekraczające około 200-350 plików.

Skrypt, który prezentuję do poprawnego działania potrzebuje bazy mySQL 4, oraz php w wersji co najmniej 4.1.3 (po drobnej modyfikacji, będzie działać także na niższych wersjach do 4).

Krok 1

Piszemy stronę internetową, z której będziemy dodawać pliki do naszej bazy.

Strona nie będzie miała praktycznie żadnego wyglądu, w końcu mamy się zająć php a nie html.
To co nam potrzebne to: 2 pola typu text, oraz jedno pole tak zwane select (można także użyć zwykłego pola tekst, jeżeli zajdzie taka potrzeba).
Uwaga!!! Pola powinny mieć takie same nazwy jak w listingu chyba, że jesteś dość zaawansowanym programistą php i wiesz, które trzeba zmienić nazwy w zmiennych przekazywanych metodą POST.

Oto listing: (Plik zapisz pod nazwą dodaj.html)

 <html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>Dodaj plik</title>
</head>

<body>
<form name="form1" method="post" action="download.php?akcja=dodaj">
<table width="750" border="0">

<tr>
<td width="238">Nazwa programu/archiwum </td>
<td width="502"><input type="text" name="nazwa"></td>
</tr>
<tr>
<td>Nazwa pliku : </td>
<td><input type="text" name="nazwa_pliku">
(wraz z rozszerzeniem, bez ścieżki dostępu)
</td>

</tr>
<tr>
<td>Kategoria</td>
<td><select name="kategoria">
<option>freeware</option>
<option>shareware</option>
</select></td>

</tr>
</table>
<p>
<input type="submit" name="Submit" value="Dodaj">
</p>
</form>
</body>
</html>

Krok 2

Piszemy skrypt, czyli: Definiujemy dane, potrzebne do połączenia się z serwerem mySQL oraz inne niezbędne dla poprawnego działania skryptu.

Aby połączyć się z serwerem mySQL, potrzebujemy kilku danych. m.in. adres serwera (dns), nazwa użytkownika (który ma prawo do dodawania, oraz aktualizowania danych), hasło użytkownika, nazwę bazy oraz prefix (będzie nam potrzebny do tworzenia przedrostków dla nazwy tabel).

Inne potrzebne nam dane, które musimy ustalić to: folder z plikami, które można pobierać oraz 2 tablice, których rolę opiszę w dalszej części kursu. Oczywiście nie zmieniaj nazw zmiennych a jedynie ich wartości.

 <?php
# Konfiguracja #################################

// serwer'a mySQL
$baza_dns = 'localhost'; // host bazy danych (domyślnie localhost)
$baza_uzytkownik = ''; // login użytkownika bazy danych
$baza_haslo = ''; // hasło dla danego użytkownika bazy
$baza = ''; // baza w której będzie przechowywana zawartość
$prefix = ''; // nie wymagane, lecz przydatne w przypadku bazy, w której istnieje
// już tabela o nazwie "download", prefix rozwiazuje ten problem
// (zaleca korzystanie się z końcówki "_")

// folder z plikami do download'u
$folder = 'download/'; // określa położenie pliku z folderem, w którym znajdują się pliki względem hosta
// wymagany na końcu ukośnik.

// boty - dla zaawansowanych
$boty = array(
// to jest przykład, nie musisz definiować google, ponieważ funkcja sama rozpoznaje, że to bot
''
);


$nie_boty = array( //strony, które są uważane przez funkcje za bota, a nie są
''
);
###############################################
?>

Krok 3

Deklarujemy co będziemy pobierać metodą GET

Pewnie Ci się wydaje, że w jaki to sposób skoro nie wiesz tak naprawdę co Ci będzie potrzebne, ale to nie prawda. Wiesz, że skrypt musi pobierać nazwę pliku, który ma zostać pobrany, z jakiej kategorii mają być wyświetlane pliki, oraz jaka akcja ma zostać wykonana.

Pierwsza jak i druga zmienna będzie pobierać dane metodą $_GET Pierwsza zmienna o nazwie „akcja” będzie sprawdzać jaką funkcję należy wywołać, czyli czy ma dodać plik, wyświetlić listę plików lub dodać tabelę do bazy (czyli niby taka instalacja).

Na początku sprawdzamy czy coś takiego w ogóle istnieje, a jeżeli nie to sami przypiszemy zmiennej wartość domyślną.

 <?php
//...
if (isset($_GET['akcja'])) $akcja = $_GET['akcja']; else $akcja = 'wyswietl';
//...
?>

Funkcja isset sprawdza czy dana mamy coś w tablicy zmiennych GET[‘akcja’] jeżeli istnieje to zmiennej akcja ($akcja) przypisujemy zawartość tej tablicy zmiennej, natomiast jeżeli nie to sami nadajemy zmiennej $akcja wartość czyli w tym przypadku "wyswietl".

W analogiczny sposób postępujemy z drugą zmienną i trzecia, tyle, że sprawdzamy tablicę zmiennych $_GET[‘kategoria’] i nadajemy inna wartość domyślną czyli "wszystkie", a do trzeciej $_GET[‘p’] – czli nazwa pliku.

 <?php
//...
if (isset($_GET['kategoria'])) $kategoria = addslashes($_GET['kategoria']); else $kategoria = 'wszystkie';
if (isset($_GET[&#8216;p'])) $kategoria = $_GET['p']; // tej zmiennej nie przypisujemy wartości domyślnej
//...
?>

Krok 4

Piszemy funkcję, która doda nam tabelę do bazy

Jak wiadomo, w coś musimy zapisywać nasze dane chociażby o nazwie programu/skryptu do pobrania, nazwę pliku, kategorię oraz ile razy został pobrany dany plik. Czyli o ile dobrze policzyłem potrzebujemy 4 pół. Pierwsze pole będzie to „nazwa” typu VarChar o długości 255, drugie to "plk" też VarChar tyle że o długości 50, kolejne pole to pole o nazwie „kategoria” VarChar 50 i ostatnie pole, które będzie liczyć ile razy pobrano nasz plik będzie nosić nazwę „pobrano” i będzie polem o typie MediumInt. Funkcję, która będzie wysyłała zapytanie do bazy wraz z prośbą o utworzenie tabeli nazwiemy "dodaj_tabele".

Oto listing:

 <?php
//....
function dodaj_tabele()
{
global $prefix;
$zapytanie = "CREATE TABLE ".$prefix."download (
'nazwa' varchar(255) NOT NULL default '',
'plk' varchar(50) NOT NULL default '',
'kategoria' varchar(50) NOT NULL default '',
'pobrano' mediumint(9) NOT NULL default '0',
PRIMARY KEY (`nazwa`)
) ENGINE=MyISAM;
";

$wynik = mysql_query($zapytanie);
}
//....
?>

Aha zapomniał bym dodać, że będziemy korzystać ze zmiennych globalnych, praktycznie cały czas będziemy potrzebowali zmiennej $prefix.

Krok 5

Funkcja, która doda nam plik, do bazy danych

Aby dodać plik do bazy będziemy potrzebowali trzech informacji. Jeżeli pamiętasz z kroku 1 to będzie to nazwa programu/skryptu, nazwa pliku do pobrania oraz kategoria. Funkcja będzie więc potrzebowała 3 parametrów. Funkcję nazwiemy "dodaj".

 <?php
//...
function dodaj($nazwa, $zrodlo, $kategoria)
{
//...
?>

Kolejny krok to dodanie zmiennej globalnej $prefix. Aby zabezpieczyć skrypt przed atakami hackerów, każdy parametr zostanie przez nas specjalnie przygotowany do tego aby nie mógł nic „nawywijać” z naszą bazą. Służy do tego funkcja addslashes.

 <?php
//...
global $prefix;

$nazwa = addslashes($nazwa);
$zrodlo = addslashes($zrodlo);
$kategoria = addslashes($kategoria);
//...
?>

Kolejną rzeczą, którą musimy zrobić to wysłać zapytanie do bazy i sprawdzić, czy taki program już istnieje w naszej bazie i jeżeli tak to po prostu uaktualnić go, jakby np. zaszła konieczność zmiany kategoria, lub nazwy pliku.

 <?php
//...
$zapytanie = "SELECT nazwa FROM ".$prefix."download WHERE nazwa='$nazwa'";
$wynik = mysql_query($zapytanie);
//...
?>

Teraz zajmiemy się wynikiem zapytania czyli zmienną $wynik. Jeżeli będzie niepusta (zwróci wartość inną niż false) oznaczać to będzie, że program o takiej nazwie istnieje i po prostu będziemy musieli wysłać zapytanie z aktualizacją danych. Natomiast jeżeli zwrócona wartość będzie wartością false, będzie to oznaczać, że plik do bazy trzeba po prostu dodać. Na koniec przeniesiemy się na stronę z listingiem wszystkich programów dzięki funkcji Header.

 <?php
//....
if (!$wynik)
{
$zapytanie = "INSERT INTO ".$prefix."download VALUES ('$nazwa', '$zrodlo', '$kategoria', 0);";
$wynik = mysql_query($zapytanie);
}
else
{
$zapytanie = "UPDATE ".$prefix."download WHERE nazwa='$nazwa' SET nazwa='$nazwa' AND plk='$zrodlo' AND kategoria='$kategoria' AND pobrano=pobrano;";
$wynik = mysql_query($zapytanie);
}
header('Location: download.php');
}
//...
?>

Krok6

Małe zabezpieczenie przed botami

W tej części zajmiemy się dwoma dziwnymi zmiennymi, które zadeklarowaliśmy w kroku 2 tegoż artykułu, czyli $boty, oraz $nie_boty.

Jak wiadomo nasze strony mogą nawiedzać różne boty (czyli np. Google, MSN), aby się przed nimi się zabezpieczyć możemy użyć pliku robots.txt, lub (tak jak to będzie w naszym przypadku) napisać własną funkcję, która będzie sprawdzać, czy dany adres to bot, czy zwykły user. Niestety nasz skrypt może się niekiedy mylić i albo nie wykrywać jakiegoś bota, albo błędnie oznaczać go jako bot. Właśnie dlatego zdefiniowane są 2 zmienne typu Array. W $boty będziemy przechowywać adresy botów (może być to dowolne słowo z adresu bota), a w $nie_boty, będziemy umieszczać adresy, które nie są botami. No ale zacznijmy pisać skrypt.

 <?php
//...
function is_bot($reffer, $agent)
{
global $boty, $nie_boty;

if (strpos($reffer, array_search($reffer, $nie_boty))) return false;
if (strpos($reffer, array_search($reffer, $boty))) return true;
if (strpos(strtolower($reffer), 'bot')) return true;
else
{
if (strpos(strtolower($agent), 'bot')) return true; else return false;
}
}
//...
?>

Najpierw ustawiamy zmienne globalne, czyli $boty i $nie_boty.
Najpierw sprawdzamy czy dany adres jest na liście dozwolonych adresów, czy nie i zwracamy odpowiednią wartość (true lub false). Potem dalej funkcją strpos sprawdzamy czy dany ciąg występuje w adresie skryptu, jeżeli tak to nie daje mu pozwolenia na pobranie pliku (funkcja zwraca wartość true) – jednak na wszelki wypadek sprawdzamy też czy słowo bot istnieje w User Agent (czyli identyfikatorze). Jeżeli tak to znaczy, że to bot jeżeli nie to możemy być w 90% przekonani, że to prawdziwy użytkownik.

Krok 7

Czas na pobranie pliku

Aby pobrać plik musimy zadeklarować dwie zmienne globalne $folder oraz $prefix.
Następnie aby zabezpieczyć się przed próbą ataku na nasz skrypt zabezpieczamy się poprzez funkcję addslashes. Kolejna czynność to wysłanie zapytania do bazy danych, w którym zwiększamy licznik, jeżeli zwrócona wartość będzie wartością false oznaczać to będzie, że podany plik nie istnieje i zwrócimy komunikat „Podany plik nie istnieje na naszym serwerze.”, w przeciwnym wypadku (jeżeli zapytanie zwrotne od bazy będzie true) sprawdzamy czy nasz gość jest botem, czy nie – jeżeli jest to wyświetlimy komunikat „Prawdopodobnie jesteś botem, jeśli tak nie jest skontaktuj się z administratorem serwisu.”. Jeżeli to nie bot to przechodzimy do ostatniej części, czyli właściwego pobierania.

Może się oczywiście zdarzyć, że np. administrator zapomni dodać pliku do folderu z plikami, lub po prostu pomyli się w nazwie i podany plik nie będzie istniał na serwerze, dlatego aby temu zapobiec skorzystamy z funkcji file_exists i sprawdzimy czy nasz plik istnieje – jeżeli nie to dostaniemy wiadomość "Podany link jest niewłaściwy. Skontaktuj się z administratorem." , w przeciwnym wypadku rozpoczniemy pobieranie pliku.

 <?php
//....
function pobierz_plik($plik)
{
global $folder, $prefix;
$plik = addslashes($plik);

$zapytanie = "UPDATE ".$prefix."download SET pobrano=pobrano+1 WHERE plk='$plik'";
$wynik = mysql_query($zapytanie);

if ($wynik)
{
if (!is_bot($_SERVER['HTTP_REFERER'], $_SERVER['HTTP_USER_AGENT']))
{
if (file_exists('http://'. $_SERVER['HTTP_HOST']. '/'.$folder.$plik)) Header('Location: http://'.$_SERVER['HTTP_HOST'].'/'.$folder.$plik); else echo 'Podany link jest niewłaściwy. Skontaktuj się z administratorem.';
} else echo "Prawdopodobnie jesteś botem, jeśli tak nie jest skontaktuj się z administratorem serwisu.";
} else echo 'Podany plik nie istnieje na naszym serwerze.';

}
//...
?>

Krok 8

Sprawdzamy ile razy nasz plik został pobrany

Schemat działania funkcji jest bardzo prosty. Wysyłamy do bazy zapytanie o ilość pobrań pliku, którego nazwę przekazujemy jako parametr funkcji $plik.

Oczywiście nie możemy zapomnieć o zabezpieczeniu danych wejściowych (addslashes) oraz o globalnej zmiennej $prefix.

 <?php
//...
function pobrano($plik)
{
global $prefix;

$plik = addslashes($plik);

$zapytanie = "SELECT pobrano FROM ". $prefix . "download WHERE plk='$plik';";
$wynik = mysql_query($zapytanie);
if ($wynik)
{
$ile = mysql_fetch_array($wynik, MYSQL_ASSOC);
return $ile['pobrano'];
} else echo &#8222;Błąd&#8221;;
}
//...
?>

Krok 9

Tworzymy listę plików wg. podziału na kategorie

Aby funkcja mogła działać poprawnie potrzebujemy jednego parametru czyli kategorii, z której mamy wyświetlić pliki. Oczywiście wykorzystujemy w tym celu zapytania do bazy danych. Jeżeli $kategoria będzie zawierać tekst o wartości "wszystkie" wtedy musimy wyświetlić wszystkie programy w kolejności alfabetycznej wg. nazwy programu oraz kategorii, czyli w zapytaniu potrzebujemy na końcu dodać ORDER BY (ułóż w kolejności) wypisujemy nasze nagłówki pół (jeżeli jest więcej niż jedno wtedy oddzielamy je przecinkiem) i jeszcze ASC czyli w kolejności rosnącej. Potem już tylko wykonujemy zapytanie i prezentujemy wyniki. Wyświetlamy aktualna kategorię oraz nazwę pliku (oraz link do niego w celu pobrania) oraz liczbę pobrań. Wykonuje to wszystko nasza pętla while, w której pobieramy z bazy wszystkie potrzebne dane, a także odwołujemy się do funkcji "pobrano" aby sprawdzić ile razy został pobrany plik.

PS. Prezentowana lista praktycznie nie ma wyglądu, po prostu nie chciałem zawracać Wam głowy html, zresztą każdy ma inne upodobania.

 <?php
function wyswietl_liste($kategoria)
{
global $prefix, $folder;

if ($kategoria == 'wszystkie')
{
$zapytanie = "SELECT * FROM ".$prefix."download ORDER BY 'nazwa', 'kategoria' ASC";
}
else
{
$kategoria = addslashes($kategoria);
$zapytanie = "SELECT * FROM ".$prefix."download WHERE kategoria='$kategoria' ORDER BY 'nazwa' ASC";
}
$wynik = mysql_query($zapytanie);
if ($wynik)
{
$ost = '';
while ($pozycje = mysql_fetch_array($wynik, MYSQL_ASSOC) )
{
if ($ost != $pozycje['kategoria'])
{
$ost = $pozycje['kategoria'];
echo $pozycje['kategoria'].'<br />';
}
echo '<a href="'.'http://'.$_SERVER['HTTP_HOST']. '/'.$folder.$pozycje['plk'].'">'. $pozycje['nazwa'].'</a> Pobrano: ' . pobrano($pozycje['plk']).'<br />'."n";
}
}
}
?>

Krok 10 (ostatni)

Łączenie się z bazą mySQL, i wykonywanie odpowiednich poleceń pobieranych ze zmiennych

Pierwszą rzecz jaką robiły to łączymy z bazą danych przy pomocy danych ze zmiennych. W razie niemożności połączenia się z bazą wyświetlamy komunikat "Nie mogę połączyć się z bazą danych.", lub "Nie mogę wybrać danej bazy" – jeżeli wybrana przez nas baza nie istnieje.

Kolejnym krokiem jest sprawdzenie czy istnieje zmienna $p, jeżeli tak to pobieramy plik wywołując funkcję „pobierz_plik” w parametrze, której przekazujemy zmienna $p. Jeżeli zmienna $p nie jest zainicjowana przechodzimy do dalszych możliwości.

Dzięki metodzie switch możemy obsłużyć zmienną $akcja. Jeżeli $akcja będzie miała wartość „dodaj” wtedy: jeżeli używaliśmy formularza i wcisnęliśmy przycisk „Dodaj” to powinny zostać utworzone zmienne w tablicy $_POST jeżeli faktycznie istnieją to wtedy wywołujemy funkcję „dodaj” w parametrze której podajemy (przed uprzednim zabezpieczeniem przez addslashes) odpowiednie wartości, czyli: $_POST[‘nazwa’], $_POST[‘nazwa_pliku’] i $_POST[‘kategoria’] – jeżeli natomiast tablica zmiennych nie zawiera tych wartości to po prostu wyświetlamy formularz , z którego możemy dodać plik. Jeżeli $akcja będzie miała wartość „wyswietl” wtedy wyświetlamy listę plików poprzez funkcję „wyświetl_listę” w parametrze której podajemy kategorię, czyli odniesienie do zmiennej $kategoria. Ostatnia możliwość to aby $akcja miała wartość „instaluj”, jeżeli tak jest to wywołujemy funkcję „dodaj_tabele()”, która utworzy wymaganą tabelę.

Na koniec rozłączamy się z bazą danych.

 <?php
//....
@
$msql = mysql_connect($baza_dns, $baza_uzytkownik, $baza_haslo) or die('Nie mogę połączyć się z bazą danych');
@
mysql_select_db($baza, $msql) or die('Nie mogę wybrać danej bazy');

if (isset($p)) pobierz_plik($p);
else
{
switch ($akcja)
{
case 'dodaj' :
{
if (isset($_POST['nazwa']) && isset($_POST['nazwa_pliku']) && isset($_POST['kategoria']))
{
$nazwa = addslashes($_POST['nazwa']);
$nazwa_pliku = addslashes($_POST['nazwa_pliku']);
$kateg = addslashes($_POST['kategoria']);
dodaj($nazwa, $nazwa_pliku , $kateg);
}
else
{
include('dodaj.html');
}
break;
}
case 'wyswietl' :
{
wyswietl_liste($kategoria);
break;
}
case 'instaluj' :
{
dodaj_tabele();
break;
}
}
}

mysql_close($msql);
?>

Zdaję sobie sprawę, że artykuł nie jest najprostszy, lecz w nim poznałeś takie funkcje jak: addslashes, isset, nauczyłeś się posługiwać tablicami zmiennych $_GET oraz $_POST oraz sortować listę pozycji w bazie mySQL, a także łączyć się z nią i rozłączać.

Na koniec - od autora

Wywoływanie skryptu powinno wyglądać w taki sposób:

  • jeżeli chcemy pobrać plik download.php?p=aaa.rar
  • jeżeli chcemy wyświetlić listę wszystkich plików download.php?akcja=wyswietl lub download.php?akcja=wyswietl&kategoria=wszystkie
  • jeżeli chcesz pokazać wyłącznie jedną kategorię download.php?akcja=wyswietl&kategoria=freeware (wyświetli kategorię freeware)
  • jeżeli chcesz dodać automatycznie tabelę download.php?akcja=instaluj

Ścieżkę do folderu z plikami, w zmiennej $folder podawaj bez host’a i ze znakiem ukośnika na końcu (czyli np. jeżeli Twój folder z plikami to http://aaa.pl/download to w zmiennej $folder wpisz: „download/”)

Pobierz załączniki

PcSA @ 12-07-2006 16:46
Brak komentarzy...
Copyright © 2005-2006 Compzone.Org. Kopiowanie i wykorzystywanie materiałów zawartych na tej stronie bez zgody autora zabronione!