输出安全的html

@param string $text
@param string $tags,不允许的html标签。
188475
public static function h($text, $tags = null)
    {
        $text = trim($text);
        $text = preg_replace('/<!--?.*-->/', '', $text); //完全过滤注释

        // 完全过滤动态代码
        $text = preg_replace('/<\?|\?' . '>/', '', $text);

        // 完全过滤js
        $text = preg_replace('/<script?.*\/script>/', '', $text);

        $text = str_replace('[', '&#091;', $text);
        $text = str_replace(']', '&#093;', $text);
        $text = str_replace('|', '&#124;', $text);

        // 过滤换行符
        $text = preg_replace('/\r?\n/', '', $text);
        //br
        $text = preg_replace('/<br(\s\/)?' . '>/i', '[br]', $text);
        $text = preg_replace('/(\[br\]\s*){10,}/i', '[br]', $text);

        // 过滤危险的属性，如：过滤on事件lang js
        while (preg_match('/(<[^><]+)( lang|on|action|background|codebase|dynsrc|lowsrc)[^><]+/i', $text, $mat)) {
            $text = str_replace($mat[0], $mat[1], $text);
        }

        while (preg_match('/(<[^><]+)(window\.|javascript:|js:|about:|file:|document\.|vbs:|cookie)([^><]*)/i', $text, $mat)) {
            $text = str_replace($mat[0], $mat[1] . $mat[3], $text);
        }

        if (empty($tags)) {
            $tags = 'table|td|th|tr|i|b|u|strong|img|p|br|div|strong|em|ul|ol|li|dl|dd|dt|a';
        }

        // 允许的HTML标签
        $text = preg_replace('/<(' . $tags . ')( [^><\[\]]*)>/i', '[\1\2]', $text);
        //过滤多余html
        $text = preg_replace('/<\/?(html|head|meta|link|base|basefont|body|bgsound|title|style|script|form|iframe|frame|frameset|applet|id|ilayer|layer|name|script|style|xml)[^><]*>/i', '', $text);

        // 过滤合法的html标签
        while (preg_match('/<([a-z]+)[^><\[\]]*>[^><]*<\/\1>/i', $text, $mat)) {
            $text = str_replace($mat[0], str_replace('>', ']', str_replace('<', '[', $mat[0])), $text);
        }

        // 转换引号
        while (preg_match('/(\[[^\[\]]*=\s*)(\"|\')([^\2=\[\]]+)\2([^\[\]]*\])/i', $text, $mat)) {
            $text = str_replace($mat[0], $mat[1] . '|' . $mat[3] . '|' . $mat[4], $text);
        }

        // 过滤错误的单个引号
        while (preg_match('/\[[^\[\]]*(\"|\')[^\[\]]*\]/i', $text, $mat)) {
            $text = str_replace($mat[0], str_replace($mat[1], '', $mat[0]), $text);
        }

        // 转换其它所有不合法的 < >
        $text = str_replace('<', '&lt;', $text);
        $text = str_replace('>', '&gt;', $text);
        $text = str_replace('"', '&quot;', $text);

        // 反转换
        $text = str_replace('[', '<', $text);
        $text = str_replace(']', '>', $text);
        $text = str_replace('|', '"', $text);

        // 过滤多余空格
        $text = str_replace('  ', ' ', $text);
        return $text;
    }
946915
public function embedTags(string $text): string
    {
        if (strpos($text, '#') !== false) {
            $text = strtr($text, $this->getTags($text));
        }

        return $text;
    }
