مشكلة مع تعبير منتظم للحصول على رمز التعليقات
سؤال
أقوم حاليًا بتصنيع صفحة منزلية حيث يمكن للمستخدمين كتابة التعليقات. يتم تشغيل سلسلة التعليقات أولاً من خلال وظيفة str_replaces المشاعر. بعد ذلك أريد أن تبادل
[url=www.whatever.com]linktext[/url]
مع:
<a href='www.whatever.com'>linktext</a>
والسبب في ذلك هو أنني أريد تجريد النص لجميع كود HTML الذي لا يتم التحكم فيه بواسطة رمز التعليق الخاص بي ، في حالة قرار بعض المستخدمين الحصول على إبداع-
واعتقد أنه سيكون من الأفضل استخدام استبدال Preg ، لكن الكود الذي انتهى به الأمر (جزئيًا من القراءة حول Reg Exp من خلال كتاب "O Reilly SQL و PHP"-جزئيًا من الويب) هو Bonkers ، والأهم من ذلك ، الأهم من ذلك ، لا يعمل.
أي مساعدة سيكون موضع تقدير ، شكرا.
ربما من الممكن تبادل الكود بأكمله ، وليس في قطاعين كما فعلت. قررت للتو أن الحصول على جزأين أصغر للعمل أولاً سيكون أسهل ، ثم دمجهما بعد ذلك.
الشفرة:
function text_format($string)
{
$pattern="/([url=)+[a-zA-Z0-9]+(])+/";
$string=preg_replace($pattern, "/(<a href=\')+[a-zA-Z0-9]+(\'>)+/", $string);
$pattern="/([\/url])+/";
$string=preg_replace($pattern, "/(<\/a>)+/", $string);
return $string;
}
المحلول
جربت قليلا مع ما يلي:
function text_format($string)
{
return preg_replace('#\[url=([^\]]+)\]([^\[]*)\[/url\]#', '<a href="$1">$2</a>', $string);
}
ومع ذلك ، فإن خطأ فوري مع هذا هو إذا linktext
فارغ ، لن يكون هناك شيء بين <a>
و </a>
. طريقة واحدة من حولها هي إجراء تمريرة أخرى مع شيء مثل هذا:
preg_replace('#<a href="([^"]+)"></a>#', '<a href="$1">$1</a>', $string);
خيار آخر هو الاستخدام preg_replace_callback ووضع هذا المنطق داخل وظيفة رد الاتصال.
أخيرًا ، من الواضح أن هذه "مشكلة" شائعة وقد تم حلها عدة مرات من قبل الآخرين ، وإذا كان استخدام حل مفتوح أكثر نضجًا هو خيار ، أوصي بالبحث عن واحد.
نصائح أخرى
يبدو أنك تستخدم شيئًا مشابهًا لـ BBCode. لماذا لا تستخدم محلل BBCode ، مثل هذا؟
كما أنه يتعامل مع Smilies ، ويحل محلها بالصور. إذا كنت تستخدم صفحة الاختبار الخاصة بهم ، فستظل ترى النص على الرغم من أنها لا تستضيف الصور وتعيين النص ALT على Smily.
إجابة Lauri Lehtinen جيدة لتعلم الفكرة وراء هذه التقنية ، ولكن يجب ألا تستخدمها في الممارسة العملية لأنها ستجعل موقعك الى ابعد حد عرضة لهجمات XSS. أيضا ، يقدّر رابط العرس العشوائي عدم وجود rel="nofollow"
على الروابط التي تم إنشاؤها.
بدلاً من ذلك ، استخدم شيئًا مثل:
<?php
// \author Daniel Trebbien
// \date 2010-06-22
// \par License
// Public Domain
$allowed_uri_schemes = array('http', 'https', 'ftp', 'ftps', 'irc', 'mailto');
/**
* Encodes a string in RFC 3986
*
* \see http://tools.ietf.org/html/rfc3986
*/
function encode_uri($str)
{
$str = urlencode('' . $str);
$search = array('%3A', '%2F', '%3F', '%23', '%5B', '%5D', '%40', '%21', '%24', '%26', '%27', '%28', '%29', '%2A', '%2B', '%2C', '%3B', '%3D', '%2E', '%7E');
$replace = array(':', '/', '?', '#', '[', ']', '@', '!', '$', '&', '\'', '(', ')', '*', '+', ',', ';', '=', '.', '~'); // gen-delims / sub-delims / unreserved
return str_ireplace($search, $replace, $str);
}
function url_preg_replace_callback($matches)
{
global $allowed_uri_schemes;
if (empty($matches[1]))
return $matches[0];
$href = trim($matches[1]);
if (($i = strpos($href, ':')) !== FALSE) {
if (strrpos($href, '/', $i) === FALSE) {
if (!in_array(strtolower(substr($href, 0, $i)), $allowed_uri_schemes))
return $matches[0];
}
}
// unescape `\]`, `\\\]`, `\\\\\]`, etc.
for ($j = strpos($href, '\\]'); $j !== FALSE; $j = strpos($href, '\\]', $j)) {
for ($i = $j - 2; $i >= 0 && $href[$i] == '\\' && $href[$i + 1] == '\\'; $i -= 2)
/* empty */;
$i += 2;
$h = '';
if ($i > 0)
$h = substr($href, 0, $i);
for ($numBackslashes = floor(($j - $i)/2); $numBackslashes > 0; --$numBackslashes)
$h .= '\\';
$h .= ']';
if (($j + 2) < strlen($href))
$h .= substr($href, $j + 2);
$href = $h;
$j = $i + floor(($j - $i)/2) + 1;
}
if (!empty($matches[2]))
$href .= str_replace('\\\\', '\\', $matches[2]);
if (empty($matches[3]))
$linkText = $href;
else {
$linkText = trim($matches[3]);
if (empty($linkText))
$linkText = $href;
}
$href = htmlspecialchars(encode_uri(htmlspecialchars_decode($href)));
return "<a href=\"$href\" rel=\"nofollow\">$linkText</a>";
}
function render($input)
{
$input = htmlspecialchars(strip_tags('' . $input));
$input = preg_replace_callback('~\[url=((?:[^\]]|(?<!\\\\)(?:\\\\\\\\)*\\\\\])*)((?<!\\\\)(?:\\\\\\\\)*)\]' . '((?:[^[]|\[(?!/)|\[/(?!u)|\[/u(?!r)|\[/ur(?!l)|\[/url(?!\]))*)' . '\[/url\]~i', 'url_preg_replace_callback', $input);
return $input;
}
الذي أعتقد أنه آمن ضد XSS. يحتوي هذا الإصدار على فائدة إضافية تفيد أنه من الممكن كتابة روابط إلى عناوين URL التي تحتوي على ']'
.
تقييم هذا الرمز مع "جناح الاختبار" التالي:
echo render('[url=http://www.bing.com/][[/[/u[/ur[/urlBing[/url]') . "\n";
echo render('[url=][/url]') . "\n";
echo render('[url=http://www.bing.com/][[/url]') . "\n";
echo render('[url=http://www.bing.com/][/[/url]') . "\n";
echo render('[url=http://www.bing.com/][/u[/url]') . "\n";
echo render('[url=http://www.bing.com/][/ur[/url]') . "\n";
echo render('[url=http://www.bing.com/][/url[/url]') . "\n";
echo render('[url=http://www.bing.com/][/url][/url]') . "\n";
echo render('[url= javascript: window.alert("hi")]click me[/url]') . "\n";
echo render('[url=#" onclick="window.alert(\'hi\')"]click me[/url]') . "\n";
echo render('[url=http://www.bing.com/] [/url]') . "\n";
echo render('[url=/?#[\\]@!$&\'()*+,;=.~] [/url]') . "\n"; // link text should be `/?#[]@!$&'()*+,;=.~`
echo render('[url=http://localhost/\\\\]d]abc[/url]') . "\n"; // href should be `http://localhost/%5C`, link text should be `d]abc`
echo render('[url=\\]][/url]') . "\n"; // link text should be `]`
echo render('[url=\\\\\\]][/url]') . "\n"; // link text should be `\]`
echo render('[url=\\\\\\\\\\]][/url]') . "\n"; // link text should be `\\]`
echo render('[url=a\\\\\\\\\\]bcde\\]fgh\\\\\\]ijklm][/url]') . "\n"; // link text should be `a\\]bcde]fgh\]ijklm`
أو فقط انظر إلى نتائج CODEPAD.
كما ترون ، فهو يعمل.