Category: 未分类

  • 花花草草

    同事收到的花:

    同事收到的花 同事收到的花

    馒头柳,挺好看的:

    馒头柳

    桃花快开了:

    桃花要开了

  • 昨晚赌赢了

    昨天晚上是我们第二次玩Texas Hold’em,最后我赢了,哈哈。

    开始的时候放舒缓的音乐,大家都舍不得下注。后来改成了斗牛士进行曲,就变得热血沸腾了。

    Texas Hold'em

    第一次的赢家这次最先出局,打扫卫生、跳绳。下次我可得小心了,不能冲动。

  • Red Hat AS 配置 Subversion

    今天在一台Red Hat AS 4的服务器上配置Subversion服务。

    首先下载源代码编译,因为没有Apache合适版本的mod_dav.h,没有生成mod_dav_svn.so,而且总是报Locale错误,删了。

    然后下了Collab Net的那个版本,配置Apache的时候说那个mod_dav_svn.so不对,只好也删了。

    最后按Subversion页面上的那个链接找到RPM包,包括apr, apr-util,安装成功,且svn/svnadmin正常运行
    。因为本来就有apr和apr-util的低版本,要用-Uvh选项升级。

    但配置Apache的时候出了问题,目录权限没问题了,访问就出错。后来在Subversion FAQ里发现Red Hat还有security con
    text的概念,正是它阻止了Apache访问代码库。于是chcon一下,可以访问了。然而加上密码验证后总是不能通过验证,这时候才想起看Apache的Log,
    原来是无法访问密码文件,permission denied. 噢,密码文件也要chcon.

    看Log很重要,Apache、Tomcat都是。

    期间有一次启动机器,随便按了几个键,好久都无法连接。插上显示器一看,原来停在选择内核那个界面上了。。。

  • 一盆花枯了

    前些天同学把一盆花放在我们宿舍窗台上,我看它叶子有点蔫,就浇了点水放到窗户外面。

    那几天下雨又下雪,它的叶子变得绿油油的,精神多了。

    可是没过多久叶子就开始变黄枯萎──原来已经冻死了。

    被我冻死的花

    听说公司要买些花来,呵呵。我还是比较喜欢看见植物的。

  • 日落真美

    昨天下了雪,今天天气晴了。空气特别清新,在18楼上,远处的山看得清清楚楚,山上还有没化的雪。

    到了黄昏,太阳落山的时候,眼看着它就在十几秒内从刺眼到消失,留下火红的余辉。深蓝的夜幕慢慢下垂,和黑色的山交融在一起。

    没想到它落得那么快。

  • 正月十五

    今天元宵节。昨天下了一整天的雨,到了晚上十一点多就飘起雪来。今天白天雪融化了,温度降了很多。

    晚上人们开始放烟花,出去看很热闹很漂亮,不过天气太冷。

    小桂子还是不改风格,上班级群里发了一句“大家中秋快乐,恭喜发财”,就跑了,留给同学们无限暇想。Shrek里驴子指着月亮问,那是什么,那个又大又圆的?今天晚上确实晴了,天上挂个又大又圆的东西,小桂子知道它是月亮:)

  • 寒假结束

    弟弟先我一天去上学,我在家也倍感无聊。周围都是小学同学,大都有了孩子,谈话没有共同语言了。

    昨天早上6:30就起床,坐车到县城。在车站看到红旗招展人山人海在等到北京的直达车,想都没想就买了到保定的票,打算从保定转车到北京。在保定站,发现等车的人更多了,被人带到个大院子里,一队人密密麻麻围了整整一圈,我们排在末尾。看见对面有个拐角,人们从那里拐出去排着队,就奇怪,拐个小弯也多放不了几个人啊。后来排到那边才发现,那里拐到了一个更大的院子里,也被人密密麻麻围了一圈,每个人刚到那里都傻眼了。排队途中不停地有开黑车的动摇人们排队的信心,让人坐他们的车。算起来,至少有一千人吧,好在车多,排了不到一小时就上了车,下午五点钟左右到了庄严肃穆的保福寺。在门口要了一笼包子,一碗面,想大吃一顿,结果吃面的时候看到了小强的尸体,真够倒霉的。

    到了宿舍,才发现是星期六,来得太早了。

    坐车接近北京的时候就感觉到在这种城市中有着和农村不一样的压力,还得拼搏。

  • 用密码保护整个blog

    WordPress 只提供对某篇文章进行密码保护,但它的标题仍然显示。如果你的Blog是写日记,可能什么都不想让外人看到。

    WP支持论坛的一个主题中给出一种非常简单的解决方案,未登录用户自动被重定向到登录页面。将以下代码复制到你的Blog根目录下,并将$siteurl变量赋予正确的值(从论坛里直接复制的代码似乎有问题)。

    <?php
    $siteurl = 'http://your.blog.url';
    
    $cookiehash = md5($siteurl);
    if(empty($_COOKIE['wordpressuser_' . $cookiehash])) :
    header('Location: /wp-login.php');
    else :
    define('WP_USE_THEMES', true);
    require('./wp-blog-header.php');
    endif;
    ?>
    

    刚才朋友让我给他弄密码保护,我把自己的改了一下,然后告诉他好了。刚才上自己Blog出了问题,才想起来改错了。。。我说怎么好几个小时没收到垃圾评论呢,看来对付spam最好的办法还是──关站。

  • GBK(GB2312)向UTF-8的编码转换

    最近做一个IE插件,要从网页中取得文字,编码到一个URL中去。在前一篇文章“中文URL编码”中,粗略地介绍了URL编码的规则,以及中文URL编码的过程,但在如何将GBK或者GB2312编码的汉字转换到UTF-8编码仍然是一个问题。编码是一个很复杂的问题,我也了解甚少,这里只是写写我的经验,欢迎补充和指正。

    在PHP、.NET中,编码的转换都比较容易。ATL中有一些宏是用来做编码转换的,我没试过,而且我更愿意用后面所讲的方法。

    在COM编程中,字符串多存储在BSTR结构中。网上许多文章都说这个数据结构中存储的就是Unicode,我就试了好多次从Unicode转UTF-8,未遂。在Debug的时候,含有中文字符串的BSTR能够正常显示,说明它的编码应该是GBK.

    如何从GBK转换到UTF-8呢?libiconv应该可以做到,然而我使用它的Windows port后,可以编译、注册COM组件,就是工具栏出不来了,于是放弃。上网搜索,得到一个被广泛转载的CChineseCode类。然而它仅仅针对汉字(每个汉字在UTF-8编码中占3个字节),如果字符串中有英文,就有麻烦了,因为英文在UTF-8编码中只有一个字节。另外有的字符会占用更多的字节。所以这个类并不适用。

    正确的方法是用Win32 API的MultiByteToWideCharWideCharToMultiByte两个函数,Wide character指的就是Unicode. GBK和UTF-8之间的转换,需要用Unicode作为桥梁(在这种方法里)。比如我们要转换这样一个字符串”编码 – Google 搜索”。

    从GBK向Unicode转换

    该字符串在BSTR类型的变量in中存储,首先将其转换为普通的字符串:

    char *lpszText = _com_util::ConvertBSTRToString(in);
    

    此时,如果用strlen函数取得lpszText的长度,则为18,4个汉字,每个占两个字节,另外有10个英文字符。所以说GBK/GB2312是MultiByte而不是WideChar. 并且有lpszText[0] == 0xb1 && lpszText[1] == 0xe0,在微软Windows Codepage 936这一页上查到果然是“编”字,更坚定了我们认为它是GBK的信心。

    转换到Unicode所用的函数是MultiByteToWideChar,第一个参数是MultiByte的Code page,如果确定是GBK,就可以使用936. 我考虑它应该是与系统有关的(比如日语系统上应该是932),所以使用CP_ACP,系统所用的Codepage.

    先通过将cchWideChar参数设置为0,取得转换后需要的空间大小,然后分配空间,再做实际的转换(转换时cbMultiByte为-1表示要转换的字符串以0结尾)。代码如下:

    int wLen = MultiByteToWideChar(CP_ACP, 0, lpszText, -1, NULL, 0);
    LPWSTR wStr = (LPWSTR)CoTaskMemAlloc(wLen * sizeof(WCHAR));
    MultiByteToWideChar(CP_ACP, 0, lpszText, -1, wStr, wLen);
    

    wLen是15,注意是指宽字符的个数,很贴心,14个字符,加上末尾的结束符。分配空间的时候也要注意,不是15个字节,而应该分配30个字节。这些在MSDN中都有说明,仔细看cchWideChar参数的介绍。最后一行代码执行后,wStr中就是这些汉字的Unicode了,查看一下,wStr[0] == 0×7f16,刚才在微软Windows Codepage 936查找时,“编”字的下面标明7f16,就是它的Unicode编码,说明一切正常。

    从Unicode向UTF-8转换

    转换到Unicode后,就可以使用WideCharToMultiByte函数将其转换到UTF-8编码,这次的code page要用CP_UTF8. 和前面的转换一样,先计算所需要的空间大小并分配,再做实际转换。

    int aLen = WideCharToMultiByte(CP_UTF8, 0, wStr, -1, NULL, 0, NULL, NULL);
    char* converted = (char*)CoTaskMemAlloc(aLen);
    WideCharToMultiByte(CP_UTF8, 0, wStr, -1, converted, aLen, NULL, NULL);
    

    aLen为23,因为4个汉字,每个占3个字节,加上10个英文字符(每个占1字节),再加末尾的’\0′,正好是23. 现在converted里就是字符串”编码 – Google 搜索”的UTF-8编码。converted[0] == 0xe7 && converted[1] == 0xbc,正是“编”字的UTF-8编码。

    好了,现在终于得到了中英文混合字符串的UTF-8字节序列,可以进行URL编码(percent encoding)了。

    如果你也看了CChineseCode类的代码,就会奇怪既然作者知道用WideCharToMultiByte做GB2312到Unicode的转换,为什么在UnicodeToUTF_8函数中要舍近求远呢?

  • 中文URL编码

    URL编码是一个比较麻烦的事情,RFC 3986是关于URI的一个标准,在它的第2节定义了字符如何在URI中进行表示,而第3节把一个URI区分为scheme, hier-part, query, fragment几个component。根据这个RFC,A URI is composed from a limited set of characters consisting of digits, letters, and a few graphic symbols. 附录A中给出了ABNF定义。

    比如URL,/blog/post139.html#comments,就包含了上述的全部四个components。这个URL不需要进行百分号编码,因为每个component中都没有保留字,全部为字母、数字或者非保留的ASCII可见字符(见RFC 3986第2.3节)。

    假设我们在Firefox中打开了这个URL,并且想通过del.icio.us的插件按钮把它收藏起来。del.icio.us插件打开一个新窗口,并通过GET方法向服务器发出请求,将这个URL和它对应的title作为query的参数传递给服务器,服务器就把这两个值填充到对应的input value属性中。

    假如不经过编码,这个GET请求中的URL就是”http://del.icio.us/flimsy?url=/blog/post139.html#comments&title=星月轮转 » Blog Archive » Blog换了个样子&noui&jump=close&v=4″。问题就出来了,#号后面的是什么呢?按理说应该解释为页面中的一个anchor,然而#comments只是url这个参数的一部分。另外,URL中含有汉字,也不符合标准。所以编码是必须的,要针对各个component,以及query中的每个参数值做percent encoding. 注意不是对整个URL(指del.icio.us的GET请求中的长URL)做,如果flimsy后面的问号被编码,服务器便不知道它后面是query部分了。正确编码后的链接应该是这样,很长,就不显示了,你可以复制链接地址来看看(似乎显示的时候浏览器又自动decode了,点击即可在地址栏看到编码后结果)

    URL编码要求先将URL转换为一个UTF-8的字节序列,然后再做percent encoding, 这在RFC 3986和W3C的网站上都有介绍。在为Firefox做插件时,主要用Javascript实现程序逻辑,而Javascript中的字符串是UTF-8编码,且有一个方便的encodeURIComponent函数可以做URL编码。除此之外,还有escape/encodeURI两个函数。关于它们三个的比较,可参考这篇文章

    如果没有现成的函数,对UTF-8字节序列进行percent encoding也是比较方便的。对于unreserved character值,不需要做转换,其它的字节全部用% HEXDIG HEXDIG来表示。另外空格除”%20″外,也可以转为”+”,节省空间。

    一个非常重要的问题就是如何把字符(ASCII字符除外,主要是中文等)转换为UTF-8的字节序列。并不是每种语言都像Javascript那样方便,比如在C++中,你得到了一个含有中文的宽字符串,怎么处理呢?Win32 API中是有一个InternetCanonicalizeUrl函数,但它只针对一个字节序列,不会考虑中文的编码转换。在MSDN“规范的URL”定义中,”Characters that must be encoded”并没有提到宽字符的处理,甚至没有提到UTF-8. 它还要求字符串中必须包含一个scheme.

    有时间的时候我会再写一篇关于怎么在Windows中把中文转换为UTF-8字节序列的文章,对进行中文URL编码的朋友也许会有帮助。见“GBK(GB2312)向UTF-8的编码转换”一文。

    PS. 网上文章一大抄,这几天体会深刻,中文文章尤甚。许多误导的文章被当作经典转来转去,充斥着搜索引擎。网上信息越来越多,有用的信息有时候却越来越难找。本文参考网上一些较为权威的资料,但仍有可能理解不对,欢迎指正。