Kontrola danych wejściowych w PHP 5

Autor: Tomasz Jędrzejewski
Data publikacji: 29.01.2005, 09:53 | Ostatnia modyfikacja: 19.11.2006, 17:42

W artykule opisany jest sposób na kontrolÄ™ poprawnoÅ›ci danych wejÅ›ciowych przychodzÄ…cych do skryptu PHP przy pomocy maperów.



Najważniejsza zasada obowiÄ…zujÄ…ca podczas tworzenia formularzy w serwisach WWW brzmi: nigdy nie ufaj internaucie i zawsze poddawaj jego dane kontroli. I jest to szczera prawda. Nigdy nie jesteÅ› pewien, czy zadania wypeÅ‚nienia formularza podejmie siÄ™ zwyczajny internauta, który zastosuje siÄ™ do polecenia "Wprowadź liczbÄ™ z zakresu 1-29384", czy też może zwyczajny debil. Dlatego każdy, kto poważnie podchodzi do projektowania serwisów WWW, powinien znaleźć i używać dobrego sposobu na kontrolÄ™ tychże danych. W tym artykule mam zamiar opisać jeden z nich.

Czym jest maper

Maper jest w zasadzie zwyczajnÄ… klasÄ…, przez którÄ… przechodzÄ… wszystkie dane wejÅ›ciowe. Programista wypeÅ‚nia, jakie pola chciaÅ‚by pobrać z tablic $_POST, $_GET itd., a także ustawia specjalne flagi definiujÄ…ce, co ma siÄ™ w nich znajdować. Jeżeli zawartość pola bÄ™dzie siÄ™ zgadzać z tym, co podaÅ‚, zostanie ono dodane do wewnÄ™trznej tablicy już zmapowanych danych, skÄ…d bÄ™dzie można je bezpiecznie pobrać.

Tak wiÄ™c do wÅ‚aÅ›ciwego miejsca, z którego skrypt bÄ™dzie czerpać dane, trafiać bÄ™dÄ… tylko te pola, które speÅ‚niajÄ… nasze wymogi, i żadne inne. Ponadto maper może nawet poddać ich zawartość wstÄ™pnej obróbce: dokonać konwersji typów czy uciąć niepotrzebne spacje!

W opisie wszystko wyglÄ…da piÄ™knie. Niestety w praktyce kod źródÅ‚owy takiego mapera jest dość zagmatwany, dlatego należy dokÅ‚adnie siÄ™ przyÅ‚ożyć do pracy. Za to rezultat koÅ„cowy jest wrÄ™cz rewelacyjny - sam używam maperów od pewnego już czasu i jestem w peÅ‚ni zadowolony, iż tak wiele pracy wykonujÄ™ praktycznie jednym poleceniem!

Do góry

Problemy

Najważniejszym problemem przy pisaniu mapera w PHP jest sama natura tego jÄ™zyka. Zapewne wiadomo Ci, że zmienne mogÄ… dowolnie zmieniać swój typ, natomiast sam parser czasem może nie przypisać takiego typu, jaki powinien. Dlatego nie możemy nigdy ufać wewnÄ™trznym funkcjom: is_string(), is_float(), is_integer(). To zmusza nas do skorzystania z pomocy innych narzÄ™dzi...

Po drugie, wiele flag okreÅ›lajÄ…cych typ danego pola nie może być mieszanych ze sobÄ…! Tak jest na przykÅ‚ad z flagami typów - maper zgÅ‚upiaÅ‚by, gdyby mu podać flagÄ™ np. "INTEGER | STRING" :). Ale jeżeli chcemy zapewnić sobie wiÄ™kszÄ… kontrolÄ™, np. sprawdzenie, czy podana wartość mieÅ›ci siÄ™ w jakimÅ› zakresie, także musimy zdefiniować do tego zestaw flag, w dodatku pobierajÄ…cy parametry! To już kompletnie wyklucza możliwość wspóÅ‚istnienia ze sobÄ… dwóch flag tego typu, jak bowiem odróżnić, które parametry należą do której flagi? Jednym z rozwiÄ…zaÅ„ jest zapisanie wszystkich dodatkowych parametrów do tablicy i pobieranie ich z niej w sposób $parametry[$i], gdzie $i to iterator. Każde polecenie, które już przetworzyÅ‚o swoje parametry, zwiÄ™kszy go o ich ilość i tym samym problem zostaje rozwiÄ…zany. Jego implementacjÄ™ pozostawiÄ™ już jednak Tobie.

