CI自动过滤掉百分号%后两位的问题解决

CodeIgniter 做的网站里,想输入一段代码:

$var = sprintf("%04d", 2);

但是发现入库后,代码变成了大发888娱乐城

$var = sprintf("d", 2);

在网上环境,本地环境都测试过,最终确认是 CodeIgniter 系统的问题。下面谈一下问题解决的过程与思维方法:

1. 是 config.php 的 permitted_uri_chars 吗?

$config[‘permitted_uri_chars‘] = ‘a-z 0-9~%.:_\-‘;

在 stackoverflow 上找到几个差不多的问题,有答案说改  config.php 的 permitted_uri_chars 就行了。

Ahem... after looking at your sample string again. Here is why you get "The URI you submitted has disallowed characters".

Short explanation: Add the ampersand & to the allowed characters list

$config[‘permitted_uri_chars‘] = ‘a-z 0-9~%.:_+&-‘;

试过了,没效果,于是就查找应用了 $config[‘permitted_uri_chars‘] 的代码。

2. 是 core/Input.php 的 _clean_input_keys() 函数问题吗?

	function _clean_input_keys($str)
	{
		$config = &get_config(‘config‘);
		if ( ! preg_match("/^[".$config[‘permitted_uri_chars‘]."]+$/i", rawurlencode($str)))
		{
			exit(‘Disallowed Key Characters.‘);
		}   

		// Clean UTF-8 if supported
		if (UTF8_ENABLED === TRUE)
		{
			$str = $this->uni->clean_string($str);
		}
		return $str;
	}

这个函数使用了 $config[‘permitted_uri_chars‘] 直接过滤 post 过来的数据,很大原因就是元凶了。我把它单独出来,经过测试发现,post $var = sprintf("%04d", 2); 过来,结果还是 $var = sprintf("%04d", 2); ,%04并未被过滤,看来还得细细地找。

3. 是 xss 的防御机制吗?

stackoverflow 有个人说他完美解决了这个问题,是 xss clean 的原因。

:) God damn URLDECODE, I have looked at the code in URI.php but the xss clean is doing the job so I missed it. Thank you now everything is perfect. – RaduM

于是我找到了 core/security.php 下的 xss_clean() 函数。把函数体代码全部注释掉,发现输入还是会把 %04 过滤掉,显然也不是 xss 的问题。

4. 问题出在 _clean_input_data() 函数

重新回到 Input.php,发现 _clean_input_data 与 _clean_input_keys 有联系。

$new_array[$this->_clean_input_keys($key)] = $this->_clean_input_data($val);

于是把 _clean_input_data() 的函数体注释掉,竟然输入没被过滤了。继续缩小范围,发现是这段代码惹得祸:

// Remove control characters
// 就是这个会把%0x过滤掉
$str = remove_invisible_characters($str);

5. 元凶找到了 remove_invisible_characters() 函数

那么 remove_invisible_characters() 这个函数是什么呢?

这个函数在 core/Common.php中,我把它揪出来:

	function remove_invisible_characters($str, $url_encoded = TRUE)
	{
		$non_displayables = array();

		// every control character except newline (dec 10)
		// carriage return (dec 13), and horizontal tab (dec 09)

		if ($url_encoded)
		{
			$non_displayables[] = ‘/%0[0-8bcef]/‘;	// url encoded 00-08, 11, 12, 14, 15
			$non_displayables[] = ‘/%1[0-9a-f]/‘;	// url encoded 16-31
		}

		$non_displayables[] = ‘/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]+/S‘;	// 00-08, 11, 12, 14-31, 127

		do
		{
			$str = preg_replace($non_displayables, ‘‘, $str, -1, $count);
		}
		while ($count);

		return $str;
	}

看这么几行代码:

if ($url_encoded)
{
	$non_displayables[] = ‘/%0[0-8bcef]/‘;	// url encoded 00-08, 11, 12, 14, 15
	$non_displayables[] = ‘/%1[0-9a-f]/‘;	// url encoded 16-31
}

