2009年8月7日星期五

对模拟卡启动高级回音消除算法的方法 (转)


摘自:http://cn.freeiris.org/forum/viewthread.php?tid=299

这个操作适用于Asterisk及Freeiris2开源通信系统。

在你安装dahdi-linux的时候,且慢. 不要马上安装。按照这个步骤来操作.

我们假设dahdi-linux在目录/home/xxx/packages/下
复制内容到剪贴板
代码:
cd /home/xxx/packages/
wget http://kernel.org/pub/linux/kernel/v2.6/linux-2.6.28.tar.bz2
tar xjf linux-2.6.28.tar.bz2
mkdir dahdi-linux-2.1.0.4/drivers/staging
cp -fR ./linux-2.6.28/drivers/staging/echo ./dahdi-linux-2.1.0.4/drivers/staging
sed -i "s|#obj-m += dahdi_echocan_oslec.o|obj-m += dahdi_echocan_oslec.o|" ./dahdi-linux-2.1.0.4/drivers/dahdi/Kbuild
sed -i "s|#obj-m += ../staging/echo/|obj-m += ../staging/echo/|" ./dahdi-linux-2.1.0.4/drivers/dahdi/Kbuild
echo 'obj-m += echo.o' > ./dahdi-linux-2.1.0.4/drivers/staging/echo/Kbuild
cd dahdi-linux-2.1.0.4
make
make install
这样,你的dahdi就已经支持了OSLEC不过你要经过设置才可以真正启用。

在freeiris2的页面中-->系统选项-->硬件语音板-->
通用参数-->模拟口软回音算法-->选择oslec
保存,重新启动设备.

启动完成后,你的模拟口就支持软回音消除了。

如果你是asterisk用户.请自己设置/etc/dahdi/system.conf

2009年8月6日星期四

边界星座表(转)

摘自: http://www.xici.net/b133213/d32319770.htm


边界星座速查表

  如果你的生日在两个星座的交界处,不清楚自己到底是什么星座,可以在这里查找1950年―1999年太阳进入每个星座的具体时间。

  例如,你出生在1980年白羊座和金牛座的交界处,可以在表中查到这一年金牛座所对应的时间是4月20日6点22分,如果你出生在这个时间之后你的星座就是金牛座,否则就是白羊座。
年份 水瓶 双鱼 白羊 金牛 双子 巨蟹 狮子 处女 天秤 天蝎 射手 摩羯
1950 1.20 22:59 2.19 13:17 3.21 12:35 4.20 23:59 5.21 23:27 6.22 7:36 7.23 18:29 8.24 1:23 9.23 22:43 10.24 7:44 11.23 5:02 12.22 18:13
1951 1.21 4:52 2.19 19:09 3.21 18:25 4.21 5:48 5.22 5:15 6.22 13:24 7.24 0:20 8.24 7:16 9.24 4:36 10.24 13:36 11.23 10:51 12.23 0:00
1952 1.21 10:38 2.20 0:56 3.21 0:13 4.20 11:36 5.21 11:03 6.21 19:12 7.23 6:07 8.23 13:02 9.23 10:23 10.23 19:22 11.22 16:35 12.22 5:43
1953 1.20 16:21 2.19 6:41 3.21 6:00 4.20 17:25 5.21 16:52 6.22 1:00 7.23 11:51 8.23 18:45 9.23 16:05 10.24 1:06 11.22 22:21 12.22 11:31
1954 1.20 22:11 2.19 12:32 3.21 11:53 4.20 23:19 5.21 22:47 6.22 6:54 7.23 17:45 8.24 0:36 9.23 21:55 10.24 6:56 11.23 4:14 12.22 17:24
1955 1.21 4:02 2.19 18:18 3.21 17:35 4.21 4:57 5.22 4:24 6.22 12:31 7.23 23:24 8.24 6:18 9.24 3:40 10.24 12:43 11.23 10:00 12.22 23:11
1956 1.21 9:48 2.20 0:04 3.20 23:20 4.20 10:43 5.21 10:12 6.21 18:24 7.23 5:19 8.23 12:14 9.23 9:35 10.23 18:34 11.22 15:49 12.22 4:59
1957 1.20 15:39 2.19 5:58 3.21 5:16 4.20 16:41 5.21 16:10 6.22 0:20 7.23 11:14 8.23 18:07 9.23 15:26 10.24 0:24 11.22 21:39 12.22 10:48
1958 1.20 21:28 2.19 11:48 3.21 11:05 4.20 22:27 5.21 21:51 6.22 5:57 7.23 16:50 8.23 23:45 9.23 21:08 10.24 6:10 11.23 3:29 12.22 16:39
1959 1.21 3:18 2.19 17:37 3.21 16:54 4.21 4:16 5.22 3:42 6.22 11:50 7.23 22:45 8.24 5:43 9.24 3:08 10.24 12:11 11.23 9:26 12.22 22:34
年份 水瓶 双鱼 白羊 金牛 双子 巨蟹 狮子 处女 天秤 天蝎 射手 摩羯
1960 1.21 9:10 2.19 23:26 3.20 22:42 4.20 10:05 5.21 9:33 6.21 17:42 7.23 4:37 8.23 11:34 9.23 8:58 10.23 18:01 11.22 15:18 12.22 4:25
1961 1.20 15:01 2.19 5:16 3.21 4:32 4.20 15:55 5.21 15:22 6.21 23:30 7.23 10:23 8.23 17:18 9.23 14:42 10.23 23:47 11.22 21:07 12.22 10:19
1962 1.20 20:58 2.19 11:14 3.21 10:29 4.20 21:50 5.21 21:16 6.22 5:24 7.23 16:17 8.23 23:12 9.23 20:35 10.24 5:40 11.23 3:01 12.22 16:14
1963 1.21 2:54 2.19 17:08 3.21 16:19 4.21 3:36 5.22 2:58 6.22 11:04 7.23 21:58 8.24 4:57 9.24 2:23 10.24 11:28 11.23 8:49 12.22 22:01
1964 1.21 8:41 2.19 22:57 3.20 22:09 4.20 9:27 5.21 8:50 6.21 16:56 7.23 3:52 8.23 10:51 9.23 8:16 10.23 17:20 11.22 14:38 12.22 3:49
1965 1.20 14:29 2.19 4:47 3.21 4:05 4.20 15:26 5.21 14:50 6.21 22:55 7.23 9:47 8.23 16:42 9.23 14:06 10.23 23:09 11.22 20:29 12.22 9:40
1966 1.20 20:19 2.19 10:37 3.21 9:52 4.20 21:11 5.21 20:32 6.22 4:33 7.23 15:22 8.23 22:17 9.23 19:42 10.24 4:50 11.23 2:14 10.22 15:28
1967 1.21 2:07 2.19 16:23 3.21 15:36 4.21 2:55 5.22 2:18 6.22 10:23 7.23 21:15 8.24 4:12 9.24 1:38 10.24 10:43 11.23 8:04 12.22 21:16
1968 1.21 7:54 2.19 22:09 3.20 21:22 4.20 8:41 5.21 8:05 6.21 16:13 7.23 3:07 8.23 10:02 9.23 7:26 10.23 16:29 11.22 13:48 12.22 2:59
1969 1.20 13:38 2.19 3:54 3.21 3:08 4.20 14:26 5.21 13:49 6.21 21:55 7.23 8:47 8.23 15:43 9.23 13:06 10.23 22:11 11.22 19:30 12.22 8:43
年份 水瓶 双鱼 白羊 金牛 双子 巨蟹 狮子 处女 天秤 天蝎 射手 摩羯
1970 1.20 19:23 2.19 9:41 3.21 8:56 4.20 20:14 5.21 19:37 6.22 3:42 7.23 14:36 8.23 21:33 9.23 18:59 10.24 4:04 11.23 1:24 12.22 14:35
1971 1.21 1:12 2.19 15:27 3.21 14:38 4.21 1:54 5.22 1:14 6.22 9:19 7.23 20:14 8.24 3:15 9.24 0:44 10.24 9:53 11.23 7:13 12.22 20:23
1972 1.21 6:58 2.19 21:11 3.20 20:21 4.20 7:37 5.21 6:59 6.21 15:06 7.23 2:02 8.23 9:02 9.23 6:32 10.23 15:41 11.22 13:02 12.22 2:12
1973 1.20 12:48 2.19 3:01 3.21 2:12 4.20 13:30 5.21 12:54 6.21 21:00 7.23 7:55 8.23 14:53 9.23 12:21 10.23 21:30 11.22 18:53 12.22 8:07
1974 1.20 18:45 2.19 8:58 3.21 8:06 4.20 19:18 5.21 18:36 6.22 2:37 7.23 13:30 8.23 20:28 9.23 17:58 10.24 3:10 11.23 0:38 12.22 13:55
1975 1.21 0:36 2.19 14:49 3.21 13:56 4.21 1:07 5.22 0:23 6.22 8:26 7.23 19:21 8.24 2:23 9.23 23:55 10.24 9:06 11.23 6:30 12.22 19:45
1976 1.21 6:25 2.19 20:40 3.20 19:49 4.20 7:03 5.21 6:21 6.21 14:24 7.23 1:18 8.23 8:18 9.23 5:47 10.23 14:58 11.22 12:21 12.22 1:34
1977 1.20 12:14 2.19 2:30 3.21 1:42 4.20 12:57 5.21 12:14 6.21 20:13 7.23 7:03 8.23 14:00 9.23 11:29 10.23 20:40 11.22 18:06 12.22 7:22
1978 1.20 18:04 2.19 8:20 3.21 7:33 4.20 18:49 5.21 18:08 6.22 2:09 7.23 13:00 8.23 19:56 9.23 17:25 10.24 2:37 11.23 0:04 12.22 13:20
1979 1.21 0:00 2.19 14:13 3.21 13:21 4.21 0:35 5.21 23:53 6.22 7:56 7.23 18:48 8.24 1:46 9.23 23:16 10.24 8:27 11.23 5:53 12.22 19:09
年份 水瓶 双鱼 白羊 金牛 双子 巨蟹 狮子 处女 天秤 天蝎 射手 摩羯
1980 1.21 5:49 2.19 20:01 3.20 19:09 4.20 6:22 5.21 5:42 6.21 13:47 7.23 0:41 8.23 7:40 9.23 5:08 10.23 14:17 11.22 11:41 12.22 0:55
1981 1.20 11:36 2.19 1:51 3.21 1:02 4.20 12:18 5.21 11:39 6.21 19:44 7.23 6:39 8.23 13:38 9.23 11:05 10.23 20:12 11.22 17:35 12.22 6:50
1982 1.20 17:31 2.19 7:46 3.21 6:55 4.20 18:07 5.21 17:22 6.22 1:23 7.23 12:15 8.23 19:15 9.23 16:45 10.24 1:57 11.22 23:23 12.22 12:38
1983 1.20 23:16 2.19 13:30 3.21 12:38 4.20 23:50 5.21 23:06 6.22 7:08 7.23 18:03 8.24 1:07 9.23 22:41 10.24 7:54 11.23 5:18 12.22 18:29
1984 1.21 5:05 2.19 19:16 3.20 18:24 4.20 5:38 5.21 4:57 6.21 13:02 7.22 23:58 8.23 7:00 9.23 4:32 10.23 13:45 11.22 11:10 12.22 0:22
1985 1.20 10:57 2.19 1:07 3.21 0:13 4.20 11:25 5.21 10:42 6.21 18:44 7.23 5:36 8.23 12:35 9.23 10:07 10.23 19:21 11.22 16:50 12.22 6:07
1986 1.20 16:46 2.19 6:57 3.21 6:02 4.20 17:12 5.21 16:28 6.22 0:30 7.23 11:24 8.23 18:25 9.23 15:58 10.24 1:14 11.22 22:44 12.22 12:02
1987 1.20 22:40 2.19 12:50 3.21 11:52 4.20 22:57 5.21 22:10 6.22 6:10 7.23 17:05 8.24 0:09 9.23 21:45 10.24 7:00 11.23 4:29 12.22 17:45
1988 1.21 4:24 2.19 18:35 3.20 17:38 4.20 4:44 5.21 3:56 6.21 11:56 7.22 22:50 8.23 5:53 9.23 3:28 10.23 12:44 11.22 10:12 12.21 23:27
1989 1.20 10:07 2.19 0:20 3.20 23:28 4.20 10:39 5.21 9:53 6.21 17:53 7.23 4:45 8.23 11:46 9.23 9:19 10.23 18:35 11.22 16:04 12.22 5:22
年份 水瓶 双鱼 白羊 金牛 双子 巨蟹 狮子 处女 天秤 天蝎 射手 摩羯
1990 1.20 16:01 2.19 6:14 3.21 5:19 4.20 16:26 5.21 15:37 6.21 23:32 7.23 10:21 8.23 17:20 9.23 14:55 10.24 0:13 11.22 21:46 12.22 11:06
1991 1.20 21:47 2.19 11:58 3.21 11:01 4.20 22:08 5.21 21:20 6.22 5:18 7.23 16:10 8.23 23:12 9.23 20:48 10.24 6:05 11.23 3:35 12.22 16:53
1992 1.21 3:32 2.19 17:43 3.20 16:48 4.20 3:57 5.21 3:12 6.21 11:14 7.22 22:08 8.23 5:09 9.23 2:42 10.23 11:57 11.22 9:25 12.21 22:43
1993 1.20 9:22 2.18 23:35 3.20 22:40 4.20 9:49 5.21 9:02 6.21 16:59 7.23 3:50 8.23 10:50 9.23 8:22 10.23 17:36 11.22 15:06 12.22 4:25
1994 1.20 15:07 2.19 5:21 3.21 4:28 4.20 15:36 5.21 14:48 6.21 22:47 7.23 9:40 8.23 16:43 9.23 14:19 10.23 23:35 11.22 21:05 12.22 10:22
1995 1.20 21:00 2.19 11:10 3.21 10:14 4.20 21:21 5.21 20:34 6.22 4:34 7.23 15:29 8.23 22:34 9.23 20:12 10.24 5:31 11.23 3:01 12.22 16:16
1996 1.21 2:52 2.19 17:00 3.20 16:03 4.20 3:09 5.21 2:23 6.21 10:23 7.22 21:18 8.23 4:22 9.23 2:00 10.23 11:18 11.22 8:49 12.21 22:05
1997 1.20 8:42 2.18 22:51 3.20 21:54 4.20 9:02 5.21 8:17 6.21 16:20 7.23 3:15 8.23 10:19 9.23 7:55 10.23 17:14 11.22 14:47 12.22 4:06
1998 1.20 14:46 2.19 4:54 3.21 3:54 4.20 14:56 5.21 14:05 6.21 22:02 7.23 8:54 8.23 15:58 9.23 13:37 10.23 22:58 11.22 20:34 12.22 9:56
1999 1.20 20:37 2.19 10:46 3.21 9:45 4.20 20:46 5.21 19:52 6.22 3:49 7.23 14:43 8.23 21:51 9.23 19:31 10.24 4:52 11.23 2:24 12.22 15:43

2009年8月1日星期六

基于asterisk构建回拨运营服务系统


    在目前手机话费居高不下的情况下,基于VOIP的通信运营服务还是有一定的市场空间,毕竟通信需求是所有手机用户的第一大需求。尽管目前有一大堆提供回拨 卡/直拨服务的voip厂商(用搜索引擎搜索一下“直拨卡”或“回拨卡”,遍地都是),但这些服务提供商鱼目混珠,很难让最终用户建立其信任感,具体看来 至少有如下几点很难克服:

  • 服务提供商的品牌
  • 服务的持久性及稳定性
  • 终端渠道的推广   
  • 技术能力

    因此如果能够在品牌上、技术实现、终端渠道推广、持续运营服务上占据主导地位,那么仍然可以在混乱中取得显著的优势。

    初步考虑一下基于asterisk的回拨(call back)服务技术实现思路。

1、call back原理

    首先用户拨打回拨平台预约接入号码,平台接收到用户主叫电话号码后主动挂断电话,在指定时间内系统自动回拨到用户的电话上,用户摘机后第一个通话链路建立 (此时用户处于接听电话的状态中),系统播放提示语音,用户拨打被叫号码(实际意义上的被叫),回拨平台收完被叫号后发起第二次呼叫,同时给用户播放相应 的提示音,如被叫摘机则第二条链路建立,同时回拨平台把两条链路搭通,主被叫通话建立,客户即可正常通话。通话完毕后,系统记录下第二条链路产生的话单并 按照相应费率,在用户的账户(或卡)上扣除。回拨系统通过“双向主动呼叫技术”,完成用户长途电话呼叫的功能。实现了用户在接听电话的状态下拨打电话的功 能,客户不需要支付接入回拨系统的接入费用。

2、回拨方式

  • 电话预约回拨(ANI CallBack)

用户通过手机拨打分配的回拨接入号以后,系统将根据呼入号码对用户信息进行验证,验证成功后系统将会建立和用户之间的通话连接并播放IVR语音流程,提示用户输入所要呼叫的对方电话号码,号码输入完成后,系统将会建立用户和对方之间的通话连接。

  • Web回拨(Web CallBack)

用户通过网站登陆Web回拨页面,输入相关信息,回拨系统接受到Web服务器提交的相关信息后对用户进行验证,验证成功后建立起用户和被叫之间的通话连接。

  • Wap回拨(Wap CallBack)

    用户用手机登录wap页面,输入相关信息,回拨系统接受到wap网关提交的相关信息后对用户进行验证,验证成功后建立起用户和被叫之间的通话连接。

  • SMS回拨(SMS CallBack)

用户通过手机编写好一定格式的短信,短信内容包括账号、密码和呼叫号码等,然后发送到回拨系统指定的接收号码,回拨系统接收到短信后进行用户验证工作,验证成功后建立起用户和被叫之间的通话连接。

 

3、网络方案

在网络部署上可以采用模拟线路回拨解决方案、数字中继线回拨解决方案以及纯软件回拨解决方等三种。

  • 模拟线回拨:

    通过普通模拟线(PSTN/GSM/CDMA/PHS)回拨,VOIP或模拟线路二次出局;

  • 数字中续线回拨:

    通过数字E1/T1专线回拨,数字E1/T1专线二次出局;

  • 纯软件回拨:

    回拨以及客户二次出局全部通过VOIP线路。

 

4、技术实现

    在openser+asterisk+aster2billing+freeradius+sugarcrm基础上进行定制开发,构建回拨业务的业务支撑系统和运营支撑系统。

    除了利用传统的voip落地外,可以考虑采用skype作为asterisk的trunk来使用,充分利用skype现有的全球网络资源。

