htmlentities

(PHP 4, PHP 5, PHP 7)

htmlentities将字符转换为 HTML 转义字符

说明

htmlentities ( string $string [, int $flags = ENT_COMPAT | ENT_HTML401 [, string $encoding = ini_get("default_charset") [, bool $double_encode = true ]]] ) : string

本函数各方面都和 htmlspecialchars() 一样, 除了 htmlentities() 会转换所有具有 HTML 实体的字符。

如果要解码(反向操作),可以使用 html_entity_decode()

参数

string

输入字符。

flags

以下一组位掩码标记,用于设置如何处理引号、无效代码序列、使用文档的类型。 默认是 ENT_COMPAT | ENT_HTML401

有效 flags 标记常量
常量名 描述
ENT_COMPAT 会转换双引号,不转换单引号。
ENT_QUOTES 既转换双引号也转换单引号。
ENT_NOQUOTES 单/双引号都不转换
ENT_IGNORE 静默丢弃无效的代码单元序列,而不是返回空字符串。 不建议使用此标记, 因为它» 可能有安全影响
ENT_SUBSTITUTE 替换无效的代码单元序列为 Unicode 代替符(Replacement Character), U+FFFD (UTF-8) 或者 � (其他),而不是返回空字符串。
ENT_DISALLOWED 为文档的无效代码点替换为 Unicode 代替符(Replacement Character): U+FFFD (UTF-8),或 �(其他),而不是把它们留在原处。 比如以下情况下就很有用:要保证 XML 文档嵌入额外内容时格式合法。
ENT_HTML401 以 HTML 4.01 处理代码。
ENT_XML1 以 XML 1 处理代码。
ENT_XHTML 以 XHTML 处理代码。
ENT_HTML5 以 HTML 5 处理代码。

encoding

An optional argument defining the encoding used when converting characters.

If omitted, the default value of the encoding varies depending on the PHP version in use. In PHP 5.6 and later, the default_charset configuration option is used as the default value. PHP 5.4 and 5.5 will use UTF-8 as the default. Earlier versions of PHP use ISO-8859-1.

Although this argument is technically optional, you are highly encouraged to specify the correct value for your code if you are using PHP 5.5 or earlier, or if your default_charset configuration option may be set incorrectly for the given input.

支持以下字符集:

支持的字符集列表
字符集 别名 描述
ISO-8859-1 ISO8859-1 西欧,Latin-1
ISO-8859-5 ISO8859-5 Little used cyrillic charset (Latin/Cyrillic).
ISO-8859-15 ISO8859-15 西欧,Latin-9。增加欧元符号,法语和芬兰语字母在 Latin-1(ISO-8859-1) 中缺失。
UTF-8   ASCII 兼容的多字节 8 位 Unicode。
cp866 ibm866, 866 DOS 特有的西里尔编码。本字符集在 4.3.2 版本中得到支持。
cp1251 Windows-1251, win-1251, 1251 Windows 特有的西里尔编码。本字符集在 4.3.2 版本中得到支持。
cp1252 Windows-1252, 1252 Windows 特有的西欧编码。
KOI8-R koi8-ru, koi8r 俄语。本字符集在 4.3.2 版本中得到支持。
BIG5 950 繁体中文,主要用于中国台湾省。
GB2312 936 简体中文,中国国家标准字符集。
BIG5-HKSCS   繁体中文,附带香港扩展的 Big5 字符集。
Shift_JIS SJIS, 932 日语
EUC-JP EUCJP 日语
MacRoman   Mac OS 使用的字符串。
''   An empty string activates detection from script encoding (Zend multibyte), default_charset and current locale (see nl_langinfo() and setlocale()), in this order. Not recommended.

Note: 其他字符集没有认可。将会使用默认编码并抛出异常。

double_encode

关闭 double_encode 时,PHP 不会转换现有的 HTML 实体, 默认是全部转换。

返回值

返回编码后的字符。

如果指定的编码 encoding 里, string 包含了无效的代码单元序列, 没有设置 ENT_IGNORE 或者 ENT_SUBSTITUTE 标记的情况下,会返回空字符串。

更新日志

版本 说明
5.6.0 The default value for the encoding parameter was changed to be the value of the default_charset configuration option.
5.4.0 encoding 参数的默认值改成 UTF-8。
5.4.0 增加常量 ENT_SUBSTITUTEENT_DISALLOWEDENT_HTML401ENT_XML1ENT_XHTMLENT_HTML5
5.3.0 增加常量 ENT_IGNORE
5.2.3 增加参数 double_encode

范例

Example #1 htmlentities() 例子

<?php
$str 
"A 'quote' is <b>bold</b>";

// 输出: A 'quote' is &lt;b&gt;bold&lt;/b&gt;
echo htmlentities($str);

// 输出: A &#039;quote&#039; is &lt;b&gt;bold&lt;/b&gt;
echo htmlentities($strENT_QUOTES);
?>

Example #2 ENT_IGNORE 用法示例

<?php
$str 
"\x8F!!!";

// 输出空 string
echo htmlentities($strENT_QUOTES"UTF-8");

// 输出 "!!!"
echo htmlentities($strENT_QUOTES ENT_IGNORE"UTF-8");
?>

参见

User Contributed Notes

2962051004 at qq dot com 03-Oct-2018 04:09
<?php

/**
 * 将中文转为Html实体
 * Convert Chinese in HTML to entity
 * Author QiangGe
 * Mail 2962051004@qq.com
 *
*/

$str = <<<EOT
你好 world
EOT;

function
ChineseToEntity($str) {
 return
preg_replace_callback(
       
'/[\x{4e00}-\x{9fa5}]/u', // utf-8
        // '/[\x7f-\xff]+/', // if gb2312
       
function ($matches) {
           
$json = json_encode(array($matches[0]));
           
preg_match('/\[\"(.*)\"\]/', $json, $arr);
           
/*
             * 通过json_encode函数将中文转为unicode
             * 然后用正则取出unicode
             * Turn the Chinese into Unicode through the json_encode function, then extract Unicode from regular.
             * I think this idea is seamless.
            */
           
return '&#x'. str_replace('\\u', '', $arr[1]). ';';
        },
$str
  
);
}

echo
ChineseToEntity($str);
// &#x4f60;&#x597d; world
Jeff 01-Jun-2018 01:25
There is a feature when writing to XML using an AJAX call to PHP that rarely is mentioned. I struggled for many hours using htmlentities() because what was getting written to my XML document was not as expected. I naturally assumed that I should be converting my strings before writing them to XML to adhere to XML rules on illegal characters. To my surprise, when converting with htmlentities() or htmlspecialchars() and then writing to an XML file, the resulting ampersands get converted afterwards! Consider the following example:

<?php
$str
= "<b>I am cool</b>" ;
$str = htmlentities($str) ;
?>

When you append $str to an XML element and save() the document, you would expect the XML document's source code to look something like this:

<ele>&lt;b&gt;I am cool&lt;/b&gt;</ele>

But that is not what happens. The resulting ampersands get converted by PHP automatically to &amp; and your source code ends up looking like this:

<ele>&amp;lt;b&amp;gt;I am cool&amp;lt;/b&amp;gt;</ele>

As you can see, this creates problems when trying to output the XML data back to HTML. It is important to remember that when writing to XML this way, special characters like ">" and "<"; PHP converts them automatically and there becomes no need to use htmlentities() in certain cases. I assume this feature is in place to aid with passing data through header queries, to avoid reserved characters conflicting with others in a header query (e.g. & or =). Now I understand this may not be the case with older versions of PHP and that this might be a feature of my version (PHP version 5.6.32). With older versions, I assume using htmlentities() or htmlspecialchars() is a must, as stated with previous notes here. Also I use the charset UTF-8 in my HTML and XML and am not sure if this also effects the results I get.

Anyway, I struggled for many hours with using htmlentities() to convert strings for XML writing and saving, when all I had to do was simply not use the function and let PHP convert my strings for me. I hope this helps because I would think I am not the only one who has struggled with this situation.
sanjayaggarwal1562 at gmail dot com 06-Oct-2017 07:07
Your take good points, every person should think about it and they have to choose their leader after known about them I am Waiting for your new article keep posting. <a href="https://yahoocustomerservice.co/faqs/"> https://yahoocustomerservice.co/faqs/</a>
chris at ocproducts dot com 10-Apr-2017 01:10
This function throws a warning on bad input even if ENT_SUBSTITUTE is set, so be prepared for this.
hajo-p 05-Jan-2014 05:18
The flag ENT_HTML5 also strips newline chars like \n with htmlentities while htmlspecialchars is not affected by that.

If you want to use nl2br on that string afterwards you might end up searching the problem like i did. This does not apply to other flags like e.g. ENT_XHTML which confused me.

Tested this with PHP 5.4 / 5.5 / 5.6-dev with same results, so it seems that this is an intended "feature".
rq 19-Sep-2013 01:37
For use of html  tags, ampersands, etc. in xml document

(f.e.

<xml>

<xmltag1><span class="data1"> data 1</span> & data2</xmltag1>

</xml>

)

one can use the CDATA brackets:

<xmltag1><![CDATA[<span class="data1"> data 1</span> & data2]]></xmltag1>

-rq
ustimenko dot alexander at gmail dot com 09-Apr-2012 02:15
For those Spanish (and not only) folks, that want their national letters back after htmlentities :)

<?php
protected function _decodeAccented($encodedValue, $options = array()) {
   
$options += array(
       
'quote'     => ENT_NOQUOTES,
       
'encoding'  => 'UTF-8',
    );
    return
preg_replace_callback(
       
'/&\w(acute|uml|tilde);/',
       
create_function(
           
'$m',
           
'return html_entity_decode($m[0], ' . $options['quote'] . ', "' .
           
$options['encoding'] . '");'
       
),
       
$encodedValue
   
);
}
?>
n at erui dot eu 20-Mar-2012 12:46
html entities does not encode all unicode characters. It encodes what it can [all of latin1], and the others slip through. &#1033; is the nasty I use. I have searched for a function which encodes everything, but in the end I wrote this. This is as simple as I can get it. Consult an ansii table to custom include/omit chars you want/don't. I'm sure it's not that fast.

// Unicode-proof htmlentities.
// Returns 'normal' chars as chars and weirdos as numeric html entites.
function superentities( $str ){
    // get rid of existing entities else double-escape
    $str = html_entity_decode(stripslashes($str),ENT_QUOTES,'UTF-8');
    $ar = preg_split('/(?<!^)(?!$)/u', $str );  // return array of every multi-byte character
    foreach ($ar as $c){
        $o = ord($c);
        if ( (strlen($c) > 1) || /* multi-byte [unicode] */
            ($o <32 || $o > 126) || /* <- control / latin weirdos -> */
            ($o >33 && $o < 40) ||/* quotes + ambersand */
            ($o >59 && $o < 63) /* html */
        ) {
            // convert to numeric entity
            $c = mb_encode_numericentity($c,array (0x0, 0xffff, 0, 0xffff), 'UTF-8');
        }
        $str2 .= $c;
    }
    return $str2;
}
wd at NOSPAMwd dot it 19-Dec-2011 02:20
Hi there,

after several and several tests, I figured out that dot:

- htmlentities() function remove characters like "à","è",etc when you specify a flag and a charset

- htmlentities() function DOES NOT remove characters like those above when you DO NOT specify anything

So, let's assume that..

<?php

$str
= "Hèèèllooo";

$res_1 = htmlentities($str, ENT_QUOTES, "UTF-8");
$res_2 = htmlentities($str);

echo
var_dump($res_1); // Result: string '' (length=0)
echo var_dump($res_2); // string 'H&egrave;&egrave;&egrave;llooo' (length=30)

?>

I used this for a textarea content for comments. Anyway, note that using the "$res_2" form the function will leave unconverted single/double quotes. At this point you should use str_replace() function to perform the characters but be careful because..

<?php

$str
= "'Hèèèllooo'";

$res_2 = str_replace("'","&#039;",$str);
$res_2 = htmlentities($str);
echo
var_dump($res_2); // string '&amp;#039;H&egrave;&egrave;&egrave;llooo&amp;#039;'

$res_3 = htmlentities($str);
$res_3 = str_replace("'","&#039;",$res_3);
echo
var_dump($res_3); // string '&#039;H&egrave;&egrave;&egrave;llooo&#039;' --> Nice
?>

Hope it will helps you.

