Académique Documents
Professionnel Documents
Culture Documents
PRZYKADOWY ROZDZIA
SPIS TRECI
KATALOG KSIEK
KATALOG ONLINE
PHP. Rozmwki
Autor: Christian Wenz
Tumaczenie: Radosaw Meryk
ISBN: 83-246-0324-7
Tytu oryginau: PHP Phrasebook
Format: B5, stron: 360
TWJ KOSZYK
DODAJ DO KOSZYKA
CENNIK I INFORMACJE
ZAMW INFORMACJE
O NOWOCIACH
ZAMW CENNIK
CZYTELNIA
FRAGMENTY KSIEK ONLINE
Wydawnictwo Helion
ul. Chopina 6
44-100 Gliwice
tel. (32)230-98-63
e-mail: helion@helion.pl
Spis treci
O autorze ............................................................................11
Wprowadzenie ...................................................................13
1 Operacje na cigach znakw ..............................................17
Porwnywanie cigw znakw ...............................................18
Sprawdzanie poprawnoci nazw uytkownikw i hase ...........19
Przeksztacanie cigw znakw na jzyk HTML .......................21
Zastosowanie znakw podziau wiersza ..................................24
Szyfrowanie cigw znakw ...................................................25
Sprawdzanie sum kontrolnych cigw znakw .......................27
Wydzielanie podcigw znakw ...............................................29
Zabezpieczanie adresw e-mail za pomoc kodw ASCII ........30
Skanowanie sformatowanych cigw znakw ........................35
Pobieranie szczegowych informacji o zmiennych ..................36
Wyszukiwanie w cigach znakw ...........................................37
Wykorzystanie wyrae regularnych POSIX .............................41
Wykorzystanie wyrae regularnych zgodnych z Perlem ..........43
Wyszukiwanie znacznikw za pomoc wyrae regularnych ......44
Sprawdzanie poprawnoci pl obowizkowych ......................45
Spis treci
Spis treci
Spis treci
Spis treci
Spis treci
Spis treci
5
Zapamitywanie
ustawie uytkownikw
pliki cookie i sesje
Zapamitywanieustawieuytkownikw
ROZDZIA 5
wysanie danych za pomoc metody GET (tzn. poprzez doczenie informacji do adresu URI dania),
W praktyce uywa si jednej z dwch metod: sesji (z wykorzystaniem metody GET lub plikw cookie) oraz plikw cookie.
160
UWAGA
Nieoficjalna specyfikacja plikw cookie jest zwizana z przegldark Netscape i cigle jest dostpna pod adresem http://
wp.netscape.com/newsref/std/cookie_spec.html. Byy prby
stworzenia specjalnego dokumentu RFC dotyczcego plikw
cookie nowej generacji, ale inicjatywy te nie doczekay si
jeszcze obsugi w adnej z popularnych przegldarek.
Pliki cookie s przesyane w nagwkach HTTP. W przypadku ustawienia pliku cookie w nagwku HTTP tworzy
si zapis Set-Cookie. Dalej wystpuje nazwa i warto
pliku cookie (obie w postaci cigu znakw) oraz opcjonalnie inne informacje, takie jak data wanoci, domena
i cieka dostpu do pliku cookie. Na przykad, jeli odwiedzimy witryn http://www.php.net, witryna PHP przele
nagwek w nastpujcej postaci (oczywicie ustawienia
jzyka i adres IP mog by inne):
ROZDZIA 5
Set-Cookie:COUNTRY=DEU%2C84.154.17.84; expires=Thu
19-May-05 15:23:29 GMT; path=/; domain=.php.net
161
ROZDZIA 5
Kiedy przegldarka (lub uytkownik) zaakceptuje plik cookie, zostanie on przesany na serwer podany w nagwku
HTTP Cookie:
Cookie:COUNTRY=DEU%2C84.154.17.84
Dla pliku cookie mona ustawi dat wanoci. Jeli zostanie ustawiona, plik bdzie przechowywany co najwyej
do tej daty. Jest to tzw. trway plik cookie (ang. persistent
cookie). Po upywie tego okresu przegldarka automatycznie go usunie cho moe to rwnie zdarzy si
wczeniej; na przykad w przypadku zapisania maksymalnej liczby plikw cookie w przegldarce najstarsze pliki
cookie zostan usunite. Jeli data wanoci pliku cookie
nie zostanie ustawiona, taki plik okrela si jako tzw.
plik sesji lub plik tymczasowy. Pliki cookie tego typu s
przechowywane tak dugo, jak dugo dziaa przegldarka
WWW. Podczas zamykania przegldarki tymczasowe pliki
cookie s usuwane.
WSKAZWKA
Aby oglda nagwki HTTP, mona skorzysta ze specjalnych
rozszerze standardowych przegldarek WWW. W przypadku
przegldarek Mozilla (wcznie z przegldark Firefox) wielkie
moliwoci oferuje rozszerzenie LiveHTTPHeaders dostpne
pod adresem http://livehttpheaders.mozdev.org/. Uytkownicy
przegldarki Microsoft Internet Explorer mog zainstalowa
pasek narzdzi ieHTTPHeaders dostpny pod adresem http://
www.blunck.info/iehttpheaders.html. Na rysunku 5.1 pokazano przykadowe nagwki dla przegldarki FireFox podczas dostpu do strony macierzystej PHP.
Do tworzenia plikw cookie suy funkcja PHP setcookie(). Funkcja przyjmuje nastpujce parametry (tylko
ROZDZIA 5
ROZDZIA 5
OSTRZEENIE
Poniewa pliki cookie s przesyane jako nagwki HTTP,
musz by utworzone przed wysaniem wyjcia HTML (chyba
e korzystamy z buforowania wynikw). W innym przypadku
uzyskamy komunikat o bdzie podobny do tego, ktry pokazano na rysunku 5.3.
<table>
<?php
foreach ($_COOKIE as $name => $value) {
printf('<tr><td>%s</td><td>%s</td></tr>',
htmlspecialchars($name),
htmlspecialchars($value));
}
?>
</table>
ROZDZIA 5
ROZDZIA 5
UWAGA
Zazwyczaj interpreter PHP automatycznie unieszkodliwia znaki
specjalne w wartociach plikw cookie poprzez poprzedzenie
ich znakami lewego ukonika (szczeglnie w przypadku przekazywania plikw cookie poprzez URL). Jednak poczwszy od
PHP 5 mona to robi rcznie, poprzez wysanie surowych
danych pliku cookie. Aby to uczyni, naley przekaza do
funkcji setrawcookie() te same parametry, ktre byy
przekazane do funkcji setcookie(). Obie funkcje dziaaj
podobnie. Rnica polega na tym, e pierwsza z nich nie koduje wartoci pliku cookie. Aby j zakodowa, naley rcznie
wywoa funkcj urlencode().
Pozbywanie si magicznych
cudzysoww (apostrofw)
z plikw cookie
Pozbywanie si magicznych cudzysoww z plikw cookie
Jeli ustawiono opcj magic_quotes, funkcja stripslashes() bdzie wywoywana rekurencyjnie dla wszystkich
danych w tablicy $_COOKIE.
if (get_magic_quotes_gpc()) {
$_COOKIE = stripCookieSlashes($_COOKIE);
}
?>
Skrypt stripCookieSlashes.inc.php naley wczy do wszystkich skryptw PHP, ktre odczytuj pliki cookie za pomoc nastpujcej instrukcji:
require_once 'stripCookieSlashes.inc.php';
<?php
function stripCookieSlashes($arr) {
if (!is_array($arr)) {
return stripslashes($arr);
} else {
return array_map('stripCookieSlashes', $arr);
}
}
ROZDZIA 5
167
ROZDZIA 5
ROZDZIA 5
setcookie('version', phpversion(),
$_GET['time'] + 21*24*60*60)
<?php
if (isset($_GET['time']) && is_int($_GET['time']))
{
setcookie('version', phpversion(),
$_GET['time'] + 21*24*60*60);
} else {
setcookie('version', phpversion(),
time() + 21*24*60*60);
}
?>
Prba wysania pliku cookie.
ROZDZIA 5
czasu i wysya j do dziaajcego na serwerze skryptu setcookie-specific.php. Najwaniejsza rnica pomidzy funkcj PHP time() a metod getTime() jzyka JavaScript
polega na tym, e ta druga zwraca liczb milisekund, jakie
upyny od pnocy 1 stycznia 1970 roku, natomiast pierwsza liczb sekund. Z tego powodu warto otrzyman ze
skryptu JavaScript naley najpierw podzieli przez 1000
i zaokrgli w d do caoci.
Kod skryptu setcookie-specific.php zamieszczono na pocztku tego podrozdziau. Przesyana warto jest wykorzystywana jako podstawa obliczenia relatywnej daty wanoci
pliku cookie.
<script language = "JavaScript"
type="text/javascript><!var epoche = (new Date() - getTime();
epoche = Math.floor(epoche/1000);
location.replace("setcookie-specific.php?time="
+ epoche);
//-></script>
Intuicyjnym sposobem usunicia pliku cookie jest ustawienie jego wartoci na pusty cig znakw. Ta operacja
nie powoduje jednak usunicia pliku cookie. Plik w dalszym cigu istnieje, cho ju nie ma ustawionej wartoci.
Lepszym sposobem jest ponowne przesanie tego samego
170
ROZDZIA 5
<?php
setcookie('version', '', time() 10*365*24*60*60);
?>
Prba usunicia pliku cookie.
171
ROZDZIA 5
OSTRZEENIE
Jeli sprbujemy ustawi dat utraty wanoci na 0, PHP pominie ten parametr, a zatem ten sposb nie zadziaa. Trzeba
uy argumentu o dodatniej wartoci na przykad 1.
172
W niektrych przypadkach istnieje potrzeba, aby pliki cookie dziaay w kilku domenach zewntrznych lub poddomenach, na przykad www.przyklad.com, sklep.przyklad.com
i ssl.przyklad.com. Sytuacja dotyczy duych witryn WWW
z wieloma poddomenami, takich jak Amazon czy eBay.
Witryny te wymagaj obsugi dla wszystkich domen najwyszego poziomu. Aby to byo moliwe, trzeba ustawi
domen pliku cookie czwarty parametr funkcji setcookie(). Jest jednak pewien kopot: nazwy domen s
prawidowe, o ile zawieraj dwie kropki. Jeli zatem ustawimy domen na .przyklad.com, do pliku cookie bd
ROZDZIA 5
173
ROZDZIA 5
Pamitacie, w jaki sposb s przesyane pliki cookie? Najpierw serwer przesya plik cookie do klienta w odpowiedzi
HTTP. W nastpnym daniu, jeli uytkownik zaakceptuje plik cookie, klient przesya go z powrotem na
serwer. Z tego powodu wywoanie funkcji setcookie()
i pniejsze sprawdzenie zawartoci tablicy $_COOKIE nie
zadziaa. Trzeba zaczeka na kolejne danie HTTP.
<?php
if (isset($_GET['step']) && $_GET['step'] == '2') {
$test_temp = isset($_COOKIE['test_temp']) ?
'obsuguje' : 'nie obsuguje';
$test_persist = isset($_COOKIE['test_persist']) ?
'obsuguje' : 'nie obsuguje';
setcookie('test_temp', '', time() - 365*24*60*60);
setcookie('test_persist', '', time() 365*24*60*60);
174
ROZDZIA 5
175
ROZDZIA 5
setcookie('cookiedata', serialize($cookiedata)
176
time() + 30*24*60*60);
}
function getCookieData($name) {
$cookiedata = getAllCookieData();
if ($cookiedata != null &&
isset($cookiedata[$name])) {
return $cookiedata[$name];
}
}
return '';
}
?>
function getAllCookieData() {
if (isset($_COOKIE['cookiedata'])) {
$formdata = $_COOKIE['cookiedata'];
if ($formdata != '') {
return unserialize($formdata);
} else {
return array();
}
} else {
return null;
}
}
ROZDZIA 5
177
ROZDZIA 5
Zapisywanie ustawie
jzykowych uytkownika
setcookie('lang', $_SERVER['PHP_SELF'], time() +
30*24*60*60, '/')
ROZDZIA 5
odczytujc nagwek HTTP Accept-Language, z ktrego mona si dowiedzie, jakie jzyki s preferowane,
Chocia kada z tych metod jest w jakim stopniu skuteczna, ostatnia (lub kombinacja kilku) jest uwaana za najbardziej przyjazn dla uytkownika. Trzeba zatem zdefiniowa
stron macierzyst zawierajc cza do wszystkich dostpnych wersji jzykowych. Wystarczy prosty jzyk HTML:
<a
<a
<a
<a
ROZDZIA 5
<?php
if (!isset($_COOKIE['lang']) ||
$_COOKIE['lang'] != $_SERVER['PHP_SELF']) {
setcookie('lang', $_SERVER['PHP_SELF'],
time() + 30*24*60*60, '/');
}
?>
UWAGA
Jest bardzo istotne, aby ustawi ciek pliku cookie na
gwny katalog serwera WWW. W innym przypadku wartoci domyln cieki bdzie katalog biecy i plik bdzie
mg by odczytany tylko w katalogu biecym i jego podkatalogach. Nie bdzie go mona go odczyta ze strony macierzystej.
Na koniec, na stronie macierzystej trzeba sprawdzi, czy
ustawiono plik cookie, a jeli tak, przekierowa uytkownika na stron zawierajc odpowiedni wersj jzykow.
W tym celu na pocztku skryptu multilingual.php trzeba
wprowadzi nastpujcy kod:
<?php
if (isset($_COOKIE['lang']) && $_COOKIE['lang']
!= '') {
header("Location: {$_COOKIE['lang']}");
}
?>
Sesje
ROZDZIA 5
Sesje
ROZDZIA 5
Skorzystanie z tej dyrektywy spowoduje utworzenie podkatalogw w katalogu /tmp do 5 poziomw w gb. Aby
mechanizm sesji PHP mg zapisywa dane w podkatalogach, trzeba je wczeniej utworzy. Do tego celu suy
skrypt mod_files.sh w katalogu ext/sessions.
Oczywicie prawo do odczytywania tego katalogu powinien posiada tylko serwer WWW. W innym przypadku
inni uytkownicy systemu mogliby odczytywa informacje o sesji potencjalnie zawierajce wraliwe dane.
182
W jaki sposb
zachowa stan sesji?
Co jednak zrobi, jeli uytkownik wyczy obsug plikw cookie? W takim przypadku mona skorzysta z innego mechanizmu. W tym celu naley ustawi nastpujc
dyrektyw:
session.use_trans_sid = 0
W tym przypadku PHP automatycznie ustawia tryb, w ktrym identyfikator sesji jest doczany do wszystkich adresw URL. Takie rozwizanie moe powodowa pewne
zagroenie (na przykad modyfikowanie sesji ang. session
fixation, lub przechwytywanie sesji ang. session hijacking), ale jest do praktyczne. Wykorzystuj je wszystkie znane witryny e-commerce, na przykad Amazon. Jeli
odwiedzimy ich witryn WWW i zaadujemy stron, identyfikator sesji zostanie automatycznie doczony na kocu
adresu URL.
ROZDZIA 5
183
ROZDZIA 5
Aktywacja sesji
UWAGA
Przekazywanie identyfikatorw sesji w adresach URL w zasadzie jest ze, poniewa odwiedzajcy mog zapisywa je
w postaci zakadek, niektre wyszukiwarki nie uwzgldniaj
witryn, w ktrych stosuje si t technik itd. W kadej witrynie e-commerce (a take w wikszoci innych witryn) trzeba
jednak wzi pod uwag, e niektrzy odwiedzajcy (potencjalni klienci!) nie wcz obsugi plikw cookie. W takim
przypadku sesje gwarantuj wygodny sposb pokonania tego
ograniczenia.
Aktywacja sesji
session_start()
ROZDZIA 5
Dostp do wszystkich danych sesji w skrypcie PHP mona uzyska za pomoc tablicy $_SESSION. Poniewa dane
s zapisane po stronie serwera, mona zapisa dane sesji
i odczyta je ju w nastpnej instrukcji PHP bez koniecznoci transmisji, tak jak to byo w przypadku plikw cookie.
185
ROZDZIA 5
Zamykanie sesji
Zamykanie sesji
session_destroy()
186
print_r($_SESSION);
echo '</pre>';
?>
session_regenerate_id()
Modyfikacje
identyfikatora sesji
ROZDZIA 5
<?php
ob_start();
session_start();
echo 'Stary: ' . session_id();
session_regenerate_id();
echo '<br />Nowy: ' . session_id();
ob_end_flush();
?>
187
ROZDZIA 5
UWAGA
W tym kodzie wykorzystano buforowanie wynikw funkcje ob_start() i ob_end_flush() poniewa funkcj
session_regenerate_id() trzeba wywoa przed wysaniem do klienta wyniku HTML.
188
WSKAZWKA
Kiedy korzystamy z formularzy HTML, PHP automatycznie
docza identyfikator sesji do atrybutu action formularza.
Jednak, aby wykorzysta formularze dynamiczne, mona doda ukryte pole zawierajce informacje o sesji:
session_name()
ROZDZIA 5
<?php
$name = htmlspecialchars(session_name());
$id = htmlspecialchars(session_id());
echo "<input type=\"hidden\" name=\"$name\"
value=\"$id\" />";
?>
189
ROZDZIA 5
Implementacja wasnego
mechanizmu zarzdzania
sesjami
session_set_save_handler(
'sess_open', 'sess_close', 'sess_read',
'sess_write', 'sess_destroy', 'sess_gc');
kolumna access jest typu VARCHAR(14) i zawiera znacznik czasu ostatniego dostpu do danych sesji.
Funkcj PHP session_set_save_handler() mona wykorzysta do zdefiniowania wasnych funkcji dla szeciu
operacji wewntrznie wykonywanych przez PHP:
otwierania sesji,
zamykania sesji,
niszczenia sesji,
ROZDZIA 5
<?php
$GLOBALS['sess_server'] = 'localhost';
$GLOBALS['sess_db'] = 'sessions';
$GLOBALS['sess_username'] = 'user';
$GLOBALS['sess_password'] = 'pass';
function sess_open() {
191
ROZDZIA 5
$GLOBALS['sess_mysqli'] = mysqli_connect(
$GLOBALS['sess_server'],
$GLOBALS['sess_username'],
$GLOBALS['sess_password']
);
mysqli_select_db($GLOBALS['sess_mysqli'],
$GLOBALS['sess_db']);
}
function sess_close() {
mysqli_close($GLOBALS['sess_mysqli']);
}
function sess_read($id) {
$result = mysqli_query(
$GLOBALS['sess_mysqli'],
sprintf('SELECT data FROM sessiondata WHERE id
= \'%s\'',
mysqli_real_escape_string($GLOBALS['sess_mysqli'],
$id))
);
if ($row = mysqli_fetch_object($result)) {
$ret = $row->data;
mysqli_query(
$GLOBALS['sess_mysqli'],
sprintf('UPDATE sessiondata SET
access=\'%s\' WHERE id=\'%s\'',
date('YmdHis'),
mysqli_real_escape_string($GLOBALS['sess_mysqli'],
$id))
);
} else {
$ret = '';
}
return $ret;
}
function sess_write($id, $data) {
mysqli_query(
$GLOBALS['sess_mysqli'],
192
mysqli_real_escape_string($GLOBALS['sess_mysqli'],
$data),
date('YmdHis'),
mysqli_real_escape_string($GLOBALS['sess_mysqli'],
$id))
);
}
return true;
}
function sess_destroy($id) {
mysqli_query(
$GLOBALS['sess_mysqli'],
sprintf('DELETE FROM sessiondata WHERE
id=\'%s\'',
mysqli_real_escape_string($GLOBALS['sess_mysqli'],
$id))
);
if
(mysqli_affected_rows($GLOBALS['sess_mysqli']) < 1)
{
mysqli_query(
$GLOBALS['sess_mysqli'],
sprintf('INSERT INTO sessiondata (data,
access, id) VALUES (\'%s\', \'%s\', \'%s\')',
ROZDZIA 5
mysqli_real_escape_string($GLOBALS['sess_mysqli'],
$id))
);
return true;
}
function sess_gc($timeout) {
$timestamp = date('YmdHis', time() - $timeout);
193
ROZDZIA 5
mysqli_query(
$GLOBALS['sess_mysqli'],
sprintf('DELETE FROM sessiondata WHERE access
< \'%s\'',
$timestamp)
);
}
session_set_save_handler(
'sess_open', 'sess_close', 'sess_read',
'sess_write', 'sess_destroy', 'sess_gc');
?>
WSKAZWKA
W pliku session.sql w archiwum z przykadami znajduj si
instrukcje SQL suce do utworzenia tabeli bazy danych MySQL. W skrypcie session_mysqli_readwrite.php wykorzystano kod z powyszego listingu w celu zapisania pewnych
danych z wykorzystaniem sesji.
Na rysunku 5.8 pokazano zawarto tabeli session po
zapisaniu do niej danych.
Tworzenie zabezpieczonego
obszaru z wykorzystaniem sesji
session_start();
if (!(isset($_SESSION['authorized']) &&
$_SESSION['authorized'] != '')) {
header("Location:
login.php?url={$_SERVER['PHP_SELF']}");
}
194
ROZDZIA 5
ROZDZIA 5
To wszystko! Przykadowy skrypt secret.php zawiera poufne informacje i jest chroniony przez kod zamieszczony
na dwch poprzednich listingach.
196
Tworzenie zabezpieczonego
obszaru bez korzystania z sesji
ROZDZIA 5
<?php
if (!(isset($_SERVER['PHP_AUTH_USER']) &&
isset($_SERVER['PHP_AUTH_PW']) &&
$_SERVER['PHP_AUTH_USER'] == 'Shelley' &&
$_SERVER['PHP_AUTH_PW'] == 'TopSecret')) {
header('WWW-Authenticate: Basic realm="Secured
area"');
header('Status: 401 Unauthorized');
} else {
?>
Jeli wykorzystanie uwierzytelniania z mechanizmem zarzdzania sesji PHP wydaje si zbyt duym obcieniem,
mona skorzysta z dwch innych moliwoci. Po pierwsze,
mona skonfigurowa serwer WWW w taki sposb, aby tylko uwierzytelnieni uytkownicy mieli dostp do niektrych
plikw lub katalogw. Na przykad uytkownicy serwera
Apache mog wykorzysta pliki .htaccess. Pod adresem
http://apache-server.com/tutorials/ATusing-htaccess.html
mona znale sporo informacji na ten temat. Serwer
Microsoft IIS jest wyposaony w narzdzie z graficznym
interfejsem uytkownika do definiowania praw dostpu,
a zatem rwnie dla tego serwera mona zdefiniowa
podobny mechanizm.
197
ROZDZIA 5
gwek 401 czy te wywietli zawarto strony. Implementacj tego mechanizmu zaprezentowano na powyszym
listingu. Okno dialogowe z pytaniem o nazw uytkownika i haso pokazano na rysunku 5.10.
pakiet Auth zawiera zbir funkcji sucych do uwierzytelniania uytkownikw, a tym samym do zabezpieczania
stron PHP,
ROZDZIA 5
199