简体   繁体   中英

php htmlentities tags exceptions leave working only certains

I have no problem to disallow all HTML tags with this code that works fine:

while($row = $result->fetch_array()){
        echo "<span class='names'>".htmlentities($row['username'])."</span>:<span class='messages'>".htmlentities($row['msg'])."</span><br>";  
}


But what if I want to allow some tags exceptions?

The result that I want is to disable any tag except <p><b><h2>



Example: (allowing <b> and disallowing <div> )

<b>sometext</b><div>sometext</div>


Expected Result:

<div>sometext</div> <div>sometext</div>

See the image: 在此处输入图片说明

HERE IS YOUR RESULT:

Please be aware at bottom to set which tags would be allowed:

function strip_html_tags( $text )
{
    $text = preg_replace(
        array(
          // Remove invisible content
            '@<b[^>]*?>.*?</b>@siu',   // HERE IS YOUR DISSALOW TAG WITH CONTENT
            '@<head[^>]*?>.*?</head>@siu',
            '@<style[^>]*?>.*?</style>@siu',
            '@<script[^>]*?.*?</script>@siu',
            '@<object[^>]*?.*?</object>@siu',
            '@<embed[^>]*?.*?</embed>@siu',
            '@<applet[^>]*?.*?</applet>@siu',
            '@<noframes[^>]*?.*?</noframes>@siu',
            '@<noscript[^>]*?.*?</noscript>@siu',
            '@<noembed[^>]*?.*?</noembed>@siu',
          // Add line breaks before and after blocks
            '@</?((address)|(blockquote)|(center)|(del))@iu',
            '@</?((h[1-9])|(ins)|(isindex)|(p)|(pre))@iu',
            '@</?((dir)|(dl)|(dt)|(dd)|(li)|(menu)|(ol)|(ul))@iu',
            '@</?((table)|(th)|(td)|(caption))@iu',
            '@</?((form)|(button)|(fieldset)|(legend)|(input))@iu',
            '@</?((label)|(select)|(optgroup)|(option)|(textarea))@iu',
            '@</?((frameset)|(frame)|(iframe))@iu',
        ),
        array(
            "\$0", // RETURNED STATEMENT
             ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
            "\$0", "\$0", "\$0", "\$0", "\$0", "\$0",
            "\$0", "\$0",
        ),
        $text );
    $to_strip =  strip_tags( $text, '<b>' );            // STRIP YOUR BOLD TAGS
    // add here to another + add content on above '@<b[^>]*?>.*?</b>@siu', and returns "\$0" on arrays
    return $to_strip;
}

      $e = '<b>from_bold_text</b><div>from_div_text</div>';

      echo strip_html_tags($e);

RESULT:

   from_bold_text<div>from_div_text</div>

 
 
 
  
  shell:~$ php ar.php <b>sometext</b>sometext shell:~$ cat ar.php <?php $t ="<b>sometext</b><div>sometext</div>"; $text = htmlentities($t, ENT_QUOTES, "UTF-8"); $text = htmlspecialchars_decode($text); $text = strip_tags($text, "<p><b><h2>"); echo $text; shell:~$ php ar.php <b>sometext</b>sometext
 
  

Note: strip_tags will NOT remove a values inside it, only tags will be removed.

$text = ' sometext'; sometext'; $text2 = strip_tags($text, ' and values. 和值。

For removing a values inside it use regex or another function with CONTENT ON MANUAL:

 
 
 
  
  <?php function strip_tags_content($text, $tags = '', $invert = FALSE) { preg_match_all('/<(.+?)[\\s]*\\/?[\\s]*>/si', trim($tags), $tags); $tags = array_unique($tags[1]); if(is_array($tags) AND count($tags) > 0) { if($invert == FALSE) { return preg_replace('@<(?!(?:'. implode('|', $tags) .')\\b)(\\w+)\\b.*?>.*?</\\1>@si', '', $text); } else { return preg_replace('@<('. implode('|', $tags) .')\\b.*?>.*?</\\1>@si', '', $text); } } elseif($invert == FALSE) { return preg_replace('@<(\\w+)\\b.*?>.*?</\\1>@si', '', $text); } return $text; } ?> Sample text: $text = '<b>sample</b> text with <div>tags</div>'; Result for strip_tags($text): sample text with tags Result for strip_tags_content($text): text with Result for strip_tags_content($text, '<b>'): <b>sample</b> text with Result for strip_tags_content($text, '<b>', TRUE); text with <div>tags</div>
 
  