20158
protected function _parseTags(&$text)
    {
        $replace = array();
        $matches = array();

        // <ktml:block extend|prepend|replace="[name]"></khtml:block>
        if(preg_match_all('#<ktml:block\s+(extend|prepend|replace)="([^"]+)"(.*)>(.*)</ktml:block>#siU', $text, $matches))
        {
            $count = count($matches[0]);

            for($i = 0; $i < $count; $i++)
            {
                $name = $matches[2][$i];

                //Create attributes array
                $defaults = array(
                    'title'   => '',
                    'extend'  => ''
                );

                $attributes = array_merge($defaults, $this->parseAttributes($matches[3][$i]));

                //Create block
                $block = array(
                    'content'  => $matches[4][$i],
                    'title'    => $attributes['title'],
                    'extend'   => $matches[1][$i],
                    'attribs'  => (array) array_diff_key($attributes, $defaults)
                );

                //Clear any prior added blocks
                if($block['extend'] == 'replace') {
                    $this->clearBlocks($name);
                }

                $this->addBlock($name, $block);

                //Do not continue adding blocks
                if($block['extend'] == 'replace') {
                    break;
                }
            }

            //Remove the tags
            $text = str_replace($matches[0], '', $text);
        }

        // <ktml:block name="[name]" condition="[condition]"></khtml:block>
        if(preg_match_all('#<ktml:block\s+name="([^"]+)"(.*"[^"]*")?>(.*)</ktml:block>#siU', $text, $matches))
        {
            $count = count($matches[1]);

            for($i = 0; $i < $count; $i++)
            {
                $name = $matches[1][$i];

                if($this->hasBlocks($name))
                {
                    $attribs     = $this->parseAttributes( $matches[2][$i] );
                    $replace[$i] = '';

                    if(isset($attribs['condition']))
                    {
                        if($this->_countBlocks($attribs['condition']))
                        {
                            unset($attribs['condition']);
                            $replace[$i] = $this->_renderBlocks($name, $attribs);
                        }
                    }
                    else $replace[$i] = $this->_renderBlocks($name, $attribs);

                    if(!empty($replace[$i])) {
                        $replace[$i] = str_replace('<ktml:block:content>', $replace[$i], $matches[3][$i]);
                    }
                }
            }

            $text = str_replace($matches[0], $replace, $text);
        }

        $replace = array();
        $matches = array();
        // <ktml:block name="[name]" condition="[condition]" />
        if(preg_match_all('#<ktml:block\s+name="([^"]+)"(.*"[^"]*")?\s+\/>#siU', $text, $matches))
        {
            $count = count($matches[1]);

            for($i = 0; $i < $count; $i++)
            {
                $name = $matches[1][$i];

                if($this->hasBlocks($name))
                {
                    $attribs     = $this->parseAttributes( $matches[2][$i]);
                    $replace[$i] = '';

                    if(isset($attribs['condition']))
                    {
                        if($this->_countBlocks($attribs['condition']))
                        {
                            unset($attribs['condition']);
                            $replace[$i] = $this->_renderBlocks($name, $attribs);
                        }
                    }
                    else $replace[$i] = $this->_renderBlocks($name, $attribs);

                }
            }

            $text = str_replace($matches[0], $replace, $text);
        }
    }
411097
function &_getInlineTags($text)
    {
        $return = NULL;
        $tagStrings = preg_split('/{(@.+)}/sU', $text, -1, PREG_SPLIT_DELIM_CAPTURE);
        if ($tagStrings) {
            $inlineTags = NULL;
            $phpdoctor =& $this->_root->phpdoctor();
            foreach ($tagStrings as $tag) {
                if (substr($tag, 0, 1) == '@') {
                    $pos = strpos($tag, ' ');
                    if ($pos !== FALSE) {
                        $name = trim(substr($tag, 0, $pos));
                        $text = trim(substr($tag, $pos + 1));
                    } else {
                        $name = $tag;
                        $text = NULL;
                    }
                } else {
                    $name = '@text';
                    $text = $tag;
                }
                $data = NULL;
                $inlineTag =& $phpdoctor->createTag($name, $text, $data, $this->_root);
                $inlineTag->setParent($this->_parent);
                $inlineTags[] = $inlineTag;
            }
            $return =& $inlineTags;
        }

        return $return;
    }
1055876
public static function em($text, $htmlOptions = array(), $tag = 'p')
    {
        $color = TbArray::popValue('color', $htmlOptions);
        if (TbArray::popValue('muted', $htmlOptions, false)) {
            self::addCssClass('muted', $htmlOptions);
        } else {
            if (!empty($color)) {
                self::addCssClass('text-' . $color, $htmlOptions);
            }
        }
        return self::tag($tag, $htmlOptions, $text);
    }
1146713
public function asHtml($text)
    {
        $stream = StreamFactory::string($text);
        return new Response($stream, self::OK, ['Content-Type' => 'text/html']);
    }
879110
public static function clearTextAllowedTags(string $text = null) : string
    {
        if (is_null($text)){
            return '';
        }
        return strip_tags(trim($text), '<p><a><strong><em><ul><li><ol><h1><h2><h3>');
    }
507840
public function setBody($html, $text = null)
    {
        $this->_htmlBody = $html;
        $this->_textBody = $text;

        return $this;
    }
1123782
public function drawText(Text $text) {

        if ( !$this->imgDst ) return;

        $fontColor = StringUtils::hex2rgb($text->getColor());
        $color = imagecolorallocatealpha($this->imgDst,
            $fontColor['r'],
            $fontColor['g'],
            $fontColor['b'],
            $text->getAlpha());
        if ( !file_exists($text->getFont()) ) {
            $text->setFont(dirname(__FILE__).$text->getFont());
        }
        $content = $this->distribute($this->imgDst, $text);

        $ttfBox = imagettfbbox($text->getFontsize(), $text->getAngle(), $text->getFont(), "我");
        $wordHeight = abs($ttfBox[7]); //文字高度

        foreach ($content as $num => $line) {
            if ( $text->isVertical() ) {    //绘制垂直文本
                foreach ($line as $key => $word) {
                    imagettftext(
                        $this->imgDst,
                        $text->getFontsize(),
                        $text->getAngle(),
                        $text->getStartX() + ($wordHeight+$text->getLineHeight())*$num ,
                        $text->getStartY() + $wordHeight*($key+0.5),
                        $color,
                        $text->getFont(),
                        $this->getEncodedText($word));
                }
            } else {
                $__text = implode('',$line);
                imagettftext(
                    $this->imgDst,
                    $text->getFontsize(),
                    $text->getAngle(),
                    $text->getStartX() ,
                    $text->getStartY() + $wordHeight*($num+1) + $text->getLineHeight()*$num,
                    $color,
                    $text->getFont(),
                    $this->getEncodedText($__text));
            }
        }
        return $this;
    }