明确了吧,他会把%0与%1开头的3个字符过滤掉。直接把这个注释掉,问题解决。

记录这个问题解决的思维全过程。

时间: 2024-10-25 22:14:52

CI自动过滤掉百分号%后两位的问题解决的相关文章

java保留小数后两位的四种写法

java保留小数后两位的四种写法 package com.btzh.mis.house.utils; import java.math.BigDecimal;import java.math.RoundingMode;import java.text.DecimalFormat; /** * Double类型数据处理类 * @author weijixiang * @date 2017/10/17. */public class NumberUtil { public static Double

输出所有形如aabb的4位完全平方数(即前两位数字相等,后两位数字也相等)

计算完全平方根可以使用math库中的sqrt完成,但需要注意以下几点:a取值应为1-9,b取值为0-9:完全平方得到的结果是浮点型,因为浮点型不像整形可能有误差的存在(TODO:浮点型计算误差),可以使用floor(sqrt(x)+0.5)来减小误差,这里稍微展开说下:如果sqrt(x)的结果本来是1,由于浮点计算的误差导致结果为0.9999,那么cast到int型其结果就是0,因此用四舍五入的方式来减少这种误差(这涉及到浮点型的精度问题,如果精度较高的浮点表示,那计算结果于预期的波动会相对较小

iOS 取后两位并且四舍五入

NSNumber *priceNum = [NSNumber numberWithFloat:123.125]; NSLog(@"----%@---",[NSString stringWithFormat:@"%.2f",round([priceNum floatValue]*100)/100]); //123.13

java获取年份的后两位

public static String getDate(Date strDate) { String date = null; if (strDate!= null) { Calendar startTime = Calendar.getInstance(); int year = startTime.get(Calendar.YEAR) - 20; // 这里初始化时间,然后设置年份.只以年份为基准,不看时间 startTime.clear(); startTime.set(Calendar

F5 irule在http response的header头内插入服务器IP的后两位

irule:when HTTP_RESPONSE { scan [IP::remote_addr] {%d.%d.%d.%d} c d HTTP::header insert "SIP" "x.$c.$d" } 结果截图: 原文地址:https://blog.51cto.com/8525378/2369806

金融支付 输入金额 小数点后两位 ,首位输入小数点

封装 如下工具类 在EditText 的addTextChangListener( )方法内的onTextChangge方法内,调用工具内即可. 工具类如下 /** * onTextChanged * @param sequence (CharSequenc s * @param editText */ public static void formatDot(CharSequence sequence,EditText editText){ String s = sequence.toStri

Double 数据保留两位小数一:五舍六入

1 package com; 2 3 public class T2 { 4 5 public static void main(String[] args) { 6 7 System.out.println(calculateProfit(0.233)); 8 System.out.println(calculateProfit(0.235)); 9 System.out.println(calculateProfit(0.237)); 10 System.out.println(calcul

python整数除法保留两位小数

在py应用中有许多拿结果中的多个整数进行运算,难免少不了除法(如单位换算等),但是整数进行运算后只会返回整数,一般结果基本需要精确到后两位,此时就可以使用以下两种方法进行解决: 1.将参与运算的任意一个整数显式的转换成float类型进行如下:     def convert_unit(num_size):         return round((float(num_size) / 1048576), 2) 2.导入division方法也可以实现    from __future__ impo

javascript实现保留两位小数一位自动补零代码实例

javascript实现保留两位小数一位自动补零代码实例:本章节介绍一下如何实现对数字保留两位小数效果,如果数字的原本小数位数不到两位,那么缺少的就自动补零,这个也是为了统一的效果,先看代码实例: function returnFloat(value){ var value=Math.round(parseFloat(value)*100)/100; var xsd=value.toString().split("."); if(xsd.length==1){ value=value.