Meng Yan ( 孟岩 )’s Weblog

Blog

Feedsky新版

by Meng Yan on May.29, 2006, under Blog

欣欣上周MSG我让我看看Feedsky的新版,初一看,吓了一大跳,ASP.NET竟然变成了PHP,这个变化实在不小。且不说这两种技术孰优孰略,看来Feedsky是下了功夫要重新架构一番。

首先,界面比以前清爽整洁了许多,也规范了很多。其实我在Feedsky刚出来的时候就注册了一个,不过一直没有公布,其中的一个原因就是用户名和密码的输入框大小不一样(还是没对齐?忘了),虽说是小问题,但是这样的小问题往往能反映一个团队的实力和态度。细节决定成败!

再说功能上的减法,确实,烧制和统计是RSS Burner的两个最基本也是最重要的功能,Feedsky删除了不少用处不大的噱头,这样挺好,减少了系统的复杂性。问题是,现在没有原因让我放弃Feedburner而转而使用Feedsky,因为没有特殊的地方。差异化生存,作为一个后来者,更要有超越前者的优势才行。加入本地Service(比如豆瓣,土豆)合烧是最容易想到的一个可以改进的地方。

Crawler的问题解决了,访问的时候已经带上了ETag,没有仔细分析Log,不知道对于其它Feed Platform应该遵循的规范考虑了没有。URL的重新设计也更加合理,feed.feedsky.com/user明显比www.feedsky.com/user更好。

团队Blog,终于加上了,这可以Web2.0服务的标志啊:P。我订阅了Feedburner的Blog,可以感觉那是一个充满激情,而且技术非常优秀的团队,希望欣欣和他的同事也能Build up一个这样的团队。

最后说说一些问题:

  1. 还是一些细节方面,比如Login.php Load出来后,焦点应该放在Username输入框;
  2. Feed预览,显示英文是"an RSS feed powered by Feedsky";
  3. 比较严重的问题,登陆页面没有采用HTTPS。对于WEB应用,如果不能很好的保护PII(Personal Identity Information),一切都明文的传来传去,非常危险;
  4. 安全设计考虑的还不够,比如,举两个简单的例子。第一,Login的时候,输入不存在的用户名,会显示"对不起,用户不存在",输入存在的用户名和密码,会显示"登陆失败!",有时候,给用户的信息不是越Detail越好,登陆系统就是这样的例子。因为给用户信息的同时,你也把这些信息暴露给了Hacker,通常的设计要求,这时候的信息要尽量简单一致(Generic Error Messages),尽量少暴露系统信息;第二,连续N次Login错误后,没有任何方法加以限制。通常常用的方法是增加图形验证界面,或者甚至禁止继续试探。
  5. 功能上,Burn后还不能完全按照时间排序。

总的来说,还是不错的,希望Skyer们越做越好,也正好公布一下我的Feedsky的Feed:http://feed.feedsky.com/dreamwords

Popularity: 57%

8 Comments more...

Subscribe My Most Popular Post

by Meng Yan on Apr.22, 2006, under Blog

还是在上周末的时候,看到了Microsoft RSS TeamSLE(Simple List Extensions)扩展。三个单词中,最重要的是List,SLE主要是用来解决Feed订阅阅读模式的某种特定需求而产生的:

  • Treat Feed as List
  • Define customized sorting functions
  • Define customized filting functions

从订阅者的角度来说,订阅了这种Feed,本地的Feed列表将完全和Feed服务器提供的保持同步。这种同步包括几个方面:

  1. Feed Item的次序与服务器上完全相同,如果有更新,则Feed Reader也会更新顺序
  2. Feed Reader不会缓存过期的Feed Item,如果某一个Item从Feed中删除,本地Feed Reader也会将它从本地(或者在线Feed Reader Storage)删除。

简单的说,你通过Feed Reader看到的Feed应该与Feed Publisher发布的完全一致。

这种特定应用的需求会有很多,比如典型的几种应用:

  • Top 10 Best Seller - 比如Top 10 畅销书籍,Top 10 Music等等,对这种Feed的关注通常是更加关注于当前那10个;
  • Wish List - 如果我已经得到了某个东西,就会把它从SLE中拿去,这样,订阅了我的Wish List的人也就不会再看到这个,不会送重复的东西了:);
  • Open Positions - 当前职位列表,过期的职位通常意义不大。

可以看到,这些应用都有一些共同的特点,就是Feed本身更倾向于一种通知(Notification),过期的Item意义不大,而且,通常,这个List本身的次序是很重要的。