106608
private function validateTag($tag, &$tags)
    {
        if (!isset($tags[$tag['name']])) {
            $tags[$tag['name']] = [];
        }

        $tags[$tag['name']][] = $tag['priority'];
    }
939866
public function writeBlockWithTags($string, array $tags = [])
    {
        if (!is_array($string)) {
            $string = explode(PHP_EOL, $string);
        }

        $strlen = 0;
        foreach ($string as $line) {
            $strlen = max($strlen, mb_strlen($line));
        }

        $tagsOpen  = '';
        $tagsClose = '';
        if (count($tags) > 0) {
            foreach ($tags as $tag) {
                $tagsOpen  .= "<{$tag}>";
                $tagsClose .= "</{$tag}>";
            }
        }

        $lines = [
            "",
            " {$tagsOpen}┌" . str_repeat("─", $strlen + 2) . "┐{$tagsClose}",
        ];

        foreach ($string as $line) {
            $padding = str_repeat(" ", $strlen - mb_strlen($line));
            $lines[] = " {$tagsOpen}│ {$line}{$padding} │{$tagsClose}";
        }

        $lines[] = " {$tagsOpen}└" . str_repeat("─", $strlen + 2) . "┘{$tagsClose}";
        $lines[] = "";

        $this->writeln($lines);
        return $this;
    }
49042
public function throwsTag($text, &$data, &$root)
    {
        $explode = preg_split('/[ \t]+/', $text);
        $this->_link = array_shift($explode);
        $data['throws'][$this->_link] = $this->_link;
        parent::tag('@throws', join(' ', $explode), $root);
    }
1223015
private function parseInlineHtml($text)
	{
		if (strpos($text, '>') !== false) {
			// convert a name markers to \labels
			if (preg_match('~^<((a|span)) (name|id)="(.*?)">.*?</\1>~i', $text, $matches)) {
				return [
					['label', 'name' => str_replace('#', '::', $this->labelPrefix . $matches[4])],
					strlen($matches[0])
				];
			}
		}
		return [['text', '<'], 1];
	}
1088193
public function tagFor($tag, $content)
    {
        //设置默认值
        $start      = 0;
        $end        = 0;
        $step       = 1;
        $comparison = 'lt';
        $name       = 'i';
        $rand       = rand(); //添加随机数，防止嵌套变量冲突

        //获取属性
        foreach ($tag as $key => $value) {
            $value = trim($value);
            $flag  = substr($value, 0, 1);
            if ('$' == $flag || ':' == $flag) {
                $value = $this->autoBuildVar($value);
            }

            switch ($key) {
                case 'start':
                    $start = $value;
                    break;
                case 'end':
                    $end = $value;
                    break;
                case 'step':
                    $step = $value;
                    break;
                case 'comparison':
                    $comparison = $value;
                    break;
                case 'name':
                    $name = $value;
                    break;
            }
        }

        $parseStr = '<?php $__FOR_START_' . $rand . '__=' . $start . ';$__FOR_END_' . $rand . '__=' . $end . ';';
        $parseStr .= 'for($' . $name . '=$__FOR_START_' . $rand . '__;' . $this->parseCondition('$' . $name . ' ' . $comparison . ' $__FOR_END_' . $rand . '__') . ';$' . $name . '+=' . $step . '){ ?>';
        $parseStr .= $content;
        $parseStr .= '<?php } ?>';

        return $parseStr;
    }
1040277
public function assertElementNonVisibility($tag, $text) {
    $element = $this->getSession()->getPage();
    /** @var \Behat\Mink\Element\NodeElement[] $nodes */
    $nodes = $element->findAll('css', $tag);
    foreach ($nodes as $node) {
      if ($node->getText() === $text) {
        $this->assertElementNotVisible($text, $node);
      }
    }
  }
1373795
public static function safeOutput($string, $clearTag = false)
    {
        if (!$clearTag) {
            $string = strip_tags($string);
        }

        return @self::htmlentitiesUTF8($string);
    }
659518
static public function toHtml($text)
    {
        // 先处理下混合的html
        $text = str_replace(['<br>', '<br/>', '<br />'], "\r\n", $text);
        $text = str_replace(['<p>', '</p>'], ["", "\r\n"], $text);
        
        /**/
        if (!static::$parse) {
            static::$parse = new Parser();
        }
        $text = static::$parse->makeHtml($text);
        
        return $text;
    }