Как я могу избежать всего кода в тегах <code></code>, чтобы позволить людям публиковать код? - PullRequest
2 голосов
/ 01 марта 2012

Что я хочу сделать, так это разрешить пользователям публиковать код, если он в этом нуждается, чтобы его можно было просматривать и не отображать.Например:

<span>
<div id="hkhsdfhu"></div>
</span>
<h1>Hello</h1>

Должен быть преобразован в:

&lt;span&gt;
&lt;div id="hkhsdfhu"&gt;&lt;/div&gt;
&lt;/span&gt;
&lt;h1&gt;Hello&lt;/h1&gt;

Только если он заключен в теги <code>.Прямо сейчас я использую следующую функцию, чтобы разрешить только определенные теги HTML и экранировать любые другие теги:

function allowedHtml($str) {
$allowed_tags = array("b", "strong", "i", "em");
$sans_tags = str_replace(array("<", ">"), array("&lt;","&gt;"), $str);
$regex = sprintf("~&lt;(/)?(%s)&gt;~", implode("|",$allowed_tags));
$with_allowed = preg_replace($regex, "<\\1\\2>", $sans_tags);
return $with_allowed;
}

Однако, если пользователь переносит свой код в теги <code> и он содержит любойразрешенные теги в моей функции выше, эти теги будут отображаться вместо экранирования.Как сделать так, чтобы что-либо в тегах <code> было экранировано (или просто < и > превратились в &lt; и &gt;)?Я знаю о htmlentities(), но я не хочу делать это для всего поста, только внутри тегов <code>.

Заранее спасибо!

Ответы [ 4 ]

3 голосов
/ 01 марта 2012

Просто используйте одну функцию preg_replace() с модификатором e , чтобы выполнить функцию htmlenteties() для всего, что найдено в <code> тегах

EDITED

function allowedHtml($str) {
  $str = htmlentities($str, ENT_QUOTES, "UTF-8");
  $allowed_tags = array("b", "strong", "i", "em", "code");
  foreach ($allowed_tags as $tag) {
    $str = preg_replace("#&lt;" . $tag . "&gt;(.*?)&lt;/" . $tag . "&gt;#i", "<" . $tag . ">$1</" . $tag . ">", $str);
  }
  return $str;
}

$reply = allowedHtml($_POST['reply']);
$reply = preg_replace("#\<code\>(.+?)\</code\>#e", "'<code>'.htmlentities('$1', ENT_QUOTES, 'UTF-8').'</code>'", $reply);
$reply = str_replace("&amp;", "&", $reply);

Переписал вашу функцию allowedHtml() и добавил str_replace() в конце.

Он протестирован и теперь должен отлично работать:)

ОБНОВЛЕНО - НОВОЕ РЕШЕНИЕ

function convertHtml($reply, $revert = false) {
  $specials = array("**", "*", "_", "-");
  $tags = array("b", "i", "u", "s");

  foreach ($tags as $key => $tag) {
    $open = "<" . $tag . ">";
    $close = "</" . $tag . ">";

    if ($revert == true) {
      $special = $specials[$key];
      $reply = preg_replace("#" . $open . "(.+?)" . $close . "#i", $special . "$1" . $special, $reply);
    }
    else {
      $special = str_replace("*", "\*", $specials[$key]);
      $reply = preg_replace("#" . $special . "(.+?)" . $special . "#i", $open . "$1" . $close, $reply);
    }
  }

  return $reply;
}

$reply = htmlentities($reply, ENT_QUOTES, "UTF-8");
$reply = convertHtml($reply);

$reply = preg_replace("#[^\S\r\n]{4}(.+?)(?!.+)#i", "<pre><code>$1
", $ reply); $ reply = preg_replace ("# \ </ code \> \ </ pre \> (\ s *) \
 \  # i", "$ 1", $ reply);

$ reply = nl2br ($ reply);
$ reply = preg_replace ("# \  \  (. *?) \ </ code \> \ </ pre \> # se", "''.convertHtml(str_replace('<br />', '', '$1'), true).'
'", $ reply);

Обсудили другое решение, и приведенный выше код это исправит. Он работает так же, как преобразование Stack Overflow html, что означает, что ** становится жирным шрифтом, * становится курсивом, _ становится подчеркнутым и - "зачеркнутым". Кроме того, все строки, начинающиеся с 4 или более пробелов, будут выводиться как код

2 голосов
/ 01 марта 2012

Я думаю, что вам лучше работать напрямую с dom, чем использовать регулярные выражения для анализа разрешенных тегов.Например, чтобы пройти через dom и экранировать содержимое в тегах <code>, вы можете сделать что-то вроде:

$doc = new DOMDocument();
$doc->loadHTML($postHtml);
$codeNode = $doc->getElementsByTagName('code')->item(0);
$escapedCode = htmlspecialchars($codeNode->nodeValue);
1 голос
/ 01 марта 2012

Вот один.

$str = preg_replace_callback('/(?<=<code>)(.*?)(?=<\/code>)/si','escape_code',$str);

function escape_code($matches) {

    $tags = array('b','strong','i','em');
    // declare the tags in this array

    $allowed = implode('|',$tags);
    $match = htmlentities($matches[0],ENT_NOQUOTES,'UTF-8');
    return preg_replace('~&lt;(/)?('.$allowed.')(\s*/)?&gt;~i','<$1$2$3>',$match);
}
1 голос
/ 01 марта 2012

Вот способ, которым вы можете сделать это с помощью preg_replace () .Обязательно вызовите эту функцию, прежде чем вызывать функцию allowedHtml, чтобы теги уже были заменены.

<?php

$post = <<<EOD
I am a person writing a post
How can I write this code?

Example:

<code>
<span>
<div id="hkhsdfhu"></div>
</span>
<h1>Hello</h1>
</code>

Pls help me...
EOD;

$post = preg_replace('/<code>(.*?)<\/code>/ise',
                     "'<code>' . htmlspecialchars('$1') . '</code>'",
                      $post);

var_dump($post);

Результат:

string(201) "I am a person writing a post
How can I write this code?

Example:

<code>
&lt;span&gt;
&lt;div id=\&quot;hkhsdfhu\&quot;&gt;&lt;/div&gt;
&lt;/span&gt;
&lt;h1&gt;Hello&lt;/h1&gt;
</code>

Pls help me..."
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...