日志分类:Develop

accept-charset与Header P3P

2009年03月20日 9:49 上午  |  分类:Develop

场景一
A网站全站均为UTF-8编码,B网站全站为GB2312编码。
A网站提供一段JS代码供B网站调用,该代码会动态生成一个FORM表单,以收集提交上来的数据。
B网站此时开始提交数据,但提交上来的中文均为乱码。
现象的产生是由于二个网站编码不一致而导致的,一般情况下使二个网站的编码一致即可。
如果无法统一编码该怎么办?

FORM有一个accept-charset属性

<form method=”post” action=”…” accept-charset=”utf-8″>

</form>

测试成功,但在IE下不成功,需要一个HACK来解决:
在form的onsubmit事件触发时动态改变document的编码,即:
onsubmit=”document.charset=’utf-8′;”

场景二
A网站提供一个页面供其它网站进行Iframe调用,该页面使用了SESSION,并进行了SESSION判断。
现象:
B网站IFRAME了A网站的页面,总显示SESSION过期,但直接在浏览器中打开该页面却又是正常的。
这是由于浏览器的安全性所致,SESSION依赖于COOKIE,A与B是二个完全不同的域,A网站没法去读取B网站下的COOKIE,所以SESSION也就失效了。
解决办法:
A网站的页面在输出头上附加一个P3P属性,值为CP=CAO PSA OUR即可。
如:

Response.AddHeader(“P3P”, “CP=CAO PSA OUR”);
if (Session[SESSIONKEY] == null)
{
//TODO:其它操作
}

Discuz中的同步登录也这样实现的

PHP需要单例模式吗?

2009年03月19日 10:33 上午  |  分类:Develop

先看看什么是单例模式
单例模式的存在在一些情况下是比较有意义的,如BlogEngine的站点配置就是采用的单例模式,而且它的载入和保存的代码是相当经典的,有兴趣可以看看它的源代码。
由于asp.net是编译型的,所以单例一直会存在于这个应用程序的生命周期里,真正可以做到这个实例在应用程序生命周期中的唯一性。

php的单例模式的实现大致如下:

class Stat{
static $instance = NULL;

static function getInstance(){
if(self::$instance == NULL){
self::$instance = new Stat();
}
return self::$instance;
}

private function __construct(){
}

private function __clone(){
}

function sayHi(){
return "The Class is saying hi to u ";
}
}
echo Stat::getInstance()->sayHi();

代码来自:http://www.cnblogs.com/cocowool/archive/2009/03/18/1415660.html
但,PHP是一种解释型的语言,在这里用单例好像看不出实际的用处,一旦整个页面执行完,变量也就消失了。

static function getInstance(){
if(self::$instance == NULL){
self::$instance = new Stat();  //这里随着页面的重载会再次执行
}
return self::$instance;
}

我接触PHP时间不长,以上写出来的只是在C#与PHP二种不同语言环境下对单例模式的认知,也许这个例子只是为了说明模式可以用很多种语言来实现,但并不意味着在各种语言环境下都能真正起作用。
asp.net中的单例是在整个应用程序域唯一。PHP中的单例只在整个页面周期内唯一

消除GD库绘制中文乱码

2009年03月13日 10:05 下午  |  分类:Develop

诚如论坛上一位朋友所说:

一般刚开始用image函数库人都不知道使用这中方法来支持中文的!

我也在这个上面卡了好久。
效果图:

一定要用支持中文的字体,然后配合imagettftext函数来使用。

$font = 'font/simhei.ttf'; //指定字体
$color = imagecolorallocate($img, 0,0,0);
$count = count($txt);
foreach($txt as $item) {
imagettftext($img, 8, 0, $x, $y, $color, $font, $item);
$y+=12;
}

如果还乱码,请先检查是在绘制图片时出错还是绘制之前就乱码。
如果绘制之前乱码可以用iconv先转换一下。
另外,用mssql_connect连mssql2005时读取中文乱码还没解决。

先不弄了,看看刚到手的玩偶


顺便b4一下蓝色,论坛签名不让放图片,弄得我这个AD没法做了:)

Discuz中的同步登录

2009年03月8日 12:40 下午  |  分类:Develop

依附于Discuz UCenter的子应用都会有一个选项:

意思很明白了,那它是如何实现的呢?
UC/Control/user.php中有一个onsynlogin方法,这里就是处理同步登录的。

function onsynlogin() {
$this->init_input();
$uid = $this->input('uid');
if($this->app['synlogin']) {
if($this->user = $_ENV['user']->get_user_by_uid($uid)) {
$synstr = '';
foreach($this->cache['apps'] as $appid => $app) {
if($app['synlogin'] && $app['appid'] != $this->app['appid']) {
$synstr .= '<script type="text/javascript" src="'.$app['url'].'/api/uc.php?time='.$this->time.'&code='.urlencode($this->authcode('action=synlogin&username='.$this->user['username'].'&uid='.$this->user['uid'].'&password='.$this->user['password']."&time=".$this->time, 'ENCODE', $app['authkey'])).'" reload="1"></script>';
}
}
return $synstr;
}
}
return '';
}

当调用该方法时,实际上会去调用该应用下api/uc.php文件,将用户名、密码及时间戳做为参数传递。
以上是实现的第一步。
第二步,当应用接收到UC的请求后,会调用uc_note类中的synlogin方法,该方法的核心是送一个P3P的HTTP头,然后种下COOKIE。

$discuz_auth_key = md5($_DCACHE['settings']['authkey'].$_SERVER['HTTP_USER_AGENT']);
header('P3P: CP="CURa ADMa DEVa PSAo PSDo OUR BUS UNI PUR INT DEM STA PRE COM NAV OTC NOI DSP COR"');
$uid = intval($uid);
$query = $this->db->query("SELECT username, uid, password, secques FROM ".$this->tablepre."members WHERE uid='$uid'");
if($member = $this->db->fetch_array($query)) {
_setcookie('sid', '', -86400 * 365);
_setcookie('cookietime', $cookietime, 31536000);
_setcookie('auth', _authcode("$member[password]t$member[secques]t$member[uid]", 'ENCODE', $discuz_auth_key), $cookietime);
} else {
_setcookie('cookietime', $cookietime, 31536000);
_setcookie('loginuser', $username, $cookietime);
_setcookie('activationauth', _authcode($username, 'ENCODE', $discuz_auth_key), $cookietime);
}

对于Disucz这种基于COOKIE验证的应用来说,就实现了同步登录。