Specification很简单,通过以下这个声明来确定某个Feed是否是SLE(支持RSS2.0 & Atom),下面是一个RSS 2.0中的例子:

  1. <rss version="2.0"  xmlns:cf="http://www.microsoft.com/schemas/rss/core/2005">
  2.   <channel>
  3.     <cf:treatAs>list</cf:treatAs>
  4.     <title> Top 10 Popular Post </title>
  5.    
  6.     ..........
  7.     ..........
  8.  
  9.   </channel>
  10. </rss>

Sorting和Grouping(Filtering)的规则举例:

  1. <cf:listinfo>       
  2.     <cf:sort ns="http://www.xerdoc.com/rss/pl/" element="date" label="Publish Date" data-type="date"/>
  3.     <cf:sort ns="http://www.xerdoc.com/rss/pl/" element="rank" label="Popular Rank" data-type="number"/>
  4.     <cf:sort ns="http://www.xerdoc.com/rss/pl/" element="comments" label="Comments" data-type="number"/>
  5.     <cf:sort ns="http://www.xerdoc.com/rss/pl/" element="pingbacks" label="Pingbacks" data-type="number"/>
  6.     <cf:sort ns="http://www.xerdoc.com/rss/pl/" element="trackbacks" label="Trackbacks" data-type="number"/>
  7.     <cf:sort ns="http://www.xerdoc.com/rss/pl/" element="pageviews" label="Page Views" data-type="number"/>
  8.     <cf:group ns="http://www.xerdoc.com/rss/pl/" element="author" label="Author"/>
  9. </cf:listinfo>

当然,SLE不止是一个针对于Feed Publisher的标准,还需要Feed Reader的支持。与一般的Feed不同,Feed Reader在处理SLE的时候会有一些特殊处理,现有的Feed Reader还基本上不支持SLE,除了IE7 Beta2。

为了试验,我做了一个简单的WordPress Most Popular Post的插件。基本的打分是采用Popular Context插件,根据留言数量,Pingback、Trackback数量,浏览数量等因素来确定一篇文章的受欢迎程度,最后,提供一个WordPress的Top 10 Popular Post的SLE,可以用IE7 Beta2订阅来看看效果。

右面可以根据Comments,Pingback,Pageview来排序,也可以Filter来选择某个作者的Post。

订阅:

Most Popular Post @ Xerdoc’s Weblog

Most Popular Post @ Meng Yan’s Weblog

相关阅读:

Simple List Extensions Specification

Simple List Extensions in action

Understanding Lists and SLE

Popularity: 53%

4 Comments more...

Trackback, Pingback & Backlink

by Meng Yan on Mar.20, 2006, under Blog

今天看到王建硕的文章《如果过得去那个临界点

做Ping,需要发的人要支持,收的人也要支持,这种分布的方式的唯一问题是,你需要很多人的协作。不是每个人都愿意协作的,圣经里的通天塔Babel就是一种努力。这就形成了网络外部性--就像一个对讲机没有用,多个才有用处。

网络外部性的东西(email, TCP/IP协议,MSN Messenger,电话)必然需要强大的外因(或者极好的运气),才可形成,但一旦形成,就会病毒性复制。

这个就像核反应堆。谁有能力击破第一个原子,以后的事情就不用你管了。这个点,有人叫做引爆点(tipping point),有人叫做临界点(Critical Mass)。

所以,搜索引擎不需要被爬的网站的配合,就可以工作,所以成功。如果依赖于别人的ping, 就像有了C2C的交易平台,却没有那足够市场经费(这是一种办法),或者经过几年的积累(这是另外一种做法)轰击原子核,很难达到Critical mass。这个和技术无关无关了。

不久前曾有过一场关于Trackback是否会死去的大讨论,我也恰巧想过这个问题。于是,昨天仔细看了TrackbackPingback,以及Backlink。

从使用的难度来说,Trackback > Pingback > Backlink。Trackback的使用方法实在太过Geek,你需要到对方的Blog上找到Trackback
URI(虽然Trackback支持Auto-Discovery,但是真正用的似乎并不多),然后把它Paste到Blog软件的Trackback
Field里面去,我觉得,这个过程对于普通用户来说绝对不可忍受。即使你做到了这点,不同Blog程序间标准的不统一,对国际化支持不佳,使得Trackback的送出是如此之难。

相比之下,Pingback要好很多,如果你的Blog软件和对方的Blog都支持了的话,用户什么都不需要做。比如WordPress,会自动的向文章引用的每一个URL发送Pingback,当然,只有对方支持才会Ping成功。支持Pingback的Blog程序也很多,包括WordPress,Dupral,其它像是MSDN
Blog也都支持(用的是.Text?)。

