מדריך PHP

מדריך PHP: בדיקות קלט ופילטרים

‏ • Internet Israel

Preg_match

במאמר קודם השתמשנו בפונקצית preg_match על מנת לבדוק ביטוי רגולרי מול טקסט כלשהו. אם הטקסט ענה על הביטוי הרגולרי, אז קיבלנו true (שזה 1). אם הטקסט לא ענה על הביטוי הרגולרי אז קיבלנו false (שזה 0).

השאלה היא איך משתמשים בזה בעולם האמיתי. השימוש ב-preg_match מסייע לנו לבצע בדיקות של קלט. נניח ויש לנו טופס שבו יש אפשרות לשלוח את כתובת המייל:

<!DOCTYPE html>

<html lang="en">
    <head>
        <meta charset="utf-8" />
        <title>My Form</title>
    </head>
    <body>
        <form action = 'form.php' method = 'post'>
            <label for='email'>
                Your E-Mail:
            </label>
            <input type='text' id='email' name='email' />
            <input type='submit' value='Send' />
        </form>
    </body>
</html>

הטופס הוא טופס סטנדרטי למדי – מה שיש בו זה שדה אי מייל (שהשם שלו הוא email) והוא שולח את הפרטים ל-form.php.

ב-form.php אנו נבדוק באמצעות ביטוי רגולרי אם כתובת המייל הזו תקינה. במידה וכן, נדפיס אותה. במידה ולא, נחזיר את המשתמש לדף הקודם.

איך אני עושה את זה? אני אריץ בדיקת preg_match עם ביטוי רגולרי של מייל, במידה ואני מקבל true, אני אדפיס את המייל. במידה ולא, אני אגרש את המשתמש באמצעות שימוש בפונקצית header:

<?php
if(preg_match('/^[a-z0-9]+@[a-z0-9-]+.[a-z]+(.[a-z]+)?$/i', $_REQUEST['email'])) {
    print 'Your mail is '.$_REQUEST['email'];
}
else {
    header('Location: '.$_SERVER['HTTP_REFERER']);
    exit;
}

אז מה קורה לנו פה? Preg_match מקבלת שני ארגומנטים. הראשון הוא הביטוי הרגולרי שאמור להיות מובן אחרי המאמר הקודם (שימו לב למודיפקטור i) והשני הוא שדה ה-email שאני מקבל מהמשתמש. אני ניגש אליו באמצעות המשתנה הסופר גלובאלי REQUEST_$.

שימו לב שאני משתמש ב-exit מיד אחרי פונקצית header על מנת לוודא שהסקריפט מפסיק לעבוד. תעשו לעצמכם הרגל בריא ובכל פעם שאתם משתמשים ב-header על מנת להעביר משתמש, תשתמשו ב-exit.

preg_replace

preg_replace מאפשרת לנו לקחת ביטוי רגולרי כלשהו ולהחליף אותו בטקסט אחר. אנחנו נדגים את השימוש באמצעות text area שהמשתמש שולח והוא ממיר את כל החיוכים של המשתמש 🙂 לתמונות. כך שאם המשתמש מכניס את סימן החיוך, מה שיוצג הוא טקסט עם תמונת חיוך. משתמשים בזה בעיקר בפורומים ובמקומות אחרים.

אז קודם כל ניצור את הטופס:

<!DOCTYPE html>

<html lang="en">
    <head>
        <meta charset="utf-8" />
        <title>My Form</title>
    </head>
    <body>
        <form action='form.php' method='post'>
            <label for='mytext'>
                Your Text:
            </label>
            <textarea id='mytext' name='mytext' rows="10" cols="20"></textarea>
            <input type='submit' value='Send' />
        </form>
    </body>
</html>

מדובר פה בטופס סטנדרטי עם textarea שה-id שלו הוא mytext. ב-form.php נקבל את הפלט, ונעשה את ההחלפה עם preg_replace. נחפש את הביטוי הרגולרי של חיוך ונחליף אותו עם img. מסובך? ממש לא, שימו לב איך זה נראה:

<?php
$new_text = preg_replace('/:-)/', '<img src="smiley.png" alt="Smiley Icon" />', $_REQUEST['mytext']);

print $new_text;

ברגע שיש לנו את הביטוי הרגולרי, קל להשתמש בכל פונקציה שהיא.

פונקציה דומה ל-preg_replace היא preg_filter, היא זהה לה כמעט לחלוטין, אך אם היא לא מבצעת החלפה אחת לפחות, היא לא תתבצע. בדוגמא שלנו למשל, אם אין ולו סמיילי אחד – preg_filter לא תחזיר שום דבר והטקסט נטול הסמיילים לא יוצג.

למרות שחיפוש וחיפוש והחלפה הן השימושים העיקריים, ישנן עוד כמה פונקציות מעניינות שמטפלות בטקסט, כולן נמצאות בדוקומנטציה ואני ממליץ לכם לבדוק אותן ולהתאמן עליהן כדי לחדד את כישורי הביטויים הרגולריים שלכם.

פילטרים