Regards,
W.D.
steve at mcdragonsoftware dot com 16-Nov-2011 08:59
I'm glad 5.4 has xml support, but many of us are working with older installations, some of us still have to use PHP4. If you're like me you've been frustrated with trying to use htmlentites/htmlspecial chars with xml output. I was hoping to find an option to force numeric encoding, lacking that, I have written my own xmlencode function, which I now offer:

usage:

$string xmlencode( $string )

it will use htmlspecialchars for the valid xml entities amp, quote, lt, gt, (apos) and return the numeric entity for all other non alpha-numeric characters.

-------------------------------------------

<?php
if( !function_exists( 'xmlentities' ) ) {
    function
xmlentities( $string ) {
       
$not_in_list = "A-Z0-9a-z\s_-";
        return
preg_replace_callback( "/[^{$not_in_list}]/" , 'get_xml_entity_at_index_0' , $string );
    }
    function
get_xml_entity_at_index_0( $CHAR ) {
        if( !
is_string( $CHAR[0] ) || ( strlen( $CHAR[0] ) > 1 ) ) {
            die(
"function: 'get_xml_entity_at_index_0' requires data type: 'char' (single character). '{$CHAR[0]}' does not match this type." );
        }
        switch(
$CHAR[0] ) {
            case
"'":    case '"':    case '&':    case '<':    case '>':
                return
htmlspecialchars( $CHAR[0], ENT_QUOTES );    break;
            default:
                return
numeric_entity_4_char($CHAR[0]);                break;
        }       
    }
    function
numeric_entity_4_char( $char ) {
        return
"&#".str_pad(ord($char), 3, '0', STR_PAD_LEFT).";";
    }   
}
?>
Waygood 06-Jun-2011 02:09
When putting values inside comment tags <!-- --> you should replace -- with &#45;&#45; too, as this would end your tag and show the rest of the comment.
robin at robinwinslow dot co dot uk 15-Apr-2011 08:14
htmlentities seems to have changed at some point between version 5.1.6 and 5.3.3, such that it now returns an empty string for anything containing a pound sign:

$ php -v
PHP 5.1.6 (cli) (built: May 22 2008 09:08:44)
$ php -r "echo htmlentities('£hello', null, 'utf-8');"
&pound;hello
$

$ php -v
PHP 5.3.3 (cli) (built: Aug 19 2010 12:07:49)
$ php -r "echo htmlentities('£hello', null, 'utf-8');"
$

(Returns an empty string the second time)

Just a heads up.
admin at wapforum dot rs 24-Feb-2011 01:11
A useful little function to convert the symbols in the different inputs.
<?php
function ConvertSimbols($var, $ConvertQuotes = 0) {
if (
$ConvertQuotes > 0) {
$var = htmlentities($var, ENT_NOQUOTES, 'UTF-8');
$var = str_replace('\"', '', $var);
$var = str_replace("\'", '', $var);
} else {
$var = htmlentities($var, ENT_QUOTES, 'UTF-8');
}
return
$var;
}
?>

Usage with quotes for example message:

$message = ConvertSimbols($message);

Usage without quotes for example link:

$link = ConvertSimbols($link, 1);
kindrosker at gmail dot com 10-Feb-2011 05:31
All Codes list

array('à'=>'&Agrave;', 'à'=>'&agrave;', 'á'=>'&Aacute;', 'á'=>'&aacute;', '?'=>'&Acirc;', 'a'=>'&acirc;', '?'=>'&Atilde;', '?'=>'&atilde;', '?'=>'&Auml;', '?'=>'&auml;', '?'=>'&Aring;', '?'=>'&aring;', '?'=>'&AElig;', '?'=>'&aelig;', '?'=>'&Ccedil;', '?'=>'&ccedil;', 'D'=>'&ETH;', 'e'=>'&eth;', 'è'=>'&Egrave;', 'è'=>'&egrave;', 'é'=>'&Eacute;', 'é'=>'&eacute;', 'ê'=>'&Ecirc;', 'ê'=>'&ecirc;', '?'=>'&Euml;', '?'=>'&euml;', 'ì'=>'&Igrave;', 'ì'=>'&igrave;', 'í'=>'&Iacute;', 'í'=>'&iacute;', '?'=>'&Icirc;', '?'=>'&icirc;', '?'=>'&Iuml;', '?'=>'&iuml;', '?'=>'&Ntilde;', '?'=>'&ntilde;', 'ò'=>'&Ograve;', 'ò'=>'&ograve;', 'ó'=>'&Oacute;', 'ó'=>'&oacute;', '?'=>'&Ocirc;', '?'=>'&ocirc;', '?'=>'&Otilde;', '?'=>'&otilde;', '?'=>'&Ouml;', '?'=>'&ouml;', '?'=>'&Oslash;', '?'=>'&oslash;', '?'=>'&OElig;', '?'=>'&oelig;', '?'=>'&szlig;', 'T'=>'&THORN;', 't'=>'&thorn;', 'ù'=>'&Ugrave;', 'ù'=>'&ugrave;', 'ú'=>'&Uacute;', 'ú'=>'&uacute;', '?'=>'&Ucirc;', '?'=>'&ucirc;', 'ü'=>'&Uuml;', 'ü'=>'&uuml;', 'Y'=>'&Yacute;', 'y'=>'&yacute;', '?'=>'&Yuml;', '?'=>'&yuml;');
galert420 at gmail dot com 05-Nov-2010 10:24
Croatian entites

<?php
$ent
= array(
   
'?'=>'&#262;',
   
'?'=>'&#263;',
   
'?'=>'&#268;',
   
'?'=>'&#269;',
   
'?'=>'&#272',
   
'?'=>'&#273',
   
'?'=>'&#352',
   
'?'=>'&#353',
   
'?'=>'&#381',
   
'?'=>'&#382'
);