Your expectation:

 
 
 
  
  $text = '<b>sometext_from_bold</b><div>sometext_from_div</div>';
 
  

// here goes function function strip_tags_content($text, $tags = '', $invert = FALSE) { .... }

// Your results

 
 
 
  
  echo strip_tags_content($text, '<b>', FALSE);
 
  

RESULT:

 
 
 
  
  <b>sometext_from_bold</b>
 
  

This code does the job, parsing the HTML code using DOMDocument . It seemed somehow more reliable than regular expressions (what happens if the user inserts an attribute in a forbidden tag? maybe containing <> ?), especially after reading this question ; it requires more work though, and is not necessarily faster.

<?

$allowed = ['strong'];  // your allowed tags
$text = "<div>\n" .
        "    <div style=\"color: #F00;\">\n" .
        "       Your <strong>User Text</strong> with DIVs.\n".
        "   </div>\n" .
        "   more <strong>text</strong>\n" .
        "</div>\n";

echo selective_escape($text, $allowed);
/* outputs:

&lt;div&gt;
    &lt;div style="color: #F00;"&gt;
       Your <strong>User Text</strong> with DIVs.
   &lt;/div&gt;
   more <strong>text</strong>
&lt;/div&gt;

*/





/** Escapes HTML entities everywhere but in the allowed tags.
 */
function selective_escape($text, $allowed_tags) {

    $doc = new DOMDocument();

    /* DOMDocument normalizes the document structure when loading,
       adding a bunch of <p> around text where needed. We don't need
       this as we're working only on small pieces of HTML.
       So we pretend this is a piece of XML code.
       */
    // $doc->loadHTML($text);
    $doc->loadXML("<?xml version=\"1.0\"?><body>" . $text . "</body>\n");

    // find the body
    $body = $doc->getElementsByTagName("body")->item(0);

    // do stuff
    $child = $body->firstChild;
    while ($child != NULL) {
        $child = selective_escape_node($child, $allowed_tags);
    }

    // output the innerHTML. need to loop again
    $retval = "";

    $child = $body->firstChild;
    while ($child != NULL) {
        $retval .= $doc->saveHTML($child);
        $child = $child->nextSibling;
    }

    return $retval;
}






/** Escapes HTML for tags that are not in $allowed_tags for a DOM tree.
 *  @returns the next sibling to process, or NULL if we reached the last child.
 *
 *  The function replaced a forbidden tag with two text nodes wrapping the
 *  children of the old node.
 */
function selective_escape_node($node, $allowed_tags) {

    // preprocess children
    if ($node->hasChildNodes()) {
        $child = $node->firstChild;
        while ($child != NULL) {

            $child = selective_escape_node($child, $allowed_tags);

        }
    }

    // check if there is anything to do on $node as well
    if ($node->nodeType == XML_ELEMENT_NODE) {
        if (!in_array($node->nodeName, $allowed_tags)) {

            // move children right before $node
            $firstChild = NULL;
            while ($node->hasChildNodes()) {
                $child = $node->firstChild;

                if ($firstChild == NULL) $firstChild = $child;
                $node->removeChild($child);

                $node->parentNode->insertBefore($child, $node);
            }

            // now $node has no children.
            $outer_html = $node->ownerDocument->saveHTML($node);

            // two cases. either ends in "/>", or in "</TAGNAME>".
            if (substr($outer_html, -2) === "/>") {

                // strip off "/>"
                $outer_html = substr($outer_html, 0, strlen($outer_html) - 2);

            } else {

                // find the closing tag
                $close_tag = strpos($outer_html, "></" . $node->nodeName . ">");

                if ($close_tag === false) {

                    // uh-oh. something wrong
                    return NULL;

                } else {

                    // strip "></TAGNAME>"
                    $outer_html = substr($outer_html, 0, $close_tag);

                }

            }

            // put a textnode before the first child
            $txt1 = $node->ownerDocument->createTextNode($outer_html . ">");
            // and another before $node
            $txt2 = $node->ownerDocument->createTextNode("</" . $node->nodeName . ">");

            // note that createTextNode automatically escapes "<>".
            $node->parentNode->insertBefore($txt1, $firstChild);
            $node->parentNode->insertBefore($txt2, $node);

            // pick the next node to process
            $next = $node->nextSibling;
            // remove node
            $node->parentNode->removeChild($node);

            return $next;
        }
    }

    // go to next sibling
    return $node->nextSibling;

}

?>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM