chrome app store in new tab

Recently Google began to put app store things into chrome new tab page.

I found this on ubuntu with chromium 9.0.597.94 (73967).

It’s pretty cool and I tried a lot of things, like my favorite  flash game Canabalt, google Talk and so on.

The apps web page is also become more attractive, comparing with chrome extension web pages.

I tried google talk app the first time I saw it, and it turned to be Chrome OS only… Google is definitely working on making Chrome OS special, and unfortunately, exclusive. I really don’t like the way as Apple goes, but on the other hand, the open minded Android market is not such a success as well.

php nslookup 安全性检查

昨天做了这个http://pp.hawkwithwind.net/nslookup.php之后,忽然想到,其实完全可以做一个网页版的命令行,远程控制服务器,其实相当于网页版的ssh了。转念一想,不行,因为那样的话安全性没有保障,等于是把自家后院交给人家随意践踏了。

想到这里,忽然意识到,自己写的那个nslookup.php,其实只是简单的把用户提交的字符串前面加一个"nslookup "然后给系统调用,这样其实是非常危险的。例如我尝试在输入框里面输入twitter.com & whoami,结果除了返回twitter的ip信息,也返回了我在服务器上的用户名。这种可怕的缺陷给黑客太多可趁之机了。立刻修改。

我目前的想法是,字符串里包含后台符号 &,分号 ; , 管道符号 | , 重定向符号 > 或者选项符号 – 的时候,就拒绝服务。另外也禁止了字符串内部的空格或者换行符。这样的话,似乎就没有其他的问题了吧?我在这方面不是很熟,估计还会有问题,欢迎黑客及爱好者们赐教~

后来又发现了好多其他可能的符号会导致插入语句。。现在我禁止的符号更多了。。包括大括号{}还有问号冒号等等都被我禁掉了。。

另外,虽然只有几行代码,我把他放到了github上,希望能给大家提供一点帮助~
https://github.com/hawkwithwind/phpNetTools

nslookup – 解决ssh隧道无法访问twitter

我最近发现,即使使用ssh隧道,有时也会无法访问twitter, facebook等知名网站,但查询自己的ip地址已经在美国,并且另外一些被墙的网站如blogger等,却又能访问。想到应该是最近GFW的新动作造成的。网上查了查,在google的实时搜索中发现了很多关于最近GFW升级的传闻,很多人抱怨自己ssh或者VPN开始不好用了。

只要能够连上ssh或者vpn,GFW就无法真正对我们造成威胁。仍然无法访问这些网站,极有可能是dns污染造成的。只要能获取到正确的ip地址,就可以访问到对应的网站。然而,网上搜索到的ip地址,往往比较旧,可能已经失效。想要得到最新最正确的dns对应ip地址,最好的方法是通过墙外的主机ping得的ip地址。将其写入自己的hosts文件就好了。

为此,我自己写了一个小小的服务,用美国主机nslookup你想问的域名,给出对应的ip。
pp.hawkwithwind.net/nslookup.php
我还提供了他的api版本,只要使用如下格式的命令,就可得到 json 格式的返回包:
pp.hawkwithwind.net/nslookup.php?server=google.com
返回形式如下
['74.125.224.176', '74.125.224.177', '74.125.224.178', '74.125.224.179', '74.125.224.180']
相信还是蛮有用的。至于原理,非常简单,用php的exec函数执行nslookup命令就可以了。

逆向工程

上帝用祂的手编写了这个世界。

科学家们则辛勤地尝试将其逆向工程。

在一个不知道目标架构,源代码语言和编译方式的前提下。

=========

计算机绝不会发现,

他们其实被程序员的上帝之手所操纵。

因为他们生活在逻辑严格的自我证明的世界里。

=========

我们,能否发现构造我们的代码之源?

或者,我们只是悄悄地从生存走向毁灭。

车窗上的雨滴

最近以来困扰我的一个物理小问题是如何通过车窗上的雨滴滑落的角度来估计车行速度。因为很不巧的是似乎每次我要旅行,就一定会下雨。所以我总是盯着这些斜斜落下的雨滴,困扰着。

