这是从手上的CodeIgniter项目中摘录下来的代码:
filtrate_quote_centent()去掉引号内的内容,支持SQL语句
split_jump_quote() 是在filtrate_quote_centent的基础上用正则式分隔带有引号字符串的函数
mb_strlen() 辅助函数,如果环境不支持原生的mb_strlen()可以带上
使用示例:
$str = 'abort on : "为什么官僚们把文\\\\\"革解释为\'食年浩截\'?",this is real?! -- \'http://www.szhgh.com/Article/opinion/zatan/201401/41886.html http://www.szhgh.com/m/show.php?classid=49&id=65714\'';
$val = filtrate_quote_centent($str);
echo 'filtrate_quote_centent($str):'.$val.PHP_EOL;
$sql = 'SELECT id,`name\'x`,`name\'m` FROM worker WHERE addr LIKE "%黑龙江\\%" AND age > getage(\'成年年龄\')';
$quote_list = array();
$val = filtrate_quote_centent($sql,'*','``',$quote_list);
print_r($quote_list);
die($val);
输出:
filtrate_quote_centent($str):abort on :"***********************",this is real?! -- '*******************************************************'
Array
(
[0] => SELECTid,`name'x`,`name'm` FROM worker WHERE addr LIKE
[1] => Array
(
["******"] => "%黑龙江\%"
)
[2] => AND age > getage(
[3] => Array
(
['****'] => '成年年龄'
)
[4] => )
)
SELECT id,`name'x`,`name'm` FROM worker WHERE addr LIKE"******" AND age > getage('****')
以下是源代码
/**
* 去除引号内的内容
* @param string $str 待处理的字符串
* @param string $repChar 引号内的替换字符,默认为*
* @param string|NULL $exclude_quote_boxchr 以此2字符包裹的引号不会当成引号字符串的一部分(引号内的内容除外),用于对sql语句的分析,一般为``,如字段名中含有',例如 `field'X`
* @param array|NULL $QuoteList 内容分节输出数组,默认为空,不输出.引号内容节点(包含头尾的引号)为array('***'=>'原内容')
* @param string $cslashes 字符串中的转义符,默认为\,sql中可能为'
* @param string $prefix 要附加的字符串前缀,默认为空
* @param string $suffix 要附加的字符串后缀,默认为空
* @return string
*/
function filtrate_quote_centent($str, $repChar='*',$exclude_quote_boxchr=NULL,array &$QuoteList=NULL,$cslashes='\\', $prefix='', $suffix='')
{
if (empty($str))return $str;
$strlen = mb_strlen($str);
if ($strlen < 1)return $str;
$c1 = NULL;
$b = -1;
$xgcount = 0;
$qlen = 0;
$hlen = 0;
$exclude_quote_arae= FALSE;//进入引号排除区域
$qlen = mb_strlen($prefix);
$hlen = mb_strlen($suffix);
$ret = $prefix . $str . $suffix;
$splitexp='/./u';
if(preg_match_all($splitexp,$ret,$matches)== $strlen + $qlen + $hlen)
{
$re = &$matches[0];
$otherchr = array();//非引号内的字符数组
for ($i = $qlen; $i < $strlen + $qlen; $i++)
{
if ($c1 === NULL && $exclude_quote_boxchr!== NULL && $re[$i]== $exclude_quote_boxchr[intval($exclude_quote_arae)])
{
$exclude_quote_arae= !$exclude_quote_arae;//进入|退出引号排除区域
}
if ( !$exclude_quote_arae && ($re[$i]== '\'' || $re[$i]== '"'))
{
if ($c1 === NULL)
{
$b = $i;
$c1 = $re[$i];
if(is_array($QuoteList)&& !empty($otherchr))
{
$QuoteList[]= implode('',$otherchr);
$otherchr = array();
}
}
else
{
if ($re[$i]== $c1 && $xgcount % 2 == 0)
{
$txt = array_slice($re,$b,$i-$b + 1);
$repr = $re[$b];
for ($j = $b + 1; $j < $i; $j++)
{
$re[$j] =$repChar;
$repr .= $repChar;
}
$repr .= $re[$i];
$c1 = NULL;
if(is_array($QuoteList)&& !empty($txt))
{
$QuoteList[]= array($repr=>implode('',$txt));
}
}
}
}
else
{
if($c1 === NULL &&is_array($QuoteList))
{
$otherchr[]= $re[$i];
}
}
if($c1 !== NULL)
{
if ($re[$i]== $cslashes)
$xgcount++;
else
$xgcount = 0;
}
}
$ret = implode('',$re);
if(is_array($QuoteList)&& !empty($otherchr))//结果链的最后一部分
{
$QuoteList[]= implode('',$otherchr);
}
}
return $ret;
}
/**
* 以正则式分隔字符串,会跳过引号中的内容
* @param string $str 待分隔的字符串
* @param string $regex 分隔符的正则式
* @param string $repChar 引号中内容的替换字符,注意:不能与分隔字符相同
* @param string|NULL $exclude_quote_boxchr 以此2字符包裹的引号不会当成引号字符串的一部分(引号内的内容除外),用于对sql语句的分析,一般为``,如字段名中含有',例如 `field'X`
* @return array
*/
function split_jump_quote($str,$regex, $repChar='*',$exclude_quote_boxchr=NULL)
{
if(empty($str)|| empty($regex))
return $str;
$quote_list = array();
$stx =filtrate_quote_centent($str,$repChar,$exclude_quote_boxchr,$quote_list);
$dels = 0;
foreach ($quote_list as $k => &$item)
{
if(is_string($item))
{
$item = preg_split($regex,$item);
}
else
{
$item = current($item);
if($k > 0)
{
if(is_string($quote_list[$k - 1]))//合并连续的引号内容
{
$quote_list[$k - 1].= $item;
unset($quote_list[$k]);
$dels++;
}
}
}
}
if($dels > 0) $quote_list = array_values($quote_list);//重排数字索引
foreach ($quote_list as $k => &$item)//合并引号串
{
if(is_string($item))
{
if($k > 0)//抽出前一组的最后一个元素:
{
$stack = array_pop($quote_list[$k-1]);
if(!empty($stack))
$item = $stack.$item;
}
if(isset($quote_list[$k + 1])&& is_array($quote_list[$k + 1]))//后一组:
{
$stack = array_shift($quote_list[$k + 1]);
if(!empty($stack))$item .= $stack;
}
}
}
//把空的数组删除:
$items = array();
foreach ($quote_list as $k => &$item)
{
if(is_array($item))
{
foreach ($item as &$it)
{
$items[]= &$it;
}
}
else
$items[]= &$item;
}
return $items;
}
if ( ! function_exists('mb_strlen'))
{
function mb_strlen($str, $encoding = NULL)
{
if (ICONV_ENABLED === TRUE)
{
return iconv_strlen($str, isset($encoding) ? $encoding : config_item('charset'));
}
return strlen($str);
}
}