Te wszystkie problemy muszą znaleźć odzwierciedlenie w naszym kodzie, jeżeli ma być on stabilny i maksymalnie "idiotoodporny".

Do góry

Zaczynamy kodowanie

W artykule tym opiszÄ™ wyłącznie sposób budowy mapera dla formularzy, aczkolwiek bez problemu da siÄ™ go przerobić na inne postacie - wystarczy pozmieniać tablice, z której bÄ™dÄ… zasysane dane i po sprawie.

CaÅ‚y kod oparty jest o programowanie obiektowe z PHP 5, które pozwoli nam wykorzystać pewnÄ… swÄ… ciekawÄ… wÅ‚aÅ›ciwość do pobierania już zmapowanych danych. Na poczÄ…tek lista staÅ‚ych opisujÄ…cych kolejne flagi:

<?php
   define('FORM_INTEGER', 1);
   define('FORM_FLOAT', 2);
   define('FORM_NUMERIC', 4);
   define('FORM_STRING', 8);
   define('FORM_TEXT', 16);
   define('FORM_PASSWORD', 32);
   define('FORM_BOOLEAN', 64);
   define('FORM_GREATHER_THAN', 128);
   define('FORM_LOWER_THAN', 256);
   define('FORM_SCOPE', 512);
   define('FORM_COMPARE', 1024);
   define('FORM_LENGTH_COMPARE', 2048);
   define('FORM_NOTYPE', 4096);
   define('FORM_REQUIRED', 8192);