דרך נוספת לבדיקת טקסט שאנו מקבלים מטופס או ממקור אחר היא באמצעות פילטרים. פילטרים הם בעצם סוג של 'ביטויים רגולריים' מוכנים מראש שאותם אפשר ליישם – אפשר לקרוא עליהם בחלק המוקדש להם בדוקומנטציה. בואו למשל נשתמש בדוגמא שלנו של טופס ששולח מייל. למדנו להשתמש בביטוי רגולרי על מנת לבדוק אם המשתמש לא חמד לנו לצון והכניס לנו משהו אחר חוץ ממייל, בואו ונראה איך עושים את זה באמצעות פונקציה שנקראת filter_input.

קודם כל, הטופס – הוא לא שונה כלל מהטופס שבו השתמשתי כדוגמא בתחילת המאמר. טופס רגיל ופשוט ששולח input:

<!DOCTYPE html>

<html lang="en">
    <head>
        <meta charset="utf-8" />
        <title>My Form</title>
    </head>
    <body>
        <form action = 'form.php' method = 'post'>
            <label for='email'>
                Your E-Mail:
            </label>
            <input type='text' id='email' name='email' />
            <input type='submit' value='Send' />
        </form>
    </body>
</html>

כפי שאנו רואים הוא שולח את ה-input ל-form.php, בואו ונשתמש ב-filter_input על מנת לוודא שמדובר במייל:

<?php

if(filter_input(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL)) {
    print 'Your mail is '.$_REQUEST['email'];
}
else {
    header('Location: '.$_SERVER['HTTP_REFERER']);
    exit;
}

אנו רואים שבמקום preg_match השתמשתי בפונקצית filter_input. לפונקציה הזו יש מספר ארגומנטים.

הארגומנט הראשון הוא סוג המשתנה, במקרה הזה INPUT_POST – השתמשתי בו כיוון שאני רוצה לבדוק קלט שנמצא ב-post. ישנם עוד סוגי משתנים כגון INPUT_GET, INPUT_COOKIE, INPUT_SESSION ו-INPUT_SERVER. הסוגים האלו אמורים להיות מאד מובנים אם טרחתם לעבור על כל המאמרים הקודמים במדריך.

הארגומנט השני הוא שם המשתנה, במקרה שלנו מדובר ב-email. בעצם, שני הארגומנטים הראשונים של filter_input הם ארגומנטים שמורכבים מה-

$_POST[’email']

שנשלח מהטופס.

הארגומנט השלישי הוא סוג הולידציה/סניטציה שאנו רוצים לעשות. יש לנו שני סוגים של פילטרים – הראשון הוא ולידציה שמקביל ל: preg_match. אם אנו משתמשים בפילטר של ולידציה, אז אם המשתנה שעובר את הבדיקה שונה ולו בתו אחד ממה שאנו מצפים לקבל, אז אנחנו מקבלים false.

כל סוגי הפילטרים של הולידציה נמצאים בחלק המוקדש לפילטרי ולידציה בדוקומנטציה.

סניטציה לעומת זאת מבצעת ניקיון של המשתנה מדברים שאנו לא מצפים לקבל בסוג של המשתנה. כך למשל, אם אני אכניס תו מסוים שלא אמור להיות בכתובת מייל (כמו רווח, או (; אז הוא יעיף אותו. הוא לא בודק אם מבנה המייל תקין. כתובת מייל כמו moshe@moshe@moshe תתקבל מבחינתו למרות שזו לא כתובת תקנית. פילטרים של סניטציה לא מחזירים true או false אלא את המחרוזת של הטקסט לאחר שהיא עברה סניטציה.

כל סוגי הפילטרים של הסניטציה נמצאים בחלק המוקדש לפילטרי סניטציה בדוקומנטציה.

אנחנו נמשיך לדבר על סניטציה מול ולידציה כאשר נדון על אבטחה. כרגע, במאמר זה אנו נתרכז בפילטרים של ולידציה בלבד.

אנו יכולים לבצע פילטור של ולידציה או סניטציה לכל משתנה שהוא, לא רק לקלט של המשתמש, Sessions או עוגיות, את זה אנו עושים באמצעות פונקצית filter_var, היא מאד מאד פשוטה ואני אדגים אותה כאן.

<?php

$my_var = '[email protected]';

if(filter_var($my_var, FILTER_VALIDATE_EMAIL)) {
    print 'Email is ok';
}
else {
    print 'Email is not ok';
}

היא מקבלת שני ארגומנטים – הראשון הוא המשתנה שאנו רוצים לבדוק וסוג הפילטר. במקרה הזה אפשר כבר לראות לפי השם שמדובר בפילטר ולידציה ולא בפילטר סניטציה. אם היה מדובר בפילטר סניטציה, לא הייתי מקבל חזרה true/false אלא מחרוזת שנקיה מתוים שלא צריכים להיות שם.

יכול להיות שתעלצו כל כך בעקבות לימוד הפילטרים, עד שתשמחו להזניח את הביטויים הרגולריים, אבל אני מפציר בכם ללמוד את שני הנושאים. שניהם חשובים מאד לא רק עבור פיתוח אלא גם עבור אבטחה.

תגיות: , ,

רן בר-זיק

מתכנת PHP מנוסה ובעל ידע רב בפיתוח לאינטרנט על בסיס LAMP. מומחה במערכות דרופל, ג'ומלה ו-וורדפרס. שולט היטב בכל מה שקשור לפרונט אנד: JavaScript: jQuery ו-MooTools,ActionScript 2/3 וכמובן HTML 5 + CSS 3.אינטרנט ישראל: www.internet-israel.com

תגובות בפייסבוק