我最初的想法很简单。就是考虑受力情况。水滴受到的重力和迎风力的合力,一定是沿着水滴滑落的方向。当然要考虑车窗的摩擦力,但是由于那个力一定跟合力的方向相反,所以不会影响夹角。也就是说,当水滴沿着45度滑落的时候,迎风力刚好等于重力。接着考虑动量和冲量关系。假设空气在时间t内撞击水滴的动量mv全都转化为推动水滴的冲量Ft。其实不然,因为空气推动水滴后会随水滴一同移动,而非耗尽全部动量。但是由于水滴在玻璃上的滑动速度非常慢,而空气的推动速度很快(这里是以车为参考系所以空气速度就是车速),我想即使忽略之也不会有太大的误差。然后我再近似认为水滴是长a宽b高c的长方体。其迎风面积为b·c。则方程如下,发现t正好可以消去。

    Ma = Va·ρa·t·b·c
    Ma·Va = F·t
    =>
    Va2·ρa·b·c = F

我们又假设F是水受到的重力

    F = Mw·g = a·b·c·ρw·g
    a·b·c·ρw·g = Va2·ρa·b·c
    Va2 = a·ρw·g / ρa

其中除了水滴的长度a只能猜测外,其他都是常量。水的密度差不多是空气的1000倍。g估算为10。水滴的长度估计为0.5cm也就是0.005m。则这个Va差不多是25km/h。

这个数值这么低,是因为我取的角度是45度。实际行驶的时候,雨滴几乎是横着划过玻璃。可惜我没有测量他的tan值。下次旅行假如我又遇到下雨就可以通过实际测量检验我的理论是否正确啦~

协程的C实现

今天正好跟ownwaterloo聊到协程,于是查了查资料,顺便写个博客记录一下吧。

我主要参考的是这篇资料http://www.chiark.greenend.org.uk/~sgtatham/coroutines.html,是Simon Tatham提出的一个协程的C实现,非常有意思。

协程的思想主要是为了解决多个任务如何分享CPU这个问题的。线程在很多协作问题上处理的不好,而且需要锁机制,导致运行缓慢,不易理解,容易出错。协程的思想是,一系列互相依赖的协程间依次使用CPU,每次只有一个协程工作,而其他协程处于休眠状态。与线程不同,协程是自己主动让出CPU,并交付他期望的下一个协程运行,而不是在任何时候都有可能被系统调度打断。因此协程的使用更加清晰易懂,并且多数情况下不需要锁机制(或者说他本身就是一个全局锁)。

Simon的举例是一个生产者消费者例子。传统的程序可能是生产者一个循环不断产生字符,之后退出。而消费者一个循环不断读取字符,并处理之。使用时或许会用一个管道,将生产者的输出重定向到消费者的输入。从而使两者协作。

Simon提出,如何使这样的简单任务无需通过管道这类操作系统相关的重型机制,就能完成。他提出,生产者或者消费者之间,有一方需要改变自己的工作模式。不再是在循环中不断处理任务,而是一次只处理一个字符然后立刻返回。而另一方依旧保持原状,只需在原本输出到或读取自标准IO的地方修改为调用对方的那个函数就可以了。

但这种写法难以维护。他提出了协程的概念,并期待写出类似这样的代码:

int function(void) {
    int i;
    for (i = 0; i < 10; i++)
        return i;   /* won't work, but wouldn't it be nice */
}

在这里return语句并不是终止函数,而是将函数转入睡眠的状态,并将CPU交付给另一个函数执行。例如生产者写入一个字符后,调用类似的return语句,交付消费者处理这个字符。稍后当消费者处理完并调用return语句后,能重新激活生产者协程,并继续这个for循环。

如何在C语言中实现这样的功能而不需使用汇编代码去hack堆栈和寄存器呢?他给出的最初的实现是使用goto语句。

int function(void) {
    static int i, state = 0;
    switch (state) {
        case 0: goto LABEL0;
        case 1: goto LABEL1;
    }
    LABEL0: /* start of function */
    for (i = 0; i < 10; i++) {
        state = 1; /* so we will come back to LABEL1 */
        return i;
        LABEL1:; /* resume control straight after the return */
    }
}

巧妙的使用静态变量存储函数状态,并使用goto语句来继续for循环。但这种写法不够优美,于是又引入了Duff’s device。

switch (count % 8) {
        case 0:        do {  *to = *from++;
        case 7:              *to = *from++;
        case 6:              *to = *from++;
        case 5:              *to = *from++;
        case 4:              *to = *from++;
        case 3:              *to = *from++;
        case 2:              *to = *from++;
        case 1:              *to = *from++;
                       } while ((count -= 8) > 0);
    }

使用这种trick来将switch-case语句作为循环中的跳转。这就避免了goto-label语句需要同时维护goto和label两处代码的麻烦。于是前面的代码可以变成这个样子。

int function(void) {
    static int i, state = 0;
    switch (state) {
        case 0: /* start of function */
        for (i = 0; i < 10; i++) {
            state = 1; /* so we will come back to "case 1" */
            return i;
            case 1:; /* resume control straight after the return */
        }
    }
}

他的文章后面还有一些内容,例如如何使用宏包装这套机制。如何使用__LINE__宏避免state被赋予相同的数值。如何避免多线程调用下干扰静态变量等等。我这里就不赘述了,大家有兴趣可参考原文。
总之读此文的两个收获一个是认识协程,一个是学习到了一种诡谲的C语言用法。非常开心。

编程艺术之文本加工

最近在推上跟人吵编辑器什么什么的,加上最近看的几本书也都提到了文本处理的一些原则和技巧,这里把我的一些观点罗列出来,同时也作为自省的一个途径。

最近读到的书籍,主要就是《程序员修炼之道》(pragmatic programmer)和《Unix编程艺术》。另外值得提及的就是《C专家编程》。凡是讨论到这个话题,这些书都无一例外的表现出他们的黑客情结,即那种恪守清规的苦行僧般的程序大师。这种恪守清规的殉道精神纵然值得敬佩,但施用于工业则未免可笑。

编辑器的争吵已经经历了几十年,作为一个无名小辈我没有必要再跳进这个泥潭了。这里推荐的是《Unix编程艺术》中对5个Unix通用文本编辑器的讨论,虽然作者本人崇尚黑客精神,但讨论时及其严谨客观,对从精简的无可挑剔的神级编辑器ed到vi到复杂到无以附加的emacs等等,都做了及其客观的评价。并根据前文提出的十几条Unix程序设计原则以及一些程序复杂度的标准,对这些项目的设计目标和崎岖的发展历程做了总结。后文对多种编程语言的评论和分析,以及使用场合介绍,同样严谨客观,推荐诸位语言死忠阅读。

无论是语言,编辑器还是任何工具,都没有绝对的好与坏的争斗。必然在其使用范围和适用条件下有其可取之处。真正的程序员不应该抱定某种特定的环境不放,而应自如的运用任何一种工具,并将其威力发挥到极致。如同武林大师,任何武器都可手到擒来,随手抄起身边板砖菜刀,都能发挥出神入化的境界。

然而说到我本人的观点,仍难以克制心中对MS visual studio系列工具的鄙夷。首先MS这种封闭的文化确实难令人苟同,再加上他着力培养初级程序员,并通过繁杂的IDE环境来潜在的支配奴役程序员的做法更是让人感到仇恨。许多通过VB入门的人都感到自己算不上程序员,或者说难以学习其他程序。许多通过VC入门的程序员都感到VC和(不使用VC的)C++简直就是两门语言。我相信离开VS,大多数C#程序员都无法工作。我想这样的例子在编程论坛的新手区,可以找到极多例子。Apple是培养傻瓜用户,MS是培养傻瓜程序员。或许商业意义上他是对的。但作为程序员则绝无法忍受。

这也是我仇恨框架的理由。程序员不应被框架所奴役,而应随心所欲的使用程序库提供的便利。程序框架(Framework)给人的感觉就是,根本就是框架在编程序,而把你程序员当成是一个函数库。是他在调用你。作为一个程序员被程序戏耍的滋味绝不好受。这也是我对java没有好感的理由。一个程序要限定好他的界限范围,而这个要求对于一个框架来说太难做到了。一个大而全的东西总想做得更大更全,最后包罗万象,然后无可避免的走向毁灭。

最后谈一谈Unix编程思想中的“懒惰原则:宁多机器一分勿多程序员一秒”以及“生成原则:让代码生成代码”。这点在《程序员修炼之道》中也有不少论述。yacc和lex可能过于复杂了,但一些简单的脚本至少是很容易编写的。学习一门脚本语言,然后试着在C或者其他重型语言开发中使用脚本语言从旁辅助,生活会变得相当美好。在linux上cat+grep已经可以做很多事情。配合bash配合awk,或者任何其他脚本,比如流行的ruby或python,许多无意义的键盘敲击都能省却,许多依赖复杂IDE的需求,例如重构代码段,寻找函数调用和声明,检查编码规范等等,都可利用脚本完成。我之所以喜欢emacs一个重要原因就是自己写的这些脚本还可链接到一个键盘快捷键上,调用更加方便。

当然所有这些话题都是见仁见智了。或许有人会认为使用IDE正是符合了“宁多机器一分无多程序员一秒”的精神。假如确定这增加了的机器的一分钟确确实实能减少程序员一秒钟的开销的话,那也确实是值得的。