echo
strtr('??????????', $ent);
?>
php dot net at softmoon-webware dot com 12-Oct-2010 02:32
<?php
$HTML_ENTS
=array("quot", "amp", "apos", "lt", "gt", "nbsp", "iexcl", "cent",
"pound","curren", "yen", "brvbar", "sect", "uml", "copy", "ordf", "laquo",
"not", "shy", "reg", "macr", "deg", "plusmn", "sup2", "sup3", "acute",
"micro", "para", "middot", "cedil", "sup1", "ordm", "raquo", "frac14",
"frac12", "frac34", "iquest", "Agrave", "Aacute", "Acirc", "Atilde", "Auml",
"Aring", "AElig", "Ccedil", "Egrave", "Eacute", "Ecirc", "Euml", "Igrave",
"Iacute", "Icirc", "Iuml", "ETH", "Ntilde", "Ograve", "Oacute", "Ocirc",
"Otilde", "Ouml", "times", "Oslash", "Ugrave", "Uacute", "Ucirc", "Uuml",
"Yacute", "THORN", "szlig", "agrave", "aacute", "acirc", "atilde", "auml",
"aring", "aelig", "ccedil", "egrave", "eacute", "ecirc", "euml", "igrave",
"iacute", "icirc", "iuml", "eth", "ntilde", "ograve", "oacute", "ocirc",
"otilde", "ouml", "divide", "oslash", "ugrave", "uacute", "ucirc", "uuml",
"yacute", "thorn", "yuml", "OElig", "oelig", "Scaron", "scaron", "Yuml",
"fnof", "circ", "tilde", "Alpha", "Beta", "Gamma", "Delta", "Epsilon",
"Zeta", "Eta", "Theta", "Iota", "Kappa", "Lambda", "Mu", "Nu", "Xi",
"Omicron", "Pi", "Rho", "Sigma", "Tau", "Upsilon", "Phi", "Chi", "Psi",
"Omega", "alpha", "beta", "gamma", "delta", "epsilon", "zeta", "eta",
"theta", "iota", "kappa", "lambda", "mu", "nu", "xi", "omicron", "pi",
"rho", "sigmaf", "sigma", "tau", "upsilon", "phi", "chi", "psi", "omega",
"thetasym", "upsih", "piv", "ensp", "emsp", "thinsp", "zwnj", "zwj", "lrm",
"rlm", "ndash", "mdash", "lsquo", "rsquo", "sbquo", "ldquo", "rdquo",
"bdquo", "dagger", "Dagger", "bull", "hellip", "permil", "prime", "Prime",
"lsaquo", "rsaquo", "oline", "frasl", "euro", "image", "weierp", "real",
"trade", "alefsym", "larr", "uarr", "rarr", "darr", "harr", "crarr", "lArr",
"uArr", "rArr", "dArr", "hArr", "forall", "part", "exist", "empty", "nabla",
"isin", "notin", "ni", "prod", "sum", "minus", "lowast", "radic", "prop",
"infin", "ang", "and", "or", "cap", "cup", "int", "there4", "sim", "cong",
"asymp", "ne", "equiv", "le", "ge", "sub", "sup", "nsub", "sube", "supe",
"oplus", "otimes", "perp", "sdot", "lceil", "rceil", "lfloor",
"rfloor", "lang", "rang", "loz", "spades", "clubs", "hearts", "diams");

// The selection of tags below is optimized for use with a webmaster's database,
// --NOT-- to process user POSTs from the World Wide Web
//  for inclusion on a public page.

//  NOT included:
//   form,  input,  select,  option,  label,  optgroup,  textarea,  area,  map,
//   html,  head,  style,  link,  meta,  base,  body,  isindex,
//   frame,  frameset,  noframes
//  (include those above at your wish,  remove those below at your wish)
$HTML_TAGS=array("a", "abbr", "acronym", "address", "applet", "b", "basefont",
"bdo", "big", "blockquote", "br", "button", "caption", "center", "cite",
"code", "col", "colgroup", "dd", "del", "dfn", "dir", "div", "dl", "dt", "em",
"embed", "fieldset", "font", "h1", "h2", "h3", "h4", "h5", "h6", "hr", "i",
"iframe", "img", "ins", "kbd", "legend", "li", "menu", "noembed", "noscript",
"object", "ol", "p", "param", "pre", "q", "s", "samp", "script", "small",
"span", "strike", "strong", "sub", "sup", "table", "tbody", "td", "tfoot",
"th", "thead", "title", "tr", "tt", "u", "ul", "var");

$Xchars = array(
 
128 => '&#8364;',
 
130 => '&#8218;',
 
131 => '&#402;',
 
132 => '&#8222;',
 
133 => '&#8230;',
 
134 => '&#8224;',
 
135 => '&#8225;',
 
136 => '&#710;',
 
137 => '&#8240;',
 
138 => '&#352;',
 
139 => '&#8249;',
 
140 => '&#338;',
 
142 => '&#381;',
 
145 => '&#8216;',
 
146 => '&#8217;',
 
147 => '&#8220;',
 
148 => '&#8221;',
 
149 => '&#8226;',
 
150 => '&#8211;',
 
151 => '&#8212;',
 
152 => '&#732;',
 
153 => '&#8482;',
 
154 => '&#353;',
 
155 => '&#8250;',
 
156 => '&#339;',
 
158 => '&#382;',
 
159 => '&#376;');
?>
h_guillaume at hotmail dot com 17-Sep-2010 01:14
I use this function to encode all the xml entities and also all the &something; that are not defined in xml like &trade;
You can also decode what you encode with my decode function.
My function works a little like the htmlentities.
You can also add other string to the array if you want to exclude them from the encoding.

<?php
function xml_entity_decode($text, $charset = 'Windows-1252'){
   
// Double decode, so if the value was &amp;trade; it will become Trademark
   
$text = html_entity_decode($text, ENT_COMPAT, $charset);
   
$text = html_entity_decode($text, ENT_COMPAT, $charset);
    return
$text;
}

function
xml_entities($text, $charset = 'Windows-1252'){
    
// Debug and Test
    // $text = "test &amp; &trade; &amp;trade; abc &reg; &amp;reg; &#45;";
   
    // First we encode html characters that are also invalid in xml
   
$text = htmlentities($text, ENT_COMPAT, $charset, false);
   
   
// XML character entity array from Wiki
    // Note: &apos; is useless in UTF-8 or in UTF-16
   
$arr_xml_special_char = array("&quot;","&amp;","&apos;","&lt;","&gt;");
   
   
// Building the regex string to exclude all strings with xml special char
   
$arr_xml_special_char_regex = "(?";
    foreach(
$arr_xml_special_char as $key => $value){
       
$arr_xml_special_char_regex .= "(?!$value)";
    }
   
$arr_xml_special_char_regex .= ")";
   
   
// Scan the array for &something_not_xml; syntax
   
$pattern = "/$arr_xml_special_char_regex&([a-zA-Z0-9]+;)/";
   
   
// Replace the &something_not_xml; with &amp;something_not_xml;
   
$replacement = '&amp;${1}';
    return
preg_replace($pattern, $replacement, $text);
}
?>
Sijmen Ruwhof 13-Sep-2010 12:18
An important note below about using this function to secure your application against Cross Site Scripting (XSS) vulnerabilities.