Kolejnym flagom przypisaÅ‚em nastÄ™pujÄ…ce po sobie potÄ™gi dwójki. DziÄ™ki temu każda z nich bÄ™dzie zajmowaÅ‚a w liczbie osobny bit i tym samym Å‚atwo bÄ™dzie sprawdzić, czy jest ustawiona. WÅ›ród nich mamy zarówno flagi opisujÄ…ce typy danych (np. FORM_STRING i FORM_NUMERIC, jak i te do sprawdzenia poprawnoÅ›ci informacji. Oto opis wszystkiego:

FORM_INTEGER
Liczba całkowita

FORM_FLOAT
Liczba zmiennoprzecinkowa (ułamek)

FORM_NUMERIC
Liczba całkowita albo ułamek

FORM_STRING
Ciąg o długości maks. 256 znaków, wśród którego musi znaleźć się przynajmniej jeden znak inny, niż cyfra.

FORM_TEXT
Wypracowanie albo coś w tym stylu. Przynajmniej jeden znak musi być inny, niż cyfra.

FORM_BOOLEAN
Typ logiczny. Dozwolone wartości: 1 lub 0.

FORM_NOTYPE
Typ nieistotny.

FORM_PASSWORD
Sprawdzanie, czy hasło zostało poprawnie potwierdzone. Jako parametru wymaga nazwy pola, z którego należy wziąć wersję do porównania.

FORM_GREATHER_THAN
Dla liczb: sprawdza, czy w polu wpisano większą wartość od podanej w parametrze.
Dla tekstu: sprawdza, czy tekst ma większą długość, niż podano w parametrze.

FORM_LOWER_THAN
Jak wyżej, ale mniejszą.

FORM_SCOPE
Dla liczb: sprawdza, czy podana liczba mieści się w zakresie określonym przez parametry.
Dla tekstu: sprawdza, czy długość tekstu mieści się w zakresie określonym przez parametry.

FORM_COMPARE
Porównuje liczbę/tekst z tym podanym w parametrze.

FORM_LENGTH_COMPARE
Porównuje długość tekstu z tą podaną w parametrze.

FORM_REQUIRED
Pole musi zostać wypełnione.

Nasza klasa bÄ™dzie zaczynać siÄ™ tradycyjnie od nagÅ‚ówka z polami. Jest on niewielki:

   class mapper{
      private $mapped_data;
      public $mapping_ok = 1;

Drugie pole bÄ™dzie przechowywaÅ‚o caÅ‚kowity stan mapowania (1 - gdy wszystkie aktualne dane zostaÅ‚y zmapowane; 0 - gdy coÅ› poszÅ‚o nie tak). W pierwszym natomiast bÄ™dziemy tworzyli referencje do zmapowanych prawidÅ‚owo zasobów. Pobierać je stamtÄ…d bÄ™dzie metoda specjalna __get():

      public function __get($name){
         if(isset($this->mapped_data[$name])){
            return $this->mapped_data[$name];
         }
         return NULL;
      } // end __get(); 

DziÄ™ki temu do poszczególnych danych możemy siÄ™ odwoÅ‚ywać w ten sposób: $maper -> nazwa_zasobu zamiast czegoÅ› w stylu $maper -> mapped_data['nazwa_zasobu']. JeÅ›li dany element nie bÄ™dzie istniaÅ‚, zwracane jest null.

Wszystkie flagi opisujące mapowanie elementu prześlemy jako liczbę. Trzeba z niej wyciągnąć sugerowany typ elementu (FORM_STRING, FORM_INTEGER itd.). Zajmie się tym ta metoda:

      private function extract_type($name, $mapping, &$extracted_type){
         if($mapping & FORM_INTEGER){
            $extracted_type = FORM_INTEGER;
            return ctype_digit($_POST[$name]);
         }elseif($mapping & FORM_FLOAT){
            $extracted_type = FORM_FLOAT;
            return preg_match('/([0-9]*?)[\.,]([0-9]*?)/', $_POST[$name]);
         }elseif($mapping & FORM_NUMERIC){
            $extracted_type = FORM_NUMERIC;
            return preg_match('/([0-9 \-]*?)([\.,][0-9]*?)?/', $_POST[$name]);
         }elseif($mapping & FORM_STRING){
            if(!ctype_digit($_POST[$name])){
               $extracted_type = FORM_STRING;
               return (strlen($_POST[$name]) < 256);
            }
         }elseif($mapping & FORM_TEXT){
            if(!ctype_digit($_POST[$name])){
               $extracted_type = FORM_TEXT;
               return 1;
            }
         }elseif($mapping & FORM_BOOLEAN){
            $extracted_type = FORM_BOOLEAN;
            return preg_match('/(0|1)/', $_POST[$name]);
         }elseif($mapping & FORM_NOTYPE){
            $extracted_type = FORM_NOTYPE;
            return 1;
         }
         return 0;
      } // end extract_type(); 

Jak widać, dodatkowo sprawdzamy tutaj, czy dane sÄ… rzeczywiÅ›cie zapisane w podanym przez nas typie. Czasami używam do tego wyrażeÅ„ regularnych Perla (preg_match()), a czasami funkcji moduÅ‚u Character type, sÅ‚użącego do sprawdzania, czy w podanej zmiennej sÄ… same cyfry itp. Nie musisz siÄ™ martwić o brak obsÅ‚ugi - od PHP 4.2 moduÅ‚ ten jest domyÅ›lnie włączony, a od PHP 4.3 jest już wbudowany (my korzystamy tu z PHP 5 :)). Dostajemy z nim ciekawÄ… funkcjÄ™ - ctype_digit(), która zwróci nam 1, jeÅ›li podany ciÄ…g zawiera wyłącznie cyfry. Pomoże nam ona w obsÅ‚udze flag FORM_INTEGER, FORM_TEXT oraz FORM_STRING.

Oto wÅ‚aÅ›ciwa metoda mapujÄ…ca dane. Może ona przyjmować od 2 do 4 parametrów. Zaczynamy wiÄ™c jÄ… kodem do ich obsÅ‚ugi:

      public function add_mapping($name, $type){
         if(func_num_args() == 3){
            $arg = func_get_arg(2);
         }elseif(func_num_args() == 4){
            $arg1 = func_get_arg(2);
            $arg2 = func_get_arg(3);
         }

Nadmiarowe parametry wprowadziÅ‚em do zmiennych tymczasowych, gdyż (z tego, co siÄ™ zdążyÅ‚em zorientować) funkcja do ich pobierania func_get_arg() zaczyna siÄ™ w przeciwnym przypadku dość dziwnie zachowywać :). Prawdopodobnie chodzi tu o ich specyficzne dziaÅ‚anie - pobieranie parametrów, co wyklucza pewne możliwoÅ›ci użycia. JeÅ›li ktoÅ› wie, o co z tym dokÅ‚adnie chodzi, prosiÅ‚bym o kontakt.

Jako pierwszÄ… obsÅ‚użymy flagÄ™ FORM_REQUIRED, gdyż jeÅ›li jakiÅ› zasób nie bÄ™dzie istnieć, choć musi, po co go bÄ™dziemy próbowali bezskutecznie mapować?

         if(!isset($_POST[$name]) && $type & FORM_REQUIRED){
            $this -> mapping_ok = 0;
            return 0;
         }

Kolejny etap to "rozpakowanie" typu zasobu przy pomocy napisanej wcześniej metody extract_type():

         if(isset($_POST[$name])){
            if(!$this -> extract_type($name, $type, $extype)){
               $this -> mapping_ok = 0;
               return 0;
            }

NastÄ™pnie mapujemy jednÄ… z trzech flag - FORM_SCOPE, FORM_GREATHER_THAN oraz FORM_LOWER_THAN. Zauważ, iż dokonujemy tu sprawdzenia typu i wyboru decyzji, czy porównywać wartość (dla liczb), czy jej dÅ‚ugość (dla tekstów):

            if($type & FORM_SCOPE){
               if($extype == FORM_STRING || $extype == FORM_TEXT){
                  if(!($arg1 < strlen($_POST[$name]) && strlen($_POST[$name]) < $arg2)){
                     $this -> mapping_ok = 0;
                     return 0;
                  }
               }else{
                  if(!($arg1 < $_POST[$name] && $_POST[$name] < $arg2)){
                     $this -> mapping_ok = 0;
                     return 0;
                  }
               }
            }elseif($type & FORM_GREATHER_THAN){
               if($extype == FORM_STRING || $extype == FORM_TEXT){
                  if(!($arg < strlen($_POST[$name]))){
                     $this -> mapping_ok = 0;
                     return 0;
                  }
               }else{
                  if(!($arg < $_POST[$name])){
                     $this -> mapping_ok = 0;
                     return 0;
                  }
               }
            }elseif($type & FORM_LOWER_THAN){
               if($extype == FORM_STRING || $extype == FORM_TEXT){
                  if(!($arg > strlen($_POST[$name]))){
                     $this -> mapping_ok = 0;
                     return 0;
                  }
               }else{
                  if(!($arg > $_POST[$name])){
                     $this -> mapping_ok = 0;
                     return 0;
                  }
               }
            }

Kolejny krok to obsÅ‚uga FORM_PASSWORD. Z parametru $arg pobieramy nazwÄ™ pola, z którym bÄ™dziemy porównywać to aktualnie mapowane. Flaga ta nie dziaÅ‚a tylko z polami FORM_TEXT - wszystkie inne sÄ… dozwolone.

Dodam, iż tu wÅ‚aÅ›nie objawia siÄ™ pewna sÅ‚abość tego mapera. Jeżeli nadamy tÄ™ flagÄ™, nie możemy nadać innej, opisujÄ…cej np. minimalnÄ… dÅ‚ugość hasÅ‚a, ponieważ obie wspóÅ‚dzielÄ… miÄ™dzy sobÄ… jeden z parametrów. Zadanie naprawienia tego pozostawiam tobie, a jedno z możliwych rozwiÄ…zaÅ„ sugerowaÅ‚em na poczÄ…tku tego tekstu.

            if($type & FORM_PASSWORD && $extype != FORM_TEXT){
               if($_POST[$name] != $_POST[$arg]){
                  $this -> mapping_ok = 0;
                  return 0;
               }
            }

Na koniec zostawiliÅ›my sobie porównywanie wartoÅ›ci i ich dÅ‚ugoÅ›ci:

            if($type & FORM_COMPARE && $extype != FORM_TEXT && $extype != FORM_NOTYPE){
               if($_POST[$name] != $arg){
                  $this -> mapping_ok = 0;
                  return 0;
               }
            }elseif($type & FORM_LENGTH_COMPARE && ($extype == FORM_TEXT || $extype != FORM_STRING)){
               if(strlen($_POST[$name]) != $arg){
                  $this -> mapping_ok = 0;
                  return 0;
               }
            }
         }

JeÅ›li kod dotarÅ‚ aż tutaj, to znak, że dany zasób przeszedÅ‚ przez wszystkie kontrole - jakakolwiek nieprawidÅ‚owość bowiem przerywaÅ‚a dziaÅ‚anie mapera poprzez wywoÅ‚anie instrukcji return 0;. StÄ…d też możemy bez przeszkód dodać referencjÄ™ do zasobu do tablicy $mapped_data oraz potwierdzić stan pola $mapping_ok.

         $this -> mapped_data[$name] = &$_POST[$name];
         $this -> mapping_ok = $this->mapping_ok && 1;
         return 1;
      } // end add_mapping();
   }
