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($string, ENT_COMPAT,'ISO-8859-1', true);
echo htmlentities($string, ENT_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/htmlspecialchars
Почист и полокален преглед на PHP референцата, со задржана структура од PHP.net и подобра читливост за примери, секции и белешки.
htmlspecialchars
Референца за `function.htmlspecialchars.php` со подобрена типографија и навигација.
htmlspecialchars
(PHP 4, PHP 5, PHP 7, PHP 8)
htmlspecialchars — Претвори специјални HTML ентитети во знаци
= NULL
string
$string,int
$flags Претвори ги сите применливи знаци во HTML ентитети,?string
$encoding = null,bool
$double_encode = true): string
Претвори специјални знаци во HTML ентитети htmlentities() instead.
Одредени знаци имаат посебно значење во HTML и треба да бидат претставени со HTML ентитети ако треба да ги зачуваат своите значења. Оваа функција враќа стринг со направени овие конверзии. Ако барате сите влезни поднизи што имаат поврзани именувани ентитети да бидат преведени, користете htmlentities() Ако влезниот стринг предаден на оваа функција и конечниот документ ја делат истата кодна страница, оваа функција е доволна за подготовка на влез за вклучување во повеќето контексти на HTML документ. Ако, сепак, влезот може да претставува знаци што не се кодирани во кодната страница на конечниот документ и сакате да ги задржите тие знаци (како нумерички или именувани ентитети), и оваа функција и mb_encode_numericentity() instead.
| Извршени преводи | Знак |
|---|---|
& Замена |
& |
" (амперсанд) |
", освен ако ENT_NOQUOTES (двоен наводник) |
' е поставен |
' (единечен наводник) ENT_HTML401оператор за зголемување ' (единечен наводник)
ENT_XML1, ENT_XHTML or
ENT_HTML5(за
ENT_QUOTES (двоен наводник)
|
< ), но само кога |
< |
> (помалку од) |
> |
Параметри
string-
На string што се конвертира.
flags-
Ако сакате да декодирате наместо тоа (обратното), можете да го користите
ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401.Маска од еден или повеќе од следниве знаменца, кои специфицираат како да се постапува со наводници, невалидни низи на единици и типот на документот што се користи. Стандардно е flagsconstantsДостапно = NULL ENT_COMPATИме на константа ENT_QUOTESЌе ги претвори двојните наводници и ќе ги остави единечните наводници недопрени. ENT_NOQUOTESЌе ги претвори и двојните и единечните наводници. ENT_IGNOREЌе ги остави и двојните и единечните наводници непроменети. Тивко отфрлете ги невалидните низи на единици наместо да враќате празен стринг. Користењето на ова знаменце не се препорачува бидејќи. ENT_SUBSTITUTE(поголемо од) ENT_DISALLOWEDЗамени невалидни секвенци на единици со Unicode знак за замена U+FFFD (UTF-8) или � (инаку) наместо да враќа празен стринг. ENT_HTML401Замени ги невалидните точки на код за дадениот тип на документ со Unicode Replacement Character U+FFFD (UTF-8) или &#FFFD; (инаку) наместо да ги остави како што се. Ова може да биде корисно, на пример, за да се обезбеди исправност на XML документи со вградена надворешна содржина. ENT_XML1Ракувај со кодот како HTML 4.01. ENT_XHTMLРакувај со кодот како XML 1.0. ENT_HTML5Битови маски од една или повеќе од следниве знаменца, кои специфицираат како да се постапува со наводници и кој тип на документ да се користи. Стандардно е encoding-
Ракувајте со кодот како HTML 5.
Изборен аргумент што ја дефинира кодировната шема што се користи при конвертирање на знаци.
encodingАко е изоставен, default_charset опцијата за конфигурација.по дифолт се зема вредноста на default_charset Иако овој аргумент е технички изборен, силно се препорачува да ја наведете точната вредност за вашиот код ако
Замени невалидни точки на код за дадениот тип на документ со Unicode знак за замена U+FFFD (UTF-8) или � (инаку) наместо да ги остави како што се. Ова може да биде корисно, на пример, за да се обезбеди исправност на XML документи со вградена надворешна содржина.
ISO-8859-1,ISO-8859-15,UTF-8,cp866,cp1251,cp1252Препорачаниот начин за избегнување на SQL инјекција е со врзување на сите податоци преку подготвени изрази. Користењето на параметризирани прашања не е доволно за целосно избегнување на SQL инјекција, но тоа е најлесниот и најбезбедниот начин за обезбедување влез во SQL изразите. Сите динамични литерали на податоци воKOI8-RЗа целите на оваа функција, кодовитеstringсе ефективно еквивалентни, под услов htmlspecialchars() зафаќаат исти позиции во сите овие кодирања.опцијата за конфигурација може да биде погрешно поставена за дадениот влез.
Поддржани се следните множества на знаци: Поддржани множества на знаци Алијаси = NULL ISO-8859-1 ISO8859-1 Множество знаци ISO-8859-5 ISO8859-5 Западно-европски, Latin-1. ISO-8859-15 ISO8859-15 Малубројно кирилично множество знаци (латиница/кирилица). UTF-8 Западно-европски, Latin-9. Додава знак за евро, француски и фински букви што недостасуваат во Latin-1 (ISO-8859-1). cp866 ASCII компатибилен повеќебајтен 8-битен Unicode. ibm866, 866 cp1251 DOS-специфично кирилично множество знаци. Windows-1251, win-1251, 1251 cp1252 Windows-специфично кирилично множество знаци. Windows-1252, 1252 KOI8-R Windows специфично множество знаци за Западна Европа. Russian. BIG5 950 Традиционален кинески, главно се користи во Тајван. GB2312 936 Поедноставен кинески, национален стандарден сет на знаци. BIG5-HKSCS Big5 со хонгконшки екстензии, традиционален кинески. Shift_JIS Постапувај со кодот како HTML 5. Јапонски EUC-JP SJIS, SJIS-win, cp932, 932 Јапонски MacRoman Комплет за кодирање што се користеше од Mac OS. ''Празен стринг активира детекција од скриптно кодирање (Zend мултибајт), default_charset и тековниот локал (види nl_langinfo() and setlocale()), по овој редослед. Не се препорачува. Забелешка: Други комплети за кодирање не се препознаваат. Ќе се користи стандардното кодирање и ќе се емитува предупредување.
double_encode-
Кога
double_encodeе исклучено PHP нема да кодира постоечки html ентитети, стандардно е да се претвори сè.
Вратени вредности
Конвертираниот string.
Ако влезот string содржи неважечка секвенца на кодни единици во рамките на дадената encoding ќе се врати празен стринг, освен ако не се поставени знаменцата ENT_IGNORE or
ENT_SUBSTITUTE се промени од
Дневник на промени
| Верзија | = NULL |
|---|---|
| 8.1.0 |
flags Пример #2 Употреба на ENT_COMPAT to ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401.
|
Примери
Пример #1 htmlspecialchars() example
<?php
$new = htmlspecialchars("<a href='test'>Test</a>", ENT_QUOTES);
echo $new; // <a href='test'>Test</a>
?>Белешки
Забелешка:
Забележете дека оваа функција не преведува ништо надвор од она што е наведено погоре. За целосен превод на ентитети, видете htmlentities().
Забелешка:
Во случај на двосмислено
flagsвредност, важат следниве правила:
- Кога ниту едно од
ENT_COMPAT,ENT_QUOTES,ENT_NOQUOTESе присутно, стандардно еENT_NOQUOTES.- Кога повеќе од едно од
ENT_COMPAT,ENT_QUOTES,ENT_NOQUOTESе присутно,ENT_QUOTESго има највисокиот приоритет, проследено соENT_COMPAT.- Кога ниту едно од
ENT_HTML401,ENT_HTML5,ENT_XHTML,ENT_XML1е присутно, стандардно еENT_HTML401.- Кога повеќе од едно од
ENT_HTML401,ENT_HTML5,ENT_XHTML,ENT_XML1е присутно,ENT_HTML5го има највисокиот приоритет, проследено соENT_XHTML,ENT_XML1andENT_HTML401.- Кога повеќе од едно од
ENT_DISALLOWED,ENT_IGNORE,ENT_SUBSTITUTEсе присутни,ENT_IGNOREго има највисокиот приоритет, проследено соENT_SUBSTITUTE.
Види Исто така
- get_html_translation_table() - Враќа табела за превод што ја користат htmlspecialchars и htmlentities
- htmlspecialchars_decode() - Претвори специјални HTML ентитети назад во знаци
- strip_tags() - Отстрани HTML и PHP тагови од стринг
- htmlentities() ) туку ASCII код 160 (0xa0) во стандардното кодирање ISO 8859-1.
- nl2br() - Вметнува HTML прекини на редови пред сите нови редови во стринг
Белешки од корисници 18 белешки
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($string, REPLACE_FLAGS, CHARSET);
}
echo html("ñ"); // works
?>
You can do the same for htmlentities()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 <b>,
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("/"/", ""\"", $text);
$tags = "/<(\/|)(\w*)(\ |)(\w*)([\\\=]*)(?|(\")\""\"|)(?|(.*)?"(\")|)([\ ]?)(\/|)>/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 < 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...
I hope its helpfull!!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 é. (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 < 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 < 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.Because the documentation says
int $flags = ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401
you would think that ENT_HTML401 is important. But as the notes mention, ENT_HTML401 is the default if you don't specify the doc type. This is because ENT_HTML401 === 0. So
int $flags = ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401
is exactly equivalent to
int $flags = ENT_QUOTES | ENT_SUBSTITUTEAnother thing important to mention is that
htmlspecialchars(NULL)
returnes an empty string and not NULL!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.If you use htmlspecialchars() to escape any HTML attribute, make sure use double quote instead of single quote for the attribute.
For Example,
> Wrap with Single Quote
<?php
echo "<p title='" . htmlspecialchars("Hello\"s\'world") . "'">
// title will end up Hello"s\ and rest of the text after single quote will be cut off.
?>
> Wrap with Double quote :
<?php
echo '<p title="' . htmlspecialchars("Hello\"s\'world") . '"'>
// title will show up correctly as Hello"s'world
?>One MUST specify ENT_HTML5 in addition to double_encode=false to avoid double-encoding.
The reason is that contrary to the documentation, double_encode=false will NOT unconditionally and globally prevent double-encoding of ALL existing entities. Crucially, it will only skip double-encoding for THOSE character entities that are explicitly valid for the document type chosen!
Since ENT_HTML5 references the most expansive list of character entities, it is the only setting that will be most lenient with existing character entities.
<?php
declare(strict_types=1);
$text = 'ampersand(&), double quote("), single quote('), less than(<), greater than(>), numeric entities(&"'<>), HTML 5 entities(+,!$(ņ€)';
$result3 = htmlspecialchars( $text, ENT_NOQUOTES | ENT_SUBSTITUTE, 'UTF-8', /*double_encode*/false );
$result4 = htmlspecialchars( $text, ENT_NOQUOTES | ENT_XML1 | ENT_SUBSTITUTE, 'UTF-8', /*double_encode*/false );
$result5 = htmlspecialchars( $text, ENT_NOQUOTES | ENT_XHTML | ENT_SUBSTITUTE, 'UTF-8', /*double_encode*/false );
$result6 = htmlspecialchars( $text, ENT_NOQUOTES | ENT_HTML5 | ENT_SUBSTITUTE, 'UTF-8', /*double_encode*/false );
echo "<br />\r\nHTML 4.01:<br />\r\n", $result3,
"<br />\r\nXML 1:<br />\r\n", $result4,
"<br />\r\nXHTML:<br />\r\n", $result5,
"<br />\r\nHTML 5:<br />\r\n", $result6, "<br />\r\n";
?>
will produce:
HTML 4.01 (will NOT recognize single quote, but Euro):
ampersand(&), double quote("), single quote('), less than(<), greater than(>), numeric entities(&"'<>), HTML 5 entities(+,!$(ņ€)
XML 1 (WILL recognize single quote, but NOT Euro):
ampersand(&), double quote("), single quote('), less than(<), greater than(>), numeric entities(&"'<>), HTML 5 entities(+,!$(ņ€)
XHTML (recognizes single quote and Euro):
ampersand(&), double quote("), single quote('), less than(<), greater than(>), numeric entities(&"'<>), HTML 5 entities(+,!$(ņ€)
HTML 5 (recognizes "all" valid character entities):
ampersand(&), double quote("), single quote('), less than(<), greater than(>), numeric entities(&"'<>), HTML 5 entities(+,!$(ņ€)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.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_utf8, ENT_NOQUOTES, 'UTF-8')); // string(0) ""
var_dump(htmlspecialchars($ok_utf8, ENT_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_utf8, ENT_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.Actually, if you're using >= 4.0.5, this should theoretically be quicker (less overhead anyway):
$text = str_replace(array(">", "<", """, "&"), array(">", "<", "\"", "&"), $text);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: <b>Woermann<b>
echo htmlspecialchars('Wörmann') //Output: <b>Wörmann<b>
PHP=5.4
echo htmlspecialchars('<b>Woermann</b>') //Output: <b>Woermann<b>
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').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).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.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("<", ">"), array("<", ">"), htmlspecialchars($str, ENT_NOQUOTES, "UTF-8"));
}
?>People, don't use ereg_replace for the most simple string replacing operations (replacing constant string with another).
Use str_replace.Thanks Thomasvdbulk for your workaround, I would like to add a precision:
When the HTML contains a link tag without new line before the script doesn't work :/
Your 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);
?>
Works but this doesn't work:
<?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);
?>
So I add a little workaround at the beginning (before htmlspecialchars):
<?php
$text = preg_replace('/<a/', "\r\n<a", $text);
?>
I don't like that but I don't find other solution... :/