PDA

View Full Version : سوال در مورد n\ و تابع mysql_real_escape_string



webpower
پنج شنبه 11 خرداد 1391, 12:05 عصر
سلام دوستان خسته نباشید
من توی یک صفحه php اول چند تا ورودی میگیرم که همشون textarea هستن بعد کارکترهای مخرب اونا رو با تابع mysql_real_escape_string خنثی میکنم. بعد از اون با (str_replace("\n","<br>",$text خط فاصله ها رو قابل ذخیره و اجرا میکنم. اما یک مشکل وجود داشت که حل شد اونم این که str_replace برای کارکتر n\ بعد از تابع mysql_real_escape_string جواب نمیداد که این دو خط رو جاهاشون رو با هم عوض کردم
اگر ممکن هست راجع به نحوه کار mysql_real_escape_string و دلیل تاثیرش روی n\ کمی توضیح بدید

eshpilen
پنج شنبه 11 خرداد 1391, 13:08 عصر
خب این mysql_real_escape_string تابع پیچیده ای هم نیست و کار شاقی انجام نمیده.

mysql_real_escape_string میاد یکسری کاراکترها رو به فرم Escape شدشون تبدیل میکنه. کلا 7 کاراکتر خاص رو (\x00, \n, \r, \, ', " and \x1a). تازه از نظر امنیتی از بین این 7 تا هم دو سه تاش بیشتر نیاز نیست که Escape بشن (کاراکترهای بک اسلش و نقل قول). خودش درمورد اینکه چرا چند کاراکتر دیگر رو هم Escape میکنه میگه:


This function quotes the other characters to make them easier to read in log files


ترجمه: این تابع بقیهء کاراکترها را Escape (یا بقول خودش quote) میکند تا خواندن آنها را در فایلهای Log آسان تر کند.

منابع:
http://dev.mysql.com/doc/refman/4.1/en/mysql-real-escape-string.html
http://php.net/manual/en/function.mysql-real-escape-string.php

خب یکی از کاراکترهایی که این تابع بخاطر خوانایی بیشتر اونها رو تبدیل میکنه هم کاراکتر \n (و همچنین \r) است. اگر اشتباه نکنم کد اسکی اولی 10 و کد اسکی دومی 13 میباشد. در رشتهء ورودی شما این کاراکترها بصورت یک تک بایت با کد اسکی ذکر شده هستن که بعد این تابع میاد و اونا رو به دو بایت/کاراکتر \n یا \r تبدیل میکنه. و البته مثلا منظور از \n دقیقا یک کاراکتر بک اسلش و بعدش کاراکتر n هست، نه کد اسکی 10.

علت اینکه str_replace شما کاراکترهای \n موجود در رشته ای رو که قبلا از تابع mysql_real_escape_string عبور کرده مچ نمیکنه همینه که درواقع وقتی شما به str_replace میگید دنبال \n بگرد، درواقع این \n شما همون موقع پردازش رشته توسط PHP تبدیل میشه به کاراکتری با کد اسکی 10 و نه بک اسلش و بعدش n بعنوان دو کاراکتر مجزا.

حالا شما اگر اول str_replace کنید دیگه این مشکل پیش نمیاد چون \n ها یا کاراکترهای با کد اسکی 10 تبدیل میشن به <br> که mysql_real_escape_string هم به <br> کاری نداره چون هیچکدام از کاراکترهایی که mysql_real_escape_string تبدیل میکنه در اون وجود ندارن.

eshpilen
پنج شنبه 11 خرداد 1391, 13:18 عصر
اینم یک مثال برای روشن شدن بیشتر:


<?php

header('Content-type: text/plain');

echo "This is the New Line char: >\n<";

echo "\n............................\n\n";

echo "This is backslash+n: >\\n<";

?>

اولی \n ای هست که تبدیل به یک کاراکتر New Line میشه. یعنی یک بایت با مقدار 10.
دومی دو کاراکتر مجزاست. یک بک اسلش و یک حرف n.
اون \n که شما در کد خودتون میزنید از نوع اوله که توسط مفسر PHP به کاراکتر New Line تبدیل میشه.
اونی که mysql_real_escape_string بیرون میده از نوع دومه که دو کاراکتر مجزاست و تنها موقع اجرای رشتهء کوئری توسط MySQL هست که این دو کاراکتر مجددا به یک کاراکتر New Line تبدیل میشن.

MMSHFE
پنج شنبه 11 خرداد 1391, 13:18 عصر
ضمن تشکر از دوستمون، دیدم بد نیست این نکته رو هم بگم که بهتره بجای str_replace که گذاشتین، از nl2br استفاده کنید:

$str = mysql_real_escape_string(nl2br($str));
موفق باشید.

eshpilen
پنج شنبه 11 خرداد 1391, 13:21 عصر
آره منم میخواستم این موردی که آقای MMSHFE (http://barnamenevis.org/member.php?55504-MMSHFE) گفتن بگم که یادم رفت.
از تابع nl2br استفاده کنید. روش شما ناقصه و منجر به باگ میشه، چون خیلی وقتا بجای یک کاراکتر \n دو کاراکتر \r\n در ورودی وجود دارن.
البته الان یه نکته ای رو درمورد این تابع در فرنسش دیدم. نکته اینه که این تابع درواقع کاراکترها رو تبدیل نمیکنه. بلکه یک <br> قبلشون اضافه میکنه. مثلا \n ها حذف نمیشن، بلکه قبل از هرکدام یک تگ br درج میشه.

مثال:


<?php

header('Content-type: text/plain');

echo nl2br(">\n<");

?>

اگر خروجی این کد رو ملاحظه کنید میبینید که بعد از تگ br یک خط جدید ایجاد شده، و این بخاطر وجود کاراکتر New Line بعد از تگ br است.