bianbian coding life

便便代码人生: 关注技术, 翻译文档, 偶尔动动手

bianbian.org

[原]php的base64解码函数

Posted by bianbian on 2007-03-19 04:22


本文Tags: ,

调用 base64_decode() 就行了。
我承认我很BT地觉得是不是php的这个函数有问题,导致我原先提到的问题产生:php处理base64编码和Unicode客户端交互的问题
于是我照着某文档,重新实现了一下。结果发现是一样的(废话)。-___-!!
我承认我错了,当然前面那个问题不是php的原因。不过既然已经写了,我就贴一下吧。至少base64解码俺是会了。哈哈,对了,还有C语言实现的base64解码,下次也来贴一下。

  1. //php功能等同于base64_decode(),所以没有任何实际用途
  2. function my_base64_decode(&$str)
  3. {
  4.     $Bstr_base64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
  5.     $len = strlen($str);
  6.     if ($len % 4 !=0)
  7.         return '';
  8.     $res = $bins = '';
  9.     for ($i = 0; $i < $len; $i++)
  10.     {
  11.         $nChar = substr($str, $i, 1);
  12.         if ($nChar == '=')
  13.             break;
  14.         $oldValue = strpos($Bstr_base64, $nChar);
  15.         $binValue = substr('000000' . decbin($oldValue), -6);
  16.         $bins .= $binValue;
  17.        
  18.         if (strlen($bins) >= 8)
  19.         {
  20.             $deChar = substr($bins, 0, 8);
  21.             $bins = substr($bins, 8);
  22.             $res .= chr(bindec($deChar));
  23.         }
  24.     }
  25.    
  26.     return $res;
  27. }
标签: ,

遵守创作共用协议,转载请链接形式注明来自http://bianbian.org 做人要厚道

相关日志

Posted in Technology, php | 3 Comments »

[原]php处理base64编码和Unicode客户端交互的问题

Posted by bianbian on 2007-03-19 01:14


本文Tags: , , , ,

最近才对编码问题真正深入研究。因为我碰到了这个问题:客户端传过来的是对UTF-16的base64编码,而php没有办法正确解码。
有关编码,可以先看看这篇文章:字符,字节和编码
关于UTF-8和UTF-16,可以参考:谈谈Unicode编码,简要解释UCS、UTF、BMP、BOM等名词
有关URL的base64处理,可以参考这篇:通过 URL 传递 base64 编码参数的问题
摘录如下:

一般情况下,URL 中的参数应使用 url 编码规则,即把参数字符串中除了 -_. 之外的所有非字母数字字符都将被替换成百分号(%)后跟两位十六进制数,空格则编码为加号(+)。但是对于带有中文的参数来说,这种编码会使编码后的字符串变得很长。如果希望有短一点的方式对参数编码,可以采用 base64 编码方式对字符串进行编码,但是 base64 编码方式不能处理 JavaScript 中的中文,因为 JavaScript 中的中文都是以 UTF-16 方式保存的。而 base64 只能处理单字节字符,所以不能直接用 base64 对带有中文的 JavaScript 字符串进行编码。但是可以通过 utf.js 这个程序中提供的 utf16to8 来将 UTF-16 编码的中文先转化为 UTF-8 方式,然后再进行 base64 编码。这样编码后的字符串,在传递到服务器端后可以直接通过 base64_decode 解码成 UTF-8 的中文字符串。但是还有个问题需要注意。base64 编码中使用了加号(+),而 + 在 URL 传递时会被当成空格,因此必须要将 base64 编码后的字符串中的加号替换成 %2B 才能当作 URL 参数进行传递。否则在服务器端解码后就会出错。

不过,我对上述的“而 base64 只能处理单字节字符”有疑问,这是base64的标准规定,还是php的缺陷?
如果是php的缺陷,我想应该能写一个针对UTF-16的base64解码函数。这样就不需要客户端来进行UTF16转成UTF8了。

补充:
按照RFC2045的定义,Base64被定义为:Base64内容传送编码被设计用来把任意序列的8位字节描述为一种不易被人直接识别的形式。(The Base64 Content-Transfer-Encoding is designed to represent arbitrary sequences of octets in a form that need not be humanly readable.)
上面第二篇摘录如下:

UTF-8以字节为编码单元,没有字节序的问题。UTF-16以两个字节为编码单元,在解释一个UTF-16文本前,首先要弄清楚每个编码单元的字节序。例如收到一个“奎”的Unicode编码是594E,“乙”的Unicode编码是4E59。如果我们收到UTF-16字节流“594E”,那么这是“奎”还是“乙”?

Unicode规范中推荐的标记字节顺序的方法是BOM。BOM不是“Bill Of Material”的BOM表,而是Byte Order Mark。BOM是一个有点小聪明的想法:

在UCS编码中有一个叫做”ZERO WIDTH NO-BREAK SPACE”的字符,它的编码是FEFF。而FFFE在UCS中是不存在的字符,所以不应该出现在实际传输中。UCS规范建议我们在传输字节流前,先传输字符”ZERO WIDTH NO-BREAK SPACE”。

这样如果接收者收到FEFF,就表明这个字节流是Big-Endian的;如果收到FFFE,就表明这个字节流是Little-Endian的。因此字符”ZERO WIDTH NO-BREAK SPACE”又被称作BOM。

UTF-8不需要BOM来表明字节顺序,但可以用BOM来表明编码方式。字符”ZERO WIDTH NO-BREAK SPACE”的UTF-8编码是EF BB BF(读者可以用我们前面介绍的编码方法验证一下)。所以如果接收者收到以EF BB BF开头的字节流,就知道这是UTF-8编码了。

Windows就是使用BOM来标记文本文件的编码方式的。

也就是说,base64编码必须针对单字节。从这个角度说,是不能对UTF-16的字串进行base64编码操作的。难怪php解码后得到的结果不一致。原来问题不是出在php上。

我又看了客户端base64编码部分的代码,确实是客户端的问题。客户端用了“(const BYTE*)sSrcBuf ”把UTF-16的双字节强制转为BYTE流之后进行base64编码,结果是错误的。难怪我解码以后英文字符之间都有莫名奇妙的“空格”(实际是“00”,但是记事本看网页源代码上的“00”显示成空格)。
实际上是这样的:比如“ABC”,UTF-8字节流是“41 42 43”。而UTF-16则是“41 00 42 00 43 00”,所以“(const BYTE*)sSrcBuf ”之后,“00”就被作为单独的一个字节进行了转码,所以解码以后就还原为UTF-8的字节流“41 00 42 00 43 00”,这时候跟初始的“41 42 43”已经不一致了(print的时候只能打出“A”)。难怪我的SQL会报出“ERROR: unterminated quoted string at or near “‘A” at character”的错,因为数据库读取SQL读到“00”就认为结束了。
这时候我冒出一个想法,要是服务器端解码以后再强制把字节流当做UTF-16转为UTF-8,结果不就一样了吗?
事实证明我的想法是正确的:

  1. $utf16 = chr(hexdec('FF')) . chr(hexdec('FE')) . base64_decode($_GET[abc]);
  2. print(iconv('UTF-16', 'UTF-8', $utf16));
  3. //输出"ABC",这是对的!

最后还有一个问题,UTF-16的BOM不一定是FF FE,也可能是FE FF。这怎么办?要是有ASCII字符还好办,两个两个的找,看“00”是在前还是在后。要是双字节都有内容呢?举上面文章的例子:“奎”的Unicode编码是594E,“乙”的Unicode编码是4E59。如果我们收到UTF-16字节流“594E”,那么这是“奎”还是“乙”?
这个问题单纯改服务器端php没有办法解决。最终的解决办法只有两个:
1)如上面文章所说,客户端UTF-16先转成UTF-8再base64编码,再提交;显示的时候转回UTF-16
2)客户端可以基于UTF-16的字节流base64编码,但是提交的时候要带上“BOM”,即指明是“FFFE”,还是“FEFF”

当然,如果能确定客户端的Unicode的BOM方式,上面的2)也可以不用。
直接在服务器端加上BOM标记进行转码即可。
好像Windows下都是FFFE的,所以可以直接用这个:

  1. //加上UTF-16 BOM的base64解码(客户端是根据FFFE的Unicode base64的)
  2. function get_utf8_from_base64_utf16(&$str)
  3. {   
  4.     $utf16 = chr(hexdec('FF')) . chr(hexdec('FE')) . base64_decode($str);
  5.     return iconv('UTF-16', 'UTF-8', $utf16);
  6. }
标签: , , , ,

遵守创作共用协议,转载请链接形式注明来自http://bianbian.org 做人要厚道

相关日志

Posted in Technology, php | 2 Comments »

[原]超级简单访问PostgreSQL的小型php类

Posted by bianbian on 2007-03-17 07:55


