客户端需要UTF-16编码的文件,但转换时,同事说不对,要小尾序的,其实不太明白这个意思,查了一下资料。
PHP里的代码也就这样了:
从某篇文章发现这样的东西:
这说明了有其它的UTF-16的编码方式,我们看看维基的说明《UTF-16》:
PHP稍微修改一下就对了:
另外有这么个代码:UTF-8 to Code Point Array Converter in PHP
把字符都转换成代表的数字了,目前不知道什么用途。。
另外,需要转换PC格式为Unix格式时,需要在转换Utf-16之前处理,否则会出现好多乱码的哦
PHP里的代码也就这样了:
$content = iconv('UTF-8', 'UTF-16', $content);
从某篇文章发现这样的东西:
from_to($string, 'UTF-16le', 'UTF-8');
这说明了有其它的UTF-16的编码方式,我们看看维基的说明《UTF-16》:
引用
UTF-16是Unicode的其中一个使用方式。 UTF是 Unicode/UCS Transformation Format,即把Unicode转做某种格式的意思。
UTF-16的大尾序和小尾序储存形式都在用。一般来说,以Macintosh制作或储存的文字使用大尾序格式,以Microsoft或Linux制作或储存的文字使用小尾序格式。
字符“朱”:
UTF-16LE 小尾序 31 67
UTF-16BE 大尾序 67 31
UTF-16的大尾序和小尾序储存形式都在用。一般来说,以Macintosh制作或储存的文字使用大尾序格式,以Microsoft或Linux制作或储存的文字使用小尾序格式。
字符“朱”:
UTF-16LE 小尾序 31 67
UTF-16BE 大尾序 67 31
PHP稍微修改一下就对了:
$content = iconv('UTF-8', 'UTF-16le', $content);
另外有这么个代码:UTF-8 to Code Point Array Converter in PHP
把字符都转换成代表的数字了,目前不知道什么用途。。
另外,需要转换PC格式为Unix格式时,需要在转换Utf-16之前处理,否则会出现好多乱码的哦
$content = str_replace("\r\n", "\n", $content);
$content = iconv('UTF-8', 'UTF-16le', $content);
$content = iconv('UTF-8', 'UTF-16le', $content);
从大的编码转换到小的编码,是会产生字符缩减的,甚至有些字在目标字符集里不存在。
比如gb2312里,“囧”、“镕”都会产生转换失败,但很奇怪,gb2312的网页里是有这样的文字的,有点不解。
先看看官方的说明吧 iconv
看示例可知
在输出字符里添加//TRANSLIT可以得到相近的意思的字符
添加//IGNORE可以忽略不能转换的
不添加,则在第一个错误的地方停止转换,也就是被截断了
如何知道被截断了或者转换失败?
有个例子可以参考一下(单位是字节还是字符,这里不确定)
比如gb2312里,“囧”、“镕”都会产生转换失败,但很奇怪,gb2312的网页里是有这样的文字的,有点不解。
先看看官方的说明吧 iconv
引用
out_charset
The output charset.
If you append the string //TRANSLIT to out_charset transliteration is activated. This means that when a character can't be represented in the target charset, it can be approximated through one or several similarly looking characters. If you append the string //IGNORE, characters that cannot be represented in the target charset are silently discarded. Otherwise, str is cut from the first illegal character and an E_NOTICE is generated.
The output charset.
If you append the string //TRANSLIT to out_charset transliteration is activated. This means that when a character can't be represented in the target charset, it can be approximated through one or several similarly looking characters. If you append the string //IGNORE, characters that cannot be represented in the target charset are silently discarded. Otherwise, str is cut from the first illegal character and an E_NOTICE is generated.
看示例可知
在输出字符里添加//TRANSLIT可以得到相近的意思的字符
添加//IGNORE可以忽略不能转换的
不添加,则在第一个错误的地方停止转换,也就是被截断了
如何知道被截断了或者转换失败?
有个例子可以参考一下(单位是字节还是字符,这里不确定)
<?
//code from http://www.aslibra.com
//code by hqlulu @ 2010-1-25
$title_origin = "something";
$title = iconv('utf-8', 'gb2312//IGNORE', $title_origin);
$percent = round(strlen($title_origin)/strlen($title), 3);
//UTF-8汉字 3字节 gb2312汉字 2字节
//最大比例为1.5,如果丢失文字,那就是有转换失败,并且比例变大
//简单例子:“我”的urlencode值 = %E6%88%91(utf-8) = %CE%D2(gb2312)
if($percent > 1.5 ){
$error[] = array('str', $title_origin);
}
?>
//code from http://www.aslibra.com
//code by hqlulu @ 2010-1-25
$title_origin = "something";
$title = iconv('utf-8', 'gb2312//IGNORE', $title_origin);
$percent = round(strlen($title_origin)/strlen($title), 3);
//UTF-8汉字 3字节 gb2312汉字 2字节
//最大比例为1.5,如果丢失文字,那就是有转换失败,并且比例变大
//简单例子:“我”的urlencode值 = %E6%88%91(utf-8) = %CE%D2(gb2312)
if($percent > 1.5 ){
$error[] = array('str', $title_origin);
}
?>
nginx配合codeIgniter有点麻烦,没有apache和lighttpd那么简单。
在apache和lighttpd里面,判断 /index.php/sth 时,如果 /index.php是一个文件,就不会当做是文件路径了
我们可以这样简单的把某些路径rewrite,达到一样的效果:
1 保持地址格式是 /index.php/control/model
2 不产生404错误或者是no input的情况
我们还需要避免类似以下地址异常:
/book/?test 404 查询字符会查找test的control
/book/&test 错误 The URI you submitted has disallowed characters.
总体而言,是查询字符的问题,我们可以有两种方式处理:
方式一:在codeIgniter处理之前避免
我们定义系统使用REQUEST_URI来处理mvc参数,不修改系统的文件,我们修改自定义的文件
文件 application/config/config.php
指定为REQUEST_URI方式处理,不是用auto,auto方式会判断查询字符
文件 index.php
我们可以直接砍掉查询字符,保证参数不受影响
方式二:发生错误之后调整
发生404错误时,我们自动跳转到相应的地址,比如去掉后面 ?xxxx 和 &xxxx
文件 application/errors/error_404.php
在 error_general.php 里也可以这样加一样的代码。
参考资料:
1 不错的nginx配置方式,本文有参考: CodeIgniter Nginx Rewrite Rule
2 CodeIgniter URLs & Nginx
3 lighttpd rewrite rule && apache mod_rewrite
$HTTP["host"] == "www.aslibra.com" {
server.document-root = "/path/to/www.aslibra.com/"
url.rewrite = (
"^/static/.*$" => "$0",
"^/(.*)$" => "index.php/$1"
)
fastcgi.server = ( ".php" =>
( "weibo"=>( "host" => "127.0.0.1","port" => 9000) )
)
}
server.document-root = "/path/to/www.aslibra.com/"
url.rewrite = (
"^/static/.*$" => "$0",
"^/(.*)$" => "index.php/$1"
)
fastcgi.server = ( ".php" =>
( "weibo"=>( "host" => "127.0.0.1","port" => 9000) )
)
}
在apache和lighttpd里面,判断 /index.php/sth 时,如果 /index.php是一个文件,就不会当做是文件路径了
我们可以这样简单的把某些路径rewrite,达到一样的效果:
1 保持地址格式是 /index.php/control/model
2 不产生404错误或者是no input的情况
server {
index index.php index.htm;
server_name www.aslibra.com;
root /Data/webapps/www.aslibra.com;
location /book/ {
if (!-e $request_filename) {
rewrite ^/book/(.*)$ /book/index.php/$1 last;
}
}
location /book/index.php {
fastcgi_pass 127.0.0.1:9000;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME /Data/webapps/www.aslibra.com/book/index.php;
}
}
index index.php index.htm;
server_name www.aslibra.com;
root /Data/webapps/www.aslibra.com;
location /book/ {
if (!-e $request_filename) {
rewrite ^/book/(.*)$ /book/index.php/$1 last;
}
}
location /book/index.php {
fastcgi_pass 127.0.0.1:9000;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME /Data/webapps/www.aslibra.com/book/index.php;
}
}
我们还需要避免类似以下地址异常:
/book/?test 404 查询字符会查找test的control
/book/&test 错误 The URI you submitted has disallowed characters.
总体而言,是查询字符的问题,我们可以有两种方式处理:
方式一:在codeIgniter处理之前避免
我们定义系统使用REQUEST_URI来处理mvc参数,不修改系统的文件,我们修改自定义的文件
文件 application/config/config.php
指定为REQUEST_URI方式处理,不是用auto,auto方式会判断查询字符
| 'AUTO' Default - auto detects
| 'PATH_INFO' Uses the PATH_INFO
| 'QUERY_STRING' Uses the QUERY_STRING
| 'REQUEST_URI' Uses the REQUEST_URI
| 'ORIG_PATH_INFO' Uses the ORIG_PATH_INFO
|
*/
$config['uri_protocol'] = "REQUEST_URI";
| 'PATH_INFO' Uses the PATH_INFO
| 'QUERY_STRING' Uses the QUERY_STRING
| 'REQUEST_URI' Uses the REQUEST_URI
| 'ORIG_PATH_INFO' Uses the ORIG_PATH_INFO
|
*/
$config['uri_protocol'] = "REQUEST_URI";
文件 index.php
我们可以直接砍掉查询字符,保证参数不受影响
//处理查询字符
$url = explode('?', $_SERVER['REQUEST_URI']);
$url = explode('&', $url[0]);
$_SERVER['REQUEST_URI'] = $url[0];
/*
|---------------------------------------------------------------
| LOAD THE FRONT CONTROLLER
|---------------------------------------------------------------
|
| And away we go...
|
*/
require_once BASEPATH.'codeigniter/CodeIgniter'.EXT;
$url = explode('?', $_SERVER['REQUEST_URI']);
$url = explode('&', $url[0]);
$_SERVER['REQUEST_URI'] = $url[0];
/*
|---------------------------------------------------------------
| LOAD THE FRONT CONTROLLER
|---------------------------------------------------------------
|
| And away we go...
|
*/
require_once BASEPATH.'codeigniter/CodeIgniter'.EXT;
方式二:发生错误之后调整
发生404错误时,我们自动跳转到相应的地址,比如去掉后面 ?xxxx 和 &xxxx
文件 application/errors/error_404.php
<?php
$url = explode('?', $_SERVER['REQUEST_URI']);
$url = explode('&', $url[0]);
if($url[0] != $_SERVER['REQUEST_URI']){
echo "<meta http-equiv=\"refresh\" content=\"0;url=$url[0]\">";
}
?>
</head>
$url = explode('?', $_SERVER['REQUEST_URI']);
$url = explode('&', $url[0]);
if($url[0] != $_SERVER['REQUEST_URI']){
echo "<meta http-equiv=\"refresh\" content=\"0;url=$url[0]\">";
}
?>
</head>
在 error_general.php 里也可以这样加一样的代码。
参考资料:
1 不错的nginx配置方式,本文有参考: CodeIgniter Nginx Rewrite Rule
2 CodeIgniter URLs & Nginx
3 lighttpd rewrite rule && apache mod_rewrite
分享一段代码,平时在使用的
清理img标签里的其它属性,保留src,如果要清理别的,自行修改即可
// code from http://www.aslibra.com/
// by hqlulu
// replace <img (any code) src="(pic url)">
// to <img src="(pic url)">
function parse_img ( $content ) {
preg_match_all ("/<img[^>]+src=\"(.+)\"[^>]*>/isU",
$content,
$out, PREG_PATTERN_ORDER);
foreach($out[1] as $k=>$v){
$content = str_replace($out[0][$k], '<img src="'.$out[1][$k].'">', $content);
}
return $content;
}
// by hqlulu
// replace <img (any code) src="(pic url)">
// to <img src="(pic url)">
function parse_img ( $content ) {
preg_match_all ("/<img[^>]+src=\"(.+)\"[^>]*>/isU",
$content,
$out, PREG_PATTERN_ORDER);
foreach($out[1] as $k=>$v){
$content = str_replace($out[0][$k], '<img src="'.$out[1][$k].'">', $content);
}
return $content;
}
清理img标签里的其它属性,保留src,如果要清理别的,自行修改即可
codeIgniter我用过一下,觉得比较的理想,很适合做开发,一个很小巧的php的MVC框架。
由于是一个框架模式,所以样例代码拿过来是很容易看清楚程序架构的,也很容易参考,这比自己写的程序要好很多,至少你很容易找到每个代码的功能和位置。
碰到一个问题:
apache里面可以这样做rewrite
两种写法都可以让index.php处理此链接,而第一种是最好的,用户输入查询也没事,比如 /topic?test=ds
第二种写法就不行了,会出现错误,地址匹配有特殊字符
但对于nginx的服务器,是不能那样写的,如果按第一种写法,会出现404错误,当作目录了
如果是lighttpd,那应该和apache类似,没有问题。
出现的错误是:
出自(系统库文件URI.php):
看代码,我们可以设置config里面 enable_query_strings 为TRUE
这次会得到什么结果:
这说明已经过了检查地址,到了路由这一部分了,这个错误是找不到相应的class/method所导致的
重要的URI处理是在 _fetch_uri_string 函数里面,调用这个过滤器是在路由控制里面:
从Router.php里面找到(大概90行)
我们可以看到路由取出来的地址是什么,比较两种方式
设置为:
测试地址为: /topic/test?site=aslibra.com
理想状态应该是进入 /topic/test
第一种情况,取得的uri为 site,这错的比较离谱
第二种为 /topic,检查server变量
都发生了错误,修改auto为REQUEST_URI应该可以有救
对于这个是支持,因为有正常的class和method,但如果是一级参数,那就出错了,比如
/topic/?site=aslibra.com
这种情况最好的解决办法是钩子处理,在系统开始的时候把查询字符都忽略了
或者,在index.php调用CI之前,就去掉,比如
钩子方式的解决办法:
新建 hooks/Uri.php
那修改auto为REQUEST_URI应该可以,查询字符支持可以不支持了
由于是一个框架模式,所以样例代码拿过来是很容易看清楚程序架构的,也很容易参考,这比自己写的程序要好很多,至少你很容易找到每个代码的功能和位置。
碰到一个问题:
apache里面可以这样做rewrite
<VirtualHost *:80>
ServerName www.aslibra.com
DocumentRoot F:\WebsiteLocal\www.aslibra.com
RewriteEngine On
RewriteRule ^/(topic|user) /index.php$0
#RewriteRule ^/(topic|user) /index.php?$0
</VirtualHost>
ServerName www.aslibra.com
DocumentRoot F:\WebsiteLocal\www.aslibra.com
RewriteEngine On
RewriteRule ^/(topic|user) /index.php$0
#RewriteRule ^/(topic|user) /index.php?$0
</VirtualHost>
两种写法都可以让index.php处理此链接,而第一种是最好的,用户输入查询也没事,比如 /topic?test=ds
第二种写法就不行了,会出现错误,地址匹配有特殊字符
但对于nginx的服务器,是不能那样写的,如果按第一种写法,会出现404错误,当作目录了
如果是lighttpd,那应该和apache类似,没有问题。
location ~^/(topic|user) {
rewrite ^/(.*) /index.php?/$1 last;
}
rewrite ^/(.*) /index.php?/$1 last;
}
出现的错误是:
引用
An Error Was Encountered
The URI you submitted has disallowed characters.
The URI you submitted has disallowed characters.
出自(系统库文件URI.php):
function _filter_uri($str)
{
if ($str != '' && $this->config->item('permitted_uri_chars') != '' && $this->config->item('enable_query_strings') == FALSE)
{
// preg_quote() in PHP 5.3 escapes -, so the str_replace() and addition of - to preg_quote() is to maintain backwards
// compatibility as many are unaware of how characters in the permitted_uri_chars will be parsed as a regex pattern
if ( ! preg_match("|^[".str_replace(array('\\-', '\-'), '-', preg_quote($this->config->item('permitted_uri_chars'), '-'))."]+$|i", $str))
{
show_error('The URI you submitted has disallowed characters.', 400);
}
}
// Convert programatic characters to entities
$bad = array('$', '(', ')', '%28', '%29');
$good = array('$', '(', ')', '(', ')');
return str_replace($bad, $good, $str);
}
{
if ($str != '' && $this->config->item('permitted_uri_chars') != '' && $this->config->item('enable_query_strings') == FALSE)
{
// preg_quote() in PHP 5.3 escapes -, so the str_replace() and addition of - to preg_quote() is to maintain backwards
// compatibility as many are unaware of how characters in the permitted_uri_chars will be parsed as a regex pattern
if ( ! preg_match("|^[".str_replace(array('\\-', '\-'), '-', preg_quote($this->config->item('permitted_uri_chars'), '-'))."]+$|i", $str))
{
show_error('The URI you submitted has disallowed characters.', 400);
}
}
// Convert programatic characters to entities
$bad = array('$', '(', ')', '%28', '%29');
$good = array('$', '(', ')', '(', ')');
return str_replace($bad, $good, $str);
}
看代码,我们可以设置config里面 enable_query_strings 为TRUE
这次会得到什么结果:
引用
404 Page Not Found
The page you requested was not found.
The page you requested was not found.
这说明已经过了检查地址,到了路由这一部分了,这个错误是找不到相应的class/method所导致的
重要的URI处理是在 _fetch_uri_string 函数里面,调用这个过滤器是在路由控制里面:
从Router.php里面找到(大概90行)
// Fetch the complete URI string
$this->uri->_fetch_uri_string();
echo $this->uri->uri_string."<hr>"; //检查
$this->uri->_fetch_uri_string();
echo $this->uri->uri_string."<hr>"; //检查
我们可以看到路由取出来的地址是什么,比较两种方式
设置为:
$config['uri_protocol'] = "AUTO";
$config['enable_query_strings'] = TRUE;
$config['enable_query_strings'] = TRUE;
测试地址为: /topic/test?site=aslibra.com
理想状态应该是进入 /topic/test
第一种情况,取得的uri为 site,这错的比较离谱
第二种为 /topic,检查server变量
引用
[QUERY_STRING] => /topic
[REQUEST_URI] => /topic/test/?site=aslibra.com
[SCRIPT_NAME] => /topic/test/
[PHP_SELF] => /topic/test/
[REQUEST_TIME] => 1259512731
[argv] => Array
(
[0] => /topic
)
[argc] => 1
)
[REQUEST_URI] => /topic/test/?site=aslibra.com
[SCRIPT_NAME] => /topic/test/
[PHP_SELF] => /topic/test/
[REQUEST_TIME] => 1259512731
[argv] => Array
(
[0] => /topic
)
[argc] => 1
)
都发生了错误,修改auto为REQUEST_URI应该可以有救
对于这个是支持,因为有正常的class和method,但如果是一级参数,那就出错了,比如
/topic/?site=aslibra.com
这种情况最好的解决办法是钩子处理,在系统开始的时候把查询字符都忽略了
或者,在index.php调用CI之前,就去掉,比如
//code from http://aslibra.com/
$tmp = explode('?',$_SERVER['REQUEST_URI']);
$_SERVER['REQUEST_URI'] = $tmp[0];
$tmp = explode('?',$_SERVER['REQUEST_URI']);
$_SERVER['REQUEST_URI'] = $tmp[0];
钩子方式的解决办法:
//配置里 $config['enable_hooks'] = TRUE;
//config/hooks.php
$hook['pre_system'] = array(
'class' => 'Uri',
'function' => 'fix',
'filename' => 'Uri.php',
'filepath' => 'hooks',
'params' => ''
);
//config/hooks.php
$hook['pre_system'] = array(
'class' => 'Uri',
'function' => 'fix',
'filename' => 'Uri.php',
'filepath' => 'hooks',
'params' => ''
);
新建 hooks/Uri.php
<?php
//code from http://aslibra.com/
class Uri{
function fix(){
$tmp = explode('?',$_SERVER['REQUEST_URI']);
$_SERVER['REQUEST_URI'] = $tmp[0];
}
}
?>
//code from http://aslibra.com/
class Uri{
function fix(){
$tmp = explode('?',$_SERVER['REQUEST_URI']);
$_SERVER['REQUEST_URI'] = $tmp[0];
}
}
?>
那修改auto为REQUEST_URI应该可以,查询字符支持可以不支持了