?>

Zauważ, jak obsÅ‚ugiwane jest pole $this->mapping_ok. DziÄ™ki zastosowaniu operatora && zrobiÅ‚em to, co "normalnie" musiaÅ‚bym robić przy użyciu instrukcji if - jeÅ›li pole to ma wartość 0, zostanie 0. JeÅ›li 1, to 1. W zasadzie ta instrukcja nie jest potrzebna, ale chciaÅ‚em pokazać, iż czasami niektóre rzeczy można w niezwykÅ‚y sposób upraszczać :). Zainteresowanych odsyÅ‚am do artykuÅ‚u "Wyrażenia w PHP".

Do góry

Przykłady

Czas pokazać dziaÅ‚anie mapera w praktyce. Pierwszy przykÅ‚ad to prosty formularz proszÄ…cy o podanie imienia, nazwiska, wieku oraz zainteresowaÅ„. Trzy pierwsze pola muszÄ… zostać wypeÅ‚nione, dwa z nich muszÄ… zawierać ciÄ…g tekstowy, jedno liczbÄ™. Ostatnie z pól powinno być zapeÅ‚nione wypracowaniem. Nasz maper idealnie nadaje siÄ™ do takiego celu. ProszÄ™ popatrzeć:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Mapper test 1</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-2"/>
</head>
 
