文字

htmlspecialchars

(PHP 4, PHP 5)

htmlspecialcharsConvert special characters to HTML entities

说明

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

Certain characters have special significance in HTML, and should be represented by HTML entities if they are to preserve their meanings. This function returns a string with these conversions made. If you require all input substrings that have associated named entities to be translated, use htmlentities() instead.

If the input string passed to this function and the final document share the same character set, this function is sufficient to prepare input for inclusion in most contexts of an HTML document. If, however, the input can represent characters that are not coded in the final document character set and you wish to retain those characters (as numeric or named entities), both this function and htmlentities() (which only encodes substrings that have named entity equivalents) may be insufficient. You may have to use mb_encode_numericentity() instead.

The translations performed are:

  • '&' (ampersand) becomes '&'
  • '"' (double quote) becomes '"' when ENT_NOQUOTES is not set.
  • "'" (single quote) becomes ''' (or ') only when ENT_QUOTES is set.
  • '<' (less than) becomes '&lt;'
  • '>' (greater than) becomes '&gt;'

参数

string

The string being converted.

flags

A bitmask of one or more of the following flags, which specify how to handle quotes, invalid code unit sequences and the used document type. The default is ENT_COMPAT | ENT_HTML401.

Available flags constants
Constant Name Description
ENT_COMPAT Will convert double-quotes and leave single-quotes alone.
ENT_QUOTES Will convert both double and single quotes.
ENT_NOQUOTES Will leave both double and single quotes unconverted.
ENT_IGNORE Silently discard invalid code unit sequences instead of returning an empty string. Using this flag is discouraged as it » may have security implications.
ENT_SUBSTITUTE Replace invalid code unit sequences with a Unicode Replacement Character U+FFFD (UTF-8) or &#FFFD; (otherwise) instead of returning an empty string.
ENT_DISALLOWED Replace invalid code points for the given document type with a Unicode Replacement Character U+FFFD (UTF-8) or &#FFFD; (otherwise) instead of leaving them as is. This may be useful, for instance, to ensure the well-formedness of XML documents with embedded external content.
ENT_HTML401 Handle code as HTML 4.01.
ENT_XML1 Handle code as XML 1.
ENT_XHTML Handle code as XHTML.
ENT_HTML5 Handle code as 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.

For the purposes of this function, the encodings ISO-8859-1, ISO-8859-15, UTF-8, cp866, cp1251, cp1252, and KOI8-R are effectively equivalent, provided the string itself is valid for the encoding, as the characters affected by htmlspecialchars() occupy the same positions in all of these encodings.

支持以下字符集:

支持的字符集列表
字符集 别名 描述
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

When double_encode is turned off PHP will not encode existing html entities, the default is to convert everything.

返回值

The converted string .

If the input string contains an invalid code unit sequence within the given encoding an empty string will be returned, unless either the ENT_IGNORE or ENT_SUBSTITUTE flags are set.

更新日志

版本 说明
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 The default value for the encoding parameter was changed to UTF-8.
5.4.0 The constants ENT_SUBSTITUTE , ENT_DISALLOWED , ENT_HTML401 , ENT_XML1 , ENT_XHTML and ENT_HTML5 were added.
5.3.0 The constant ENT_IGNORE was added.
5.2.3 The double_encode parameter was added.

范例

Example #1 htmlspecialchars() example

<?php
$new 
htmlspecialchars ( "<a href='test'>Test</a>" ENT_QUOTES );
echo 
$new // &lt;a href=&#039;test&#039;&gt;Test&lt;/a&gt;
?>

注释

Note:

Note that this function does not translate anything beyond what is listed above. For full entity translation, see htmlentities() .

参见

  • get_html_translation_table() - 返回使用 htmlspecialchars 和 htmlentities 后的转换表
  • htmlspecialchars_decode() - 将特殊的 HTML 实体转换回普通字符
  • strip_tags() - 从字符串中去除 HTML 和 PHP 标记
  • htmlentities() - Convert all applicable characters to HTML entities
  • nl2br() - 在字符串所有新行之前插入 HTML 换行标记

用户评论:

[#1] PoV [2015-05-17 23:59:37]

Be aware of the encoding of your source files!!! 

Some of the suggestions here make reference to workarounds where you hard-code an encoding.

<?php
  
echo htmlspecialchars('<b>W?rmann</b>');  // Why isn't this working?
?>


As it turns out, it may actually be your text editor that is to blame.

As of PHP 5.4, htmlspecialchars now defaults to the UTF-8 encoding. That said, many text editors default to non-UTF encodings like ISO-8859-1 (i.e. Latin-1) or WIN-1252. If you change the encoding of the file to UTF-8, the code above will now work (i.e. the ? is encoded differently in UTF-8 and ISO-8859-1, and you need the UTF-8 version).

Make sure you are editing in UTF-8 Unicode mode! Check your UI or manual for how to convert files to Unicode. It's also a good idea to figure out where to look in your UI to see what the current file encoding is.

[#2] Albert [2015-04-16 14:30:15]

The code I posted this morning (for giving back to htmlspecialchars etc. the old default ISO encoding) had some strange problem, didn't work if a page was reloaded! Here the code I came up with, without this problem:

<?php
if (version_compare(phpversion(), "5.3.3"">")) {
    
runkit_function_copy('htmlspecialchars''htmlspecialchars_new');
    
runkit_function_redefine(
        
'htmlspecialchars',
        
'$string, $flags, $encoding',
        
'return $encoding == "" ? htmlspecialchars_new($string, ENT_COMPAT | ENT_HTML401, "ISO-8859-1") : htmlspecialchars_new($string, $flags, $encoding);'
    
);

    
runkit_function_copy('htmlentities''htmlentities_new');
    
runkit_function_redefine(
        
'htmlentities',
        
'$string, $flags, $encoding',
        
'return $encoding == "" ? htmlentities_new($string, ENT_COMPAT | ENT_HTML401, "ISO-8859-1") : htmlentities_new($string, $flags, $encoding);'
    
);

    
runkit_function_copy('html_entity_decode''html_entity_decode_new');
    
runkit_function_redefine(
        
'html_entity_decode',
        
'$string, $flags, $encoding',
        
'return $encoding == "" ? html_entity_decode_new($string, ENT_COMPAT | ENT_HTML401, "ISO-8859-1") : html_entity_decode_new($string, $flags, $encoding);'
    
);
}
?>


So first I copy the original function, then I redefine the same.

[#3] Albert [2015-04-16 10:21:48]

I found a simple solution for the changed default character encoding in htmlspecialchars, htmlentities and html_entity_decode, so my (very) old code kept running:

<?php
if (version_compare(phpversion(), "5.3.3"">")) {
    
runkit_function_rename('htmlspecialchars''htmlspecialchars_new');
    
runkit_function_add(
        
'htmlspecialchars',
        
'$string, $flags, $encoding',
        
'return $encoding == "" ? htmlspecialchars_new($string, ENT_COMPAT | ENT_HTML401, "ISO-8859-1") : htmlspecialchars_new($string, $flags, $encoding);'
    
);

    
runkit_function_rename('htmlentities''htmlentities_new');
    
runkit_function_add(
        
'htmlentities',
        
'$string, $flags, $encoding',
        
'return $encoding == "" ? htmlentities_new($string, ENT_COMPAT | ENT_HTML401, "ISO-8859-1") : htmlentities_new($string, $flags, $encoding);'
    
);

    
runkit_function_rename('html_entity_decode''html_entity_decode_new');
    
runkit_function_add(
        
'html_entity_decode',
        
'$string, $flags, $encoding',
        
'return $encoding == "" ? html_entity_decode_new($string, ENT_COMPAT | ENT_HTML401, "ISO-8859-1") : html_entity_decode_new($string, $flags, $encoding);'
    
);
}
?>

[#4] sascham78 at php dot net [2014-10-01 08:57:58]

If you are using UTF-8 encoding with htmlspecialchars() you may experience blank values with certain language-specific characters i.e. spanish or portuguese "????". 
So instead of using
<?php
$utf8encoded
htmlspecialchars($stringENT_QUOTES'UTF-8');
?>

try 
<?php
$utf8encoded
utf8_encode(htmlspecialchars($stringENT_QUOTES));
?>

[#5] glapa.wojciech.com [2014-01-29 04:32:56]

To show result in comment it should be:

<?php
$new 
htmlspecialchars("<a href='test'>Test</a>"ENT_QUOTES);
echo 
htmlspecialchars($new); // &lt;a href=&#039;test&#039;&gt;Test&lt;/a&gt;
?>


...

[#6] Felix D. [2014-01-09 23:00:14]

Another thing important to mention is that
htmlspecialchars(NULL)
returnes an empty string and not NULL!

[#7] support at playnext dot ru [2013-10-03 08:31:18]

For those having problems after the change of default value of $encoding argument to UTF-8 since PHP 5.4.

If your old non-UTF8 projects ruined - pls consider:
1. http://php.net/manual/en/function.override-function.php
2. http://php.net/manual/ru/function.runkit-function-redefine.php

The idea - you override the built-in htmlspecialchars() function with your customized variant which is able to respect non UTF-8 default encoding. This small piece of code can be then easily inserted somewhere at the start of yout project. No need to rewrite all htmlspecialchars() entries globally.

I've spent several hours with both approaches. Variant 1 looks good especaially in combination with http://www.php.net/manual/en/function.rename-function.php as it allows to call original htmlspecialchars() with just altered default args. The code could be as follows:

<?php
rename_function
('htmlspecialchars''renamed_htmlspecialchars');
function 
overriden_htmlspecialchars($string$flags=NULL$encoding='cp1251'$double_encode=true) {
    
$flags $flags $flags : (ENT_COMPAT|ENT_HTML401);
    return 
renamed_htmlspecialchars($string$flags$encoding$double_encode);
}
override_function('htmlspecialchars''$string, $flags, $encoding, $double_encode''return overriden_htmlspecialchars($string, $flags, $encoding, $double_encode);');
?>


Unfortunatelly this didn't work for me properly - my site managed to call overriden function but not every time I reloaded the pages. Moreover other PHP sites crashed under my Apache server as they suddenly started blaming htmlspecialchars() was not defined. I suppose I had to spend more time to make it work thread/request/site/whatever-safe.

So I switched to runkit (variant 2). It worked for me, although even after trying runkit_function_rename()+runkit_function_add() I didn't managed to recall original htmlspecialchars() function. So as a quick solution I decided to call htmlentities() instead:

<?php
function overriden_htmlspecialchars($string$flags=NULL$encoding='UTF-8'$double_encode=true) {
    
$flags $flags $flags : (ENT_COMPAT|ENT_HTML401);
    
$encoding $encoding $encoding 'cp1251';
    return 
htmlentities($string$flags$encoding$double_encode);
}
runkit_function_redefine('htmlspecialchars''$string, $flags, $encoding, $double_encode''return overriden_htmlspecialchars($string, $flags, $encoding, $double_encode);'); 
?>


You may be able to implement your more powerfull overriden function.
Good luck!

[#8] Dave [2013-06-20 11:59:59]

As of PHP 5.4 they changed default encoding from "ISO-8859-1" to "UTF-8". So if you get null from htmlspecialchars or htmlentities

where you have only set 
<?php
echo htmlspecialchars($string);
echo 
htmlentities($string);
?>


you can fix it by
<?php
echo htmlspecialchars($stringENT_COMPAT,'ISO-8859-1'true);
echo 
htmlentities($stringENT_COMPAT,'ISO-8859-1'true);
?>
 

On linux you can find the scripts you need to fix by

grep -Rl "htmlspecialchars\\|htmlentities" /path/to/php/scripts/

[#9] minder at ufive dot unibe dot ch [2013-05-19 13:06:00]

Problem

In many PHP legacy products the function htmlspecialchars($string) is used to convert characters like < and > and quotes a.s.o to HTML-entities. That avoids the interpretation of HTML Tags and asymmetric quote situations.

Since PHP 5.4 for $string in htmlspecialchars($string) utf8 characters are expected if no charset is defined explicitly as third parameter in the function. Legacy products are mostly in Latin1 (alias iso-8859-1) what makes the functions htmlspecialchars(), htmlentites() and html_entity_decode() to return empty strings if a special character, e. g. a German Umlaut, is present in $string:

PHP<5.4

echo htmlspecialchars('<b>Woermann</b>') //Output: &lt;b&gt;Woermann&lt;b&gt;
echo htmlspecialchars('W?rmann') //Output: &lt;b&gt;W?rmann&lt;b&gt;

PHP=5.4

echo htmlspecialchars('<b>Woermann</b>') //Output: &lt;b&gt;Woermann&lt;b&gt;
echo htmlspecialchars('<b>W?rmann</b>') //Output: empty

Three alternative solutions

a) Not runnig legacy products on PHP 5.4
b) Change all find spots in your code from 
htmlspecialchars($string) and *** to 
htmlspecialchars($string, ENT_COMPAT | ENT_HTML401, 'ISO-8859-1')
c) Replace all htmlspecialchars() and *** with a new self-made function

*** The same is true for htmlentities() and html_entity_decode();

Solution c

1 Make Search and Replace in the concerned legacy project:
Search for:        htmlspecialchars
Replace with:   htmlXspecialchars
Search for:        htmlentities
Replace with:   htmlXentities
Search for:        html_entity_decode
Replace with:   htmlX_entity_decode
2a Copy and paste the following three functions into an existing already everywhere included PHP-file in your legacy project. (of course that PHP-file must be included only once per request, otherwise you will get a Redeclare Function Fatal Error).

function htmlXspecialchars($string, $ent=ENT_COMPAT, $charset='ISO-8859-1') {
return htmlspecialchars($string, $ent, $charset);
}

function htmlXentities($string, $ent=ENT_COMPAT, $charset='ISO-8859-1') {
return htmlentities($string, $ent, $charset);
}

function htmlX_entity_decode($string, $ent=ENT_COMPAT, $charset='ISO-8859-1') {
return html_entity_decode($string, $ent, $charset);
}

or 2b crate a new PHP-file containing the three functions mentioned above, let's say, z. B. htmlXfunctions.inc.php and include it on the first line of every PHP-file in your legacy product like this: require_once('htmlXfunctions.inc.php').

[#10] Mike Robinson [2013-03-14 00:46:49]

Unfortunately, as far as I can tell, the PHP devs did not provide ANY way to set the default encoding used by htmlspecialchars() or htmlentities(), even though they changed the default encoding in PHP 5.4 (*golf clap for PHP devs*). To save someone the time of trying it, this does not work:

<?php
ini_set
('default_charset'$charset); // doesn't work.
?>


Unfortunately, the only way to not have to explicitly provide the second and third parameter every single time this function is called (which gets extremely tedious) is to write your own function as a wrapper:

<?php
define
('CHARSET''ISO-8859-1');
define('REPLACE_FLAGS'ENT_COMPAT ENT_XHTML);

function 
html($string) {
    return 
htmlspecialchars($stringREPLACE_FLAGSCHARSET);
}

echo 
html("?"); // works
?>


You can do the same for htmlentities()

[#11] strange dot alex at gmail dot com [2013-03-07 05:24:52]

> For the purposes of this function, the encodings ISO-8859-1, ISO-8859-15, UTF-8, cp866, cp1251, cp1252, and KOI8-R are effectively equivalent, provided the string itself is valid for the encoding, as the characters affected by htmlspecialchars() occupy the same positions in all of these encodings. 

This is not true, actually!
$txt = "Russian text in KOI8-r<br>"; // type here realy russian text in koi8-r !

htmlspecialchars($txt,null,'KOI8-R') = Russian text in KOI8-r<br>
htmlspecialchars($txt,null,'UTF-8') =
 Result is EMPTY !!!

[#12] odegroot+php at gmail dot com [2012-06-18 09:57:24]

This function can be used to escape single quotes only, and not double quotes, by calling it as follows.

<?php $escaped_string htmlspecialchars($stringENT_QUOTES & ~ENT_COMPAT$encoding); ?>

This works because single/double quote escaping actually each have their own flag.

#define ENT_HTML_QUOTE_NONE         0
#define ENT_HTML_QUOTE_SINGLE       1
#define ENT_HTML_QUOTE_DOUBLE       2

#define ENT_COMPAT      ENT_HTML_QUOTE_DOUBLE
#define ENT_QUOTES      (ENT_HTML_QUOTE_DOUBLE | ENT_HTML_QUOTE_SINGLE)
#define ENT_NOQUOTES    ENT_HTML_QUOTE_NONE

Snippet from: php-src/ext/standard/html.h
https://github.com/php/php-src/blob/master/ext/standard/html.h

[#13] steve at mcdragonsoftware dot com [2011-10-17 21:13:25]

I am working with xml and zip functions to create an xlsx document from a template. Just as I thought I had it finished it stopped working. After a bit of hunting I discovered my zip file began with php notices about undefined constant. I have no idea why my installation can't remember what ENT_XML1 is, it used to know it (or so I thought)

To save anyone else this headache I recommend adding the code at the top of your scripts to verify that these constants are registered. Something like:

defined( "ENT_XML1") or define( "ENT_XML1", 16 );

for each constant you use. Again, I don't know why this problem suddenly came up, but better safe than "Excel cannot open the file....... format... extension... corrupted... blah blah blah".

cheers :)

here's a list of the constant values (since they are not on this page) as taken from html.h for php5 

#define ENT_HTML_QUOTE_NONE 0
#define ENT_HTML_QUOTE_SINGLE    1
#define ENT_HTML_QUOTE_DOUBLE          2
#define ENT_HTML_IGNORE_ERRORS 4
#define ENT_HTML_SUBSTITUTE_ERRORS  8
#define ENT_HTML_DOC_TYPE_MASK (16|32)
#define ENT_HTML_DOC_HTML401    0
#define ENT_HTML_DOC_XML1 16
#define ENT_HTML_DOC_XHTML 32
#define ENT_HTML_DOC_HTML5 (16|32)

#define ENT_HTML_SUBSTITUTE_DISALLOWED_CHARS 128

#define ENT_COMPAT ENT_HTML_QUOTE_DOUBLE
#define ENT_QUOTES (ENT_HTML_QUOTE_DOUBLE | ENT_HTML_QUOTE_SINGLE)
#define ENT_NOQUOTES ENT_HTML_QUOTE_NONE
#define ENT_IGNORE ENT_HTML_IGNORE_ERRORS
#define ENT_SUBSTITUTE ENT_HTML_SUBSTITUTE_ERRORS
#define ENT_HTML401 0
#define ENT_XML1 16
#define ENT_XHTML 32
#define ENT_HTML5 (16|32)
#define ENT_DISALLOWED 128

[#14] ivan at lutrov dot com [2011-06-15 01:30:07]

Be careful, the "charset" argument IS case sensitive. This is counter-intuitive and serves no practical purpose because the HTML spec actually has the opposite.

[#15] info at 8th dot at [2011-05-12 11:28:57]

English:
I'd found THE Final Solution!
it finds and replaces all unknown letters!
(like ?, ?, ?, ?, and much much more)

it turn em in a HTML AND XML compatible format

parameter: $text: a String with unsuported letters in it
return: a String where all unsupported(XML und HTML) letters are changed into the Unicode value (for example &#196;)

Deutsch/German:
Ich hab die perfekte L?sung gefunden!
Es findet und tauscht alle unbekannten Buchstaben!
(wie ?, ?, ?, ?, und viel viel mehr)

es tauscht sie in ein HTML und XML kompatibles Format

parameter: $text: ein String mit nichtunterst??zten Buchstaben
return: ein String wo alle von XML und HTML ununterst??tzten Buchstaben ins Unicode-Format getauscht sind (z.B. &#196;)

FUNCTION:

<?php
function umlaute($text){
    
$returnvalue="";
    for(
$i=0;$i<strlen($text);$i++){
        
$teil=hexdec(rawurlencode(substr($text$i1)));
        if(
$teil<32||$teil>1114111){
            
$returnvalue.=substr($text$i1);
        }else{
            
$returnvalue.="&#".$teil.";";
        }
    }
    return 
$returnvalue;
}
?>

[#16] pinkgothic at gmail dot com [2011-03-11 05:00:20]

Please note that this function results in an E_WARNING when display_errors is off and an invalid multibyte string is passed to it (e.g. with 'utf-8' as the encoding parameter and broken utf-8 characters somewhere in the string).

This is ESPECIALLY IMPORTANT if you have an EXCEPTION-THROWING ERROR HANDLER, since even though you can't reproduce it in a development mode where display_errors is on, you MUST wrap your function call in a try-catch, or your application will crash.

[ The reason PHP makes this distinction is because this is a core function and many production servers are misconfigured to have display_errors on (to prevent such things as path disclosure from error messages from accidentally cropping up). See: http://bugs.php.net/bug.php?id=47494 ]

[#17] Thomasvdbulk at gmail dot com [2010-12-28 10:05:34]

i searched for a while for a script, that could see the difference between an html tag and just < and > placed in the text, 
the reason is that i recieve text from a database,
wich is inserted by an html form, and contains text and html tags, 
the text can contain < and >, so does the tags,
with htmlspecialchars you can validate your text to XHTML,
but you'll also change the tags, like <b> to &lt;b&gt;,
so i needed a script that could see the difference between those two...
but i couldn't find one so i made my own one, 
i havent fully tested it, but the parts i tested worked perfect!
just for people that were searching for something like this,
it may looks big, could be done easier, but it works for me, so im happy.

<?php
function fixtags($text){
$text htmlspecialchars($text);
$text preg_replace("/=/""=\"\""$text);
$text preg_replace("/&quot;/""&quot;\""$text);
$tags "/&lt;(\/|)(\w*)(\ |)(\w*)([\\\=]*)(?|(\")\"&quot;\"|)(?|(.*)?&quot;(\")|)([\ ]?)(\/|)&gt;/i";
$replacement "<$1$2$3$4$5$6$7$8$9$10>";
$text preg_replace($tags$replacement$text);
$text preg_replace("/=\"\"/""="$text);
return 
$text;
}
?>


an example:

<?php
$string 
"
this is smaller < than this<br /> 
this is greater > than this<br />
this is the same = as this<br />
<a href=\"http://www.example.com/example.php?test=test\">This is a link</a><br />
<b>Bold</b> <i>italic</i> etc..."
;
echo 
fixtags($string);
?>


will echo:
this is smaller &lt; than this<br /> 
this is greater &gt; than this<br /> 
this is the same = as this<br /> 
<a href="http://www.example.com/example.php?test=test">This is a link</a><br /> 
<b>Bold</b> <i>italic</i> etc...

I hope its helpfull!!

[#18] Anonymous [2010-08-01 13:48:16]

This may seem obvious, but if you want to output arbitrary (i.e. user-input) data as an attribute inside an HTML tag (such as the INPUT tags on a FORM), be aware of whether you are using ENT_QUOTES or ENT_COMPAT.  If you're using ENT_COMPAT, the attribute must be wrapped in double-quotes, as single-quotes will not be encoded and the user will be able to inject arbitrary HTML attributes (including javascript behavior) inside the tag, even though they will not be able to inject arbitrary HTML tags.

Also, if you want to allow users to input HTML attributes without them being double-encoded on display, there are two ways to accomplish this:

1 - Run their input through htmlentities_decode() followed by htmlspecialchars().

2 - Call htmlspecialchars() with $double_encode=false.

There is one functional difference between these two methods:  If you want to perform any search-replace on a user's input (such as word censoring in a message-board application), the second method will allow users to circumvent it by HTML-encoding their input, whereas the first will not.

[#19] nachitox2000 [at] hotmail [dot] com [2010-07-01 05:57:41]

I had problems with spanish special characters. So i think in using htmlspecialchars but my strings also contain HTML.
So I used this :) Hope it help

<?php
function htmlspanishchars($str
{
    return 
str_replace(array("&lt;""&gt;"), array("<"">"), htmlspecialchars($strENT_NOQUOTES"UTF-8"));
}
?>

[#20] nessthehero at gmail dot com [2010-05-19 11:53:04]

Here's a simple function I wrote for parsing form data.

It checks if it's an array and it is recursive (it calls itself).

It also decodes things that have already been encoded so it doesn't change &amp; to &amp;amp;

[In this version,] I found it easier to use a regular expression to check and see if any previously encoded data exists, then decode it repeatedly until there is none left, then re-encode it.

<?php
function formspecialchars($var)
    {
        
$pattern '/&(#)?[a-zA-Z0-9]{0,};/';
        
        if (
is_array($var)) {    // If variable is an array
            
$out = array();      // Set output as an array
            
foreach ($var as $key => $v) {      
                
$out[$key] = formspecialchars($v);         // Run formspecialchars on every element of the array and return the result. Also maintains the keys.
            
}
        } else {
            
$out $var;
            while (
preg_match($pattern,$out) > 0) {
                
$out htmlspecialchars_decode($out,ENT_QUOTES);       
            }                             
            
$out htmlspecialchars(stripslashes(trim($out)), ENT_QUOTES,'UTF-8',true);     // Trim the variable, strip all slashes, and encode it
            
        
}
        
        return 
$out;
    }
?>

[#21] Anonymous [2009-09-18 10:16:01]

This may seem obvious, but it caused me some frustration. If you try and use htmlspecialchars with the $charset argument set and the string you run it on is not actually the same charset you specify, you get any empty string returned without any notice/warning/error.

<?php

$ok_utf8 
"A valid UTF-8 string";
$bad_utf8 "An invalid UTF-8 string";

var_dump(htmlspecialchars($bad_utf8ENT_NOQUOTES'UTF-8'));  // string(0) ""

var_dump(htmlspecialchars($ok_utf8ENT_NOQUOTES'UTF-8'));  // string(20) "A valid UTF-8 string"

?>


So make sure your charsets are consistent

<?php

$bad_utf8 
"An invalid UTF-8 string";

// make sure it's really UTF-8
$bad_utf8 mb_convert_encoding($bad_utf8'UTF-8'mb_detect_encoding($bad_utf8));

var_dump(htmlspecialchars($bad_utf8ENT_NOQUOTES'UTF-8'));  // string(23) "An invalid UTF-8 string" 

?>


I had this problem because a Mac user was submitting posts copy/pasted from a program and it contained weird chars in it.

[#22] Anonymous [2009-09-16 21:43:26]

Just a few notes on how one can use htmlspecialchars() and htmlentities() to filter user input on forms for later display and/or database storage... 

1. Use htmlspecialchars() to filter text input values for html input tags.  i.e.,

echo '<input name=userdata type=text value="'.htmlspecialchars($data).'" />';

 
2. Use htmlentities() to filter the same data values for most other kinds of html tags, i.e.,

echo '<p>'.htmlentities($data).'</p>';

3. Use your database escape string function to filter the data for database updates & insertions, for instance, using postgresql, 

pg_query($connection,"UPDATE datatable SET datavalue='".pg_escape_string($data)."'");
 

This strategy seems to work well and consistently, without restricting anything the user might like to type and display, while still providing a good deal of protection against a wide variety of html and database escape sequence injections, which might otherwise be introduced through deliberate and/or accidental input of such character sequences by users submitting their input data via html forms.

[#23] chuck at N0SPAM1command dot com [2009-08-12 07:06:58]

NOTE:
I made an error in my last post.

The last 3 lines should have read
<?php

...

$text get_page($url);
--------^^^^^^^^
$new htmlspecialchars($textENT_QUOTES); // here is the magic :)

    
echo '<pre>' .$new'</pre>';

?>


OOPS!

[#24] hm2k at php.net [2009-06-22 10:02:28]

<?php


function htmlspecialchars_deep($mixed$quote_style ENT_QUOTES$charset 'UTF-8')
{
    if (
is_array($mixed)) {
        foreach(
$mixed as $key => $value) {
            
$mixed[$key] = htmlspecialchars_deep($value$quote_style$charset);
        }
    } elseif (
is_string($mixed)) {
        
$mixed htmlspecialchars(htmlspecialchars_decode($mixed$quote_style), $quote_style$charset);
    }
    return 
$mixed;
}
?>

[#25] hello at haroonahmad dot co dot uk [2009-03-23 13:56:04]

a common confusion among beginner is that what is the difference between htmlentities() and htmlspecialchars() really, because the manual examples are converting angular brackets for both.

well, htmlentities() will ALSO look for other language characters in the string e.g German, French or Italian etc. So if you think your attacker can use some foreign language characters for a XSS attack in URL etc then use htmlentities() instead of htmlspecialchars().

I hope it helps, 

Haroon Ahmad

[#26] Kenneth Kin Lum [2008-10-08 18:45:17]

if your goal is just to protect your page from Cross Site Scripting (XSS) attack, or just to show HTML tags on a web page (showing <body> on the page, for example), then using htmlspecialchars() is good enough and better than using htmlentities().  A minor point is htmlspecialchars() is faster than htmlentities().  A more important point is, when we use  htmlspecialchars($s) in our code, it is automatically compatible with UTF-8 string.  Otherwise, if we use htmlentities($s), and there happens to be foreign characters in the string $s in UTF-8 encoding, then htmlentities() is going to mess it up, as it modifies the byte 0x80 to 0xFF in the string to entities like &eacute;.  (unless you specifically provide a second argument and a third argument to htmlentities(), with the third argument being "UTF-8").

The reason htmlspecialchars($s) already works with UTF-8 string is that, it changes bytes that are in the range 0x00 to 0x7F to &lt; etc, while leaving bytes in the range 0x80 to 0xFF unchanged.  We may wonder whether htmlspecialchars() may accidentally change any byte in a 2 to 4 byte UTF-8 character to &lt; etc.  The answer is, it won't.  When a UTF-8 character is 2 to 4 bytes long, all the bytes in this character is in the 0x80 to 0xFF range. None can be in the 0x00 to 0x7F range.  When a UTF-8 character is 1 byte long, it is just the same as ASCII, which is 7 bit, from 0x00 to 0x7F.  As a result, when a UTF-8 character is 1 byte long, htmlspecialchars($s) will do its job, and when the UTF-8 character is 2 to 4 bytes long, htmlspecialchars($s) will just pass those bytes unchanged.  So htmlspecialchars($s) will do the same job no matter whether $s is in ASCII, ISO-8859-1 (Latin-1), or UTF-8.

[#27] brendel at krumedia dot de [2008-05-15 10:28:26]

I know some people posted similar functions but may be you are looking for this version:

function jschars($str)
{
$str = mb_ereg_replace("\\\\", "\\\\", $str);
$str = mb_ereg_replace("\"", "\\\"", $str);
$str = mb_ereg_replace("'", "\\'", $str);
$str = mb_ereg_replace("\r\n", "\\n", $str);
$str = mb_ereg_replace("\r", "\\n", $str);
$str = mb_ereg_replace("\n", "\\n", $str);
$str = mb_ereg_replace("\t", "\\t", $str);
$str = mb_ereg_replace("<", "\\x3C", $str); // for inclusion in HTML
$str = mb_ereg_replace(">", "\\x3E", $str);
return $str;
}

if you use smarty your code may look like:

<a onclick="alert('{$text|jschars|htmlchars}');return false;">Test</a>

(Yes, we have the shortcur htmlchars instead of htmlspecialchars, so we are able to tell the encoding e.g. UTF-8 or ISO-8859-1 to htmlspecialchars)

[#28] php dot net at orakio dot net [2008-04-10 11:26:33]

I was recently exploring some code when I saw this being used to make data safe for "SQL".

This function should not be used to make data SQL safe (although to prevent phishing it is perfectly good).

Here is an example of how NOT to use this function:

<?php
$username 
htmlspecialchars(trim("$_POST[username]"));

$uniqueuser $realm_db->query("SELECT `login` FROM `accounts` WHERE `login` = '$username'");
?>


(Only other check on $_POST['username'] is to make sure it isn't empty which it is after trim on a white space only name)

The problem here is that it is left to default which allows single quote marks which are used in the sql query. Turning on magic quotes might fix it but you should not rely on magic quotes, in fact you should never use it and fix the code instead. There are also problems with \ not being escaped. Even if magic quotes were used there would be the problem of allowing usernames longer than the limit and having some really weird usernames given they are to be used outside of html, this just provide a front end for registering to another system using mysql. Of course using it on the output wouldn;t cause that problem.

Another way to make something of a fix would be to use ENT_QUOTE or do:

<?php
$uniqueuser 
$realm_db->query('SELECT `login` FROM `accounts` WHERE `login` = "'.$username.'";');
?>


Eitherway none of these solutions are good practice and are not entirely unflawed. This function should simply never be used in such a fashion.

I hope this will prevent newbies using this function incorrectly (as they apparently do).

[#29] ish1301 at gmail doooot com [2007-11-20 02:56:59]

used this function for making a variable javascript compatible

<?php
function jsspecialchars$string '') {
    
$string preg_replace("/\r*\n/","\\n",$string);
    
$string preg_replace("/\//","\\\/",$string);
    
$string preg_replace("/\"/","\\\"",$string);
    
$string preg_replace("/'/"," ",$string);
    return 
$string;
}
?>

hope this may help those embedding php in javascripts

[#30] solar-energy [2007-06-16 03:21:40]

also see function "urlencode()", useful for passing text with ampersand and other special chars through url

(i.e. the text is encoded as if sent from form using GET method)

e.g.

<?php
echo "<a href='foo.php?text=".urlencode("foo?&bar!")."'>link</a>";
?>


produces

<a href='foo.php?text=foo%3F%26bar%21'>link</a>

and if the link is followed, the $_GET["text"] in foo.php will contain "foo?&bar!"

[#31] terminatorul at gmail dot com [2007-04-27 10:04:40]

To html-encode Unicode characters that may not be part of your document character set (given in the META tag of your page), and so can not be output directly into your document source, you need to use mb_encode_numericentity(). Pay attention to it's conversion map argument.

[#32] frank at codedor dot be [2007-01-16 13:25:08]

If you seem to have a problem with rendering dynamic RSS files from a database - try using htmlspecialchars() or htmlentities() on the text you are rendering. 

Since XML and RSS is very strict about what is allowed inside nodes, you need to make sure everything is "A-OK" according to XML standards ...

Especially if the database you're pulling data from is fi. Latin-Swedish encoding, which seems to be the standard setting for MySQL databases.

[#33] richard at mf2fm dot com [2006-03-03 01:06:20]

I had a script which detected swearing and wanted to make sure that words such as 'f &uuml; c k' didn't slip through the system.

After using htmlentities(), the following line converts most extended alphabet characters back to the standard alphabet so you can spot such problems..

$text=eregi_replace("&([a-z])[a-z0-9]{3,};", "\\\\1", $text);

This changes, for example, '&uuml;' into 'u' and '&szlig' into 's'.  Sadly it also converts '&pound;' and '&para;' into 'p' so it's not perfect but does solve a lot of the problems

[#34] mikiwoz at yahoo dot co dot uk [2005-10-06 14:40:00]

I am not sure, maybe I'm missing something, but I have found something interesting:
I've been working on a project, where I had to use htmlspecialchars (for opbvious reasons). I olso needed to de-code the encoded string. What I have done was almost a copy and paste from php.net:
$trans=get_html_translation_table(HTML_SPECIALCHARS, ENT_QUOTES);
$trans=array_flip($trans);
$string=strtr($encoded, $trans);
(it looked a bit different in my code, but the idea is clear)
I couldn't get the apostrophe sign de-coded, and I needed it for the <A> tags. After an hour or so of debuging, I decided do print_r($trans). What I got was:
...
[&#39;] => '
...
BUT the apostrophe was encoded to $#039; -> note the zero.
I don't suppose it's a bug, but it definetely IS a potential pitfall, watch out for this one.

[#35] Luiz Miguel Axcar (lmaxcar at yahoo dot com dot br) [2005-09-01 06:16:13]

Hello,

If you are getting trouble to SGDB write/read HTML data, try to use this:

<?php

//from html_entity_decode() manual page
function unhtmlentities ($string) {
   
$trans_tbl =get_html_translation_table (HTML_ENTITIES );
   
$trans_tbl =array_flip ($trans_tbl );
   return 
strtr ($string ,$trans_tbl );
}

//read from db
$content stripslashes (htmlspecialchars ($field['content']));

//write to db
$content unhtmlentities (addslashes (trim ($_POST['content'])));

//make sure result of function get_magic_quotes_gpc () == 0, you can get strange slashes in your content adding slashes twice

//better to do this using addslashes
$content = (! get_magic_quotes_gpc ()) ? addslashes ($content) : $content;

?>

[#36] urbanheroes {at} gmail {dot} com [2005-04-30 11:32:29]

In response to the note made by Alexander Nofftz on October 2004, &#39; is used instead of &apos; because IE unfortunately seems to have trouble with the latter.

[#37] took [2005-04-23 09:14:51]

[#38] [2005-03-11 04:22:26]

function htmlspecialchars_array($arr = array()) {
   $rs =  array();
   while(list($key,$val) = each($arr)) {
       if(is_array($val)) {
           $rs[$key] = htmlspecialchars_array($val);
       }
       else {
           $rs[$key] = htmlspecialchars($val, ENT_QUOTES);
       }    
   }
   return $rs;
}

[#39] zolinak at zoli dot szathmari dot hu [2004-12-14 04:46:54]

A sample function, if anybody want to turn html entities (and special characters) back to simple. (eg: "&egrave;", "<" etc)

function html2specialchars($str){
$trans_table = array_flip(get_html_translation_table(HTML_ENTITIES));
return strtr($str, $trans_table);
}

[#40] thelatesundayshow.com @ nathan (flip it) [2004-09-02 11:51:55]

heres a version of the recursive escape function that takes the array byref rather than byval so saves some resources in case of big arrays

function recurse_array_HTML_safe(&$arr) {
foreach ($arr as $key => $val)
if (is_array($val))
recurse_array_HTML_safe($arr[$key]);
else
$arr[$key] = htmlspecialchars($val, ENT_QUOTES);
}

[#41] moc.xnoitadnuof@310symerej [2004-04-21 04:04:45]

Here are some usefull functions.
They will apply || decode, htmlspecialchars || htmlentities recursivly to arrays() || to regular $variables. They also protect agains "double encoding".

<?PHP
function htmlspecialchars_or$mixed$quote_style ENT_QUOTES ){
    return 
is_array($mixed) ? array_map('htmlspecialchars_or',$mixedarray_fill(0,count($mixed),$quote_style)) : htmlspecialchars(htmlspecialchars_decode($mixed$quote_style ),$quote_style);
}

function 
htmlspecialchars_decode$mixed$quote_style ENT_QUOTES ) {
    if(
is_array($mixed)){
      return 
array_map('htmlspecialchars_decode',$mixedarray_fill(0,count($mixed),$quote_style));
  }
  
$trans_table get_html_translation_tableHTML_SPECIALCHARS$quote_style );
    if( 
$trans_table["'"] != '&#039;' ) { # some versions of PHP match single quotes to &#39;
        
$trans_table["'"] = '&#039;';
    }
    return (
strtr($mixedarray_flip($trans_table)));
}

function 
htmlentities_or($mixed$quote_style ENT_QUOTES){
    return 
is_array($mixed) ? array_map('htmlentities_or',$mixedarray_fill(0,count($mixed),$quote_style)) : htmlentities(htmlentities_decode($mixed$quote_style ),$quote_style);
}

function 
htmlentities_decode$mixed$quote_style ENT_QUOTES ) {
  if(
is_array($mixed)){
      return 
array_map('htmlentities_decode',$mixedarray_fill(0,count($mixed),$quote_style));
  }
    
$trans_table get_html_translation_table(HTML_ENTITIES$quote_style );
    if( 
$trans_table["'"] != '&#039;' ) { # some versions of PHP match single quotes to &#39;
        
$trans_table["'"] = '&#039;';
    }
    return (
strtr($mixedarray_flip($trans_table)));
}
?>


These functions are an addition to an earlier post. I would like to give the person some credit but I do not know who it was.

<?php  ;llnu=u!eJq dHd?>

[#42] _____ at luukku dot com [2002-09-14 14:21:44]

People, don't use ereg_replace for the most simple string replacing operations (replacing constant string with another).
Use str_replace.

[#43] joseph at nextique dot com [2002-02-20 01:21:43]

Here is a handy function to htmlalize an array (or scalar) before you hand it off to xml.

function htmlspecialchars_array($arr = array()) {
$rs =  array();
while(list($key,$val) = each($arr)) {
if(is_array($val)) {
$rs[$key] = htmlspecialchars_array($val);
}
else {
$rs[$key] = htmlspecialchars($val, ENT_QUOTES);
}
}
return $rs;
}

[#44] [2001-07-14 23:18:54]

If your sending data from one form to another, the data in the textareas and text inputs may need to have htmlspecialchars("form data", ENT_QUOTES) applied, assuming you will ever have quotes or less-than signs or any of those special characters.  Using htmlspecialchars will make the text show up properly in the second form.  The changes are automatically undone whenever the form data is submitted. It does seem a little strange, but it works and my headache is now starting to go away.

AZ

[#45] ryan at ryano dot net [2001-06-29 03:06:10]

Actually, if you're using >= 4.0.5, this should theoretically be quicker (less overhead anyway):

$text = str_replace(array("&gt;", "&lt;", "&quot;", "&amp;"), array(">", "<", "\"", "&"), $text);

上一篇: 下一篇: