« June 2005 | Main | August 2005 »

July 26, 2005

maildrop - Webmail dev problem - 解决了几个隐晦问题

这两天解决了几个开发中遇到的疑难杂症,特此篆文记录。

无论在软件项目的实施,还是系统的开发甚至只是编写一小段代码,经常会遇到一些让人白思不得其解的问题,耗费了大量的时间,用尽了办法却位能解决。感觉就有点得了疑难杂症,便访天下名医却不得根治一样。

但最后发现这些问题的症结,往往都是很小小的问题,却不为人所注意,或者隐藏得非常深入,常人难以发现。

Maildrop 的0x0B故障分析及解决
使用maildrop作为VDA/MDA的用户为数不少,绝大多数用户使用maildrop都是因为其过滤能力强,过滤语言灵活,支持Quota,并可与MySQL/LDAP及小型dbm对接,可外挂各种程序,如SpamAssassin,杀毒软件,甚至SMS等,实现复杂的功能。

但是maildrop常见的一个问题就是经常会遇到0x0B的意外退出问题。除了编译器(使用的Gcc c++版本问题)和编译优化指令太高(如高于O2等)的问题外,还有少数问题是不为人们所注意的。

在自己开发一个全新的webmail系统中,maildrop的投递uid/gid都是250,这样的配置跑了几年都没任何问题,工作得非常可靠。但是由于webmail需要直读Maildir,按常规的方法必须设置成setuid/gid程序,或将apache的User/Group设置成250,这样非常麻烦,尤其在新的SELinux下会造成诸多不便,为此使用了Suexec的配置,但是Suexec的RPM包默认UID_MIN >= 500,于是将user/group从250/250改成了1000/1000,结果问题就来了。

投递邮件时,maildrop死活都返回0x0B错误,无论我将user/group改成多少也好,包括mysql里的uidnumber/gidnumber、maildropmysql.config里的default等都改了,完全没有任何效果。

后来再试验su成uid=1000的用户呼叫maildrop发现也是0x0B错误,只有在root权限下没问题,于是又查了maildrop的INSTALL甚至看了source!都是无任何迹象显示与这个错误有关,于是只有google了。但也没什么有效的解决办法。

后来偶然看到一个法文的邮件列表上,看到有人在讨论maildrop的mysql配置,忽然想到,自己的maildrop rpm包自动设置了/etc/maildropmysql.config文件属性是uid=250, gid=250的,于是ls -l /etc/maildropmysql.config一看,原来症结就在这里!

我改了所有该改的地方,就是没有对配置文件的owner/group进行修改,而配置文件原本的属性是600,这样导致了maildrop换成其他uid/gid运行时无法读取配置文件,导致了0x0B错误。执行:

chown -R 1000.1000 /etc/maildropmysql.config

之后一切问题就迎刃而解了。

Webmail解决setuid/gid问题
昨天正在着手解决全新设计的webmail系统setuid/gid的问题,以适应在SELinux下的应用。自己怕麻烦,暂时不想去做相应的policy,所以只有动脑筋了。

幸好RHEL/CentOS/FC3等自带的policy都支持suexec,因此就决定利用suexec来实现与apache不同的运行uid/gid,以达到直接访问Maildir的目的。

在虚拟主机中的配置:

.....
SuexecUserGroup vuser vgroup
Alias /extmail/ /var/www/cgi-bin/extmail/
<Location "/extmail/cgi">
  SetHandler cgi-script
  Options +ExecCGI
</Location>
.......

注意: 之所以将cgi程序放到/var/www下是因为Suexec的docroot限制在了这里,详细的suexec编译参数可以通过Suexec -V查看,以下是CentOS 4.1的结果:

 -D AP_DOC_ROOT="/var/www"
 -D AP_GID_MIN=100
 -D AP_HTTPD_USER="apache"
 -D AP_LOG_EXEC="/var/log/httpd/suexec.log"
 -D AP_SAFE_PATH="/usr/local/bin:/usr/bin:/bin"
 -D AP_UID_MIN=500
 -D AP_USERDIR_SUFFIX="public_html"

最后,将程序及模板等属性全部改为要运行的uid/gid即可:

chown -R vuser.vgroup /var/www/cgi-bin/extmail

重新启动httpd,通过/var/log/httpd/suexec.log可以看到如下的信息:
[2005-07-26 20:55:51]: uid: (1000/vuser) gid: (1000/1000) cmd: folders.cgi

证明配置成功,这样webmail就不必再设置为setuid了,而且apahce也不必以1000/1000的id来运行了。

chdir()引起的模板问题之解决
开发Webmail时,引入了模板机制,这将大大提高了用户修改的便捷程度,也缩短了开发人员的工作周期。但是这几天遇到了一个问题,在调用了Storage::Maildir模块之后,模板的解析就无论如何都不正常了,总说file not found,但明明文件没有任何错误。

而如果先于呼叫Storage::Maildir之前解析模板则完全没问题,开始怀疑是SELinux的问题,但kernel日志里又无任何不妥。

后来通过一点一点分析,包括对template解析库的修改等都印证了各种代码都没有问题。最后将目光放到了Storage::Maildir,该模块在use的时候会利用chdir()初始化当前工作路径,这样做之后,将使cgi程序的工作路径和之前不同了,对于没使用绝对路径进行模板解析的应用,自然会遇到问题。

代码分析:


my $tpl = Ext::Template->new("../html/");
my $mm = Ext::Storage::Maildir;

$tpl->assign(TEST => 1);

restore_path(); # XXX recover working directory
$tpl->process("index.html");
$tpl->print;
....

sub restore_path {
     my $src=$ENV{SCRIPT_FILENAME};
     $src=~s#(.*)/[^\/]+$#$1#;
     chdir($src);
}

上述代码中,在进行模板解析之前,呼叫restore_path(),将工作路径恢复到调用Storage::Maildir之前的原始状态。这样解析就不再有问题了。

Posted by hzqbbc at 09:18 PM | Comments (0)

July 22, 2005

Apache under SELinux - 让Apache跑得顺起来!

对于刚使用Redhat Enterprise Linux4 或Fedora Core 2以上/CentOS 4的用户,一定会为Apache经常无法正常运转,报以"Permission denied"等错误而大为不解,甚至大为恼火。

其实这是因为这些系统里激活了SELinux,而用户的apache配置与SELinux的配置策略有抵触产生的,只有通过适当调整,使apache的配置和访问符合策略才能正常使用。

现在下面来分析一下SELinux中有关httpd(apache)的context定义(略有删节)

/home/[^/]+/((www)|(web)|(public_html))(/.+)? system_u:object_r:httpd_user_content_t
/var/www(/.*)?                  system_u:object_r:httpd_sys_content_t
/var/www/cgi-bin(/.*)?          system_u:object_r:httpd_sys_script_exec_t
/usr/lib/cgi-bin(/.*)?          system_u:object_r:httpd_sys_script_exec_t
/var/www/perl(/.*)?             system_u:object_r:httpd_sys_script_exec_t
/var/www/icons(/.*)?            system_u:object_r:httpd_sys_content_t
/var/cache/httpd(/.*)?          system_u:object_r:httpd_cache_t
/etc/vhosts             --      system_u:object_r:httpd_config_t
/usr/sbin/httpd         --      system_u:object_r:httpd_exec_t
/usr/sbin/apache(2)?    --      system_u:object_r:httpd_exec_t
/usr/sbin/suexec        --      system_u:object_r:httpd_suexec_exec_t
/var/log/httpd(/.*)?            system_u:object_r:httpd_log_t
/var/log/apache(2)?(/.*)?       system_u:object_r:httpd_log_t
/var/log/cgiwrap\.log.* --      system_u:object_r:httpd_log_t
/var/cache/ssl.*\.sem   --      system_u:object_r:httpd_cache_t
/var/cache/mod_ssl(/.*)?        system_u:object_r:httpd_cache_t
/var/run/apache(2)?\.pid.* --   system_u:object_r:httpd_var_run_t
/var/lib/httpd(/.*)?            system_u:object_r:httpd_var_lib_t
/var/lib/php/session(/.*)?      system_u:object_r:httpd_var_run_t
/etc/apache-ssl(2)?(/.*)?       system_u:object_r:httpd_config_t
/usr/lib/apache-ssl(/.*)? --    system_u:object_r:httpd_exec_t
/usr/sbin/apache-ssl(2)? --     system_u:object_r:httpd_exec_t
/var/log/apache-ssl(2)?(/.*)?   system_u:object_r:httpd_log_t
/var/run/apache-ssl(2)?\.pid.* -- system_u:object_r:httpd_var_run_t
/var/run/gcache_port    -s      system_u:object_r:httpd_var_run_t
/var/lib/squirrelmail/prefs(/.*)?       system_u:object_r:httpd_squirrelmail_t
/usr/bin/htsslpass --   system_u:object_r:httpd_helper_exec_t
/usr/share/htdig(/.*)?          system_u:object_r:httpd_sys_content_t
/var/lib/htdig(/.*)?            system_u:object_r:httpd_sys_content_t

针对上述的内容,可以对如下的几个常见问题进行简单处理:

1.phpmyadmin在非默认/var/www/html目录下无法运转
通常类似的情况都是在配置了虚拟主机时,访问/phpmyadmin等提示403访问拒绝,日志里也提示Permission denied,这是因为phpmyadmin防止的目录及文件本身属性不符合context要求。

假设phpmyadmin放在/web目录下,那么执行:

chcon -R -t httpd_user_content_t /web

则会令/web及其下所有子目录/文件,包括phpmyadmin文件都获得了httpd_user_content_t的属性,如果其传统的Unix属性对httpd来说是可读的话,再重新访问一下就应该可以了。

2./home目录下的虚拟主机无法运转
与问题1也是类似的,不过根据上文中context的定义,/home目录下必须是用户的$HOME/www或public_html或web目录才是httpd_user_content_t类型,因此建议将要作为web页面的内容放置在用户的$HOME/www或web或public_html里,并确保其属性是httpd_user_content_t,使用如下命令查看:

ls -Z /home/abc/
drwxr-xr-x  abc   abc   user_u:object_r:user_home_dir_t    tmp
drwxrwxr-x  abc   abc   user_u:object_r:httpd_user_content         www

如不是,则可通过chcon来逐级目录及文件更改,直至最后能访问:

chcon -R -t httpd_user_content_t /home/abc/web
chcon -t user_home_dir_t /home/abc

3.CGI程序无法运行
如果cgi程序放在/var/www/cgi-bin/里也无法执行,遇到403或500错误的话,可以检查cgi程序的属性,按SELinux contexts文件里定义的,/var/www/cgi-bin/里必须是httpd_sys_script_exec_t 属性。通过ls -Z查看,如果不是则通过如下命令更改:

chcon -t httpd_sys_script_exec_t /var/www/cgi-bin/*.cgi

如果是虚拟主机里的cgi,则参考问题2使之能正常使用普通的功能后,再通过chcon设置cgi文件的context为httpd_sys_script_exec_t即可。

4.Setuid/gid 程序无法运行
例如早期的SqWebMail及qmailadmin等,需要setuid/gid的支持,但在SELinux下这将受到严格限制。第一种方法是比较彻底的办法,能保留系统的安全性,通过:

audit2allow -l -i /var/log/messages

将SELinux拒绝的信息转换为相应的policy allow指令,将这些指令添加到SELinux policy 的src里相应的配置文件,重新生成policy并加载。但这样做相对比较麻烦。

另一个方法最简单,但将使apache得不到保护。首先确定SELinux 类型是targeted的:

cat /etc/selinux/config|grep SELINUXTYPE

然后,使apache脱离SELinux保护:

setsebool -P httpd_disable_trans 1

然后重启动apache:

/etc/init.d/httpd restart

这样所有apache强制的检查都失效,需要setuid/gid的程序可以正常使用。但这样带来了增加漏洞的危险,对于迫切需要运行而又很急的情况,本方法是一个最大限度减少系统安全缺失的最后办法。对于取消SELinux 未必是一个好方法。

Posted by hzqbbc at 10:02 PM | Comments (0)

July 20, 2005

SELinux Introduce - SELinux技术简介

在Redhat Enterprise Linux 4.0或Fedora Core 2 Linux以上版本的Linux中,有不少用户经常会遇到诸如apache的Permission denied,X windows打不开等等问题,抛开一些常规配置错误外,很大一部分原因是因为激活了SELinux的缘故。

什么是SELinux?SELinux全称是Security Enhanced Linux,由美国国家安全部(National Security Agency)领导开发的GPL项目,它拥有一个灵活而强制性的访问控制结构,旨在提高Linux系统的安全性,提供强健的安全保证,可防御未知攻击,据称相当于B1级的军事安全性能。比MS NT所谓的C2等高得多。

应用SELinux后,可以减轻恶意攻击或恶意软件带来的灾难,并提供对机密性和完整性有很高要求的信息很高的安全保障。

SELinux vs Linux
普通Linux安全和传统Unix系统一样,基于自主存取控制方法,即DAC,只要符合规定的权限,如规定的所有者和文件属性等,就可存取资源。在传统的安全机制下,一些通过setuid/setgid的程序就产生了严重安全隐患,甚至一些错误的配置就可引发巨大的漏洞,被轻易攻击。

而SELinux则基于强制存取控制方法,即MAC,透过强制性的安全策略,应用程序或用户必须同时符合DAC及对应SELinux的MAC才能进行正常操作,否则都将遭到拒绝或失败,而这些问题将不会影响其他正常运作的程序和应用,并保持它们的安全系统结构。

SELinux on Redhat Linux
在RHEL4.0或FC3以上的版本中,可以在安装时就选择是否激活SELinux,系统自动会安装相应的内核、工具、程序等。由于SELinux的MAC机制将极大的影响了现有引用,因此RHEL4/FC3中已预配置了大量兼容现有应用的安全策略。

SELinux的配置相关文件都在/etc/selinux下,其中/etc/selinux/targeted目录里就包含了策略的详细配置和context定义,以下是主要文件及功用:

/etc/selinux/targeted/contexts/*_context 默认的context设置
/etc/selinux/targeted/contexts/files/* 精确的context类型划分
/etc/selinux/targeted/policy/* 策略文件

使用Redhat 默认的策略对正常应用带来的影响比较小,兼容性相对比较好。对于需要提供虚拟主机或大量应用的用户而言,则会带来不小的麻烦,需要仔细阅读SELinux的手册进行调整。

其中Fedora Core 的官方网站上有相关的Apache/SELinux的策略调整文档,建议web用户仔细阅读。

激活SELinux的操作系统,需要对策略和模式进行变更时,一般不需要重启动即可获得变化,主要就是透过libselinux软件包实现。libselinux包含了对策略的控制/管理工具,其中getsebool/setsebool是读取/设置SELinux 布尔值的工具,getenforce/setenforce则是设置强制性的工具。

Why SELinux?
毫无疑问:安全!如今Internet上病毒、攻击层出不穷,信息安全受到了严重威胁,而普通Linux的安全性要做得很好并不容易,且没有一个中央化的安全体系结构,因此使用SELinux可以使用强制的访问控制来进行小颗粒度的权限控制,并提高系统的稳定性,简化了防系统崩溃的调整工作,达到信息保密和完整性的要求。

SELinux主要的改进在于:
  • 对内核对象和服务的访问控制
  • 对进程初始化、继承和程序执行的访问控制
  • 对文件系统、目录、文件和打开文件描述的访问控制
  • 对端口、信息和网络接口的访问控制。

    SELinux still difficult
    控制的东西越多使用起来就越容易复杂,SELinux也不例外,目前SELinux还在不断完善中,管理和控制策略并不是一件轻松的事,需要丰富的系统知识和经验,并且必须仔细阅读SELinux相关的文档,做大量的尝试。

    相关链接

    NSA SELinux官方主页
    SELinux 手册及HOWTO
    SELinux介绍
    SELinux文档及论文
    Customize Apache SELinux Policy
    SELinux FAQ
    由新的SELinux安全级别产生的问题及解决方法

    Posted by hzqbbc at 01:56 AM | Comments (0)

    July 18, 2005

    SYN attack - 遭遇SYN攻击

    曾几何时,Linux系统还被追捧为安全性较好的系统,很多系统管理员为自己管理的Linux服务器很少被攻击成功而感到自豪。但步入新的Internet年代,各种各样的攻击逐步盯上了Linux,而TCP/IP网络固有的缺陷也被Cracker大肆利用。

    很不走运,手下管理的多台Linux服务器也遭到了不同类型、不同程度的攻击,包括SYN攻击,CLOSE_WAIT攻击,抢占资源(如web的连接等)等等。如果是那些少量ip组成的大规模攻击,一般情况下封ip就能比较好的解决问题了。

    如果是DDOS就更难办了。这两天,有2台服务器遇到了大规模的SYN_RECV DDOS攻击。主要是针对web的,导致了web访问缓慢并停止服务,甚至机器失去了响应。要对付SYN攻击,得从多个方面入手,如果是分布很广的攻击,还得从交换机、路由器等更高一级的层次进行杜绝。

    下面是应付这几天攻击的基本方法:

    1)SYN cookie
    在linux下以root权限执行:

    echo 1 > /proc/sys/net/ipv4/tcp_syncookies
    

    这个方法打开了syncookie功能,但实际效果几乎感觉不到。

    2)增大backlog
    通过增加backlog的数值,可以一定程度减缓大量SYN请求导致TCP连接阻塞的状况,一般这个数值系统默认是1024,实验增加到1280~2048:

    echo "2048" > /proc/sys/net/ipv4/tcp_max_syn_backlog
    

    这样在强度不是很高的攻击下,系统响应能力提高了一点。

    3)缩短retries次数
    Linux系统默认的tcp_synack_retries是5次,将这个数值减少可以提高系统响应能力,实验改为2次:

    echo "2" > /proc/sys/net/ipv4/tcp_synack_retries
    

    修改后,SYN_RECV的数量有了少量减少,系统响应也快了一些。

    4)限制SYN频率
    上述的几个方法实际效果并不理想,尤其是DDOS攻击基本无效,目前比较有效的是对SYN的频率和次数进行限制,这样最大限度的控制了单个IP地址发动攻击的能力。

    例如将SYN请求的次数限制在30次每分钟,系统默认是5次/秒,显然太高,同时将burst从默认的5个降低到2个。

    /sbin/iptables -A INPUT -p tcp --tcp-flags SYN,ACK,FIN,RST SYN -m \
      limit --limit 30/m --limit-burst 2 -j ACCEPT
    

    注意: 该命令在shell下输入,'\'符号表示续行。

    进行此操作后,对正常的用户而言无任何感觉上的差异,而并发的SYN请求量下降了不少,服务响应基本正常了。

    5)封锁IP/IP段
    对于某些单独IP的DOS攻击,封ip简单有效,方法也非常容易:

    /sbin/iptables -A INPUT -s a.b.c.d -j REJECT
    

    为了大规模快速的封IP地址/段,我写个小脚本:

    #!/bin/sh
    IPSRC=`cat ip.txt`
    for i in $IPSRC;do
            /sbin/iptables -A INPUT -s $i -j REJECT
    done
    

    在ip.txt里保存如下格式的ip地址段:

    211.95.208.0/24
    219.78.190.0/24
    4.7.220.0/24
    68.163.195.0/24
    211.162.165.0/24
    ......
    

    结束语

    虽然采取了种种手段,但是攻击依然没停止过,上述的方法只是减弱了攻击的影响,但却不能彻底解决问题。除了利用IPTables外,还可在应用软件层做一定的连接频率,连接数等限制,例如Apache有一个mod_limitipconn模块就可以实现类似功能。

    Module Limit connection

    Posted by hzqbbc at 12:46 AM | Comments (1)

    July 14, 2005

    Webdav - ideal share protocol - Webdav简介

    WebDAV(Web-based Distributed Authoring and Versioning)是一种基于 HTTP 1.1协议的通信协议.它扩展了HTTP 1.1,在GET、POST、HEAD等几个HTTP标准方法以外添加了一些新的方法,使应用程序可直接对Web Server直接读写,并支持写文件锁定(Locking)及解锁(Unlock),还可以支持文件的版本控制。

    Microsoft windows2000/XP及IE, Office还有Adobe/MicroMedia的DW等都支持Webdav,这又大大增强了Web应用的价值,以及效能。对于需要大量发布内容的用户而言,应用WebDav可以降低对CMS系统的依赖,而且能够更自由的进行创作。上传、下载变得轻松自如。

    有关Webdav的信息主要集中在Webdav 资源站:http://www.webdav.org

    用该站一句话来概括Webdav,可以表述为:
    Briefly: WebDAV stands for "Web-based Distributed Authoring and Versioning". It is a set of extensions to the HTTP protocol which allows users to collaboratively edit and manage files on remote web servers.

    配置Apache,体验WebDav

    介绍再多不如亲自体验一下,到Apache官方网站,找到mod_dav的文档,简单的配置了一下即可实现最基本的Webdav 服务端了。

    首先要确保激活mod_dav及mod_dav_fs模块,即在httpd.conf保证有:

    LoadModule dav_module modules/mod_dav.so
    LoadModule dav_fs_module modules/mod_dav_fs.so
    
    <IfModule mod_dav_fs.c>
        # Location of the WebDAV lock database.
        DAVLockDB /var/lib/dav/lockdb
    </IfModule>
    

    如果用的系统自带apache的rpm包的话,默认就已经安装并配置好mod_dav了。只需要针对具体的目录进行一下配置即可使用。

    在httpd.conf增加如下一段配置内容:

    Alias /webdav /usr/local/webdav
    <Location /webdav>
    Dav On
    AuthType Basic
    AuthName DAV
    AuthUserFile /usr/local/webdav/.htpasswd
    
    <LimitExcept GET OPTIONS>
        Require valid-user
    </LimitExcept>
    </Location>
    

    然后创建/usr/local/webdav目录,注意一点,这个目录必须对apache是可写/可读的,所以需要更改owner:

    mkdir -p /usr/local/webdav
    chown -R apache.apache /usr/local/webdav
    

    最后增加授权用户,用htpasswd程序生成即可。

    htpasswd -c /usr/local/webdav/.htpasswd test
    

    连续输入2次test即可生成一个test用户,密码是test的。

    然后重启apache。

    客户端配置

    这里以最常用的Windows 2000/XP为例。Windows 2000/XP等已内置了Webdav的支持,能实现方便的web文件夹功能。

    打开“网上邻居”,左边菜单里点击“添加一个网上邻居”,在“键入这个快捷方式要打开的网站、FTP站点或网络位置的地址”中输入Webdav 服务器的URL。在本例里,使用的URL是:
    http://www.hzqbbc.com/webdav

    将url填进去后,并完成提示就可以了。访问该Web文件夹时必须输入刚才生成的用户名和密码,这时在网上邻居里就出现一个网络文件夹图标,可以象常规的文件夹一样进行拖、拉操作。感觉方便极了。再也不用烦琐的使用ftp或cms来操作。

    如果希望IE也能使用Webdav的文件夹,则在菜单->打开->勾选“以Web 文件夹方式打开”并输入URL即可。

    上载时和web ftp差不多:

    Useful links

    http://www.webdav.org/
    http://www.webdav.org/other/faq.html
    IETF WebDAV Quota
    http://jakarta.apache.org/slide/
    http://www.carrel.org/2005/03/31/mod_dav-quota-patch-redux/
    http://webdav.todo.gr.jp/download/
    http://pretender.blogdriver.com/pretender/389261.html
    http://httpd.apache.org/docs-2.0/mod/mod_dav_fs.html
    http://httpd.apache.org/docs-2.0/mod/mod_dav.html
    http://www.needful.de/docs/projekte/webdav-quota/
    http://www.geocities.co.jp/Hollywood/4471/webdav/webdav.html
    http://mailman.lyra.org/pipermail/dav-dev/2001-March/002132.html
    http://lists.samba.org/archive/samba/2004-February/081614.html

    Posted by hzqbbc at 10:40 AM | Comments (1)

    July 12, 2005

    Power of New Tech - “乌合之众”的力量

    短评
    最近几年涌现的blog, wiki及更新换代的IM,P2P等技术,极大的冲击了整个网络。后知后觉的我才发现这些应用正逐步形成一场革命,洪水般冲击着传统。

    换句俗点的话,现在人气已成为最能评估网络经济的关键指标了。聚合了人,才有发展,人气一旦衰败,那么再新奇有趣再有价值的东西都会一夜之间变成了历史,甚至是垃圾。离开人气,一切都是枉谈!

    下文是转自CCW(计世网)的文章:

    在文件共享、网志、Wiki等新一代的互联网技术以及MySpace和Meetup等社交网络服务的推动下, 10亿的在线民众正迅速形成一股前所未有的集体力量,正在改变经济秩序。

    “乌合之众”的力量

    这是个巨大、可怕的有机体。世界各地近10亿的在线民众(以及他们共享的知识、社交关系、在线声誉、计算能力等等)正迅速形成一股前所未有的集体力量。人类历史上第一次,跨时间和空间的大规模合作突然变得经济起来。在线市场eBay公司创建人、董事长Pierre M. Omidyar说:“力量正在发生根本的变化。人们无论身处何处都将走到一起,使用Internet,颠覆他们参与其中的活动。”

    集体的呼喊

    看到我们的力量。正是网志背后的力量击倒了CBS主持人Dan Rather,动摇了媒体权势集团。全球开放源代码Linux程序员甚至使强大的Microsoft感到害怕。由数百万台志愿者的PC组成的虚拟超级计算机,帮助预测全球气候变化,分析基因疫病,发现新行星和恒星。投资管理机构Marketocracy公司甚至为7万位虚拟交易者运营一个股票市场联盟(rotisserie league)。它撇去最优资产组合的泡沫,为其6千万美元互助基金购买和出售真正的股票。

    尽管技术公司可能走在前面,但它们的努力正在震动其他行业,包括娱乐、出版和广告业。好莱坞遭受1亿人利用Kazaa和BitTorrent等程序在线共享歌曲和电影的全面进攻。广告支撑的媒体业同样遇到了这种情况:Google公司的王牌搜索引擎实际上调查数百万网页创作者的集体判断来决定最相关的搜索结果。在这一过程中,它创建了一个价值数十亿美元的超级目标广告市场,这个市场从杂志广告和报纸分类广告那里吸走资金。

    从Procter & Gamble到Dow Chemical这样最具实力的传统公司,也开始纷纷向虚拟平民敞开怀抱。其潜在的好处是巨大的。如果公司可以敞开怀抱接受来自热情的顾客和合作伙伴的贡献,将帮助他们更快地、更高成功率地――并且以更低的成本、更小的风险――开发产品和服务。LEGO Group利用Internet确定和召集最热情的顾客,来帮助它更有效地进行设计和营销。Eli Lilly、HP和其他厂商正在经营“预测市场”。这个市场从在线群众中吸取集体的智慧。这些在线群众帮助评估政府是否批准药品或产品未来的销路如何。

    同时,对等的力量向任何向现状投资(invested in the status quo)的人带来了困难的挑战。企业,既那些指挥与控制的大本营,可能遭遇最大的震动。它们日益需要对付由具有在网上联合起来得到他们需要的东西的力量的顾客专门组织。实际上,顾客正在创造他们自己想要的东西――例如,与同事一起设计自己的软件,利用网志表达自己的观点,而不用去等待报纸发表他们的信件。Michigan大学Stephen M. Ross商学院教授、2004年《竞争的未来:与顾客一起创造独特的价值》一书共同作者C.K. Prahalad说:“这是工业民主化。我们正在看到一个民有、民治和民享的经济的诞生。”

    对等生产

    对等生产预示着即将来到的更彻底变化。《聪明的民众:下一个社会革命》一书的作者Howard Rheingold,看到了一条贯穿于互联网、移动设备和eBay的反馈系统(在这个系统中,买家和卖家根据每一次交易相互评级)等不同创新中的共同线索。他认为它们是新经济秩序的支柱。Rheingold还帮助领导着Cooperation Project,即由试图为新的发展前景计划未来的学术机构和企业组成的网络。他认为:“它们就像是使资本主义变为可能的股票公司和责任保险。它们可能使某种新经济系统成为可能。”

    也许它们已在发挥作用了。研究网络经济学的耶鲁法学院教授Yochai Benkler认为,这种在线合作正在刺激经济学两个古典支柱――公司和市场――之外的新生产模式的出现。“对等生产”,就是他给开放源代码软件、文件共享以及Amazon.com公司的数篇百万顾客产品评论这类工作起的名称,在既没有传统的企业监管,也没有像付款这样的市场刺激的条件下,也在创造价值。

    的确,对等生产代表着一场经济突变――至少在涉及日益推动经济增长的信息产品、服务和内容时。两百多年前,James Watt发明的蒸汽机引发了工业革命,从而将生产资料集中在拥有实现规模经济的资本的庞大、强壮的企业手中。现在,廉价的计算机和新社交软件与服务――以及使汇集这些资本投资变得容易的无处不在的互联网的通信能力――开始将生产能力还给人民。Benkler说:“这与我们自工业革命后一直看到的各种东西完全不同。”

    听起来好像对所有向现状投资的人形成了威胁?的确如此。实际上,正如Rheingold的书名所暗示的那样,这种新的合作力量可能存在着黑暗的一面,尤其是如果它导致暴民统治的话。解决问题最好方法常常来自达尔文或爱因斯坦那样的孤独天才的灵光闪现。如果这些家伙迷失在合作的群众中,那将是一场悲剧。显然,对等生产存在自己的局限。几乎可以肯定,它将永远不能建设铁路,不能种麦子,运营核电站或创作伟大的小说。

    但是,这种合作的力量扩展超越信息、知识和媒体等容易共享的商品的范围。人们还将开始利用互联网汇集实实在在的商品。从某种意义上讲,Skype使人们能够共享计算机硬件。例如,由于Web作为会议场所和日程安排协调员的能力,共享汽车变得经济起来。像Zipcar和Flexcar这样的服务,使成员可以利用Internet在拥挤的城市中几乎按需以小时计费预定汽车。

    是什么推动这种团结精神?最主要的是,新一代的互联网技术。它们包括文件共享、网志、wikis的群体编辑网站以及像MySpace和Meetup公司这样的社交网络服务。Meetup帮助纽约从Howard Deaniacs到英格兰斗牛犬所有者的每一个人组成本地组织。这些技术最终将以一种与电子邮件或传统网站不同的方式释放Internet独特的潜力。与其他任何媒介不同,互联网可以同时将许多人与其他许多人连接在一起。

    让这些新技术有别于互联网第一代技术的东西,是它们将自我兴趣变为社会福利的方式――以及真正的经济价值。它们具有技术图书出版商Tim O'Reilly称之为“参与架构”的东西,因此人们很容易做自己的事情:在他们的网站上创建与他们喜欢的另一个网站的链接、给歌曲打分或通过在线产品评论炫耀自己的知识。然后,这些行为可以被汇集成为对许多人有用的东西:Yahoo上帮助人们建立个性化的互联网电台的30亿歌曲评级,或帮助人们确定热门产品还是废物的Amazon的数百万顾客创作的产品评论。Amazon CEO Jeffrey P. Bezos感叹道:“你邀请社区参与,然后得到所有这些帮助。”

    这也是好得令人吃惊的帮助。新的研究显示,常常自下而上组织起来的合作,在蚁群这样的自然现象到市场和城市等人类制度的各种事物中,发挥远比我们想像大得多的作用。最后结果是他们在解决很多问题时比最聪明的个人还聪明。

    互联网的超级形成组织的能力暗示着近乎幽灵般的群体智能的诞生。在保罗二世教皇去世几分钟后,数百位eBay卖家就在网络上公布出售的相关产品。无论它是否对世界事件或Sony公司的PSP游戏机这样的新产品做出响应,eBay的集体智能对于需求变化的反应比具有多个管理层批准层次的传统公司更快。虽然eBay最近在美国和德国的一些成熟市场增速放缓,但集体智慧帮助保持可观的增长,今年的毛商品销售额预测将增长30%,达到450亿美元。正如eBay CEO Margaret C. Whitman指出的那样:“拥有一支由百万人组成的大军比指挥与控制系统要好得多。”

    越来越多的公司开始理解这种逻辑。如果他们能够让其他人帮助他们设计和开发产品的话,他们最后得到的是现成的顾客――这意味着大大降低棘手的开发新产品和市场业务中的风险。因此,企业将利用网络群体改进从研发到营销的各种任务。Eli Lilly下属e.Lilly研究员副总裁Alpheus Bingham说:“如果我可以同时进入一百万个大脑中,我会遇到一个与众不同的大脑。”

    例如,Procter & Gamble公司每年17亿美元的研发部门正在利用集体在线智力托拉斯,如马萨诸塞州Andover市Lilly公司InnoCentive。这是个由173个国家中8万个独立的 “解决者”组成的网络。这些人员集体为Boeing、DuPont以及其他30家大型公司解决研究问题。InnoCentive CEO Darren J. Carroll说:“我们志在实现科学民主化。”

    P&G显然取得了成功。P&G提交给InnoCentive的网络的24个请求中的1/3以上得到了答案,该公司为每个答案支付了5000多美元。通过利用InnoCentive以及其它联系独立的人才的途径,P&G将源于公司之外的新产品的数据由3年前的20%增加到了35%。结果是,每研发人员的销售额增加了40%左右。

    在线大众不仅只是提供想法:有时他们还差不多成为完全的生产人员。在游戏设计商Linden Lab的虚拟在线世界Second Life中,参与者自己开发几乎所有东西,从人物、建筑到这个虚拟世界中玩的游戏。这家拥有45名员工、毛利不足5百万美元的公司,通过向玩家出售他们可以在上面创作自己的作品的虚拟土地来赚钱。即使假设他们的工作成果中只有10%是有用的,这仍等于传统游戏公司的一支100人的团队。Linden CEO Philip Rosedale说:“我们建立了一个基于市场的、效率更高的创作数据内容的系统。”

    同样,在线群体开始将营销由传声筒变为对话。例如,LEGO Group将成年LEGO火车模型爱好者请到纽约办公室,请他们检查新设计。Intel工程师、俄勒冈Portland市的LEGO迷Steve Barile参加了那次活动。他说:“我们对所有的设计嗤之以鼻。”结果,LEGO公司全球社区开发经理Jake McKee说:“我们严格地按照他们给我们的建议去生产。”新火车头,“Santa Fe Super Chief”,2002年展示给了250位爱好者,在没有进行其它方式的营销的情况下,他们的口碑帮助第一批1万套模型在不到两周内销售一空。

    企业规划员甚至开始利用在线群众的智慧来预测未来,更准确地预测利润和销售额。预测市场使人们实际上按照不同预测购买股票,常常用真钱购买。最著名的是,它们在爱荷华大学的试验爱荷华电子市场中被用来决定――非常准确地――总统选举最可能的获胜者。NewsFutures公司CEO Emile Servan-Schreiber说,在Internet上组建组织的方便性,造成它们的应用爆炸式发展。NewsFutures是一家经营着4万个针对公司和出版物的预测市场的咨询机构。

    乌合之众的狂热

    尽管存在种种好处,但基于互联网的合作存在很多需要警惕的风险。显然,并不是所有的群众都是明智的。甚至《群众的智慧》一书作者Surowiecki也怀疑互联网将怀有相同想法的人如此紧密地联系在一起,以致可能放大小团体思想。他指出“我们相互交流的越多,就可能变得越不明智。”不鼓励独立想法的群体可能会抑制来自才华横溢的个人的立竿见影的想法。他们还可能成为随大流买进或抛出股票的民众。

    正如许多公司知道的那样,在线部落会迅速调转枪口反对他们。去年9月,自行车锁制造商Kryptonite试图贬低一部展示如何用BIC笔打开自行车锁的博客录像片。但是,这段录像迅速在互联网上传播,迫使该公司花费1000多万美元更换车锁。


    为了对付这种日益增长的群众力量,企业必须谋划自己的新角色,学习经营的新方法,才能与时俱进。在在线声音的合唱中,他们不能将秘密保持很长时间,这正是苹果公司在爱好者网站泄露未发布产品的秘密时得到的教训。经理和雇员必须学习如何听从顾客的指挥而不是老板的指挥。斯坦福大学教授Walter W. Powell说:“网络正在成为创新的发源地。公司将变得更加多孔、更加分散。”


    但是,这些挑战证明我们谈的不仅仅是一种新资本主义工具――至少不同由大资本家垄断的工具。新贵们,即专门组织(ad hoc groups)和新公司,掌握着比老牌企业大得多的主动权。他们正在改变一个又一个行业,改变的速度是单个公司无法应付的。

    这种现象的发生速度没有什么行业比软件业更快。开源软件开发协作正迅速超越像Linux这样的基本实用软件的范围进入主流应用程序。SugarCRM公司就是一个尤其具有启发意义的例子。该公司在Siebel Systems公司和salesforce.com公司统治的客户关系管理软件市场提供开放源代码版本的软件。这家只有10名员工的公司的软件(CEO John Roberts将该软件称之为“全球聪明的CRM工程师协作的结果”)已经被免费下载了235,000多次。

    该公司靠服务(如技术支持和一个每月收费40美元的基于Web的服务)以及特性更全面的企业软件(每年每用户收费239美元)赚钱。成立还不到一年的SugarCRM没有透露财务情况,不过它的业务模型暗示着软件行业运营方式的重大变化。SpikeSource公司是一家提供多种开放源代码产品的新兴厂商。公司CEO Kim Polese说:“人人都可以参与开放源代码的事实正在创建一种新的市场生态系统。”或者正像Roberts乐观地补充说的那样:“我们将把100亿美元的市场空间变为10亿美元的市场空间。”

    同样可怕的前景也摆在其它正迅速走向数字化的基于信息的行业的面前,如娱乐、媒体和出版业。人们不仅共享歌曲和影响――合法或非法――而且还自己创作内容并且培育规模可观的读者。这种威胁来自1千多万个网志。据Pew Internet & American Life Project说,大体上有5千3百万美国人向Interent贡献各种材料,从产品评论到eBay评级。

    最惊人的例子:Wikipedia。每个月大约500万人访问这个免费在线百科全书。这个在线百科全书共有用200种语言撰写的150万个条目,数量超过了《大英百科全书》的12万个条目,而且具有令人惊讶的高质量。这些条目是由世界各地的志愿专家提供的。共同创建人Jimmy Wales说:“我们的工作证明传统的专有产品可以多快地为开放替代产品所取代。”与《大英百科全书》不同,Wales没有将目标放在创造大量(如果有的话)收入上。不过,他指出:“这并不意味着我们不会摧毁他们的生意。”《大英百科全书》发言人Tom Panelas说,文章的巨大数量并不是衡量质量的尺度,而且可能会给大多数读者和研究人员造成过重的负担。

    然而,合作的群众再一次向报纸这样陷于四面楚歌的媒体抛出救命绳。韩国有着5年历史的在线报纸OhmyNews聚集了3.6万名“公民记者”,撰写每天多达200篇的报道。报道的内容广泛,从政治抗议到电影。据一项国际杂志调查显示,其每日100万访问者的流行度,使它成为韩国第六大最具影响力的媒体机构――超过了三个电视网中的一个。共同创办人Oh Yeon Ho解释说:“这是人人参与的新闻业。”他说OhmyNews去年实现了赢利。这种概念也开始在美国火起来。

    甚至交易有形商品的行业也开始被互联网推动的共享完全颠覆。例如,在零售业,“消费者”开始成为卖给他们商品的商家的积极参与者,从而将古老的意见箱变化某种更具影响力的东西。在Amazon.com,成千上万的志愿者编写顾客指南和心仪产品清单。Amazon还让成千上万从Target Stores到个体户的商家在Amazon网页上卖东西。

    此外,Amazon正在向6.5万名软件开发人员开放产品数据库、结算服务以及其他更多服务背后的技术。他们在开发新的服务,或通过把条形码扫描到手机中,将传统商店的价格与Amazon的价格进行比较的能力。部分由于这些举措,去年69亿美元的销售额给公司带来了实实在在的利润。

    这就提出了一个重要观点:我们所有人将必须承担更多的责任。为了从新的合作工具和服务中得到最大的回报,我们必须以新的方式(如给eBay上的卖主评级或在Wikipedia中撰写短文)贡献时间和才能。然而,回报将是我们不仅消费而且帮助创建的更加个性化的产品和服务。(Businessweek)

    原文引自:
    http://www.ccw.com.cn/news2/it/htm2005/20050711_10H52.htm

    Posted by hzqbbc at 09:46 AM | Comments (0)

    July 11, 2005

    MT Related Entries Plugin - 新增相关文章的插件

    一直以来都希望MovableType可以实现相关文章的功能,但官方似乎一直没有开发这种功能的意图。在MT的插件网站上找到一个叫MTRelatedEntriesByKeywords,能轻松支持相关文章功能。

    使用方法非常简单,在Individial Archives模板中,增加下面的内容:

    <b>Related Toptics | 相关文章</b></br>
    <MTRelatedEntriesByKeyword>
      <MTEntries>
      <li><a href="<$MTEntryLink$>"><$MTEntryTitle$></a>
      (<$MTEntryDate format="%Y/%m/%d"$>)</li>
      </MTEntries>
    </MTRelatedEntriesByKeyword>
    

    安装
    将relatedkeyword.pl拷贝到mt的plugins目录里即可。

    配置好模板后,在每个文档的Keywords栏里输入相应的关键字即可,不过这个插件只支持以空格为分割符的关键字,我进行了小修改,使之支持了逗号(,)或空格来分隔关键字,并自动识别。

    主要实现如下:

    
    my $dim = '\s+'; # XXX
    $dim = '\s*,\s*' if($entry->keywords =~ /,/);
    my @ekey = split (/$dim/, $entry->keywords);
    ......
    

    另一个插件:RelatedEntryKeywords
    该插件是根据RelatedEntriesByKeywords插件实现的,功能非常简单,可输出每个文档的关键字,这样可以方便的对关键字处理,包括Link或搜索等。

    目前利用这个小插件实现了每个关键字的搜索,从而提高一点Google Adsense的展示量:-)

    主要代码如下:

    
    #!/usr/bin/perl
    #
    # GetEntryKeywords - by He Zhiqiang<hzqbbc@hzqbbc.com>
    #
    use strict;
    use MT::Template::Context;
    #use MT::Entry;
    my $plugin;
    eval {
       require MT::Plugin;
       $plugin = new MT::Plugin({
              name => 'Get Entry Keywords',
              description => 'A plugin for listing entry keywords/tags, very simple.',
              doc_link => 'http://www.hzqbbc.com/blog',
              author_name => 'He Zhiqiang',
              author_link => 'http://www.hzqbbc.com',
              version => '0.01'
        });
       MT->add_plugin($plugin);
    };
    
    MT::Template::Context->add_container_tag (RelatedEntryKeywords => \&get_keywords);
    MT::Template::Context->add_tag(ThisKeyword => \&this_keyword);
    
    sub get_keywords {
       my ($ctx, $args) = @_;
       my $dim = '\s+'; # XXX default dim
       my $res = '';
       my $blog_id = $ctx->stash ('blog_id');
       my $entry = $ctx->stash ('entry')
         or return $ctx->error("No entry found.");
     
       return "" if (!defined $entry->keywords);
       $dim = '\s*,\s*' if($entry->keywords =~ /,/);
     
       my $builder = $ctx->stash ('builder');
       my $tokens = $ctx->stash ('tokens');
     
       my @keys = split (/$dim/, $entry->keywords);
       foreach my $key (@keys) {
          $ctx->stash ('this_keyword', $key);
          defined(my $out = $builder->build($ctx, $tokens))
            or return $ctx->error($ctx->errstr);
          $res .= $out;
        }
     
       $res;
    }
    
    sub this_keyword {
       my $ctx = shift;
       $ctx->stash ('this_keyword');
    }
    

    Posted by hzqbbc at 09:18 AM | Comments (1)

    July 05, 2005

    OpenSource APF Server Plan - 开源(GPL) APS计划

    APF 项目已经运作了1年多,基本达到了测试的目的,目前的使用状况已经比较稳定了。随着垃圾邮件的日益泛滥,以及对电子邮件服务器功能上要求的增加,迫切需要一种能实现诸如精确的邮件收/发控制,频率控制,集成多种技术的方案。

    我已决定将目前运营的APF Server系统进行改造,开发出OpenSource版本的APF Server(简称APS-oss),以GPL版权释出。

    APS-os 计划拥有如下的基本特性:

    o.支持qmail, sendmail, postfix 其中对postfix提供最完善支持
    o.支持中等精度的访问控制(ACL)可实现内/外网,限制进出等高级功能
    o.支持简单的频率控制,未来提供自动封缩/解封ip技术
    o.内置APF client代码,支持APF服务器规则集
    o.支持accept-fork模型,后期考虑支持多路复用
    o.可选支持thread

    ....更多特性

    在支持特性中,APF client代码将融入一些APF Server运营系统中的特性,如简单的MX/IP 校验,来信ip/域名的猜测/侦测,自动频率控制,甚至是per host/domain/sender的频率控制等。并提供一定程度cache机制,例如识别结果缓冲,dns缓冲等,以提供尽可能高的性能。

    APS-os 采用纯perl编写,如果采用多进程模式的话,对于一个中等流量的邮件服务器来说,完全是可以应付的。对于高流量的邮件服务器,可以使用多路复用或thread版本的APS-os,但thread版的稳定性无法得到很好的保证。需要更多的测试。

    目前该项目已经纳入开发计划中,等基础资源具备后,就准备开始。......

    希望大家支持。。现在缺的东西还很多,服务器,带宽,一点点开发费用,美工LOGO设计等... :-(

    Posted by hzqbbc at 10:47 AM | Comments (0)

    July 03, 2005

    Travel story - 云南丽江之行 - 玉龙雪山、红豆杉

    整个云南之行,最激动人心,最壮阔的景色无疑是玉龙雪山,来丽江不上雪山,那简直是来了也枉然!

    从丽江要上雪山,得经过几个步骤,首先要先从城内坐车到大索道的起点站,然后买票,排队坐专车到大索道入口。

    由于高原地带的垂直气候影响,山下天气明媚,可是山上却环绕着阴云,在大索道入口处旁边有专门出租物品的商店,包括什么大衣、氧气瓶等。对于没带够衣服或者年纪大需要吸氧的人,真是有点雪中送炭的感觉了。

    我自己带了足够的衣物,上缆车前已经从头到脚武装了一番,还戴上了在城里买的牛仔帽,这次可要做一回雪山牛仔了:-) 上山的缆车需要排队等30-40分钟,缆车可以容纳6个人,听说缆车上下高度差有1000多米,全程2400多米,需要10-15分钟才上到山顶,这个过程正好可以欣赏“垂直气候”的地貌。

    大索道入口的人龙,排队可是够久的了。不远处就是雪山了,云雾缭绕。

    云雾笼罩着山腰,偶尔有阳光穿进云雾,此时真有点重见光明的感觉了

    几乎垂直的山坡上,生长着各种高原植物,尤其是各种杉类。

    山顶光线和能见度异常的好

    刚开始上缆车时,头顶是厚厚的乌云,越往上光线越暗,没一会缆车一头扎进了云海,四周白茫茫啥也看不见,真有点蓬莱仙境的感觉。快到山顶的时候,雾忽然神奇地消失了,好象进入了另一个世界,视线忽然清晰起来,山顶的天气和山腰简直是天渊之别!

    山顶的光线并不象想象那么强,自己是没带墨镜也没任何不妥。温度也不很低,如果穿羽绒服就有点夸张了。一般穿件毛衣+风衣就足够了,只是风很大,没个帽子的话有点难受。

    终年不化的积雪

    山崖下的浮云

    安全区域外的雪地

    通往高处的栈道,从图中可以看到,部分被雪埋了。

    作为南方人,踩在雪地的感觉就是不同,当时真的有说不出的激动。不仅仅是因为在雪山上,更因为是在高达海拔4500多米的高原上!山顶这里海拔4506米,四周有简易围栏围着,大概有2-3万平方米的活动空间。本来还有一条栈道通到4680的高处,可是由于部分栈道被冰雪覆盖,所以上不去,感觉非常非常遗憾。

    太阳出来了..

    顶峰左侧的小山峰

    蔚蓝的天空和白云

    游客在山顶嬉戏打闹,纷纷照相留念

    小小的滑雪场,山边是浓重的云雾

    光秃秃的山头,背后是蓝天白云,真想闭目冥想

    这样的蓝天,真是狂拍不厌

    山顶上有不少人脱下衣服拍照留念,这个猛mm不怕冷,佩服!

    山另一边的岩石

    下山时仰视山崖

    山腰的云杉

    山顶空气非常干净,能见度非常高,因此绝对是摄影的圣地。但遗憾的是玉龙雪山的最高峰一直环绕着白云,始终不能一睹芳容。由于山顶风很大,天气变化得非常快,一时阳光灿烂,一时又被雾气所笼罩,整个感觉就象身处云海里飞翔一般,离白云只觉咫尺之遥。

    在这个海拔4500多米的高山上,身体稍微差点的,都容易出现头疼、头晕和呼吸不顺畅的高原反应。幸好自己暂时没任何反应,于是肆意的到处乱跑,享受着这美妙的感觉。

    红豆杉一角,水堤上有一只供游人骑的牦牛

    红豆杉全景

    据说这里就是甘海子

    白天游玩玉龙雪山之后,晚上最适宜做的就是逛逛古城,享受一下悠闲,找个地方吃吃小吃,舒服的过一个晚上。

    旅游贴士

    在古城里稍微偏一点的地方,有不少物美价廉的小饭庄,有的还在河边有露天的席位,一边是小桥流水,一边吃着风味美食,确实别有一番滋味。

    在雪山上,切记不要快跑,不要随便蹲下,不要随便坐下,否则都容易头晕。

    Posted by hzqbbc at 09:22 AM | Comments (0)