<body>
<table width="60%">
   <form method="post" action="przyklad1.php?co=przetworz">
   <tr>
      <td width="40%">ImiÄ™ *:</td>
      <td width="60%"><input type="text" name="imie" value="<?=$_POST['imie']?>"/></td>
   </tr>
   <tr>
      <td width="40%">Nazwisko *:</td>
      <td width="60%"><input type="text" name="nazwisko" value="<?=$_POST['nazwisko']?>"/></td>
   </tr>
   <tr>
      <td width="40%">Wiek *:</td>
      <td width="60%"><input type="text" name="wiek" value="<?=$_POST['wiek']?>"/></td>
   </tr>
   <tr>
      <td width="40%">Zainteresowania:</td>
      <td width="60%"><textarea name="zainteresowania" rows="6" cols="40"><?=$_POST['zainteresowania']?></textarea></td>
   </tr>
   <tr>
      <td width="100%" colspan="2"><input type="submit" value="Wyślij"/></td>
   </tr>
   </form>
</table>
* - pola wymagają wypełnienia.<br/>
 
<?php
 
   if($_GET['co'] == 'przetworz'){
      require('./maper.php');
 
      $maper = new mapper;
      if(!$maper -> add_mapping('imie', FORM_STRING | FORM_REQUIRED | FORM_GREATHER_THAN, 2)){
         echo '<font color="red">Źle wypełnione pole `imię`!</font><br/>';
      }
      if(!$maper -> add_mapping('nazwisko', FORM_STRING | FORM_REQUIRED | FORM_GREATHER_THAN, 2)){
         echo '<font color="red">Źle wypełnione pole `nazwisko`!</font><br/>';
      }
      if(!$maper -> add_mapping('wiek', FORM_INTEGER | FORM_REQUIRED | FORM_SCOPE, 10, 99)){
         echo '<font color="red">Źle wypełnione pole `wiek`!</font><br/>';
      }
      $maper -> add_mapping('zainteresowania', FORM_TEXT);
 
      if(!$maper -> mapping_ok){
         echo '<font color="red">Formularz został niewłaściwie wypełniony.</font><br/>';
      }else{
         echo 'Twoje imiÄ™ to '.$maper->imie.'<br/>';
         echo 'Twoje nazwisko to '.$maper->nazwisko.'<br/>';
         echo 'Twój wiek to '.$maper->wiek.' lat<br/>';
         if($maper->zainteresowania != NULL){
            echo 'Twoje zainteresowania to: <i>'.$maper->zainteresowania.'</i><br/>';
         }
      }
 
   }
?>
</body>
</html>

Najpierw dołączamy klasÄ™ mapera i tworzymy jego obiekt. Zauważ, iż każde z mapowanych pól możemy obsÅ‚użyć na dwa sposoby. Pierwszy to wrzucenie wywoÅ‚ania metody add_mapping() do instrukcji IF. Wtedy bÄ™dziemy wiedzieli, na którym polu coÅ› nawaliÅ‚o i dokÅ‚adnie wskażemy to internaucie. Drugi sposób to sprawdzenie stanu pola mapping_ok. JeÅ›li bÄ™dzie ono równać siÄ™ zeru, coÅ› poszÅ‚o nie tak, a co za tym idzie, internauta wprowadziÅ‚ zÅ‚e dane.