这里废话一下Pingback的实现,其实很简单,每个客户端负责对指定的URL发送Pingback。而服务器端有两种办法来提供Pingback的地址:HTTP Header和Link Element。

HTTP/1.1 200 OK
Date: Sun, 08 Sep 2002 15:05:37 GMT
Server: Apache/1.3.26 (Unix)
Last-Modified: Thu, 28 Dec 2000 03:18:26 GMT
ETag: "65044-15b9c-3a4ab102"
Accept-Ranges: bytes
Content-Length: 88988
Connection: close
Content-Type: image/png
X-Pingback: Pingback Server URI
<link rel="pingback" href="Pingback Server URI">

可惜,标准总是好的,现实总是残酷的,并不是每个人都愿意遵循标准。显然,Trackback的提出者MT就不愿意支持Pingback。因此,我认可建硕说的,“当一件事情有赖于多于一个人的努力才能成功的话,他成功的可能性就小很多”。

这样看下来,Backlink就是最简单的了。如果你不知道什么是Backlink,就去看看Google的官方Blog。哦,对,这个。。。,那就拿Google中国黑板报来说吧,每篇文章后面会有一个“引用此贴的链接:”,就好比MT中Trackback到此篇文章的链接一样。下面列出的是一些链接到这篇文章的Blog。看看代码,你会发现,其实很简单:

  1. <script
  2.  type="text/javascript" src="http://www.blogger.com/dyn-js/backlink.js?blogID=20904277&postID=113976536783718339" defer="true">
  3.   </script>
  4.  
  5.   <noscript>
  6.   <a href="
  7. http://search.blogger.com/blogsearch?q=link:http%3A%2F%2Fgooglechinablog.com%2F2006%2F02%2Fgoogle.html">See links to this post</a>
  8.   </noscript>

正是Google Blog Search中的反向链接查询结果。

就像建硕所说的那样,搜索引擎不需要被爬的网站配合,就可以自己工作。有的时候,与其花费时间去推广一个标准,真的不如另辟蹊径,去找执行力更好的解决方案。

我觉得,无论从实现者的角度,还是从最终用户的角度,Backlink都是最简单的,事实上,他也确实成为我现在查看Backlink,进行Ego
Surfing的主要工具了。

还有,如果你希望Backlink成为文章的一部分,要展现给读者,那么就学习GoogleChinaBlog吧。Google Blog Search提供了Backlink的RSS,然后再用RSS -> JavaScript的工具生成一个JavaScript,嵌入你的页面中,就可以了。

其它:

Trackback VS Pingback

Popularity: 53%

10 Comments more...

coComment Preview

by Meng Yan on Feb.06, 2006, under Blog

一直希望有一个很好的Comments解决方案,帮我解决以下几个问题:

  1. 帮我追踪我所有的留言,记录这些留言的痕迹;
  2. 更进一步的追踪这些留言的Post,来看看Blog的主人对我的留言有什么反馈。

有一段曾经用Trackback来解决问题,这样做的结果是只有长篇大论才被记住,很多一两句的留言就不自觉地放弃了,反正也无法跟踪反馈 :P。久而久之,积极性越来越低,已经很少留言了。

Herock曾经建议采用社会化书签来对留言进行统一管理,可是关键在于,Bookmark下这些URL只是一些静态的信息,留言的组织和追踪还是靠你自己,还是很麻烦。

这两天偶尔看到coComment这个服务,看起来能够帮我解决我所面临的问题,就想试试。昨晚留下了Email,没想到一早就收到了invitation code。

用起来说简单也简单,说复杂也复杂,需要你在Browser中添加一个Bookmarklet,在点击留言提交的按钮前,点击这个Bookmarklet,然后点击的时候就同时把留言提交到coComment去了。

简单看了一下它的Bookmarklet代码,发现它是根据各种Blog系统的特征找到Comments的Form,然后在这个Form的提交Button后面添加一个个人信息的Logo,然后在修改Form的提交部分,让留言同时提交到coComments去。

看了一下代码,现在支持的Blog系统包括:

xanga.com

myspace.com

msn.com

blogger.com

typepad

blogs.com

wordpress.com

kaywa.com

这种做法够Hack的,不过想想也没办法。本来最好的办法是弄一个标准,然后大家都按照这个标准把留言Ping到某一个服务,不过,这似乎是不可能的,于是,就Hack这个提交的Form了。

不过,这种太过Geek的做法能够被普通用户所接纳么?我很担心。

最后的Conversation组织的不错,Fancy,而且也提供RSS来让我追踪我留言的各条Post,目前还没有收到更新,只能看看再说了,呵呵。对了,还提供Share的功能,把自己的留言Share出来。

还有,就是要提两个意见:

  1. 能不能做的更彻底一点儿,点击这个Bookmarklet的时候能自动帮我填留言的Form呢?我指的当然是Name,Blog这些信息,可以把它存在coComments的帐户里面。
  2. 把针对各种Blog系统的模版尽量抽象,然后提供一个可以方便扩充的Plugin机制(或者叫做Provider,Add-on),毕竟,coComments根本没精力提供所有系统的Comments模版,可以把这些工作留给社区来做,比如,吉子就可以做一个针对Sohu Blog的,嘿嘿。

Update:

  1. 简单测试了一下,发现coComment只能追踪同样是通过coComments服务的留言,不爽,不过也没有太好的办法,除非各家都提供自己的Comments RSS;
  2. 昨天用的时候就像可以写一个GreaseMonkey的脚本,来自动干这件事儿,结果这不,今儿就有了,这下更方便了;
  3. 还有一点想说的就是,这个服务的一个让我用的原因就是他不会让你失去什么,你的留言只是拷贝了一份在他那儿,所以,得到的就算是赚得吧。

Popularity: 41%

19 Comments more...

IE7 Beta2 Preview

by Meng Yan on Feb.04, 2006, under Blog

距离上次装Beta1已经有半年的时间了,这半年,用IE的时间大大的增加,不舍Firefox的主要原因是开放的架构和丰富的插件。

昨晚装上了IE7 Beta2试了试(这回也是英文版,不过不需要像上次那样Hack了:P),注意到一些细小的地方,比如:

  1. 上次的CSS Fixed的问题得到了解决;
  2. Tab上的Close按钮(据说这是得到了Blog中的反馈而加上的功能);
  3. Alt键开/关菜单;
  4. Quick Tabs预览,这个太Cool了(估计Firefox会很快出来类似的插件吧);
  5. "Delete Browse History"(虽然是已有功能的汇总,不过这个功能应该会有很多人需要);
  6. Full Screen的处理非常好,比Firefox的处理更加方便和人性化;
  7. Search Engine中默认为MSN Search,不过可以很方便的设置为Google或者其它;
  8. Native XMLHTTPRequest Object的支持,这样,今后写AJAX代码不用再区分浏览器了。

最让我印象深刻的是IE Blog这次的宣传攻势:

Native XMLHTTPRequest object - IE7中对XMLHTTPRequest的Native支持

Frequently Asked Questions for the IE7 Beta 2 Preview - IE7中的常见问题

Windows RSS Platform - RSS的支持,期待API的公开

Security issue in IE7? - 第一个漏洞?

A New Look for IE - IE7 UI的变化

Part 1: Hello feeds - 对Feed的支持,Feed Reading Page不错,非常方便

Part 2: Discover and Subscribe to Feeds

Part 3: Read and Manage Feeds

What’s New for CSS in Beta 2 Preview? - IE7对CSS支持的进展

A quick note on the Beta 2 Preview user agent string - IE7的User Agent String

ClearType Text in IE7 - ClearType的支持,很多人对这个抱怨不少,不过在我的LCD上,表现还不错

看完这些,深刻的感受到Blog对于互联网产品所起到的作用,无论是Feature,Security Issue,FAQ,Comments,都可以利用Blog传播出去,也可以利用Comments来得到很多有价值的反馈。

另外还有两点感受就是:

  1. IE正在变的越来越Open,这是一个好的开始(插件部分似乎没有大的变化,不知道是不是有Firefox那么多的Extension Point)
  2. 有竞争真好,越来越好的Firefox和IE正在让我的互联网体验越来越棒

Popularity: 44%

1 Comment more...

解决WordPress 2.0的comments始终为0的问题

by Meng Yan on Jan.21, 2006, under Blog

升级到WordPress2.0后,只有少数插件遇到了问题,都与Permalinks有关。不过,最近发现,SK2也有些问题,留言数目总是0,今晚有时间Debug了一下,发现WordPress2.0中”wp-posts”表里面新增了一个”comment-count”字段,这其实是”wp-comments”中取出的这个Post所有留言之和。之所以做这样违反范式的冗余设计,应该是效率上的考虑。这就带来了更新上的问题。SK2做的时候当然不会知道这个,所以就带来了问题。

发现了一个SK2的插件,用于解决这个问题 - SK2-WP2Compatibility (注意,这是SK2的插件,而不是WordPress的插件,有时间我要研究一下SK2的插件机制)。这个插件很简单,看看代码就知道了。

  1. $c = $wpdb->get_row( "SELECT count(*) as c FROM {$wpdb->comments} WHERE comment_post_ID = '$cmt_object->post_ID' AND comment_approved = '1'" );
  2. if( is_object( $c ) ) {
  3. $this->log_msg(__(" Wordpress 2.0 detected - going to update comment counts" ), 4);
  4. $wpdb->query( "UPDATE $wpdb->posts SET comment_count = '$c->c' WHERE ID = '$cmt_object->post_ID'" );
  5. }

不过,SK最新的2.1版本中已经解决了这个问题,所以,只需要升级到SK2.1就可以了。

Popularity: 27%

Leave a Comment more...

升级到WordPress2.0

by Meng Yan on Dec.31, 2005, under Blog

前两天升级到了WordPress 2.0,可惜Jerome’s Keywords不能正常工作,点击会出现404的错误。看了一下代码,发现WP2.0对底层Permalinks的实现作了很大的改动,郁闷。正巧看到有人推荐Ultimate Tag Warrior,决定元旦的时候换一下。昨天下午把这个插件推荐给Robin,没想到这家伙手脚真快,晚上就升级了。结果今天早晨来就看到Jerome’s Keywords升级到1.9,兼容WP2.0,呵呵。

Update:  同样是由于Permalinks的原因,WordPress Feedburner Plugin的作者也给出了最新的版本

昨晚升级的时候看了一下Archives,这两个月的Post真是少得可怜,忙是一种借口。手头想干的事情很多,却还都没有开始或者进展缓慢,还是得给自己加油 。

Popularity: 26%

Leave a Comment : more...

Flock

by Meng Yan on Oct.21, 2005, under Blog

今早收到Flock的邀请,下了一个体验一下。

Flock最大的特色就是加入了对Delicious, Flickr, Blog等社会化软件的支持,将他们集成到这个浏览器中。

1) Delicious

Flock的Favorite管理默认就是采用Delicious,第一次导入需要的时间长一些,这样,可以直接用Favorite中的”Star and Tag …”将你感兴趣的内容贴到Delicious上面去,不过我觉得原来的Bookmarklet也很方便 :P。

2) Flickr

试了一下,可以把Flickr的图片拖入到Blog Editor窗口中来,确实挺方便。

3) Blog

很简单,还是利用开放的XML-RPC接口,来远程的进行Blog发送,并且支持Ping到Technorati的Tag。

总的感觉是像一个装了各种社会化插件的Firefox,这些确实都是我平常经常用到的,其实原来的Firefox + Extension + Bookmarklet已经能很好的满足我的需求,不知道能不能用起来这个浏览器。

Technorati Tags: , , , ,

Popularity: 26%

Leave a Comment more...

Some hacking to support Baidu and Sogou in StatTraq

by Meng Yan on Aug.30, 2005, under Blog

一直用Stattraq插件来统计Blog的访问信息,使用起来还不错。后来发现,我的Blog上很多关键词都是来自Baidu,而Stattraq根本没有对Baidu的特殊处理,于是Hack一下,让Stattraq也能统计百度的信息。

1)BaiduRobot

在"stattraq.php"的函数"statTraqGetBrowser"中,添加对Baidu Robot的识别(顺便也识别一下Sogou的Robot吧):

  1. <?php
  2. }else if(strpos($ua, "Baiduspider") !== false){
  3.         $browser_type = ST_BOT;
  4.         $s_id = "Baiduspider";
  5.         return "Baiduspider";
  6.     }else if(strpos($ua, "sohu-search") !== false){
  7.         $browser_type = ST_BOT;
  8.         $s_id = "SogouBot";
  9.         return "SogouBot";
  10.     }
  11. ?>

原理很简单,就是分析HTTP头中的"HTTP_USER_AGENT"信息,负责任的搜索引擎都会给出自己的标志,比如Google的"Googlebot",MSN的"msnbot"等等,对于那些把自己伪装成浏览器的搜索引擎,不统计也罢。

一个需要注意的问题是大小写不能搞错。

然后再修改一下"stattraq-install.php",主要是为了今后的升级:

  1. <?php
  2. $sqlQuery = "UPDATE {$tablestattraq} SET user_agent_type=1
  3.         WHERE browser = 'Googlebot' OR
  4.              browser = 'msnbot' OR
  5.             browser = 'Baiduspider' OR
  6.             browser = 'SogouRobot' OR
  7.             ... "
  8. ?>

2) SE Saturation

在StatTraq的SE Saturation中,可以看到对各个搜索引擎收录你文章的统计,同样,加上百度和Sogou。

在"search_engine_stat.php"中,找到相应的代码段,并添加如下信息:

  1. <?php
  2. $baidu = getPageDBResults("Baiduspider", $date_format, $time_frame, $betweenClause, $orderBy);
  3. $sogou = getPageDBResults("SogouBot", $date_format, $time_frame, $betweenClause, $orderBy);
  4.  
  5. ...
  6.  
  7. if($baidu)
  8. {
  9.     $baidu_count = $baidu->cnt;
  10. }
  11. if($sogou)
  12. {
  13.     $sogou_count = $sogou->cnt;
  14. }
  15.  
  16. ...
  17.  
  18. echo '<tr><td>Number of Pages Indexed</td><td class="right">' . $google_count . '</td><td class="right">' . $yahoo_count . '</td><td class="right">' . $msn_count . '</td><td class="right">' . $baidu_count . '</td><td class="right">' . $sogou_count . '</td></tr>';
  19. echo '<tr><td>Number of Pages <em>Not</em> Indexed</td><td class="right">' . ($total - $google_count) . '</td><td class="right">' . ($total - $yahoo_count) . '</td><td class="right">' . ($total - $msn_count) . '</td><td class="right">' . ($total - $baidu_count) . '</td><td class="right">' . ($total - $sogou_count) . '</td></tr>';
  20. echo '<tr><td>Percent Saturation</td><td class="right">' . floor(($google_count/$total)*100) . '%</td><td class="right">' . floor(($yahoo_count/$total)*100) . '%</td><td class="right">' . floor(($msn_count/$total)*100) . '%</td><td class="right">' . floor(($baidu_count/$total)*100) . '%</td><td class="right">' . floor(($sogou_count/$total)*100) . '%</td></tr>';
  21.  
  22. ...
  23.  
  24.     <dt>Baidu.com</dt>
  25.     <dd><a href="http://www.baidu.com/search/url_submit.html">http://www.baidu.com/search/url_submit.html</a></d>
  26.     <dt>Sogou.com</dt>
  27.     <dd><a href="http://db.sohu.com/regurl/regform.asp?Step=REGFORM&class=">http://db.sohu.com/regurl/regform.asp?Step=REGFORM&class=</a></d>
  28.  
  29. ?>

显然,这里的"BaiduSpider"和"SogouRobot"就是我们刚才修改的那个函数的返回值。

3)统计用Baidu访问的关键词(Search Team)

在"stattraq.php"的函数"statTraqGetSearchPhrase"中,添加针对Baidu和Sogou的解析:

  1. <?php
  2.     }else if(strpos($referrer, "baidu.")!== false){
  3.         $key = "wd";
  4.     }else if(strpos($referrer, "sogou.")!== false){
  5.         $key = "query";
  6. ?>

原理很简单,就是分析referrer中的Query串(Baidu默认是采用GB2312来传递,这个比较烦人)。

比如:

http://www.google.com/search?hl=zh-CN&q=xerdoc&…

"q"就是Key。

Update (2005.11.04)

修改一下StatTraq中文乱码的错误:

1) Summary页面中的乱码:

1.打开/wp-stattraq/reporter/summary.php,找到第140行
<?php echo htmlentities(stripslashes($row->post_title));?> ,修改为
<?php echo htmlentities(stripslashes($row->post_title),ENT_NOQUOTES,’utf-8′);?>

2.打开/wp-stattraq/reporter/query_strings.php,找到第88行
htmlentities($row->search_phrase) ,修改为
htmlentities($row->search_phrase,ENT_NOQUOTES,’utf-8′)

- 解决StatTraq的乱码问题

2) Baidu, Sogou等query串的转码:

用iconv来进行转码

  1. if($gb2312 == true && extension_loaded("iconv"))
  2.     $phrase = iconv("gb2312","UTF-8",$phrase);

Popularity: 43%

4 Comments more...

Dissect WordPress Themes

by Meng Yan on Jul.26, 2005, under Blog

还是想用Nat在OOS上的一段话来作为开头:

You have to give people work to do.
Create an “architecture of participation” as Tim O’Reilly says.

要想真正成功,必须能够提供一个可以供人参与的架构,Eclipse如此,Firefox亦如此。与Plugin一样,WordPress中的Theme机制也非常灵活和强大,社区贡献出的一个个漂亮的Theme都是这个良好架构下的杰作。

1)读取系统中所有可用Themes

  1. <?php 
  2. function get_themes()
  3. ?>

这个函数用来从文件系统得到所有的Themes。首先列出’wp-content/themes’的文件夹,然后跳过”.’、’..’、’CVS’(跳过CVS目录,这个在Xerdoc DSearch的Theme中也遇到过,因为都是采用CVS进行源码管理 :-)):

  1. <?php 
  2. if ($theme_dir{0} == '.' || $theme_dir == '..' || $theme_dir == 'CVS') {
  3.     continue;
  4. }
  5. ?>

然后会判断每个目录中是否有Stylesheet ’style.css’文件,如果有,列为Theme候选目录,否则加入到’$wp_broken_themes’中。

接下来,就利用函数

  1. <?php 
  2. function get_theme_data($theme_file);
  3. ?>

来从’style.css’中提取Theme的描述信息,包括’Theme Name’、’Version’、’Author’等等。同WordPress中的插件类似,这些描述信息是存在’style.css’中的。

  1. <?php 
  2. Theme Name: WordPress Default
  3. Theme URI: http://wordpress.org/
  4. Description: The default WordPress theme based on the famous Kubrick.
  5. Version: 1.5
  6. Author: Michael Heilemann
  7. Author URI: http://binarybonsai.com/
  8. ?>

第三步,需要判断命名冲突。这种情况发生的原因是:将一个Theme拷贝,然后做修改,可是Theme的Descriptor并没有修改。可见,WordPress在人性化上真是做足了功夫,值得学习。

这样,合格的Theme就读取完毕了。不合格的Theme会被放到"Broken Theme"这个Section中,需要重新进行修改才能使用。

2)更换Theme

更换Theme很简单,先来看看当Active一个Theme的时候我们所Access的URL:

http://localhost/blog/wp-admin/themes.php?action=activate&template=sixties-datetitle&stylesheet=sixties-datetitle

Plugin一样,Active Theme的信息(其实就是目录名称)也保存在数据库中。但是需要存两项,分别是"template"和"stylesheet"。这是为了处理Style的CSS文件与模板文件(比如index.php)放在不同目录的情况。

  1. <?php 
  2. if (isset($_GET['template'])) {
  3.     update_option('template', $_GET['template']);
  4. }
  5.  
  6. if (isset($_GET['stylesheet'])) {
  7.     update_option('stylesheet', $_GET['stylesheet']);
  8. }
  9. ?>

3)Theme的加载

首先看看我们访问WordPress的过程。当我们访问’http://yoursite/blog/’的时候,访问的是’index.php’文件:

  1. <?php 
  2. define('WP_USE_THEMES', true);
  3. require('./wp-blog-header.php');
  4. ?>

在’wp-blog-header.php’文件中,可以看到下面的重定向过程:

  1. <?php 
  2. // Template redirection
  3. if ( defined('WP_USE_THEMES') && constant('WP_USE_THEMES') ) {
  4.     do_action('template_redirect');
  5.     if ( is_feed() && empty($doing_rss) ) {
  6.         include(ABSPATH . '/wp-feed.php');
  7.         exit;
  8.     } else if ( is_trackback() && empty($doing_trackback) ) {
  9.         include(ABSPATH . '/wp-trackback.php');
  10.         exit;
  11.     } else if ( is_404() && get_404_template() ) {
  12.         include(get_404_template());
  13.         exit;
  14.     } else if ( is_search() && get_search_template() ) {
  15.         include(get_search_template());
  16.         exit;
  17.     } else if ( is_home() && get_home_template() ) {
  18.         include(get_home_template());
  19.         exit;
  20.     } else if ( is_single() && get_single_template() ) {
  21.         include(get_single_template());
  22.         exit;
  23.     } else if ( is_page() && get_page_template() ) {
  24.         include(get_page_template());
  25.         exit;
  26.     } else if ( is_category() && get_category_template()) {
  27.         include(get_category_template());
  28.         exit;       
  29.     } else if ( is_author() && get_author_template() ) {
  30.         include(get_author_template());
  31.         exit;
  32.     } else if ( is_date() && get_date_template() ) {
  33.         include(get_date_template());
  34.         exit;
  35.     } else if ( is_archive() && get_archive_template() ) {
  36.         include(get_archive_template());
  37.         exit;
  38.     } else if ( is_comments_popup() && get_comments_popup_template() ) {
  39.         include(get_comments_popup_template());
  40.         exit;
  41.     } else if ( is_paged() && get_paged_template() ) {
  42.         include(get_paged_template());
  43.         exit;
  44.     } else if ( file_exists(TEMPLATEPATH . "/index.php") ) {
  45.         include(TEMPLATEPATH . "/index.php");
  46.         exit;
  47.     }
  48. } else {
  49.     // Process feeds and trackbacks even if not using themes.
  50.     if ( is_feed() && empty($doing_rss) ) {
  51.         include(ABSPATH . '/wp-feed.php');
  52.         exit;
  53.     } else if ( is_trackback() && empty($doing_trackback) ) {
  54.         include(ABSPATH . '/wp-trackback.php');
  55.         exit;
  56.     }
  57. }
  58. ?>

可以看到,根据访问的不同,会定向到不同的页面。比如访问首页的时候,’is_home’返回为true,这样,将会利用get_home_template(),重定向到home template。

  1. <?php 
  2. function get_home_template() {
  3.     $template = '';
  4.  
  5.     if ( file_exists(TEMPLATEPATH . "/home.php") )
  6.         $template = TEMPLATEPATH . "/home.php";
  7.     else if ( file_exists(TEMPLATEPATH . "/index.php") )
  8.         $template = TEMPLATEPATH . "/index.php";
  9.  
  10.     return apply_filters('home_template', $template);
  11. }
  12. ?>

在’wp-setting.php’中,可以找到’TEMPLATEPATH’的定义:

  1. <?php 
  2. define('TEMPLATEPATH', get_template_directory());
  3. ?>

get_template_directory()的定义为:

  1. <?php 
  2. function get_template_directory() {
  3.     $template = get_template();
  4.     $template_dir = get_theme_root() . "/$template";
  5.     return apply_filters('template_directory', $template_dir, $template);
  6. }
  7. ?>

get_template则是从数据库中取出现在使用的Theme,再加上Theme Root的路径,即可得到我们选择的Theme的路径。

  1. <?php 
  2. function get_template() {
  3.     return apply_filters('template', get_settings('template'));
  4. }
  5. ?>

因此,这样就定位到所选择Theme的目录,并访问相应的文件。

4)Template的模式

其实对于一个能够提供Theme的程序而言,在程序的构架上必须要实现数据和表现的分离。通常我们所说的MVC(Model、View、Controller)架构就是这个意思。

在WordPress中,是这样来实现数据和实现的分离的。

  1. XHTML。用Div等用来表现数据,CSS来描述这些数据的表现形式,用这种方式来实现数据和表现的分离;
  2. 在程序内部,采用Template来进行数据展现。

以 ‘Default’ Theme为例:

  1. <?php
  2. <?php get_header(); ?>
  3.  
  4.     <div id="content" class="narrowcolumn">
  5.  
  6.     <?php if (have_posts()) : ?>
  7.        
  8.         <?php while (have_posts()) : the_post(); ?>
  9.                
  10.             <div class="post" id="post-<?php the_ID(); ?>">
  11.                 <h2><a href="<?php the_permalink() ?>" rel="bookmark" title="Permanent Link to <?php the_title(); ?>"><?php the_title(); ?></a></h2>
  12.                 <small><?php the_time('F jS, Y') ?> <!-- by <?php the_author() ?> --></small>
  13.                
  14.                 <div class="entry">
  15.                     <?php the_content('Read the rest of this entry &raquo;'); ?>
  16.                 </div>
  17.        
  18.                 <p class="postmetadata">Posted in <?php the_category(', ') ?> <strong>|</strong> <?php edit_post_link('Edit','','<strong>|</strong>'); ?>  <?php comments_popup_link('No Comments &#187;', '1 Comment &#187;', '% Comments &#187;'); ?></p>
  19.             </div>
  20.    
  21.         <?php endwhile; ?>
  22.  
  23.         <div class="navigation">
  24.             <div class="alignleft"><?php next_posts_link('&laquo; Previous Entries') ?></div>
  25.             <div class="alignright"><?php previous_posts_link('Next Entries &raquo;') ?></div>
  26.         </div>
  27.        
  28.     <?php else : ?>
  29.  
  30.         <h2 class="center">Not Found</h2>
  31.         <p class="center">Sorry, but you are looking for something that isn't here.</p>
  32.         <?php include (TEMPLATEPATH . "/searchform.php"); ?>
  33.  
  34.     <?php endif; ?>
  35.  
  36.     </div>
  37.  
  38. <?php get_sidebar(); ?>
  39.  
  40. <?php get_footer(); ?>
  41. ?>

"get_header"和"get_footer"分别用来得到该页的Header和Footer,其实就是两个DIV块儿。Post的主体同样是一个大的Div(<div id="content" class="narrowcolumn">),在该Theme的CSS中即可以看到对这个DIV的表现定义,包括字体、背景颜色、边距等等。

  1. .narrowcolumn {
  2.     float: left;
  3.     padding: 0 0 20px 45px;
  4.     margin: 0px 0 0;
  5.     width: 450px;
  6. }

Post的内容由"have_posts()", "the_post()", "the_ID()"得到,具体见,风格同样定义在CSS文件中。

Popularity: 46%

3 Comments more...

Looking for something?

Use the form below to search the site:

Still not finding what you're looking for? Drop a comment on a post or contact us so we can take care of it!