When printing user input in an attribute of an HTML tag, the default configuration of htmlEntities() doesn't protect you against XSS, when using single quotes to define the border of the tag's attribute-value. XSS is then possible by injecting a single quote:

<?php
$_GET
['a'] = "#000' onload='alert(document.cookie)";
?>

XSS possible (insecure):

<?php
$href
= htmlEntities($_GET['a']);
print
"<body bgcolor='$href'>"; # results in: <body bgcolor='#000' onload='alert(document.cookie)'>
?>

Use the 'ENT_QUOTES' quote style option, to ensure no XSS is possible and your application is secure:

<?php
$href
= htmlEntities($_GET['a'], ENT_QUOTES);
print
"<body bgcolor='$href'>"; # results in: <body bgcolor='#000&#039; onload=&#039;alert(document.cookie)'>
?>

The 'ENT_QUOTES' option doesn't protect you against javascript evaluation in certain tag's attributes, like the 'href' attribute of the 'a' tag. When clicked on the link below, the given JavaScript will get executed:

<?php
$_GET
['a'] = 'javascript:alert(document.cookie)';
$href = htmlEntities($_GET['a'], ENT_QUOTES);
print
"<a href='$href'>link</a>"; # results in: <a href='javascript:alert(document.cookie)'>link</a>
?>
Wired 13-May-2010 05:22
I needed a simple little function to take a string and convert extended ascii characters into html entities. I couldn't find a function for this so I whipped one up.

<?php
/* Convert Extended ASCII Characters to HTML Entities */
function ascii2entities($string){
    for(
$i=128;$i<=255;$i++){
       
$entity = htmlentities(chr($i), ENT_QUOTES, 'cp1252');
       
$temp = substr($entity, 0, 1);
       
$temp .= substr($entity, -1, 1);
        if (
$temp != '&;'){
           
$string = str_replace(chr($i), '', $string);
        }
        else{
           
$string = str_replace(chr($i), $entity, $string);
        }
    }
    return
$string;
}

echo
ascii2entities("?");
?>
phil at lavin dot me dot uk 08-Apr-2010 08:34
The following will make a string completely safe for XML:

<?php
function philsXMLClean($strin) {
       
$strout = null;

        for (
$i = 0; $i < strlen($strin); $i++) {
               
$ord = ord($strin[$i]);

                if ((
$ord > 0 && $ord < 32) || ($ord >= 127)) {
                       
$strout .= "&amp;#{$ord};";
                }
                else {
                        switch (
$strin[$i]) {
                                case
'<':
                                       
$strout .= '&lt;';
                                        break;
                                case
'>':
                                       
$strout .= '&gt;';
                                        break;
                                case
'&':
                                       
$strout .= '&amp;';
                                        break;
                                case
'"':
                                       
$strout .= '&quot;';
                                        break;
                                default:
                                       
$strout .= $strin[$i];
                        }
                }
        }

        return
$strout;
}
?>
sirarthur at sirarthur dot info 05-Oct-2009 01:05
When happens that you want to encode special characters but not the HTML tags using this function you've two options:

a) Build your own function and go replace by character; eg.

<?php
 
for($i = 0; $i < strlen($string); $i++){
     switch(
substr($string,$i,1)){
       
//..... A VERY HUGE switch here with all characters to encode.
   
}
 }
?>

b) use this function and simple restore the html tags afterwards. Which gives you a 6 line function as follow:

<?php
 
function keephtml($string){
         
$res = htmlentities($string);
         
$res = str_replace("&lt;","<",$res);
         
$res = str_replace("&gt;",">",$res);
         
$res = str_replace("&quot;",'"',$res);
         
$res = str_replace("&amp;",'&',$res);
          return
$res;
}
?>
montana 08-Jul-2009 09:54
under what circumstances would someone want a ntilde [?] to be converted into "?±" as htmlentities does?
the correct method of translation should return the accurate NCR for the multibyte unicode sequence
which in this case is &#241;

<?php

   
//simple task: convert everything from utf-8 into an NCR[numeric character reference]
   
class unicode_replace_entities {
        public function
UTF8entities($content="") {
           
$contents = $this->unicode_string_to_array($content);
           
$swap = "";
           
$iCount = count($contents);
            for (
$o=0;$o<$iCount;$o++) {
               
$contents[$o] = $this->unicode_entity_replace($contents[$o]);
               
$swap .= $contents[$o];
            }
            return
mb_convert_encoding($swap,"UTF-8"); //not really necessary, but why not.
       
}

        public function
unicode_string_to_array( $string ) { //adjwilli
           
$strlen = mb_strlen($string);
            while (
$strlen) {
               
$array[] = mb_substr( $string, 0, 1, "UTF-8" );
               
$string = mb_substr( $string, 1, $strlen, "UTF-8" );
               
$strlen = mb_strlen( $string );
            }
            return
$array;
        }

        public function
unicode_entity_replace($c) { //m. perez
           
$h = ord($c{0});   
            if (
$h <= 0x7F) {
                return
$c;
            } else if (
$h < 0xC2) {
                return
$c;
            }
           
            if (
$h <= 0xDF) {
               
$h = ($h & 0x1F) << 6 | (ord($c{1}) & 0x3F);
               
$h = "&#" . $h . ";";
                return
$h;
            } else if (
$h <= 0xEF) {
               
$h = ($h & 0x0F) << 12 | (ord($c{1}) & 0x3F) << 6 | (ord($c{2}) & 0x3F);
               
$h = "&#" . $h . ";";
                return
$h;
            } else if (
$h <= 0xF4) {
               
$h = ($h & 0x0F) << 18 | (ord($c{1}) & 0x3F) << 12 | (ord($c{2}) & 0x3F) << 6 | (ord($c{3}) & 0x3F);
               
$h = "&#" . $h . ";";
                return
$h;
            }
        }
    }