Przyjrzyj siÄ™ wywoÅ‚aniu add_mapping(), a w szczególnoÅ›ci sposobowi łączenia ze sobÄ… poszczególnych flag (tu również odsyÅ‚am do artykuÅ‚u "Wyrażenia w PHP"). JeÅ›li flagi tego wymagajÄ…, podajemy od jednego do dwóch dodatkowych parametrów.

Pole "zainteresowania" nie jest wymagane, a więc musimy sprawdzić, czy internauta je wypełnił. Posłuży nam do tego to, o czym wspomniałem przy omawianiu metody __get() obsługującej te właśnie wywołania. Jeśli coś nie jest stworzone, zwracamy wartość null.

Drugi przykład koncentruje się na fladze FORM_PASSWORD.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Maper test 2</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-2">
</head>
 
<body>
<table width="60%">
   <form method="post" action="przyklad2.php?co=przetworz">
   <tr>
      <td width="40%">Nick:</td>
      <td width="60%"><input type="text" name="nick" value="<?=$_POST['nick']?>"/></td>
   </tr>
   <tr>
      <td width="40%">Hasło:</td>
      <td width="60%"><input type="password" name="haslo"/></td>
   </tr>
   <tr>
      <td width="40%">Powtórz hasło:</td>
      <td width="60%"><input type="password" name="haslo2"/></td>
   </tr>
   <tr>
      <td width="100%" colspan="2"><input type="submit" value="Wyślij"/></td>
   </tr>
   </form>
</table>
 
<?php
 
   if($_GET['co'] == 'przetworz'){
      require('./maper.php');
 
      $maper = new mapper;
      if(!$maper -> add_mapping('nick', FORM_STRING | FORM_REQUIRED | FORM_GREATHER_THAN, 5)){
         echo '<font color="red">Źle wypełnione pole `nick`!</font><br/>';
      }
      if(!$maper -> add_mapping('haslo', FORM_STRING | FORM_REQUIRED | FORM_PASSWORD, 'haslo2')){
         echo '<font color="red">Podane hasła nie zgadzają się ze sobą lub mają niewłaściwy format!</font><br/>';
      }
 
      if(!$maper -> mapping_ok){
         echo '<font color="red">Formularz został niewłaściwie wypełniony.</font><br/>';
      }else{
         echo 'Twój nick to '.$maper->nick.'<br/>';
         echo 'Twoje hasło to '.$maper->haslo.'<br/>';
      }
 
   }
?>
</body>
</html>

Pole nick mapujemy podobnie, jak w przykÅ‚adzie poprzednim. JeÅ›li chodzi o hasÅ‚a, tu wywoÅ‚ujemy add_mapping() tylko na jednym z pól, a nazwÄ™ drugiego podajemy za opcjonalny parametr. W ten sposób dokonujemy caÅ‚ej kontroli.

Pobaw siÄ™ tymi przykÅ‚adami i spróbuj je samodzielnie rozszerzyć o kilka innych wÅ‚aÅ›ciwoÅ›ci. Eksperymentuj z różnymi kombinacjami flag.

Do góry

Zakończenie

Mapery to bardzo ciekawy sposób kontrolowania tego, co otrzymujemy z formularza. Niestety nie widziałem żadnego "gotowego" skryptu, na którym można by się wzorować. Całą powyższą metodę działania i inne duperele opracowałem sam, w wolnej chwili, podczas opracowywania kolejnego z moich dziwnych programistycznych wynalazków :). Muszę jednak stwierdzić, że sprawdza się znakomicie.

W ramach praktyki polecam Ci przerobić przedstawiony tu kod tak, aby obsługiwał dane z adresu URL. Spróbuj dodać do niego flagę BASE64, która spowoduje uprzednie zdekodowanie danych przesłanych właśnie w formacie Base64, bardzo dobrze sprawdzającym się w przypadku URL'i.

Na tym kończę ten artykuł. Miłego pisania!

Autor: Tomasz "Zyx" Jędrzejewski, www.zyxist.com

Do góry

Waszym zdaniem:

shize :: 18.04.2007, 12:26 :: #88

Czy preg_match z FORM_NUMERIC i FORM_FLOAT nie zwróci 1 w przypadku kiedy oprócz poprawnego wyrażenia znajdzie się niepożądany znak?

Twoim zdaniem:

Reklama

banner

Partnerzy

CityDesign.pl
phpSolutions