HTML_filter class
| From: | Maxim Vysotskiy | Date: | Tue, 23 Oct 2001 14:50:52 +0000 |
| Subject: | HTML_filter class | ||
| Groups: | php.pear.dev | ||
| Request: | Send a blank email to pear-dev+get-2364@lists.php.net to get a copy of this message | ||
Hello pear-dev pear-dev,
As I wrote here couple weeks before I'm working on filtering class for
HTML
Here goes first draft version for that with example of use
It can filter HTML string to escape "unsafe" tags with < >, and leave
safe tags untouched
There is possibility to filter attributes, leaving only safe
attributes
To add "safe" tags to class use
addTag($tagname[, $attr1name, [$attr2name ...]])
method, which accepts
safe tag name as first parameter, and any count of attribute names as
following parameters. So, if u pass only one parameter to that method,
then all attributes of that tag will be stripped. If u call this
method second time with same tagname - it will substitute previous
settings for that tag
to get a filtered string use
filter($stringtoparse)
method. It accepts a string, and then return filtered variant of it. If
u dont pass a parameter there, this method will return a filtered
variant of internal storage string, which is setup in constructor
HTML_filter($html);
That's pretty it
any input is welcome
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4: */
// +----------------------------------------------------------------------+
// | PHP version 4.0 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997, 1998, 1999, 2000, 2001 The PHP Group |
// +----------------------------------------------------------------------+
// | This source file is subject to version 2.0 of the PHP license, |
// | that is bundled with this package in the file LICENSE, and is |
// | available at through the world-wide-web at |
// | http://www.php.net/license/2_02.txt.
|
// | If you did not receive a copy of the PHP license and are unable to |
// | obtain it through the world-wide-web, please send a note to |
// | license@php.net so we can mail you a copy immediately. |
// +----------------------------------------------------------------------+
// | Author: Maxim Vysotskiy <maxy_v@mail.ru> |
// +----------------------------------------------------------------------+
//
// $Id$
/**
* Short description.
* Class for filtering an HTML text.
*
* Detail description
*
*
* @author Maxim Vysotskiy
* @version 0.1
* @copyright
* @since
* @access public
*/
class HTML_filter
{
/**
* Description
* @var
* @since 1.0
* @access private
*/
var $_storage = "";
/**
* Description
* @var
* @since 1.0
* @access private
*/
var $_tagsNA = array();
/**
* Description
* @var
* @since 1.0
* @access private
*/
var $_tagsWA = array();
/**
* Short description.
*
* Detail description
* @param
* @since 1.0
* @access private
* @return void
* @throws
*/
function HTML_filter($str='')
{
$this->_storage=$str;
} // end func
/**
* Short description.
*
* Detail description
* @param
* @since 1.0
* @access private
* @return void
* @throws
*/
function _addTag($tag)
{
$fnd=false;
reset ($this->_tagsNA);
while (list($key,$val) = each($this->_tagsNA)) {
if (strtoupper($val)==strtoupper($tag)) {
$fnd=true;
break;
}
}
if (!$fnd) {
array_push ($this->_tagsNA,$tag);
}
} // end func
/**
* Short description.
*
* Detail description
* @param
* @since 1.0
* @access private
* @return void
* @throws
*/
function removeTag($tag)
{
$fnd=false;
reset ($this->_tagsNA);
while (list($key,$val) = each($this->_tagsNA)) {
if (strtoupper($val)==strtoupper($tag)) {
$fnd=true;
break;
}
}
if ($fnd) {
unset($this->_tagsNA[$key]);
return true;
}
reset ($this->_tagsWA);
while (list($key,$val) = each($this->_tagsWA)) {
if (strtoupper($val[0])==strtoupper($tag)) {
$fnd=true;
break;
}
}
if ($fnd) {
unset($this->_tagsWA[$key]);
return true;
}
} // end func
/**
* Short description.
*
* Detail description
* @param
* @since 1.0
* @access private
* @return void
* @throws
*/
function addTag($tag)
{
if (func_num_args()==1) {
return $this->_addTag($tag);
}
reset ($this->_tagsWA);
while (list($key,$val) = each($this->_tagsWA)) {
if (strtoupper($val[0])==strtoupper($tag)) {
$fnd=true;
break;
}
}
$args=func_get_args();
if ($fnd) {
$this->_tagsWA[$key]=$args;
}
else {
array_push ($this->_tagsWA,$args);
}
} // end func
/**
* Short description.
*
* Detail description
* @param
* @since 1.0
* @access private
* @return void
* @throws
*/
function _process($html,$arr_tags,$tags_a)
{
//this function has two filters:
//first (tags that are in $arr_tags array) leave these tags, but strips all attrinutes from
it
//second (tags that)
// why should there be a null character
$html = preg_replace('/\0/', '', $html);
// convert the ampersants to null characters
$html = preg_replace('/\&/', '\0', $html);
// convert the sharp brackets to there html code and excape special charachters such as
"
$html = preg_replace('/</', '<', $html);
$html = preg_replace('/>/', '>', $html);
// restore the tags that are concidered safe
$tags=implode('|',$arr_tags);
if ($tags) {
//this statement not only escapes "unsafe" tags, but also removes all attributes
from SAFE tags
$html = preg_replace("/<(($tags)(|\s.*)?)>/i",
'<\1>', $html);
$html = preg_replace("/<\\/($tags)>/i", '</\1>',
$html);
}
if (count($tags_a)){
while (list($k,$v)=each($tags_a))
{
$a_tags.='|'.$v[0];
preg_match_all
("/<((".$v[0].").*?)>/i",$html,$out, PREG_PATTERN_ORDER);
for ($i=0;$i<count($out[0]);$i++)
{
//echo $out[0][$i]."\n";
$tag_str='';
$pos=strpos($html,$out[0][$i]);
if (!(is_string($pos) && !$pos))
{
$tag_str.='<'.$v[0];
for ($j=1;$j<count($v);$j++)
{
if (preg_match(
'/\\s*'.$v[$j].'(\\s*=\\s*(\'[^\']*\'|"[^"]*"|[-a-zA-Z0-9.\\/:;+*%?!&$()_#=~\'"]*))?/i'
,substr(substr($out[0][$i],4+strlen($v[0])),0,-4),$attrs_matches))
$tag_str.='
'.$v[$j].(strlen($attrs_matches[1])?'='.$attrs_matches[2]:'');
}
$tag_str.='>';
$html=substr($html,0,$pos).$tag_str.substr($html,$pos+strlen($out[0][$i]));
}
}
}
$a_tags=substr($a_tags,1);
$html = preg_replace("/<\\/($a_tags)>/i",
'</\1>', $html);
}
// restore the ampersants
$html = preg_replace('/\0/', '&', $html);
return($html);
} // end func
/**
* Short description.
*
* Detail description
* @param
* @since 1.0
* @access private
* @return void
* @throws
*/
function filter($html='')
{
return
$this->_process((strlen($html)?$html:$this->_storage),$this->_tagsNA,$this->_tagsWA);
} // end func
/**
* Short description.
*
* Detail description
* @param
* @since 1.0
* @access private
* @return void
* @throws
*/
function printNATags()
{
echo "<PRE>";
reset ($this->_tagsNA);
while (list($key,$val)=each($this->_tagsNA)) {
echo "\n$val";
}
echo "</PRE>";
} // end func
/**
* Short description.
*
* Detail description
* @param
* @since 1.0
* @access private
* @return void
* @throws
*/
function printWATags()
{
echo "<PRE>";
reset ($this->_tagsWA);
while (list($key,$val)=each($this->_tagsWA)) {
$f=true;
reset ($val);
while (list($k,$v)=each($val)) {
if (!$f) {
echo "\t";
}
$f=false;
echo $v."\n";
}
}
echo "</PRE>";
} // end func
} // end class
$html='
<!doctype html public "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title> New Document </title>
<meta name="Generator" content="EditPlus">
<meta name="Author" content="">
<meta name="Keywords" content="">
<meta name="Description" content="">
</head>
<body>
<!-- header -->
<table cellpadding="0" cellspacing="0" border="0"
bgcolor="#0087e6" width="740">
<tr>
<td background="img/back.jpg" align="center"
width="180"><img src="img/logo.gif" width="180"
height="49" border="0" alt=" mobil.by "></td>
<td align="right" background="img/back.jpg"><img
src="img/468_01.gif" width="468" height="60" hspace="6"
vspace="6" border="0" alt=""></td>
</tr>
<tr>
<td colspan="2" height="1"
background="img/dot_h.gif"><img src="img/x.gif" width="1"
height="1" border="0"></td>
</tr>
<tr bgcolor="#339feb">
<td colspan="2">
<table cellpadding="2" cellspacing="0"
border="0" width="100%">
<tr>
<td align="left"
class="taxText"><a href="index02.html"><b>mobil.by</a> \
каталог</b></td>
<td align="right">
<table cellpadding="2"
cellspacing="0" border="0">
<tr><form>
<td><input
type="text" value=" поиск" class="form" style="width:
130px"></td>
<td><input
type="image" src="img/but_srch.gif" width="29" height="14"
border="0" alt=" Искать " hspace="2"></td>
</tr></form>
</table>
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td colspan="2" bgcolor="#ffffff"><img
src="img/x.gif" width="1" height="4" border="0"
alt=""></td>
</tr>
</table>
<!-- end header -->
<!-- body -->
</body>
</html>
';
$p=new HTML_filter($html);
$p->addTag('a','href','target');
$p->addTag('img','src','border');
$p->addTag('b');
$p->addTag('t');
$p->addTag('body');
$p->addTag('font');
$p->addTag('hr');
$p->addTag('h1','style','color');
$p->printWATags();
echo "<HR>";
echo "<PRE>";
echo $p->filter();
echo "</PRE>";
?>
---------------------
Maxim Vysotskiy
VPISystems Programmer
Minsk
mailto:vysotmax@vpi-minsk.com
ICQ: 44197964
---------------------