本文Tags: , , ,

实在受不了ADOdb之类的庞大库了,还有网上下的几个库也超级难用,我自己写了一个。只当简单的用,事务之类的我还没有用到,所以没有写进去。感兴趣的可以补充。好像里面的函数有些要php 4.2以上的。
使用示例:

  1. <?php
  2. $db = & new PostgreSQL();
  3. //single record:
  4. $record = & $db->query_first("SELECT * FROM table WHERE id=xxx");
  5. //many lines:
  6. if ($records = & $db->query_all("SELECT * FROM table WHERE id>xxx")) {
  7.     foreach ($records as &$record) {
  8.         ...
  9.     }
  10. }
  11. $db->close();
  12. ?>

类的代码:
Read the rest of this entry »

标签: , , ,

遵守创作共用协议,转载请链接形式注明来自http://bianbian.org 做人要厚道

相关日志

Posted in Technology, php | 1 Comment »

[原]php用UTF-8编码总结

Posted by bianbian on 2007-03-16 18:25


本文Tags: , ,

前几天说的PostgreSQL ERROR原来是php文件没有UTF-8编码导致的问题。
以前说过如果JS文件不是UTF8会在IE有bug,所以JS代码也要用UTF-8。
还有数据库也都要用UTF-8。
php用UTF-8总结:
1) php文件本身必须是UTF-8编码。不像Java会生成class文件,避免这个问题。
2) php要输出头:header(”Content-Type: text/html; charset=UTF-8″);
3) meta标签无所谓,有header所有浏览器就会按header来解析
4) 所有外围都得用UTF8,包括数据库、*.js、*.css(CSS影响倒不大)
5) 最后,php本身不是Unicode的,所有substr之类的函数得改成mb_substr(需要装mbstring扩展);或者用iconv转码(基本上的linux都装了,没装的话download、tar、make、make install,很简单的)
特别郁闷的:
文件系统函数不支持UTF-8!

听说php6已经内置Unicode支持,以后试一下。

标签: , ,

遵守创作共用协议,转载请链接形式注明来自http://bianbian.org 做人要厚道

相关日志

Posted in Technology, php | No Comments »

[原]php版md5,sha-1哪个更快

Posted by bianbian on 2007-03-16 08:01


本文Tags: , ,

一般随机密码都是rand()出来的,我就偷懒直接拿md5,sha-1这些函数来算了:

  1. $s = microtime(true);
  2. for($i = 0; $i < 100000; $i++)
  3.     getRandomPassword();
  4. echo microtime(true) - $s;
  5.  
  6. function getRandomPassword()
  7. {
  8.     ///除去substr和rand的版本:
  9.     //md5(microtime();
  10.     return substr(md5(microtime()), rand(0, 20), 8);
  11. }

经过测试,md5比sha1快(废话 - -):

function with substr and rand only function
md5 1.94637799263 1.79774594307
sha-1 2.12755990028 1.97592806816
标签: , ,

遵守创作共用协议,转载请链接形式注明来自http://bianbian.org 做人要厚道

相关日志

Posted in Technology, php | No Comments »

[原]发现php几个很方便的函数

Posted by bianbian on 2007-03-16 05:03


本文Tags: , ,

确实好久没接触php了,发现自己很落后了。呵呵,其实几年以前我还是php的超级粉丝。
嗯,突然想起大二时用php做过的一个网站:http://www.geohohai.com。这是我第一份Parttime Job,虽然因为客户的需求不是很明确导致我做的很累,不过从和客户谈、合同编写、项目整体规划、项目文档、美工、编码、部署、验收演示整个流程都是自己一个人搞定,我还是很感谢他们给了我这个长足进步的机会的,也是此后靠IT经济自理的正式开端(以前搞家教,真是的:认真备课教的学生反而没进步;随便瞎吹的反而大进步。真是汗颜)。
我又突然怀念起那一个人的浦口暑假,听着梁静茹,啜着咖啡,为了第一份薪水拼命敲键盘,背后是穿过窗帘的夕阳洒下的斑驳。。。。。为什么回忆总是美好的呢?
刚才点过去突然发现几年过去了,他们已经换成asp了。寒,他们又重复开发了一次,不过基本上的美工和系统架构还是我那个:我也是看链接是asp才发现的。架构也基本上是当时我能想出来最先进的了:所有菜单、所有内容都是后台生成的;菜单配置是程序生成JavaScript代码。嗯,又发神经看了一下JS代码,果然这个还在:
/* 本文件由系统产生,请勿更改 Written by http://dzren.com */
说到http://dzren.com,真是遗憾。原来是“东中人”的意思,做的是我高中母校的校友录,是我学网页编程的练习场所。承蒙大家支持和当时年轻气盛,也有兴旺发达的几年零几个月。可惜没有精力维护下去,现在域名都给别人捡走了。留了几百兆的压缩包在我硬盘上(主要是有上传的照片)。每次看到都伤心一番。。。。
。。。。离题了一大通。。。。
php还是在快速开发方面有很大的优势和进步。这次因为项目转别人的ASP+ACCESS到php+PostgreSQL平台,嗯,重温了一下。发现不用写Java的配置文件,还真是爽啊。
嗯,突然不想写了,贴个Example的代码吧(来自Tore Bjlseth),大家都看得明白:

  1. $url1 = "action=search&interest[]=sports&interest[]=music&sort=id";
  2. $str = parse_str($url1, $output);
  3.  
  4. // Modifying criteria:
  5. $output['sort'] = "interest";
  6.  
  7. $url2 = http_build_query($output);
  8.  
  9. echo "<br>url1: ".$url1;
  10. echo "<br>url2: ".$url2;
  11. /*
  12. Results in:
  13. url1: action=search&interest[]=sports&interest[]=music&sort=id
  14. url2: action=search&interest[0]=sports&interest[1]=music&sort=interest
  15.  
  16. (Array indexes are automatically created.)
  17. */
标签: , ,

遵守创作共用协议,转载请链接形式注明来自http://bianbian.org 做人要厚道

相关日志

Posted in Technology, php | 2 Comments »

[原]php使用PostgreSQL的编码问题

Posted by bianbian on 2007-03-15 02:43


本文Tags: , , ,

php 5.2 PostgreSQL 8.1
数据库是用UTF8编码建的:
./createdb -E UNICODE xxxx
但是用php插入中文数据的时候会报错:
ERROR: invalid byte sequence for encoding “UTF8″ ….

看字面意思,好像是因为数据库是UTF8,而插入的数据不是UTF8导致的错误。到psql终端下:

# \encoding
UTF8
# show client_encoding;
UTF8

前面一个UTF8是数据库的编码,后一个表示客户端数据编码(就是插入数据的编码)。
怎么解决?

本问题已经解决,请参考这里:php用UTF-8编码总结

标签: , , ,

遵守创作共用协议,转载请链接形式注明来自http://bianbian.org 做人要厚道

相关日志

Posted in Database, Technology, php | No Comments »

[呜]可怜的信用卡终于申请下来了

Posted by bianbian on 2007-03-14 00:09


本文Tags: ,

申普卡被据了,只好Young卡了。。。5555。。。
申请卡名 申请卡别 收件日期 申请进度情况
Young卡
(VISA 普卡) 主卡 2007-03-02 恭喜您,您申请的信用卡已被批准,很快您会收到我们为您寄发的卡片。

标签: ,

遵守创作共用协议,转载请链接形式注明来自http://bianbian.org 做人要厚道

相关日志

Posted in Not IT | No Comments »

[原]用pgAdmin建表的时候一定不要大写

Posted by bianbian on 2007-03-12 17:35


本文Tags: ,

想为了省事,没装PowerDesign,直接用了pgAdmin设计表。
我K,被它害死了:每个表每个字段有大写的都用了引号引起来。。。
导致的后果就是:拼SQL语句的时候必须也加上引号,不然每次都
ERROR:relocation [TableName] does not exist…..

于是简单的“insert into Table(Column1,Column2)...”必须写成“insert into "Table"("Column1", "Column2")....”

我说,还不如重新建表吧。。。K pgAdmin它大爷。。。。

标签: ,

遵守创作共用协议,转载请链接形式注明来自http://bianbian.org 做人要厚道

相关日志

Posted in Database, Technology | No Comments »

[哈]蛮搞笑的嘛。。。

Posted by bianbian on 2007-03-10 20:40


本文Tags:

*嘘嘘 20:12:31
便便吃了么?我吃完了,,,

标签:

遵守创作共用协议,转载请链接形式注明来自http://bianbian.org 做人要厚道

相关日志

Posted in Not IT, bianbian & xuxu | No Comments »

[原].NET反编译工具Reflector

Posted by bianbian on 2007-03-07 10:59


本文Tags: ,

其实.NET的dll和Java的class文件是类似的,果然也有对应的“反编译”工具:Reflector
真的很好用,我谢谢它了!
到Reflector官方网站(http://www.aisto.com/roeder/dotnet/)下载最新版本下载后
(要填姓名、单位和email,姓名要中间空一格,比如“bianbian xuxu”)
解压缩会有一个Reflector.exe直接就可以运行,界面如下:
.NET反编译工具
打开一个.NET的库DLL,直接点方法就可以看源码了。。。。
这里是它的一些插件:
http://www.codeplex.com/reflectoraddins
其中我就用了FileDisassembler,功能就是将所有dll反编译的源码导出来。

标签: ,

遵守创作共用协议,转载请链接形式注明来自http://bianbian.org 做人要厚道

相关日志

Posted in C#, Technology | 2 Comments »

[哈]对未来的美好展望

Posted by bianbian on 2007-03-07 06:58


本文Tags: ,

用psp wifi无线看电脑上的PMP-AVC电影成功!

现在出了个牛人,在psp上能看rm和rmvb的格式了
虽然有待完善,毕竟是有希望的!这个牛人还是Chinese,赞美你阿!!

于是我展望未来,wifi看rmvb!

哇,那是怎样的美景阿,再也不用辛苦地转码了。

希望这个牛人爆发阿,瞬间推出完美版。。。。

由于侵权,我们要保护好牛人。谁问都说不知道。

可耻地流口水了。。。

标签: ,

遵守创作共用协议,转载请链接形式注明来自http://bianbian.org 做人要厚道

相关日志

Posted in Entertainment, Not IT | 3 Comments »

[哈]PSP 3.10 OE-A版本太牛X了

Posted by bianbian on 2007-03-01 23:42


本文Tags:

哈哈哈哈,可以直接玩ISO了!!不需要DEVHOOK了(其实应该是牛人把DEVHOOK写到PSP固件里了)。
哈哈哈哈,还能直接玩电脑上的ISO!!
加上PPA,可以wifi看电脑上的电影了,怎一个爽字了得。
还有Cheat Master外挂,类似FPE和金山游侠的游戏数据修改工具哦~哈哈

标签:

遵守创作共用协议,转载请链接形式注明来自http://bianbian.org 做人要厚道

相关日志

Posted in Entertainment, Not IT | 2 Comments »

[原]C#里更改控件的显示Z顺序

Posted by bianbian on 2007-03-01 23:00


本文Tags: , , ,

Z顺序(Z-Index)就是控件在绘制时候哪个在上哪个在下的顺序,就像PhotoShop里面的图层顺序。这个是很有用的,最早的虚拟形象(QQShow之类)就是利用Z顺序将N多小图片组合在一起拼合成一张图片,用图层相互覆盖的原理显示复杂的虚拟形象。扯远了,其实简单的说就是如下所示(B的Z-Index比A大,于是遮住了重叠的部分):
z-index.GIF
可是今天在C#里找了半天也没有发现设置Z顺序的方法。真是郁闷得紧。
于是想看看C#的设计器是怎么实现的,用设计器分别设计了A重叠B和B重叠A(又怀念Delphi一下),查看Design的源代码,OMG,还是没有涉及Z-Index的方法。。。
再看了一下,看来只跟Add到this.Controls里面的顺序有关了。验证了一下,果然如此:先Add的控件会在最上面。。。。。真是汗颜。。。。。
知道了原理,想个解决办法也不难了:就是Add控件进this.Controls之前根据啥属性(我看Tag属性挺好的)排个序。
如果需要运行中间改变某个控件的Z顺序,我看只能在this.Controls里综合运用Remove、Add了。。。
试验了一下,是可以的,代码写得实在太丑了,我就不献丑了。:(

标签: , , ,

遵守创作共用协议,转载请链接形式注明来自http://bianbian.org 做人要厚道

相关日志

Posted in C#, Technology | 2 Comments »

[嗯]二月马上过去了

Posted by bianbian on 2007-02-28 22:39


本文Tags:

祝大家春节愉快,居然开学了。
明天游泳馆终于开放了,憋了一个月没游泳,哇哇哇。
这个月基本上处于忙碌、看片、过节的状态,所以没啥技术文章,还请大家原谅。
另外,恭喜Delphi 2007 for WIN32公布,这是Borland卖了IDE后的第一个版本,我还没有试过。

标签:

遵守创作共用协议,转载请链接形式注明来自http://bianbian.org 做人要厚道

相关日志

Posted in Not IT | No Comments »