//
   
    //utf-8 environment   
   
$content = "<strong>ba?o ba?o ba?o</strong>日本語 = nihongo da ze.<br />";

   
$oUnicodeReplace = new unicode_replace_entities();
   
$content = $oUnicodeReplace->UTF8entities($content);
    echo
"<br />Result:<br />";
    echo
$content;
   
$source = htmlentities($content);
    echo
"<br />htmlentities of resulting data:<br />";
    echo
$source;

    echo
"<br /><br />Note: Entities get replaced with 'literals' in textarea FF3<br /><br />";
    echo
"<textarea style='width:300px;height:150px;'>";
    echo
$content;
    echo
"</textarea>";
   
    echo
"<br /><br />For editing NCR's rather than 'literals' in a textarea<br /><br />";
    echo
"<textarea style='width:300px;height:150px;'>";
    echo
preg_replace("/(&#)+/","&amp;#",$content); 
    echo
"</textarea>";

?>
brianhamner at yahoo dot com 08-Jul-2009 09:26
If you want something simple that actually works, try this. Strips MS word and other entities and returns a clear data string:

<?php
//call this function

function DoHTMLEntities ($string) {
   
$trans_tbl[chr(145)] = '&#8216;';
   
$trans_tbl[chr(146)] = '&#8217;';
   
$trans_tbl[chr(147)] = '&#8220;';
   
$trans_tbl[chr(148)] = '&#8221;';
   
$trans_tbl[chr(142)] = '&eacute;';
   
$trans_tbl[chr(150)] = '&#8211;';
   
$trans_tbl[chr(151)] = '&#8212;';
    return
strtr ($string, $trans_tbl);
}

//insert your string variable here

       
$foo = str_replace("\r\n\r\n","",htmlentities($your_string));
       
$foo2 = str_replace("\r\n"," ",$foo);
       
$foo3 = str_replace(" & ","&amp;",$foo2);
        echo
DoHTMLEntities ($foo3);
?>
mzvarik at gmail dot com 14-May-2009 05:03
CZECH entities:

<?php
$ent
= array(
   
'ě' => '&#283;',
   
'ě' => '&#282;',
   
'?' => '&#353;',
   
'?' => '&#352;',
   
'?' => '&#269;',
   
'?' => '&#268;',
   
'?' => '&#345;',
   
'?' => '&#344;',
   
'?' => '&#382;',
   
'?' => '&#381;',
   
'y' => '&#253;',
   
'Y' => '&#221;',
   
'á' => '&#225;',
   
'á' => '&#193;',
   
'í' => '&#237;',
   
'í' => '&#205;',
   
'é' => '&#233;',
   
'é' => '&#201;',
   
'ú' => '&#250;',
   
'?' => '&#367;',
   
'?' => '&#366;',
   
'?' => '&#271;',
   
'?' => '&#270;',
   
'?' => '&#357;',
   
'?' => '&#356;',
   
'ň' => '&#328;',
   
'?' => '&#327;'
);

echo
strtr('ě????yáíéú???ňě????Yáíéú????', $ent);
?>
gunter [dot] sammet [at] gmail [dot] com 13-Jan-2009 10:48
Had a heck of a time to get my rss entities right. using htmlentities didn't work and using html_entity_decode didn't work either. Ended up writing a custom function to encode and decode. It might still need some work but I thought to share it because I couldn't find anything on the net. Always open for suggestions to improve it! Here it is:

<?php
  $entity_custom_from
= false;
 
$entity_custom_to = false;
  function
html_entity_decode_encode_rss($data) {
    global
$entity_custom_from, $entity_custom_to;
    if(!
is_array($entity_custom_from) || !is_array($entity_custom_to)){
     
$array_position = 0;
      foreach (
get_html_translation_table(HTML_ENTITIES) as $key => $value) {
       
//print("<br />key: $key, value: $value <br />\n");
       
switch ($value) {
         
// These ones we can skip
         
case '&nbsp;':
            break;
          case
'&gt;':
          case
'&lt;':
          case
'&quot;':
          case
'&apos;':
          case
'&amp;':
           
$entity_custom_from[$array_position] = $key;
           
$entity_custom_to[$array_position] = $value;
           
$array_position++;
            break;
          default:
           
$entity_custom_from[$array_position] = $value;
           
$entity_custom_to[$array_position] = $key;
           
$array_position++;
        }
      }
    }
    return
str_replace($entity_custom_from, $entity_custom_to, $data);
  }
?>
Tom Walter 16-Oct-2008 07:14
Note that as of 5.2.5 it appears that if the input string contains a character that is not valid for the output encoding you've specified, then this function returns null.

You might expect it to just strip the invalid char, but it doesn't.

You can strip the chars yourself like so:

iconv('utf-8','utf-8',$str);

You can combine that with htmlentities also:

$str = htmlentities(iconv('UTF-8', 'UTF-8//IGNORE', $str, ENT_QUOTES, 'UTF-8');

Should give you a string with htmlentities encoded to utf-8, and any unsupported chars stripped.
Kenneth Kin Lum 22-Sep-2008 04:47
use htmlspecialchars() if you are passing in a usual ASCII string.  It is faster than htmlentities().

For example, if you are just doing

htmlentities('<div style="background: #fff"></div>');

then you can just use htmlspecialchars().  htmlentities() will look for all possible ways to convert string into html entities, such as &copy; or &eacute; (which is e with an acute accent on top).

Note that ASCII is just 7 bit, which is 0x00 to 0x7F.  htmlspecialchars() will handle characters inside this range already.  htmlentities() is for the 8-bit Latin-1 (ISO-8859-1) to handle European characters, or for UTF-8 when the 3rd argument is "UTF-8" to handle UTF-8 characters, or other types of encodings using different values for the 3rd argument passed into htmlentities().
snevi at im dot com dot ve 21-Jul-2008 06:10
correction to my previous post and improvement of the function: (the post was changed by the html parser and the characters displays as they should not)

<?php
   
function XMLEntities($string)
    {
       
$string = preg_replace('/[^\x09\x0A\x0D\x20-\x7F]/e', '_privateXMLEntities("$0")', $string);
        return
$string;
    }

    function
_privateXMLEntities($num)
    {
   
$chars = array(
       
128 => '&#8364;',
       
130 => '&#8218;',
       
131 => '&#402;',
       
132 => '&#8222;',
       
133 => '&#8230;',
       
134 => '&#8224;',
       
135 => '&#8225;',
       
136 => '&#710;',
       
137 => '&#8240;',
       
138 => '&#352;',
       
139 => '&#8249;',
       
140 => '&#338;',
       
142 => '&#381;',
       
145 => '&#8216;',
       
146 => '&#8217;',
       
147 => '&#8220;',
       
148 => '&#8221;',
       
149 => '&#8226;',
       
150 => '&#8211;',
       
151 => '&#8212;',
       
152 => '&#732;',
       
153 => '&#8482;',
       
154 => '&#353;',
       
155 => '&#8250;',
       
156 => '&#339;',
       
158 => '&#382;',
       
159 => '&#376;');
       
$num = ord($num);
        return ((
$num > 127 && $num < 160) ? $chars[$num] : "&#".$num.";" );
    }
?>

in the previous post, to correct the HEX values that are not rendered, the program use a for each cicle, but that introduces a mayor complexity in execution time, so, we use the ability to call functions in the preg_replace second parameter, and ceate another funcion that evaluates the ord of the character given, and if it is between 127 and 160 it returns the modified HEX value to be understood by the browser and not brake the XML
(this work with dynamic XML generated form php with dynamic data from any source)

p.d: the '&'(&) should appear in this post as a single ampersand character and not as the html entity
keenskelly at gmail dot com 09-Jul-2008 10:00
Correction to my previous post: the set of ENTITY declarations must be inside a <!DOCTYPE element; also &nbsp; is NOT pre-defined in XML and must be left in the entity list. I also extended the list with the windows 1252 character set using a sample function borrowed from php.net user comments and extended with euro entity which we need for our app. Here is the final code that is in our production app:

<?php

// Generate a list of entity declarations from the HTML_ENTITIES set that PHP knows about to dump into the document
function htmlentities_entities() {
       
$output = "<!DOCTYPE html [\n";
        foreach (
get_html_translation_table_CP1252(HTML_ENTITIES) as $value) {
               
$name = substr($value, 1, strlen($value) - 2);
                switch (
$name) {
                       
// These ones we can skip because they're built into XML
                       
case 'gt':
                        case
'lt':
                        case
'quot':
                        case
'apos':
                        case
'amp': break;
                        default:
$output .= "<!ENTITY {$name} \"&{$name};\">\n";
                }
        }
       
$output .= "]>\n";
        return(
$output);
}

// ref: http://php.net/manual/en/function.get-html-translation-table.php#76564
function get_html_translation_table_CP1252($type) {
       
$trans = get_html_translation_table($type);
       
$trans[chr(130)] = '&sbquo;';    // Single Low-9 Quotation Mark
       
$trans[chr(131)] = '&fnof;';    // Latin Small Letter F With Hook
       
$trans[chr(132)] = '&bdquo;';    // Double Low-9 Quotation Mark
       
$trans[chr(133)] = '&hellip;';    // Horizontal Ellipsis
       
$trans[chr(134)] = '&dagger;';    // Dagger
       
$trans[chr(135)] = '&Dagger;';    // Double Dagger
       
$trans[chr(136)] = '&circ;';    // Modifier Letter Circumflex Accent
       
$trans[chr(137)] = '&permil;';    // Per Mille Sign
       
$trans[chr(138)] = '&Scaron;';    // Latin Capital Letter S With Caron
       
$trans[chr(139)] = '&lsaquo;';    // Single Left-Pointing Angle Quotation Mark
       
$trans[chr(140)] = '&OElig;';    // Latin Capital Ligature OE
       
$trans[chr(145)] = '&lsquo;';    // Left Single Quotation Mark
       
$trans[chr(146)] = '&rsquo;';    // Right Single Quotation Mark
       
$trans[chr(147)] = '&ldquo;';    // Left Double Quotation Mark
       
$trans[chr(148)] = '&rdquo;';    // Right Double Quotation Mark
       
$trans[chr(149)] = '&bull;';    // Bullet
       
$trans[chr(150)] = '&ndash;';    // En Dash
       
$trans[chr(151)] = '&mdash;';    // Em Dash
       
$trans[chr(152)] = '&tilde;';    // Small Tilde
       
$trans[chr(153)] = '&trade;';    // Trade Mark Sign
       
$trans[chr(154)] = '&scaron;';    // Latin Small Letter S With Caron
       
$trans[chr(155)] = '&rsaquo;';    // Single Right-Pointing Angle Quotation Mark
       
$trans[chr(156)] = '&oelig;';    // Latin Small Ligature OE
       
$trans[chr(159)] = '&Yuml;';    // Latin Capital Letter Y With Diaeresis
       
$trans['euro'] = '&euro;';    // euro currency symbol
       
ksort($trans);
        return
$trans;
}

?>

[EDIT BY danbrown AT php DOT net: The user's original note contained the following text:

"So here's something fun: if you create an XML document in PHP and use htmlentities() to encode text data, then later want to read and parse the same document with PHP's xml_parse(), unless you include entity declarations into the generated document, the parser will stop on the unknown entities.

To account for this, I created a small function to take the translation table and turn it into XML <!ENTITY> definitions. I insert this output into the XML document immediately after the <?xml?> line and the parse errors magically vanish"
]
za at byza dot it 15-Apr-2008 09:15
Trouble when using files with different charset?

htmlentities and html_entity_decode can be used to translate between charset!

Sample function:

<?php
function utf2latin($text) {
  
$text=htmlentities($text,ENT_COMPAT,'UTF-8');
   return
html_entity_decode($text,ENT_COMPAT,'ISO-8859-1');
}
?>
marktpitman at gmail dot com 15-Oct-2007 07:21
I just thought I would add that if you're using the default charset, htmlentities will not correctly return the trademark ( ™ ) sign.

Instead it will return something like this: a?¢

If you need the trademark symbol, use:

<?php htmlentities( $html, ENT_QUOTES, "UTF-8" ); ?>
D. Gasser 24-Apr-2007 10:40
When using UTF-8 as charset, you'll have to set UTF-8 in braces, otherwise the varaible is not recognized.
q (dot) rendeiro (at) gmail (dot) com 07-Mar-2007 04:41
I've seen lots of functions to convert all the entities, but I needed to do a fulltext search in a db field that had named entities instead of numeric entities (edited by tinymce), so I searched the tinymce source and found a string with the value->entity mapping. So, i wrote the following function to encode the user's query with named entities.

The string I used is different of the original, because i didn't want to convert ' or ". The string is too long, so I had to cut it. To get the original check TinyMCE source and search for nbsp or other entity ;)

<?php

$entities_unmatched
= explode(',', '160,nbsp,161,iexcl,162,cent, [...] ');
$even = 1;
foreach(
$entities_unmatched as $c) {
    if(
$even) {
       
$ord = $c;
    } else {
       
$entities_table[$ord] = $c;
    }
   
$even = 1 - $even;
}

function
encode_named_entities($str) {
    global
$entities_table;
   
   
$encoded_str = '';
    for(
$i = 0; $i < strlen($str); $i++) {
       
$ent = @$entities_table[ord($str{$i})];
        if(
$ent) {
           
$encoded_str .= "&$ent;";
        } else {
           
$encoded_str .= $str{$i};
        }
    }
    return
$encoded_str;
}

?>
realcj at g mail dt com 06-Nov-2006 10:41
If you are building a loadvars page for Flash and have problems with special chars such as " & ", " ' " etc, you should escape them for flash:

Try trace(escape("&")); in flash' actionscript to see the escape code for &;

% = %25
& = %26
' = %27

<?php
function flashentities($string){
return
str_replace(array("&","'"),array("%26","%27"),$string);
}
?>

Those are the two that concerned me. YMMV.
daviscabral[arroba]gmail[ponto]com 28-Jul-2006 12:52
unhtmlentities for all entities:

<?php

function unhtmlentities ($string) {
  
$trans_tbl1 = get_html_translation_table (HTML_ENTITIES);
   foreach (
$trans_tbl1 as $ascii => $htmlentitie ) {
       
$trans_tbl2[$ascii] = '&#'.ord($ascii).';';
   }
  
$trans_tbl1 = array_flip ($trans_tbl1);
  
$trans_tbl2 = array_flip ($trans_tbl2);
   return
strtr (strtr ($string, $trans_tbl1), $trans_tbl2);
}

?>
info at pirandot dot de 22-Jul-2006 07:14
The data returned by a text input field is ready to be used in a data base query when enclosed in single quotes, e.g.
<?php
   mysql_query
("SELECT * FROM Article WHERE id = '$data'");
?>
But you will get problems when writing back this data into the input field's value,
<?php
  
echo "<input name='data' type='text' value='$data'>";
?>
because hmtl codes would be interpreted and escape sequences would cause strange output.

The following function may help:
<?php
function deescape ($s, $charset='UTF-8')
{
  
//  don't interpret html codes and don't convert quotes
  
$s  htmlentities ($s, ENT_NOQUOTES, $charset);

  
//  delete the inserted backslashes except those for protecting single quotes
  
$s  preg_replace ("/\\\\([^'])/e", '"&#" . ord("$1") . ";"', $s);

  
//  delete the backslashes inserted for protecting single quotes
  
$s  str_replace ("\\'", "&#" . ord ("'") . ";", $s);

   return 
$s;
}
?>
Try some input like:  a'b"c\d\'e\"f\\g&x#27;h  to test ...
anonymous 26-Apr-2006 12:38
This function will encode anything that is non Standard ASCII (that is, that is above #127 in the ascii table)

<?php
// allhtmlentities : mainly based on "chars_encode()"  by Tim Burgan <timburgan@gmail.com> [http://www.php.net/htmlentities]
function allhtmlentities($string) {
    if (
strlen($string) == 0 )
        return
$string;
   
$result = '';
   
$string = htmlentities($string, HTML_ENTITIES);
   
$string = preg_split("//", $string, -1, PREG_SPLIT_NO_EMPTY);
   
$ord = 0;
    for (
$i = 0; $i < count($string); $i++ ) {
       
$ord = ord($string[$i]);
        if (
$ord > 127 ) {
           
$string[$i] = '&#' . $ord . ';';
        }
    }
    return
implode('',$string);
}
?>
edo at edwaa dot com 17-Nov-2005 08:48
A version of the xml entities function below. This one replaces the "prime" character (′) with which I had difficulties.

<?php
// XML Entity Mandatory Escape Characters
function xmlentities($string) {
   return
str_replace ( array ( '&', '"', "'", '<', '>', '?' ), array ( '&amp;' , '&quot;', '&apos;' , '&lt;' , '&gt;', '&apos;' ), $string );
}
?>
info at bleed dot ws 14-Oct-2005 10:42
here the centralized version of htmlentities() for multibyte.

<?php
function mb_htmlentities($string)
{
   
$string = htmlentities($string, ENT_COMPAT, mb_internal_encoding());
    return
$string;
}

?>
jake_mcmahon at hotmail dot com 29-Apr-2004 02:29
This fuction is particularly useful against XSS (cross-site-scripting-). XSS makes use of holes in code, whether it be in Javascript or PHP. XSS often, if not always, uses HTML entities to do its evil deeds, so this function in co-operation with your scripts (particularly search or submitting scripts) is a very useful tool in combatting "H4X0rz".
wwb at 3dwargamer dot net 31-Mar-2004 04:49
htmlentites is a very handy function, but it fails to fix one thing which I deal with alot: word 'smart' quotes and emdashes.

The below function replaces the funky double quotes with &quot;, funky single quotes with standard single quotes and fixes emdashes.

<?php
   
function CleanupSmartQuotes($text)
    {
       
$badwordchars=array(
                           
chr(145),
                           
chr(146),
                           
chr(147),
                           
chr(148),
                           
chr(151)
                            );
       
$fixedwordchars=array(
                           
"'",
                           
"'",
                           
'&quot;',
                           
'&quot;',
                           
'&mdash;'
                           
);
        return
str_replace($badwordchars,$fixedwordchars,$text);
    }
?>
Bassie (: 05-Jan-2003 04:07
Note that you'll have use htmlentities() before any other function who'll edit text like nl2br().

If you use nl2br() first, the htmlentities() function will change < br > to &lt;br&gt;.