Jednoduchá kontrola proměnných
Formuláře jsou prakticky nejjednodušším způsobem jak lze získat data od uživatele. S touto jednoduchostí jde ruku v ruce nebezpečí těchto dat. Uživatelům nemůžeme nikdy věřit a proto je nutné všechny tyto vstupy zabezpečit a data ověřovat. Nestačí například napsat, že v daném formulářovém inputu musí být zadán platný email, protože se vždy najde někdo, kdo se pokusí zadat libovolný řetězec, a nejen to. Špatně ošetřený vstup může vést k chybám jako SQL injection nebo XSS. Takový formulář je součástí téměř každého webu a pokud vás už přestalo bavit u každého takového formuláře neustále dokola provádět kontroly, můžete si vytvořit několik jednoduchých funkcí, které se o kontrolu budou starat. Ovšem nemusí se jednat pouze o formuláře, ale také bezpochyby o kontrolu proměnných ve skriptu. V tomto příkladu si vytvoříme třídu, v níž bude mít každá metoda na starosti kontrolu jiné hodnoty.
Kontrola délky řetězce
int check_length( mixed $var, int $min, int $max );
Začneme něčím jednodušším, a to metodou pro kontrolu délky řetězce. Vstupní hodnoty budou tří: kontrolovaný řetězec, minimální délka a nakonec maximální délka. Minimální délku bychom mohli dát jako nepovinný parametr, který by měl výchozí hodnotu 0, ale to už nechám na vás.
V metodě se nebudeme omezovat pouze pro kontrolu délky řetězce, ale bude umožňovat i kontrolu velikosti pole. Tím zabijeme dvě mouchy jednou ranou:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
function check_length( $var, $min, $max ){ if( !is_int( $min ) || !is_int( $max ) ) return 0; switch( gettype( $var ) ){ case 'string' : { return ( strlen( trim( $var ) ) < $min || strlen( trim( $var ) ) > $max ? 0 : 1 ); //break; } case 'array' : { //recursive count $count = count( $var, COUNT_RECURSIVE ); return ( $count < $min || $count > $max ? 0 : 1 ); //break; } default: return 0; } } |
Metoda vrací jedničku nebo nulu podle výsledku kontroly.
Kontrola data
int check_date( string $date [, string $splitting ]);
Další metoda na kterou se podíváme a která bude určitě taky často využívána je kontrola datumu. Datum je většinou zadáváno ve tvaru ROK-MĚSÍC-DEN. Tento vstup bude předpokládat i naše metoda a takto zadané datum bude jedním ze vstupních parametrů. Druhý parametru bude oddělovací znak, který je v datumu použit.
Metoda nejprve, pomocí funkce explode, rozdělí datum na jeho jednotlivé částí a potom kontroluje, zda se jedná o platné datum:
1 2 3 4 5 6 7 8 9 10 |
function check_date( $date, $splitting = '-' ){ if( trim( $date ) == NULL ) return 0; list( $year, $month, $day ) = explode( $splitting, $date ); if( intval( $year ) == 0 || intval( $month ) == 0 || intval( $day ) == 0 ) return 0; return ( checkdate( $month, $day, $year ) ? 1 : 0 ); } |
Kontrola hesla
int check_password( strin $password_1, string $password_2 [, int $min, int $max ] );
Pokud máme hotovou metodu pro kontrolu délky řetězce, můžeme vytvořit další metodu, a to pro kontrolu hesla. Hesla jsou kontrolována dost často a všechno co většinou potřebujeme je kontrolovat maximální a minimální počet znaků, které uživatel zadal.
Metoda bude tedy velmi jednoduchá. Pro kontrolu délky využijeme metodu, která kontroluje délku řetězce, zde stačí kontrolovat pouze jedno zadání hesla, neboť potom provedeme kontrolu na shodnost, a tím pádem ošetříme případ, kdy by nebylo další zadání hesla v povoleném rozsahu:
1 2 3 4 5 6 7 8 9 |
function check_password( $pass1, $pass2, $min = 5, $max = 1000 ){ if( self::check_length($pass1, $min, $max ) == 0 ) return 0; if( $pass1 != $pass2 ) return 0; return 1; } |
Kontrola IP adresy
int check_ip_address( string $address );
Občas, i když asi ne často, budeme potřebovat provést kontrolu IP adresy. Adresu budeme požadovat ve tvaru: 127.0.0.1 a všechny ostatní případy budou vyhodnoceny jako FALSE.
Dále budeme požadovat aby všechny 4 čísla IP adresy byly v rozmezí 0-255 a poslední podmínka bude, aby čísla které jsou zadány byli 4. Na začátku metody ošetříme ještě případ, kdy uživatel zadal na konci IP adresy znak „.“:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
function check_ip_address( $ip ){ $ip = trim( $ip); if( empty( $ip ) ) return 0; $ip = ( substr( $ip, -1, 1 ) == '.' ? substr( $ip, 0, -1 ) : $ip ); if( count( $ip = explode('.', $ip ) ) != 4 ) return 0; foreach( $ip as $value ){ if( !is_numeric( $value ) || $value < 0 || $value > 255 ) return 0; } return 1; } |
Kontrola URL adresy
int check_url( string $url [, int $check_domain ] );
Co dost často provádíme je kontrola URL adresy. U URL adresy je většinou nejpodstatnější kontrolovat protokol, který byl zadán, protože uživatelé často do takového pole zadají jenom nesmyslnou spleť znaků. V poli si tedy nadefinujeme, které všechny protokoly budou povolené (v tomto případě pouze http, https a ftp, ale seznam si můžete rozšířit podle sebe ). Jako jeden ze vstupních parametrů bude tedy zadaná URL adresa. Metoda nám umožní navíc i kontrolu pravosti zadané URL adresy. Tento příklad ovšem většinou nebude fungovat pod systémem windows, proto je zde tato kontrola určena druhým, nepovinným parametrem:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
function check_url( $url_addres, $check_domain = 0 ){ if( trim( $url_addres ) == NULL ) return 0; $scheme = array('http', 'https', 'ftp'); $url = parse_url( trim( $url_addres ) ); if( in_array( $url['scheme'], $scheme) == 0 ) return 0; if( $url['host'] == NULL ) return 0; if( $check_domain == 0 ) return 1; if ( getmxrr ( $url['host'], $MX ) ) return $MX; else return 0; } |
Kontrola telefonního čísla
int check_phone( string $pnumber, [, int $length ] );
Kontrolu telefonního čísla musíme většinou provádět na základě nějaké vstupní masky (formátu v jakém je telefonní číslo přijatelné ). V našem případě bude telefon požadován ve tvaru: +xxx xxx xxx xxx. První parametr bude potom telefonní číslo. Pro jistotu si vytvoříme i druhý, nepovinný parametr, který určí maximální délku telefonního čísla.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
function check_phone( $pnumber, $length = 12 ){ //phone number format: +xxx xxx xxx xxx $pnumber = trim( $pnumber ); if( substr( $pnumber, 0, 1 ) != '+') return 0; $replace = array( ' ', '+' ); $replacent = array('', ''); $pnumber = str_replace( $replace, $replacent, $pnumber); if( strlen( $pnumber ) != $length ){ return 0; } return 1; } |
Navíc bychom mohli ještě překontrolovat zda je celé telefonní číslo zadáno jako číselná hodnota.
Kontrola PSČ
int check_zipcode( string $zip_code [, int $max_length ] );
Kontrola PSČ může být taky často užitečná. Psč bude moci být v našem případě zadána pouze jako číselná hodnota doplněna maximálně mezerou. Vstupní parametry jsou tedy hodnota PSC a nepovinný parametr je délka PSC bez zadaných mezer. Mezery před kontrolou délky ořežeme:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
function check_zipcode( $zip_string, $length = 5 ){ if( $zip_string == NULL || !is_int( $length ) ) return 0; $chars = array('0', '1', '2', '3', '4', '5', '6', '7', '8', '9'); $zip_string = trim( $zip_string ); for( $i = 0; $i < strlen( $zip_string ); $i++ ){ if( !in_array( $zip_string[ $i ], $chars ) && ord(" ") != ord( $zip_string[ $i ] ) ) return 0; } if( $length == 0 ) return 1; $zip_string = str_replace(' ', '', $zip_string ); return ( strlen( $zip_string ) != $length ? 0 : 1 ); } |
Kontrola emailu
int check_email( string $email [, int $check_domain ] );
Velmi důležitá metoda je kontrola emailu. Metoda nám umožňuje, stejně jako metoda pro kontrolu URL adresy, kontrolovat navíc doménu, ovšem tato funkce zase zřejmě nebude fungovat pod systémem Windows a proto je tato funkce opět omezena nepovinným parametrem.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
function check_email( $var, $check_domain = 0 ){ if( empty( $var ) ) return 0; $return = ( !eregi("^[_a-z0-9-]+(.[_a-z0-9-]+)*@[a-z0-9-]+(.[a-z0-9-]+)*(.[a-z]{2,3})$", $var ) ? 0 : 1 ); if( $check_domain == 0 ) return $return; list ( $username, $domain ) = split ("@",$var ); if ( getmxrr ( $domain, $MX ) ) return $MX; else return 0; } |
Kontrola rodného čísla
check_personal_identification_number( string $pin );
Poslední metodu pro kontrolu, kterou si vytvoříme a která může být užitečná je kontrola rodného čísla. Maska rodného čísla je už trochu složitější. Musíme zde kontrolovat všechna zadaná čísla, která se liší u muže a ženy.
Metoda má jediný vstupní parametr, kterým je právě rodné číslo, které je přesně určené:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
function check_personal_idenfication_number( $number ){ //516111/458 $len = strlen( strval( intval( str_replace('/', '', $number ) ) ) ); if( $len < 9 || $len > 10 ) return 0; $pin['year'] = substr( $number, 0, 2); $pin['month'] = intval( substr( $number, 2, 2 ) ); $pin['day'] = intval( substr( $number, 4, 2 ) ); $pin['ending'] = substr( $number, 6, 3); $pin['check_number'] = substr($number, 9, 1); //year if( $len == 9 ){ if( $pin['year'] > 53 ) return 0; else $pin['year'] = 19 . $pin['year']; } else if( $len == 10 ){ $pin['year'] = ( date('y') >= $pin['year'] ? 20 . $pin['year'] : 19 . $pin['year'] ); } //month if( $pin['month'] > 50 && $pin['month'] < 63 ) $pin['month'] -= 50; if( $pin['month'] < 1 || $pin['month'] > 12 ) return 0; //check days if( $pin['day'] > cal_days_in_month(CAL_GREGORIAN, $pin['month'], $pin['year'] ) ) return 0; return 1; } |
Tím máme hotovy všechny základní funkce, potřebné pro kontrolu dat.
Strip slashes
Navíc si uvedeme ještě jednu metodu, která se bude starat o ořezání magic quotes, a to podle nastavené direktivy Magic Quotes GPC v php.ini.
Metoda uvede vždy všechny vstupní pole na stejné hodnoty a to s ořezanými Magic Quotes:
1 2 3 4 5 6 7 8 9 10 11 |
function _stripslashes( & $array ){ $magic_quotes_gpc = get_magic_quotes_gpc(); if( is_array( $array ) ){ while ( list ( $key, $value ) = each ( $array ) ) { $array[ $key ] = trim( htmlspecialchars( $magic_quotes_gpc == 1 ? stripslashes( $value ) : $value ) ); } } else{ $array = trim( htmlspecialchars( $magic_quotes_gpc == 1 ? stripslashes( $array ) : $array ) ); } } |
Jako vstupní parametr je pole předané jako reference. Změna se tedy provádí přímo na tomto poli.
Na závěr se zase podívejme co jsme vytvořili:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 |
class check_variable{ function __construct(){} function check_phone( $pnumber, $length = 12 ){ //phone number format: +xxx xxx xxx xxx $pnumber = trim( $pnumber ); if( substr( $pnumber, 0, 1 ) != '+') return 0; //$replace = array( 0x20, 0x43 ); $replace = array( ' ', '+' ); $replacent = array('', ''); $pnumber = str_replace( $replace, $replacent, $pnumber); if( strlen( $pnumber ) != $length ){ return 0; } return 1; } function _stripslashes( & $array ){ $magic_quotes_gpc = get_magic_quotes_gpc(); if( is_array( $array ) ){ while ( list ( $key, $value ) = each ( $array ) ) { $array[ $key ] = trim( htmlspecialchars( $magic_quotes_gpc == 1 ? stripslashes( $value ) : $value ) ); } } else{ $array = trim( htmlspecialchars( $magic_quotes_gpc == 1 ? stripslashes( $array ) : $array ) ); } } function check_email( $var, $check_domain = 0 ){ if( empty( $var ) ) return 0; $return = ( !eregi("^[_a-z0-9-]+(.[_a-z0-9-]+)*@[a-z0-9-]+(.[a-z0-9-]+)*(.[a-z]{2,3})$", $var ) ? 0 : 1 ); if( $check_domain == 0 ) return $return; list ( $username, $domain ) = split ("@",$var ); if ( getmxrr ( $domain, $MX ) ) return $MX; else return 0; } function check_length( $var, $min, $max ){ if( !is_int( $min ) || !is_int( $max ) ) return 0; switch( gettype( $var ) ){ case 'string' : { return ( strlen( trim( $var ) ) < $min || strlen( trim( $var ) ) > $max ? 0 : 1 ); //break; } case 'array' : { //recursive count $count = count( $var, COUNT_RECURSIVE ); return ( $count < $min || $count > $max ? 0 : 1 ); //break; } default: return 0; } } function check_date( $date, $splitting = '-' ){ if( trim( $date ) == NULL ) return 0; list( $year, $month, $day ) = explode( $splitting, $date ); if( intval( $year ) == 0 || intval( $month ) == 0 || intval( $day ) == 0 ) return 0; return ( checkdate( $month, $day, $year ) ? 1 : 0 ); } function check_url( $url_addres, $check_domain = 0 ){ if( trim( $url_addres ) == NULL ) return 0; $scheme = array('http', 'https', 'ftp'); $url = parse_url( trim( $url_addres ) ); if( in_array( $url['scheme'], $scheme) == 0 ) return 0; if( $url['host'] == NULL ) return 0; if( $check_domain == 0 ) return 1; if ( getmxrr ( $url['host'], $MX ) ) return $MX; else return 0; } function check_password( $pass1, $pass2, $min = 5, $max = 1000 ){ if( $pass1 != $pass2 ) return 0; if( self::check_length($pass1, $min, $max ) == 0 ) return 0; return 1; } function check_personal_idenfication_number( $number ){ //516111/458 $len = strlen( strval( intval( str_replace('/', '', $number ) ) ) ); if( $len < 9 || $len > 10 ) return 0; $pin['year'] = substr( $number, 0, 2); $pin['month'] = intval( substr( $number, 2, 2 ) ); $pin['day'] = intval( substr( $number, 4, 2 ) ); $pin['ending'] = substr( $number, 6, 3); $pin['check_number'] = substr($number, 9, 1); //year if( $len == 9 ){ if( $pin['year'] > 53 ) return 0; else $pin['year'] = 19 . $pin['year']; } else if( $len == 10 ){ $pin['year'] = ( date('y') >= $pin['year'] ? 20 . $pin['year'] : 19 . $pin['year'] ); } //month if( $pin['month'] > 50 && $pin['month'] < 63 ) $pin['month'] -= 50; if( $pin['month'] < 1 || $pin['month'] > 12 ) return 0; //check days if( $pin['day'] > cal_days_in_month(CAL_GREGORIAN, $pin['month'], $pin['year'] ) ) return 0; return 1; } function check_ip_address( $ip ){ $ip = trim( $ip); if( empty( $ip ) ) return 0; $ip = ( substr( $ip, -1, 1 ) == '.' ? substr( $ip, 0, -1 ) : $ip ); if( count( $ip = explode('.', $ip ) ) != 4 ) return 0; foreach( $ip as $value ){ if( !is_numeric( $value ) || $value < 0 || $value > 255 ) return 0; } return 1; } function check_zipcode( $zip_string, $length = 0 ){ if( $zip_string == NULL || !is_int( $length ) ) return 0; $chars = array('0', '1', '2', '3', '4', '5', '6', '7', '8', '9'); $zip_string = trim( $zip_string ); for( $i = 0; $i < strlen( $zip_string ); $i++ ){ if( !in_array( $zip_string[ $i ], $chars ) && ord(" ") != ord( $zip_string[ $i ] ) ) return 0; } if( $length == 0 ) return 1; $zip_string = str_replace(' ', '', $zip_string ); return ( strlen( $zip_string ) != $length ? 0 : 1 ); } } |
No, proc vetsina z toho jde prepsat na jednoradkove regularni vyrazy ?
A od kdy nemuze mit IP adresa na druhe a treti pozici 0 ? Ipadresa 123.0.0.1 je naprosto platna. Dokonce se na ni da pingnout. Kde udelali navrhari chybu ?
Kontrola telefonniho cisla je upne zavadejici, ze by to autor nekde opsal a moc nad tim nekoumal ? A vida, regularni vyraz pri kontrole emailu. A mam krasny email na domene .info – jaka skoda, ze neni platny …
No, jsme strasne radi za takto prinosnou tridu pro kontrolu vstupu a urcite ji pouzijeme na svem dalsim projektu…
Dobry den,
za IP adresu se omlouvam, chybka byla jenom v textu. Pokud by jste se podival do kodu, tak 0 projde bez problemu.
Ujistuji vas ze kontrolu telefonu jsem nikde neopsal 🙂
Jinak pokud jde o email, tak mate samozrejme pravdu, ale nic vam nebrani si kod upravit jak budete chtit, pro moje ucely mi to vyhoduje presne tak jak to je.