استفاده از عبارتهای منظم در php با کمک دو کتابخانهی درونی امکانپذیر است. کتابخانهی اول که از مدل POSIX پیروی میکند و شامل تابعهای ereg، ereg_replace، split و … است و کتابخانهی دوم که از مدل PERL پیروی میکند و شامل تابعهای preg_match، preg_replace، preg_split و … میشود.
استفاده از سری توابع POSIX در نسخههای جدید php منسوخ شده است و توصیه شده تا برنامهنویسان از کتابخانهی PERL استفاده کنند.
تلاش میکنیم با چند مثال ساده، شیوهی استفاده از عبارتهای منظم در php با استفاده از کتابخانهی PCRE یا سازگار با PERL را مرور کنیم.
سادهترین شکل استفاده از عبارتهای منظم، عمل جستجو است که این تابع انجام آن را بر عهده دارد.
دو پارامتر ابتدایی این تابع اجباری هستند که به ترتیب «عبارت منظم» و «رشتهی هدف» را مشخص میکنند. برای مثال به نمونه کد زیر توجه کنید:
<?php $found = preg_match( '/amib/', 'http://amib.ir/weblog' ); echo $found; // عدد ۱ را در خروجی نشان میدهد ?>
مقدار خروجی این تابع عدد «۰» یا «۱» به معنی پیدا نشدن یا پیدا شدن عبارت مورد جستجو است. استفاده از علامت ممیز«/» قبل و بعد از عبارت منظم اجباری است.
به مثال بعدی دقت کنید:
<?php $found = preg_match( '/https?:\/\//', 'http://amib.ir/weblog' ); echo $found; // عدد ۱ را در خروجی نشان میدهد ?>
عبارت منظم به کار رفته در مثال بالا برای یافتن «https://» یا «http://» استفاده میشود. برای به کارگیری علامت ممیز «/» داخل عبارت منظم، لازم است تا آن را با ممیزوارو «\» پیشوند کنید. علامت سوال «?» پس از حرف «s» به معنی اختیاری بودن آن است.
در مثال بعدی از علامت Caret «^» و نشان دلار «$» به معنی ابتدا و انتهای خط استفاده میکنیم:
<?php $found = preg_match( '/^09[123]\d{8}$/', '09391234567' ); echo $found; // عدد ۱ را در خروجی نشان میدهد ?>
دستور بالا رشتهی مقابل خود را برای شباهت با شمارهی موبایل بررسی میکند. استفاده از علامتهای Caret و نشان دلار سبب میشود تا فقط رشتههایی پذیرفته شوند که پیش و پس از شمارهی موبایل حرف دیگری وجود نداشته باشد.
پارامترهای دیگر تابع preg_match برای «خارج کردن بخشهایی از عبارت در قالب متغیر»، «تنظیمات پیشرفتهی عبارت منظم» و «محل شروع جستجو» میشوند که شرح آنها در این مقالهی کوتاه نمیگنجد.
تابع مفید بعدی preg_replace است که وظیفهی جستجو با کمک عبارت منظم و جایگزین کردن را بر عهده دارد. در هنگام جایگزین کردن میتوان از متغیرهای تعریف شده در عبارت منظم استفاده کرد. به مثال زیر توجه کنید:
<?php $hide_mobile = preg_replace( '/09[123]\d{8}/', '****', 'Mobile: 09391234567' ); echo $hide_mobile; // Mobile: **** ?>
کد بالا عبارت مقابل خود را برای شمارهی موبایل جستجو میکند و آن را با چهار ستاره «****» جایگزین میکند.
برای تعریف متغیر درون عبارت منظم و استفاده از آن در رشتهی جایگزین، بخش مورد نظر را داخل پرانتز قرار میدهیم و به ترتیب با «$1»، «$2» و … آنها را فراخوانی میکنیم:
<?php $add_code_to_mobile = preg_replace( '/0(9[123]\d{8})/', '+98$1', 'Mobile: 09391234567' ); echo $add_code_to_mobile; // Mobile: +989391234567 ?>
کد بالا رشتهی مقابل خود را برای یافتن شمارهی موبایل بدون کد کشور جستجو میکند، شمارههای قرار گرفته مقابل «۰» را در پرانتز قرار میدهد تا متغیری از آن بسازد و سپس شمارهی یافته شده را با عبارت «+98$1» جایگزین میکند. دقت کنید که عبارت «$1» پس از «+98» به معنی اولین متغیر تعریف شده در عبارت منظم است.
[0-9] | اعداد |
[a-z] | حروف کوچک |
[A-Z] | حروف بزرگ |
[a|b] | a b |
[abc] | a و b و c |
[a-c] | a تا c |
+ | یک یا بیشتر |
* | صفر یا بیشتر |
? | یک |
{3} | فقط ۳ کاراکتر |
{2,3} | حداقل دو حداکثر ۳ |
^ | ابتدای الگو |
$ | انتهای الگو |
[^a-z] | شامل حروف کوچک نباشد |
\d | کاراکتر عدد |
\D | کاراکتر غیر عددی |
\w | کاراکتر حروف |
\W | کاراکتر غیر حروف |
\s | یک فضای خالی |
یکی از مهمترین قسمتهای برنامه نویسی وب با PHP، اعتبار سنجی و کنترل داده های ورودی توسط کاربر است؛ فرم ها، اصلی ترین ابزار برقراری ارتباط با کاربران سایت میباشند و اطمینان از اینکه کاربر فرم را در قالب صحیح پر کرده باشد از مشکلات آتی جلوگیری میکند. علاوه بر این در مواقعی، فردی که فرم را پر میکند، لزوما کاربر اصلی سایت نیست و هدفی به غیر از هدف اصلی فرم دارد. باید توجه داشت که اگر داده های ورودی از فرم ها به خوبی بررسی و پاکسازی نشوند، میتوانند به عنوان مهمترین وسیله نفوذ به سیستم تلقی شوند. برای جلوگیری از این مسائل باید داده های ورودی از فرم ها را قبل از پردازش و ارسال به پایگاه داده، بررسی و پاکسازی کنیم. استفاده از عبارات منظم (Regular Expressions) میتواند برای این موضوع مناسب باشد، که در زیر به انواع داده های فرم و نحوه اعتبار سنجی آن توسط عبارات منظم در PHP اشاره شده است:
اعتبار سنجی فرم ایمیل:
اعتبار سنجی فرم ایمیل را میوانید به 3 روشی که در زیراشاره میشود انجام دهید. اولین روش به این صورت است:
function isValidEmail($email){ return eregi('^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0- 9-]+)*(\.[a-z]{2,3})$', $email); }
یک روش بهتر هم هست که میتوانید ازآن استفاده کنید:
function isValidEmail($email){ return preg_match('/^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0- 9-]+)*(\.[a-z]{2,3})$/i', $email); }
و اگر از PHP 5.2 به بالا استفاده میکنید میتوانید از این روش فرم ایمیل رو اعتبار سنجی کنید:
function fnValidateEmail($email) { return filter_var($email, FILTER_VALIDATE_EMAIL); }
پاکسازی ایمیل:
ما حتی میتوانیم برای اطمینان بیشتر ایمیل گرفته شده را پاکسازی کنیم:
function fnSanitizeEmaill($string) { return preg_replace( '((?:\n|\r|\t|%0A|%0D|%08|%09)+)i' , '', $string ); }
و یا در PHP 5.2 به بالا از روش زیر برای پاکسازی استفاده کنید:
function fnSanitizeEmaill($url) { return filter_var($url, FILTER_SANITIZE_EMAIL); }
بررسی وجود ایمیل با php :
این کار امکان پذیر نیست ولی میشود تا حد زیادی با بررسی دامنه ایمیل از وجود آن مطلع شد:
function check_email($email) { $email_error = false; $Email = htmlspecialchars(stripslashes(strip_tags(trim($email)))); if ($Email == '') { email_error = true; } elseif (!eregi('^([a-zA-Z0-9._-])+@([a-zA-Z0-9._-])+\.([a-zA- Z0-9._-])([a-zA-Z0-9._-])+', $Email)) { email_error = true; } else { list($Email, $domain) = split('@', $Email, 2); if (! checkdnsrr($domain, 'MX')) { email_error = true; } else { $array = array($Email, $domain); $Email = implode('@', $array); } } if (email_error) { return false; } else{return true;} }
اعتبار سنجی اعداد:
برای بررسی اعداد در یک فرم میتوانیم از توابع داخلی PHP استفاده کنیم:
function fnValidateNumber($value) { #is_ double($value); #is_ float($value); #is_ int($value); #is_ integer($value); return is_numeric($value); }
و در PHP 5.2 وبالاتر به این شکل عمل میکنیم:
function fnValidateNumber($value) { #return filter_var($value, FILTER_VALIDATE_FLOAT); // float return filter_var($value, FILTER_VALIDATE_INT); # int }
پاکسازی اعداد:
با استفاده از تابع زیر میتوانیم اعداد داخل فرم را پاکسازی کنیم:
function fnSanitizeNumber($str) { #letters and space only return preg_match('/[^0-9]/', '', $str); }
و در PHP 5.2 به بالا:
function fnSanitizeNumber($value) { #return filter_var($value, FILTER_SANITIZE_NUMBER_FLOAT); // float return filter_var($value, FILTER_SANITIZE_NUMBER_INT); # int }
اعتبار سنجی رشته ها:
بیشتر در اعتبار سنجی نام و نام خانوادگی و .. به کار میرود و فقط حروف و فاصله را قبول میکند:
function fnValidateStringr($str) { #letters and space only return preg_match('/^[A-Za-z\s ]+$/', $str); }
پاکسازی رشته ها:
برای پاک کردن فرم از کاراکترهای غیر رشته ای به کار میرود:
function fnSanitizeStringr($str) { #letters and space only return preg_replace('/[^A-Za-z\s ]/', '', $str); }
در PHP 5.2 و بالاتر میتوان از توابع قدرتمند داخلی PHP استفاده کرد:
function fnSanitizeStringr($str) { return filter_var($str, FILTER_SANITIZE_STRIPPED); # only 'String' is allowed eg. '<br>HELLO</br>' => 'HELLO' }
اعتبار سنجی اعداد و حروف:
تابع زیر فرم را بررسی میکند تا فقط حروف و اعداد به کار رفته باشد:
function fnValidateAlphanumeric($string) { return ctype_alnum ($string); }
پاکسازی حروف و اعداد:
با تابع زیر میتوان داده گرفته شده از فرم را پاکسازی کرد به طوری که فقط حروف و اعداد باقی بمانند، به این صورت که کارکترهایی مانند (! و @ و ؟ و…) حذف میشوند:
function fnSanitizeAlphanumeric($string) { return preg_replace('/[^a-zA-Z0-9]/', '', $string); }
اعتبار سنجی URL:
تابع زیر از صحیح بودن فرمت آدرس URL اطمینان حاصل میکند:
function fnValidateUrl($url){ return preg_match('/^(http(s?):\/\/|ftp:\/\/{1})((\w+\.){1,})\w{2,}$/i', $url); }
و در PHP 5.2 به بالا به صورت:
function fnValidateUrl($url) { return filter_var($url, FILTER_VALIDATE_URL); }
پاکسازی URL:
در PHP 5.2 به بالا به صورت زیر است:
function fnSanitizeUrl($url) { return filter_var($url, FILTER_SANITIZE_URL); }
بررسی وجود URL:
با تابع زیر میتوانید از وجود یک url اطمینان حاصل کنید:
function url_exist($url) { $url = @parse_url($url); if (!$url) { return false; } $url = array_map('trim', $url); $url['port'] = (!isset($url['port'])) ? 80 : (int)$url['port']; $path = (isset($url['path'])) ? $url['path'] : ''; if ($path == '') { $path = '/'; } $path .= (isset($url['query'])) ? '?$url[query]' : ''; if (isset($url['host']) AND $url['host'] != @gethostbyname($url['host'])) { if (PHP_VERSION >= 5) { $headers = @get_headers('$url[scheme]://$url[host]:$url[port]$path'); } else { $fp = fsockopen($url['host'], $url['port'], $errno, $errstr, 30); if (!$fp) { return false; } fputs($fp, 'HEAD $path HTTP/1.1\r\nHost: $url[host]\r\n\r\n'); $headers = fread($fp, 4096); fclose($fp); } $headers = (is_array($headers)) ? implode('\n', $headers) : $headers; return (bool)preg_match('#^HTTP/.*\s+[(200|301|302)]+\s#i', $headers); } return false; }
بررسی وجود عکس در URL:
با تابع زیر میتونید متوجه بشوید که در Url گرفته شده عکسی وجود دارد یا خیر:
function image_exist($url) { if(@file_get_contents($url,0,NULL,0,1)){return 1;}else{ return 0;} }
تابع زیر آدرس IP خاصی را بررسی میکند:
function fnValidateIP($IP){ return preg_match('/^(([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]).) {3}([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$/',$IP) }
و در PHP 5.2 و بالاتر:
function fnValidateIP($ip) { return filter_var($ip, FILTER_VALIDATE_IP); }
قبل از مقایسه نام کاربری در پایگاه داده از این اعتبار سنجی برای کمتر کردن فشار بر روی پایگاه داده استفاده میشود:
function fnValidateUsername($username){ #alphabet, digit, @, _ and . are allow. Minimum 6 character. #Maximum 50 characters (email address may be more) return preg_match('/^[a-zA-Z\d_@.]{6,50}$/i', $username); }
برای بررسی امنیت رمزعبور داده شده توسط کاربر میتوانید از تابع زیر استفاده کنید که بررسی میکند تا رمز عبور حداقل 8 کاراکتر تشکیل شود واز حروف بزرگ و کوچک و اعداد نیز استفاده کند.
function fnValidatePassword($password){ #must contain 8 char, 1 uppercase, 1 lowercase and 1 number return preg_match('/^(?=^.{8,}$)((?=.*[A-Za-z0-9])(?=.*[A-Z])(?=.*[a-z]))^.*$/', $password); }
اعتبار سنجی تاریخ با فرمت “MM-DD-YYYY” یا “MM-DD-YY” از 0000 تا 9999 :
function fnValidateDate($date){ #05/12/2109 #05-12-0009 #05.12.9909 #05.12.99 return preg_match('/^((0?[1-9]|1[012])[- /.](0?[1-9]|[12][0- 9]|3[01])[- /.][0-9]?[0-9]?[0-9]{2})*$/', $date); }
اعتبار سنجی تاریخ با فرمت “YYYY-DD-MM” یا “YY-MM-DD” از 0000 تا 9999 :
function fnValidateDate($date){ #2009/12/11 #2009-12-11 #2009.12.11 #09.12.11 return preg_match('#^([0-9]?[0-9]?[0-9]{2}[- /.](0?[1- 9]|1[012])[- /.](0?[1-9]|[12][0-9]|3[01]))*$#'', $date); }
با تابع زیر میتوانید از صحیح بودن قالب بندی کد پستی اطمینان حاصل کنید:
function fnValidateIRPostal($postalcode){ #eg. 56789-01234 return preg_match('/^([0-9]{5})(-[0-9]{5})?$/i',$postalcode); }
تابع زیر داده های ما را برای جلوگیری از Sql Injection پاکسازی میکند:
function _clean($str){ return is_array($str) ? array_map('_clean', $str) : str_replace('\\', '\\\\', htmlspecialchars((get_magic_quotes_gpc() ? stripslashes($str) : $str), ENT_QUOTES)); } //usage call it somewhere in beginning of your script _clean($_POST); _clean($_GET); _clean($_REQUEST);// and so on..
و این تابع از حملات XSS و JS و Sql Injection با پاک کردن تگها جلوگیری میکند:
function _clean($str){ return is_array($str) ? array_map('_clean', $str) : str_replace('\\', '\\\\', strip_tags(trim(htmlspecialchars((get_magic_quotes_gpc() ? stripslashes($str) : $str), ENT_QUOTES)))); } //usage call it somewhere in beginning of your script _clean($_POST); _clean($_GET); _clean($_REQUEST);// and so on..