Code Examples / Notes » phpentities

roland dot swingler

You don't need these custom conversion functions.
This function will only work for the first 128 ascii characters if no character set is specified. If you specify the character set in an http header:
<?php
header('Content-type: text/html; charset=utf-8');
htmlentities('string to be encoded', ENT_QUOTES, 'utf-8');
?>
then it will work for all html entities. It outputs the named rather than the numerical entities, but html_entity_decode() will decode both numerical and textual entities (it will treat &#8364; and &euro; as the same).
BTW, if you are dealing with form submitted data, it is a good idea to add the accept-charset="character set" attribute
to the form as well.

kumar

without heavy scientific analysis, this seems to work as a quick fix to making text originating from a Microsoft Word document display as HTML:
function DoHTMLEntities ($string)
{
$trans_tbl = get_html_translation_table (HTML_ENTITIES);

Unfortunately, there are differences between what is shown in the preview window and what is shown on the web site; thus, the extreme number of backslashes in my former note.
The corrected note:
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 ...

webmaster

To replace any characters in a string that could be 'dangerous' to put in an HTML/XML file with their numeric entities (e.g. &#233 for é [e acute]), you can use the following function:
function htmlnumericentities($str){
return preg_replace('/[^!-%\x27-;=?-~ ]/e', '"&#".ord("$0").chr(59)', $str);
};//EoFn htmlnumericentities
To change any normal entities (e.g. &euro;) to numerical entities call:
$str = htmlnumericalentities(html_entity_decode($str));

attila

Thx for that function, pinkpanther at swissonline dot ch, though the number of digits after the '#' can be 4, not 3.
I bumped into this when struggeling with the euro sign (&#8364;).
function htmlentities2( $myHTML)
{
$translation_table = get_html_translation_table( HTML_ENTITIES, ENT_QUOTES);
$translation_table[chr( 38)] = '&';
return preg_replace( "/&(?![A-Za-z]{0,4}\w{2,3};|#[0-9]{2,4};)/", "&amp;" , strtr( $myHTML, $translation_table));
}

stewey

This version of macRomanToIso (originally posted by: marcus at synchromedia dot co dot uk) offers a couple of improvements. First, it removes the extra slashes '\' that broke the original function. Second, it adds four quote characters not supported in ISO 8859-1. These are the left double quote, right double quote, left single quote and right single quote.
Be sure to remove the line breaks from the two strings going into strtr or this function will not work properly.
Be careful what text you apply this to. If you apply it to ISO 8859-1 encoded text it will likely wreak havoc. I'll save you some trouble with this bit of advice: don't bother trying to detect what charset a certain text file is using, it can't be done reliably. Instead, consider making assumptions based upon the HTTP_USER_AGENT, or prompting the user to specify the character encoding used (perhaps both).
<?php
/**
* Converts MAC OS ROMAN encoded strings to the ISO 8859-1 charset.
*
* @param string the string to convert.
* @return string the converted string.
*/
function macRomanToIso($string)
{
return strtr($string,
"\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b
\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97
\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa1\xa4\xa6\xa7
\xa8\xab\xac\xae\xaf\xb4\xbb\xbc\xbe\xbf\xc0\xc1
\xc2\xc7\xc8\xca\xcb\xcc\xd6\xd8\xdb\xe1\xe5\xe6
\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf1\xf2\xf3
\xf4\xf8\xfc\xd2\xd3\xd4\xd5",
"\xc4\xc5\xc7\xc9\xd1\xd6\xdc\xe1\xe0\xe2\xe4\xe3
\xe5\xe7\xe9\xe8\xea\xeb\xed\xec\xee\xef\xf1\xf3
\xf2\xf4\xf6\xf5\xfa\xf9\xfb\xfc\xb0\xa7\xb6\xdf\xae
\xb4\xa8\xc6\xd8\xa5\xaa\xba\xe6\xf8\xbf\xa1\xac
\xab\xbb\xa0\xc0\xc3\xf7\xff\xa4\xb7\xc2\xca\xc1
\xcb\xc8\xcd\xce\xcf\xcc\xd3\xd4\xd2\xda\xdb\xd9
\xaf\xb8\x22\x22\x27\x27");
}
?>

This is a simple script that I'm using to encode and decode values from a form. Save it with the name that you wish.
<?php
/* When you call anyone of the two functions, set the $_str
variable to the string that you want to encode or decode */
/* This function encodes the string.
You can safetly use this function to save its result in a
database. It eliminates any space in the beginning ou end
of the string, HTML and PHP tags, and encode any special
char to the usual HTML entities (&[...];), eliminating the
possibility of bugs in inserting data on a table */
function encodeText($_str) {
$_str = strip_tags($_str);
$_str = trim($_str);
$_str = htmlentities($_str);
$_str = str_replace("\r\n", "#BR#", $_str);
return($_str);
}
/* This function decodes the string.
If you are showing the string in the body of a page, you
can set the $_form variable to "false", and the function will
use the "BR" tag to the new lines. But, if you need to show
the string in a textarea, text or other input types of a form
set the $_form variable to "true", then the function will use
the "\r\n" to the new lines */
function decodeText($_str, $_form) {
$trans_tbl = get_html_translation_table (HTML_ENTITIES);
$trans_tbl = array_flip ($trans_tbl);
$_str = strtr($_str, $trans_tbl);
if ($_form) {
$_nl = "\r\n";
} else {
$_nl = "";
}
$_str = str_replace("#BR#", "$_nl", $_str);
return($_str);
}
?>

penfield888

This is a followup to the older note by mirrorball_girl (5 Jan 2003) for those who may follow.
Rather than making an exception for the en-dash (#150) and translating it to a hyphen, you could use the &#8211; unicode en-dash entity (assuming that you are serving up your pages as UTF-8 or some such encoding.
Also, the whole thing can be done better with mb_detect_order, mb_detect_encoding and mb_convert_encoding if all you want to do is serve up a web page (if you need to convert to pure ASCII, that's another issue). You need to have multi-byte support enabled on your PHP server.
Basically, the problem is with older MS programs that use Windows-1252 for their encoding, so all you really need to do is
- detect for Win-1252
- if present, convert to UTF-8
- serve up your pages as UTF-8
See the manual on Multibyte String Functions for more information.

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".

sr

There's no sane reason to use htmlentities() instead of htmlspecialchars(). As long as you specify the charset of a page with a Content-Type meta in the head of a page (which you should ALWAYS do in the first place), escaping all characters is completely pointless and will only grow the size of your page. Only the special HTML characters (<, >, &, etc.) need to be escaped, which is exactly what htmlspecialchars() does.

duke

The function xmlentities works great, but there can be up to 5 numbers after the &# string. See this for example:
&#12505;&#12540;&#12473;&#12508;&#12540;
&#12523;&#12473;&#12479;&#12540;&#12474;2
This is a valid (wrapped) japanese string. To successfully use it with xmlentities, you need to replace
return preg_replace("/&(?![A-Za-z]{0,4}\w{2,3};|#[0-9]{2,3};)/","&#38;" , strtr($string, $trans));
with
return preg_replace("/&(?![A-Za-z]{0,4}\w{2,3};|#[0-9]{2,5};)/","&#38;" , strtr($string, $trans));
(3 to 5).
Duke

Regarding the two great function posted by pinkpather and webwurst; one to encode xml entities, the other to encode only the entities of a string not already encoded. I've combined these two. And IMHO made a small improvement by making the translation table static:
<?php
function xmlentities($string, $quote_style=ENT_QUOTES)
{
static $trans;
if (!isset($trans)) {
$trans = get_html_translation_table(HTML_ENTITIES, $quote_style);
foreach ($trans as $key => $value)
$trans[$key] = '&#'.ord($key).';';
// dont translate the '&' in case it is part of &xxx;
$trans[chr(38)] = '&';
}
// after the initial translation, _do_ map standalone '&' into '&#38;'
return preg_replace("/&(?![A-Za-z]{0,4}\w{2,3};|#[0-9]{2,3};)/","&#38;" , strtr($string, $trans));
}
?>
Here's the snippet of code I'm testing with:
<?php
echo "

Please, don't use htmlentities to avoid XSS! Htmlspecialchars is enough!
If you don't specify the encoding, Latin1 will be used, so there is a problem if someone wants to use your software in a non-English environment.

halocastle

Okay, so maybe this SHOULD be posted under Urlencode, but there's more talk of foiling XSS attacks here than there, soâ¦
Be VERY careful validating submitted data not to miss something. By that I mean EVERYTHING passed in the $_POST array, including keys (the names of the form fields themselves) is susceptible to XSS attacks. Any hack can add whatever they want to your form and submit it to your script:
<input type="hidden" name="<script>alert('â¦the form_fields_NAMES can get you, too!');</script>" value="We all validate form_field_VALUES, butâ¦">
Step one of course is to adopt a sensible naming convention for your form fields, to whit: name="always_lower_case" (underscores do NOT get encoded because they are valid URL characters). So, you should never find a "%" in one of your form field NAMES. Here's what I do:
foreach($_POST as $key => $val) {
// scrubbing the field NAME...
if(preg_match('/%/', urlencode($key)*)) die('FATAL::XSS hack attempt detected. Your IP has been logged.');
// okay, got here, now scrubbing the field VALUE...
[ scrub $val here by using htmlentities or a custom replacement function ];
...;
}
* %3Cscript%3Ealert%28%27%85the+form_fields_NAMES+can+get+you%...
P.S. Yes, remove the asterisk!

bassie :

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;.

eion

many people below talk about using
<?php
mb_convert_encode($s,'HTML-ENTITIES','UTF-8');
?>
to convert non-ascii code into html-readable stuff. Due to my webserver being out of my control, I was unable to set the database character set, and whenever PHP made a copy of my $s variable that it had pulled out of the database, it would convert it to nasty latin1 automatically and not leave it in it's beautiful UTF-8 glory.
So [insert korean characters here] turned into ?????.
I found myself needing to pass by reference (which of course is deprecated/nonexistent in recent versions of PHP)
so instead of
<?php
mb_convert_encode(&$s,'HTML-ENTITIES','UTF-8');
?>
which worked perfectly until I upgraded, so I had to use
<?php
call_user_func_array('mb_convert_encoding', array(&$s,'HTML-ENTITIES','UTF-8'));
?>
Hope it helps someone else out

root

It may come to you as a surprise, but i've noticed that in Firefox (as of 1.0), the text presented in "View selection source" is not the same as "View page source"; Il you want to see the REAL result of htmlentities() you should look at the entire source;
almost become mad before i discover this :)

justin

In response to soapergem at gmail dot com 10-May-2006 02:14 - If any of you are attempting to use this or anything else to foil XSS attacks, test this or any other function out _first_ before you put it into a development environment. To test out if you think your code will pass, just visit http://www.gnucitizen.org/xssdb/application.htm for some potential attacks. After doing this myself it is apparent that just simply using htmlspecialchars is sufficient.

If you're looking to provide bare bones protection to email addresses posted to the web try this:
###
$string = 'arjini@mac.com';
for($i=0;$i<strlen($string);++$i){
$n = rand(0,1);
if($n)
$finished.='&#x'.sprintf("%X",ord($string{$i})).';';
else
$finished.='&#'.ord($string{$i}).';';
}
echo $finished;
###
This randomly encodes a mix of hex and oridinary HTML entities for every character in the address. Note that a decoding mechanism for this could probably be written just as easily, so eventually the bots will be able to cut through this like butter, but for now, it seems like most harvesters are only looking for non-hex html entities.

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 &;
& = %26
' = %27
<?php
function flashentities($string){
return str_replace(array("&","'"),array("%26","%27"),$string);
}
?>
Those are the two that concerned me. YMMV.

q dot rendeiro

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;

I've been dissatisfied with all the solutions I've yet seen for converting text into html entities, which all seem to have some drawback or another. So I wrote my own, borrowing heavily from other code posted on this site.http://www.prolifique.com/entities.php.txt
makeSafeEntities() should take any text, convert it from the specified charset into UTF-8, then replace all inappropriate characters with appropriate (and legal) character entities, returning generic ISO-8859 HTML text. Should NOT reconvert any entities already in the text.
makeAllEntities() does the same, but converts the entire string to entities. Useful for obscuring email addresses (in a lame but nonetheless somewhat effective way).
Suggestions for improvement welcome!

I use this function to convert imput from MS Word into html (ascii) compatible output. I hope it would work also for you.
I have enabled magic_quotes on my server so maybe you won't need stripslashes and addslashes.
I've also noticed that Opera 8.51 browses behaves somehow different from IE 6 and Firefox 1.5. I haven't check this functions with other browsers.
<?php
function convert_word_to_ascii($string)
{
$string = stripslashes($string);

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: Ã¢ï¿½Â¢
If you need the trademark symbol, use:
htmlentities( $html, ENT_QUOTES, "UTF-8" );

I found in a previous not the function for encoding the input... which worked great, but it also encoded the &nbsp and that was being automatically added in my POST, so I created and Output function to go with it that worked for me:
function VerbatimInput($String)
{
$Output = mysql_escape_string(htmlentities(addslashes($String)));
return $Output;
}
function VerbatimOutput($Input)
{
$Output = str_replace("&lt;br /&gt;", "", "$Input");
$Output = str_replace("&amp;nbsp;", "&nbsp", "$Output");
return $Output;
}

Hi, from some machines (Mac for example), when submiting a form characters with accents makes the wrong encode.
For example: Ã­ -> &Atilde;&shy instead of &iacute;

soapergem

Here's another version of that "allhtmlentities" function that an anonymous user posted in the last comment, only this one would be significantly more efficient. Again, this would convert anything that has an ASCII value higher than 127.
<?php
function allhtmlentities($string)
{
return preg_replace('/[^\x00-\x7F]/e', '"&#".ord("$0").";"', $string);
}
?>

guillaume beaulieu

Here's a simple script to transform filename with accented character in it into much more usable unaccented character for a restrictive filesystem.
$string = htmlentities($stringToModify);
/* Take the first letter of the entity (if you got filename with ([<>] in it the result will probably remain lookable*/
$string = preg_replace("/\&(.)[^;]*;/", "\\1", $string);
/* Change the whitespace into _*/
$string = preg_replace("/[ ]/", "_", $string);
/* Dance ! */
print $string;

Convert any language (Japanese, French, Chinese, Russian, etc...) to unicode HTML entities like &#XXXX;
In one line!
$new=mb_convert_encoding($s,"HTML-ENTITIES","auto");
where $s is your string (may be a FORM submitted one).
Enjoy~

allthough it is much more complex than this, please note that if you're using xhtml the character encoding you specify within your document is "associated" with the encoding used by php.
e.g.:
<?xml version="1.0" encoding="..."?>
may also assess the manner form data is submitted. as it is prepared before sending it does not matter whether it is post or get.
to give you something stoutly have a look at mozilla firefox (0.9.3) where submitting form data...
<?xml version="1.0" encoding="ISO-8859-1"?>
...converts ä to %E4
<?xml version="1.0" encoding="UTF-8"?>
...converts ä to %C3%A4
or at internet explorer (6.0) where encoding is ignored while submit but default values of an input field let you recognize the same thing.
this may confuse you getting the desired &auml; afterwards.

A quick revision to my last comment. For some reason, leaving the control characters in the safe range seemed to screw things up. So instead, using this function will do what everybody else here is trying to do, but it will do so in a single line:
<?php
$text = preg_replace('/[^\x09\x0A\x0D\x20-\x7F]/e', '"&#".ord($0).";"', $text);
?>

root nospam cyberdark.net

A little function that may help someone. Is useful where, FE, someone writes a text through a content management panel and is also able to put html (bolds, italics,...), so we don't want to convert html tags but all the rest. The code offers a few examples of extra entities.
function myhtmlentities($str) {

/*
15Jan05
Within <textarea>, Browsers auto render & display certain "HTML Entities" and "HTML Entity Codes" as characters:
&lt; shows as < -- &amp; shows as & -- etc.
Browsers also auto change any "HTML Entity Codes" entered in a <textarea> into the resultant display characters BEFORE UPLOADING. There's no way to change this, making it difficult to edit html in a <textarea>
"HTML Entity Codes" (ie, use of &#60 to represent "<", &#38 to represent "&" &#160 to represent "&nbsp;") can be used instead. Therefore, we need to "HTML-Entitize" the data for display, which changes the raw/displayed characters into their HTML Entity Code equivalents before being shown in a <textarea>.
how would I get a textarea to contain "&lt;" as a literal string of characters and not have it display a "<"
&amp;lt; is indeed the correct way of doing that. And if you wanted to display that, you'd need to use &amp;amp;lt;'. That's just how HTML entities work.
htmlspecialchars() is a subset of htmlentities()
the reverse (ie, changing html entity codes into displayed characters, is done w/ html_entity_decode()
google on ns_quotehtml and see http://aolserver.com/docs/tcl/ns_quotehtml.html
see also http://www.htmlhelp.com/reference/html40/entities/
*/