5、核心系统

   软交换系统、AAA系统 、计费系统、帐务系统、结算系统、卡管理系统、代理商管理系统、CRM系统、充值支付系统

6、运营模式

    通信服务:国际长途、国内长途、回拨卡、IP话吧、skype互通

    广告服务:PPC(pay per call)

    增值业务服务:呼叫中心SaaS、一号通、IP传真机、商务总机、web800

7、参考运营商

    http://www.rebtel.com

    http://www.talkplus.com/

    http://www.jajah.com

    http://www.voipstunt.com

    http://www.voipdiscount.com

    http://www.ipdrum.com

    http://www.ribbit.com/

    http://www.fring.com/

    http://www.flurry.com/

    http://www.mig33.com

    http://www.rimeri.com/

    http://www.boknow.com/

 

2009年7月29日星期三

比较全的PHP编码转换类(转)

转载:http://blog.163.com/wzd_0210/blog/static/24384962008215112636864/


因为对编码不熟悉,在处理起一些编码问题来,经常搞得抓耳挠腮的,最近在PHPChina中发现了一个高人写的类。可以完成一下转换

Charset::convert(string input,string incharset,string outcharset)

Charset::unescape(string escaped,string outcharset)

Charset::escape(string string,string incharset)

Charset::jsondecode(string encoded,string outcharset)

Charset::jsonencode(mix value,string incharset)

Charset::pinYin(string chinese,string incharset)

PHP代码


<?php   
/*  
 * 编码转换    
 * 说明:  
 * jsonencode 有参考Services_JSON 但有很大区别 此处可以将utf-8 gb2312 big5都可以jsonencode  
 * jsondecode 自己原创 该算法是模拟目录读取的方法   
 *   可以将json中中文unicode编码unescape为gbk big5 utf8   
 */  
define('TABLE_DIR','./table');   
define('USEEXISTS',FALSE);//是否使用系统存在的php内置编码转换函数   
//其实php内置编码转换函数转换的不够好   
class Charset{   
       
    private static $target_lang,$source_lang;   
    protected static $string = '';   
    protected static $table = NULL;  

PHP代码


/**  
 * 编码互换  
 *  
 * @param string $source  
 * @param string $source_lang  输入编码 'utf-8' or 'gb2312' or 'big5'  
 * @param string $target_lang  输出编码 'utf-8' or 'gb2312' or 'big5'  
 * @return string  
 */  
static public function convert($source,$source_lang,$target_lang='utf-8'){   
    if($source_lang != ''){   
        $source_lang = str_replace(   
            array('gbk','utf8','big-5'),   
            array('gb2312','utf-8','big5'),   
            strtolower($source_lang)   
        );   
    }   
    if($target_lang != ''){   
        $target_lang = str_replace(   
            array('gbk','utf8','big-5'),   
            array('gb2312','utf-8','big5'),   
            strtolower($target_lang)   
        );   
    }   
    if($source_lang == $target_lang||$source == ''){   
        return $source;   
    }   
    $index = $source_lang."_".$target_lang;   
    if(USEEXISTS&&!in_array($index,array('gb2312_big5','big5_gb2312'))){//繁简互换并不是交换字符集编码    
        if(function_exists('iconv')){   
            return iconv($source_lang,$target_lang,$source);   
        }   
        if(function_exists('mb_convert_encoding')){   
            return mb_convert_encoding($source,$target_lang,$source_lang);   
        }   
    }   
    $table = self::loadtable($index);   
    if(!$table){   
        return $source;   
    }   
    self::$string = $source;   
    self::$source_lang = $source_lang;   
    self::$target_lang = $target_lang;   
    if($source_lang=='gb2312'||$source_lang=='big5'){   
        if($target_lang=='utf-8'){   
            self::$table = $table;   
            return self::CHS2UTF8();   
        }   
        if($target_lang=='gb2312'){   
            self::$table = array_flip($table);   
        }else{   
            self::$table = $table;   
        }   
        return self::BIG2GB();   
    }elseif(self::$source_lang=='utf-8'){   
        self::$table = array_flip($table);   
        return self::UTF82CHS();   
    }   
    return NULL;   
}  

PHP代码


/**  
 * js 中的unescape功能  
 *   
 * @param string $str       源字符串  
 * @param string $charset   目标字符串编码 'utf-8' or 'gb2312' or 'big5'  
 * @return string  
 */  
static public function unescape($str,$charset='utf-8'){   
    $charset = strtolower($charset);   
    self::$target_lang = str_replace(   
        array('gbk','utf8','big-5'),   
        array('gb2312','utf-8','big5'),   
        $charset  
    );   
    if(self::$target_lang!='utf-8'&&   
        !(USEEXISTS&&(function_exists('mb_convert_encoding')||function_exists('iconv')))   
    ){   
        self::$table = array_flip(self::loadtable('unescapeto'.$charset));   
    }   
    return preg_replace_callback('/[\\\\|%]u(\w{4})/iU',array('Charset','descape'),$str);   
}  

PHP代码


/**  
 * js 中的escape功能  
 *   
 * @param string $str       源字符串  
 * @param string $charset   源字符串编码 'utf-8' or 'gb2312' or 'big5'  
 * @return string  
 */  
static public function escape($str,$charset='utf-8'){   
    $escaped = '';   
    $charset = strtolower($charset);   
    $charset = str_replace(   
        array('gbk','big-5','utf8'),   
        array('gb2312','big5','utf-8'),   
        $charset  
    );   
    $ulen = strlen($str);   
    if($charset!='utf-8'){   
        $table = self::loadtable($charset.'escape');   
        for($i=0;$i<$ulen;$i++){   
            $c = $str[$i];   
            if(ord($c)>0x80){   
                $bin = $c.$str[$i+1];   
                $i += 1;   
                $escaped .= sprintf('\u%04X',$table[hexdec(bin2hex($bin))]);   
                // bin2hex 返回的是string 必须再转化   
            }else{   
                $escaped .= $c;   
            }   
        }   
        return $escaped;   
    }else{   
        for($i=0;$i<$ulen;$i++){   
            $c = $str[$i];   
            $char = ord($c);   
            switch ($char>>4){   
                case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:   
                    $escaped .= $c;   
                    break;   
                case 12: case 13:   
                    $char = ((($char&0x1F)<<6)|(ord($str[++$i])&0x3F));   
                    $escaped .= sprintf('\u%04X',$char);   
                    break;   
                case 14:   
                    $char = ((($char&0x0F)<<12)|((ord($str[++$i])&0x3F)<<6)|(ord($str[++$i])&0x3F));   
                    $escaped .= sprintf('\u%04X',$char);   
                    break;   
                default:$escaped .= $c;break;   
            }   
            /*$cb = decbin(ord($c));  
            if(strlen($cb)==8){  
                $csize = strpos(decbin(ord($cb)),"0");  
                for($j=0;$j < $csize;$j++){  
                    $i++;  
                    $c .= $str[$i];  
                }  
                $escaped .= sprintf('\u%04X',self::utf82u($c));  
            }else{  
                $escaped .= $c;  
            }*/  
        }   
        return $escaped;   
    }   
}  

PHP代码


/**  
 * json_decode  
 *   
 * @param string $encoded   源字符串  
 * @param string $charset   目标字符串编码 'utf-8' or 'gb2312' or 'big5'  
 * @return string/array/boolean/null  
 */    
static public function jsondecode($encoded,$charset='utf-8'){   
    $encoded = preg_replace('/([\t\b\f\n\r ])*/s','',$encoded);//eat whitespace   
    self::$target_lang = $charset;   
    $c = self::cursor($encoded);   
    switch($c){   
        case '{':return self::parseArray($encoded);   
        case '[':return self::parseArray($encoded,FALSE);   
        case '"':return self::string_find($encoded);   
        case 't':return TRUE;   
        case 'f':return FALSE;   
        case 'n':return NULL;   
        default:return self::num_read($c.$encoded);   
    }   
}  

PHP代码


/**  
 * json_encode  
 *   
 * @param mixvar $var       多类型变量  
 * @param string $charset   默认'utf-8'源变量中字符编码 'utf-8' or 'gb2312' or 'big5'  
 * @return string  
 */  
static public function jsonencode($var,$charset=NULL){   
    if(is_null($charset)){   
        $charset = self::$source_lang;   
    }else{   
        self::$source_lang = $charset;   
    }   
    if(!$charset){   
        $charset = 'utf-8';   
    }   
    switch (gettype($var)){   
        case 'boolean':   
            return $var ? 'true' : 'false';   
        case 'NULL':   
            return 'null';   
        case 'integer':   
            return (int) $var;   
        case 'double':   
        case 'float':   
            return (float) $var;   
        case 'string':   
            $var = strtr($var,array("\r" => '\\r',"\n" => '\\n',"\t" => '\\t',"\b"  => '\\b',   
                "\f" => '\\f','\\' => '\\\\','"' => '\"',"\x08" => '\b',"\x0c" => '\f')  
            );  
            $var = self::escape($var,$charset);  
            return '"'.$var.'"';  
        case 'array':  
            return self::encodearray($var);  
        case 'object':  
            $var = get_object_vars($var);  
            return self::encodearray($var);  
        default:return 'null';   
    }   
}  

PHP代码


    /**  
     * 汉字拼音  
     *  
     * @param string $str  
     * @param string $charset     输入编码 'utf-8' or 'gb2312' or 'big5'  
     * @return string  
     */  
    static public function PinYin($str,$charset='utf-8'){   
        if($charset!='gb2312'){   
            $str = self::convert($str,$charset,'gb2312');   
        }   
        self::$table = include(TABLE_DIR.'./pinyin.php');   
        $gblen = strlen($str);   
        $pin = '';   
        for($i=0;$i<$gblen;$i++){   
            $c = ord($str[$i]);   
            if($c > 0x00A0){   
                $index = 0x10000-($c*0x0100 + ord($str[++$i]));   
                $pin .= self::getPinYin($index);   
            }else{   
                $pin .= $str[$i];   
            }   
        }   
        return trim($pin);   
    }   
    static protected function getPinYin($index){   
        if($index==0x1534) return 'yan';   
        if($index>0x4F5F||$index<0x2807){   
            return '';   
        }   
        if(!self::$table){   
            return '';   
        }   
        while(true){   
            if(!isset(self::$table[$index])){   
                $index += 1;   
                if($index > 0x4F5F){   
                    return '';   
                }   
                continue;   
            }else{   
                return self::$table[$index];   
            }   
        }   
        return '';   
    }   
    static protected function loadtable($index){   
        static $table = array();   
        $tabIndex = '';   
        switch ($index) {   
            case 'gb2312_utf-8':   
            case 'utf-8_gb2312':   
            case 'gb2312escape':   
            case 'unescapetogb2312':   
                $tabIndex = 'gbkutf';   
                break;   
            case 'big5_utf-8':   
            case 'utf-8_big5':   
            case 'big5escape':   
            case 'unescapetobig5':   
                $tabIndex = 'big5utf';   
                break;   
            case 'gb2312_big5':   
            case 'big5_gb2312':   
                $tabIndex = 'gbkbig5';   
                break;   
            default:return NULL;   
        }   
        if(!isset($table[$tabIndex])){   
            $table[$tabIndex] = @include(TABLE_DIR."/".$tabIndex.".php");   
        }   
        return $table[$tabIndex];   
    }   
    static protected function descape($str){   
        $dec = hexdec($str[1]);   
        $str = self::u2utf8($dec);   
        if(self::$target_lang == 'utf-8'){   
            return $str;   
        }   
        if(USEEXISTS){   
            if(function_exists('iconv')){   
                return iconv('utf-8',self::$target_lang,$str);   
            }   
            if(function_exists('mb_convert_encoding')){   
                return mb_convert_encoding($str,self::$target_lang,'utf-8');   
            }   
        }   
        if(isset(self::$table[$dec])){   
            return self::hex2bin(dechex(self::$table[$dec]));   
        }else{   
            return "&#".$dec.";";   
        }   
    }   
    static protected function parseArray($str,$index=TRUE){   
        $result = array();   
        $fp = self::array_open($index,$str);//模拟打开目录   
        while($fp){   
            $type = '';   
            $key = '';   
            $value = self::array_read($fp,$type,$index,$key);//模拟读取目录   
            if($type=='{'){   
                if($index){   
                    $result[$key] = self::parseArray($fp);//递归   
                }else{   
                    $result[] = self::parseArray($fp);   
                }   
            }elseif($type=='['){   
                if($index){   
                    $result[$key] = self::parseArray($fp,FALSE);   
                }else{   
                    $result[] = self::parseArray($fp,FALSE);   
                }   
            }else{   
                if($index){   
                    $result[$key] = $value;   
                }else{   
                    $result[] = $value;   
                }   
            }   
        }   
        return $result;   
    }   
    static protected function array_open($index=TRUE,$string){   
        if($index){   
            $end = '}';   
            $new = '{';   
        }else{   
            $end = ']';   
            $new = '[';   
        }   
        $endpos = self::getpos($string,$end);   
        //用getpos获得$endpos 因为要判断{,},[,]是不是在字符串里面   
        $newpos = self::getpos($string,$new);   
        $fp = '';   
        if($endpos===FALSE){   
            return 'null';   
        }elseif($newpos===FALSE||$newpos>$endpos){   
            $fp = substr($string,0,$endpos);   
            $string = substr($string,$endpos+1);   
            return $fp;   
        }else{// 条件'if($newpos<$endpos)'可以不要了 找到与自己匹对结束符   
            $i = 1;   
            while($i){   
                $endpos = self::getpos($string,$end,$endpos+1);   
                $newpos = self::getpos($string,$new,$endpos+1);   
                if($endpos===FALSE){   
                    return 'null';   
                }elseif($newpos===FALSE){   
                    $i-=1;   
                    continue;   
                }elseif($newpos<$endpos){   
                    $i+=1;   
                    continue;   
                }else{   
                    continue;   
                }   
            }   
            $fp = substr($string,0,$endpos);   
            $string = substr($string,$endpos+1);   
            return $fp;   
        }   
    }   
    static protected function getpos($string,$sign,$offset=0){   
        /**  
         * 判断是否在字符串里面原理:  
         * 取得$offset到$pos($sign)位置之间字符串中'"'个数  
         * 如果为奇数说明在字符串里面 否则在字符串外面  
         */  
        $pos = strpos($string,$sign,$offset);   
        if($pos===FALSE){   
            return FALSE;   
        }   
        $str = substr($string,$offset,$pos-$offset);   
        $arr = array();   
        preg_match_all('/"/',str_replace('\"','',$str),$arr);   
        $in = count($arr[0])%2;   
        if(!$in){   
            return $pos;   
        }   
        do{   
            $next = strpos($string,$sign,$pos+1);   
            if($next===FALSE){   
                return FALSE;   
            }   
            $str = substr($string,$pos,$next-$pos);   
            $arr = array();   
            preg_match_all('/"/',str_replace('\"','',$str),$arr);   
            $in = !(count($arr[0])%2);   
            $pos = $next;   
        }while($in);   
        return $pos;   
    }   
    static protected function array_read($fp,$type,$index=TRUE,$key=null){   
        if($fp[0]==','){   
            self::cursor($fp);//跳过','   
        }   
        if($index){//有索引的数组    
            self::cursor($fp);//跳过 '"'合法   
            $key = self::string_find($fp);//读取索引值   
            self::cursor($fp);//跳过':'   
        }   
        $c = self::cursor($fp);   
        switch($c){   
            case '{':   
                $type='{';   
                return NULL;   
            case '[':   
                $type='[';   
                return NULL;   
            case '"':   
                $rs = self::string_find($fp);   
                $s = self::cursor($fp);//跳过','or '}' or ']' 要求合法   
                if(!($s==','||$s==null)){   
                    die('parse error1!');   
                }   
                return $rs;   
            case 't':   
                if(self::cursor($fp,3)=='rue'){//跳过'rue'   
                    $s = self::cursor($fp);//跳过','or '}' or ']' 要求合法   
                    if(!($s==','||$s==null)){   
                        die("parse error$s!");  
                    }  
                    return TRUE;  
                }else{  
                    die('parse error3!');  
                }  
            case 'f':  
                if(self::cursor($fp,4)=='alse'){  
                    $s = self::cursor($fp);//跳过','or '}' or ']' 要求合法  
                    if(!($s==','||$s==null)){  
                        die('parse error4!');  
                    }  
                    return FALSE;  
                }else{  
                    die('parse error5!');  
                }  
            case 'n':  
                if(self::cursor($fp,3)=='ull'){//跳过'ull'  
                    $s = self::cursor($fp);//跳过','or '}' or ']' 要求合法  
                    if(!($s==','||$s==null)){  
                        die('parse error6!');  
                    }  
                    return NULL;  
                }  
            default:  
                $pos = strpos($fp,',');  
                if($pos===FALSE){  
                    $num = substr($fp,0);  
                    $fp = '';  
                }else{  
                    $num = substr($fp,0,$pos);  
                    $fp = substr($fp,$pos+1);  
                }  
                return self::num_read($c.$num);  
        }  
    }  
    static protected function string_find(&$str){  
        $end = strpos($str,'"',0);   
        while($str[$end-1]=='\\'){  
            $end = strpos($str,'"',$end+1);  
            if($end===FALSE){  
                return 'null';  
            }  
        }  
        $escaped = strtr(  
            rtrim(self::cursor($str,$end+1),'"'),  
            array('\\"' => '"','\\\\'=> '\\','\\/'=> '/','\\b' => chr(8),  
                '\\f'=>chr(12),'\\n'=>chr(10),'\\r'=> chr(13),  
                '\\t'=>chr(9),'\\u'=>'%u'  
            )  
        );  
        return self::unescape($escaped,self::$target_lang);  
    }  
    static protected function num_read($str){  
        $matches = array();  
        if (preg_match('/-?([0-9])*(\.[0-9]*)?((e|E)((-|\+)?)[0-9]+)?/s',$str,$matches)){  
            $num = $matches[0];  
            $val   = intval($num);  
            $fval  = floatval($num);  
            $value = $val?$val:$fval;  
            return $value;  
        }else{  
            return NULL;  
        }  
    }  
    static protected function cursor(&$str,$shift=1){  
        $get = substr($str,0,$shift);  
        $str = substr($str,$shift);  
        return $get;  
    }  
    static protected function encodearray($array){  
        if(!$array){  
            return 'null';  
        }  
        if((array_keys($array)!==range(0,sizeof($array)- 1))){  
            $rs = '';  
            foreach($array as $key=>$value){  
                $rs .= ','.self::jsonencode(strval($key)).':';  
                if(is_array($value)){  
                    $rs .= self::encodearray($value);  
                }else{  
                    $rs .= self::jsonencode($value);  
                }  
            }  
            $rs = '{'.ltrim($rs,',').'}';  
            return $rs;  
        }else{  
            $rs = '';  
            foreach($array as $value){  
                if(is_array($value)){  
                    $rs .= ','.self::encodearray($value);  
                }else{  
                    $rs .= ','.self::jsonencode($value);  
                }  
            }  
            $rs = '['.ltrim($rs,',').']';  
            return $rs;  
        }  
    }  
    static protected function CHS2UTF8(){  
        $utf8 = "";  
        while(self::$string){  
            if (ord(self::$string[0]) > 0x80){  
                $bin = substr(self::$string,0,2);  
                $utf8 .= self::u2utf8(self::$table[hexdec(bin2hex($bin))]);  
                self::$string = substr(self::$string,2);  
            }else{  
                $utf8 .= self::$string[0];  
                self::$string = substr(self::$string,1);  
            }  
        }  
        return $utf8;  
    }  
    static protected function UTF82CHS(){  
        $chs  = "";  
        $ulen = strlen(self::$string);  
        for($i=0;$i<$ulen;$i++){  
            $c = self::$string[$i];  
            $char = ord($c);  
            switch ($char>>4){  
                case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:  
                    $chs .= $c;  
                    break;  
                case 12: case 13:  
                    $char = self::$table[(($char&0x1F)<<6)|(ord(self::$string[++$i])&0x3F)];  
                    $chs .= self::hex2bin(dechex($char));  
                    break;  
                case 14:  
                    $char = self::$table[  
                        (($char&0x0F)<<12)  
                        |((ord(self::$string[++$i])&0x3F)<<6)  
                        |(ord(self::$string[++$i])& 0x3F)  
                    ];  
                    $chs .= self::hex2bin(dechex($char));  
                    break;  
                default:$chs .= $c;break;  
            }  
        }  
        /*for($i=0;$i<$ulen;$i++){  
            $c = self::$string[$i];  
            $cb = decbin(ord($c));  
            if(strlen($cb)==8){  
                $csize = strpos(decbin(ord($cb)),"0");  
                for($j=0;$j < $csize;$j++){  
                    $i++;  
                    $c .= self::$string[$i];  
                }  
                $c = self::utf82u($c);  
                if(isset(self::$table[$c])){  
                    $chs .= self::hex2bin(dechex(self::$table[$c]));  
                }else{   
                    $chs .= "&#".$c.";";  
                }  
            }else{  
                $chs .= $c;  
            }  
        }*/  
        return trim($chs);  
    }  
    static protected function BIG2GB(){  
        $ret = '';  
        while(self::$string){  
            if(ord(self::$string[0]) > 0x80){  
                $index = hexdec(bin2hex(self::$string[0].self::$string[1]));  
                $value = self::$table[$index];  
                $ret .= self::hex2bin(dechex($value));  
                self::$string = substr(self::$string,2);  
            }else{  
                $ret .= self::$string[0];  
                self::$string = substr(self::$string,1);  
            }  
        }  
        return $ret;  
    }  
    static protected function u2utf8($c){  
        $str = '';  
        if ($c < 0x80){  
            $str.= chr($c);  
        }elseif($c < 0x800){  
            $str.= chr(0xC0 | $c>>6);  
            $str.= chr(0x80 | $c & 0x3F);  
        }elseif($c < 0x10000){  
            $str.= chr(0xE0 | $c>>12);  
            $str.= chr(0x80 | $c>>6 & 0x3F);  
            $str.= chr(0x80 | $c & 0x3F);  
        }elseif($c < 0x200000){  
            $str.= chr(0xF0 | $c>>18);  
            $str.= chr(0x80 | $c>>12 & 0x3F);  
            $str.= chr(0x80 | $c>>6 & 0x3F);  
            $str.= chr(0x80 | $c & 0x3F);  
        }  
        return $str;  
    }  
    static protected function utf82u($c){  
        switch(strlen($c)) {  
            case 1:  
                return ord($c);  
                break;  
            case 2:  
                $n  = (ord($c[0]) & 0x3f) << 6;  
                $n += ord($c[1]) & 0x3f;  
                return $n;  
                break;  
            case 3:  
                $n  = (ord($c[0]) & 0x1f) << 12;  
                $n += (ord($c[1]) & 0x3f) << 6;  
                $n += ord($c[2]) & 0x3f;  
                return $n;  
                break;  
            case 4:  
                $n  = (ord($c[0]) & 0x0f) << 18;  
                $n += (ord($c[1]) & 0x3f) << 12;  
                $n += (ord($c[2]) & 0x3f) << 6;  
                $n += ord($c[3]) & 0x3f;  
                return $n;  
                break;  
            default:return '';break;  
        }  
    }  
    static protected function hex2bin($hexdata){  
        $bindata = '';   
        for ($i = 0, $count = strlen($hexdata); $i < $count; $i += 2){   
            $bindata .= chr(hexdec($hexdata[$i].$hexdata[$i + 1]));   
        }   
        return $bindata;   
    }   
}  

PHP 开发中的中文编码问题(转)

转载:http://www.phpchina.com/bbs/thread-68629-1-1.html

  PHP程序设计中中文编码问题曾经困扰很多人,导致这个问题的原因其实很简单,每个国家(或区域)都规定了计算机信息交换用的字符编码集,如美国的扩 展 ASCII 码, 中国的 GB2312-80,日本的 JIS 等。作为该国家/区域内信息处理的基础,字符编码集起着统一编码的重要作用。字符编码集按长度分为 SBCS(单字节字符集),DBCS(双字节字符集)两大类。早期的软件(尤其是操作系统),为了解决本地字符信息的计算机处理,出现了各种本地化版本 (L10N),为了区分,引进了 LANG, Codepage 等概念。但是由于各个本地字符集代码范围重叠,相互间信息交换困难;软件各个本地化版本独立维护成本较高。因此有必要将本地化工作中的共性抽取出来,作一 致处理,将特别的本地化处理内容降低到最少。这也就是所谓的国际化(118N)。各种语言信息被进一步规范为 Locale 信息。处理的底层字符集变成了几乎包含了所有字形的 Unicode。

  现在大部分具有国际化特征的软件核心字符处理都是以 Unicode 为基础的,在软件运行时根据当时的ocale/Lang/Codepage 设置确定相应的本地字符编码设置,并依此处理本地字符。在处理过程中需要实现 Unicode 和本地字符集的相互转换,甚或以 Unicode 为中间的两个不同本地字符集的相互转换。这种方式在网络环境下被进一步延伸,任何网络两端的字符信息也需要根据字符集的设置转换成可接受的内容。

  数据库中的字符集编码问题

  流行的关系数据库系统都支持数据库字符集编码,也就是说在创建数据库时可以指定它自己的字符集设置,数据库的数据以指定的编码形式存储。当应用程序访 问数据时,在入口和出口处都会有字符集编码的转换。对于中文数据,数据库字符编码的设置应当保证数据的完整性。GB2312、GBK、UTF-8 等都是可选的数据库字符集编码;当然我们也可以选择 ISO8859-1 (8-bit),只是我们得在应

  用程序写数据之前先将 16Bit 的一个汉字或 Unicode 拆分成两个 8-bit 的字符,读数据之后也需要将两个字节合并起来,同时还要判别其中的 SBCS 字符,因此我们并不推荐采用 ISO8859-1 作为数据库字符集编码。这样不但没有充分利用数据库自身的字符集编码支持,而且同时也增加了编程的复杂度。编程时,可以先用数据库管理系统提供的管理功能 检查其中的中文数据是否正确。

  PHP 程序在查询数据库之前,首先执行 mysql_query("SET NAMES xxxx"); 其中 xxxx 是你网页的编码(charset=xxxx),如果网页中 charset=utf8,则 xxxx=utf8,如果网页中 charset=gb2312,则xxxx=gb2312,几乎所有 WEB 程序,都有一段连接数据库的公共代码,放在一个文件里,在这文件里,加入 mysql_query("SET NAMES xxxx") 就可以了。

  SET NAMES 显示客户端发送的 SQL 语句中使用什么字符集。因此,SET NAMES 'utf-8' 语句告诉服务器"将来从这个客户端传来的信息采用字符集 utf-8"。它还为服务器发送回客户端的结果指定了字符集(例如,如果你使用一个 SELECT 语句,它表示列值使用了什么字符集)。

  定位问题时常用的技巧

  定位中文编码问题通常采用最笨的也是最有效的办法�在你认为有嫌疑的程序处理后打印字符串的内码。通过打印字符串的内码,你可以发现什么时候中文字符 被转换成 Unicode,什么时候Unicode 被转回中文内码,什么时候一个中文字成了两个 Unicode 字符,什么时候中文字符串被转成了一串问号,什么时候中文字符串的高位被截掉了……

  取用合适的样本字符串也有助于区分问题的类型。如:"aa啊 aa?@aa" 等中英相间,GB、GBK特征字符均有的字符串。一般来说,英文字符无论怎么转换或处理,都不会失真(如果遇到了,可以尝试着增加连续的英文字母长度)。

  解决各种应用的乱码问题

  1) 使用 标签设置页面编码

  这个标签的作用是声明客户端的浏览器用什么字符集编码显示该页面,xxx 可以为 GB2312、GBK、UTF-8(和 MySQL 不同,MySQL 是 UTF8)等等。因此,大部分页面可以采用这种方式来告诉浏览器显示这个页面的时候采用什么编码,这样才不会造成编码错误而产生乱码。但是有的时候我们会 发现有了这句还是不行,不管 xxx 是哪一种,浏览器采用的始终都是一种编码,这个情况我后面会谈到。

  请注意, 是属于 HTML 信息的,仅仅是一个声明,仅表明服务器已经把 HTML 信息传到了浏览器。

  2) header("content-type:text/html; charset=xxx");

  这个函数 header() 的作用是把括号里面的信息发到 http 标头。如果括号里面的内容为文中所说那样,那作用和 标签基本相同,大家对照第一个看发现字符都差不多的。但是不同的是如果有这段函数,浏览器就会永远采用你所要求的 xxx 编码,绝对不会不听话,因此这个函数是很有用的。为什么会这样呢?那就得说说 http 标头和 HTML信息的差别了:

  http 标头是服务器以 http 协议传送 HTML 信息到浏览器前所送出的字串。而 标签是属于 HTML 信息的,所以 header() 发送的内容先到达浏览器,通俗点就是 header() 的优先级高于 (不知道可不可以这样讲)。假如一个 php 页面既有header("content-type:text/html;charset=xxx"),又有,浏览器就只认前者 http 标头而不认 meta 了。当然这个函数只能在 php 页面内使用。

  同样也留有一个问题,为什么前者就绝对起作用,而后者有时候就不行呢?这就是接下来要谈的Apache 的原因了。

  3) AddDefaultCharset

  Apache 根目录的 conf 文件夹里,有整个 Apache 的配置文档 httpd.conf。

  用文本编辑器打开 httpd.conf,第 708 行(不同版本可能不同)有 AddDefaultCharset xxx,xxx为编码名称。这行代码的意思:设置整个服务器内的网页文件 http 标头里的字符集为你默认的 xxx字符集。有这行,就相当于给每个文件都加了一行 header("content-type:text/html; charset=xxx")。这下就明白为什么明明 设置了是 utf-8,可浏览器始终采用 gb2312 的原因。

  如果网页里有 header("content-type:text/html; charset=xxx"),就把默认的字符集改为你设置的字符集,所以这个函数永远有用。如果把 AddDefaultCharset xxx 前面加个"#",注释掉这句,而且页面里不含 header("content-type…"),那这个时候就轮到 meta 标签起作用了。

  下面列出以上的优先顺序:

  .. header("content-type:text/html; charset=xxx")

  .. AddDefaultCharset xxx

  ..

  如果你是 web 程序员,建议给你的每个页面都加个header("content-type:text/html;charset=xxx"),这样就可以保证它在任何服务器都能正确显示,可移植性也比较强。

  4) php.ini 中的 default_charset 配置:

  php.ini 中的 default_charset = "gb2312" 定义了 php 的默认语言字符集。一般推荐注释掉此行,让浏览器根据网页头中的 charset 来自动选择语言而非做一个强制性的规定,这样就可以在同台服务器上提供多种语言的网页服务。