显示标签为“网络”的博文。显示所有博文
显示标签为“网络”的博文。显示所有博文

2012年5月13日星期日

OpenWRT DNS

就我所知,目前可以应对DNS劫持的方法有以下这么些:

  1. 使用加密的通道进行DNS查询。
  2. 使用TCP协议发送DNS请求。
  3. 使用监听于非标准端口的DNS服务器。
  4. 设法挡掉伪造的DNS应答。

方案一的实现方式有VPN、Tor等等,前者需要额外的开销,后者速度和稳定性不佳,暂不考虑。

使用TCP协议发送DNS请求

由于GFW只污染了使用UDP协议发往服务器53端口的请求,所以改用TCP协议发送请求就可以规避污染。只是具体到OpenWRT,其默认采用的dnsmasq无法强制使用TCP协议向上游服务器转发请求,所以非要用这个法子,就得再装一个unbound。而unbound的资源占用对路由器来说颇为不低,所以这个方案对OpenWRT来说实用性并不强。

opkg install unbound后,修改/etc/unbound/unbound.conf:

server:
  port: 5353
  do-ip4: yes
  do-ip6: no
  do-udp: yes
  do-tcp: yes
  tcp-upstream: yes
forward-zone:
  name: "."
  forward-addr: 8.8.8.8
  forward-addr: 8.8.4.4

然后修改/etc/config/dhcp:

config 'dnsmasq'
        #option 'resolvfile' '/tmp/resolv.conf.auto'
        option 'noresolv' '1'
        list 'server' '127.0.0.1#5353'

注释掉resolvfile并打开noresolv选项,是为了让dnsmasq不使用resolvfile中的DNS服务器进行查询,下同。

使用监听于非标准端口的DNS服务器

如上所说,GFW只污染了使用UDP协议发往服务器53端口的请求,所以若是某个服务器由非标准端口提供DNS服务,同样可以规避DNS污染。

使用非标准端口的DNS服务器不多,Google DNS就不行。有个德国隐私基金会倒是提供了一组服务器,不过速度也太慢了点。于是没得选了,只剩下OpenDNS。

修改/etc/config/dhcp:

config 'dnsmasq'
        #option 'resolvfile' '/tmp/resolv.conf.auto'
        option 'noresolv' '1'
        list 'server' '208.67.222.222#5353'
        list 'server' '208.67.220.220#5353'

针对OpenDNS查询不存在的域名显示广告的问题,可以用dnsmasq的bogus-nxdomain来解决,将下面这一句加入dnsmasq的配置文件即可。(如果遇到国内流氓运营商的劫持问题,也可以用这个法子来试试。)

bogus-nxdomain=67.215.65.132

设法挡掉伪造的DNS应答

用tcpdump或Wireshark抓包可以看到,GFW会在正确的DNS应答之前加塞几条错误应答。如果我们可以分辨哪些是GFW伪造的应答并将其忽略,同样可以达到规避DNS污染的目的。

GFW伪造的应答分两种,一种返回一个错误的IP,另外一种不包含任何查询结果。针对后一种情况,AntiDNSPoisoning提供了如下规则:

iptables -I INPUT -p udp --sport 53 -m u32 --u32 "4 & 0x1FFF = 0 && 0 >> 22 & 0x3C @ 8 & 0x8000 = 0x8000 && 0 >> 22 & 0x3C @ 14 = 0" -j DROP
iptables -I FORWARD -p udp --sport 53 -m u32 --u32 "4 & 0x1FFF = 0 && 0 >> 22 & 0x3C @ 8 & 0x8000 = 0x8000 && 0 >> 22 & 0x3C @ 14 = 0" -j DROP

由于需要安装iptables-mod-u32和kmod-ipt-u32,我的OpenWRT需要重新编译,所以暂时没法实际测试。我依照原文的说法,写了下面两条规则丢掉Answer、Authority和Additional均为0的应答:

iptables -I INPUT -p udp --sport 53 -m string --algo bm --hex-string "|81 80 00 01 00 00 00 00 00 00|" --from 30 --to 40 -j DROP
iptables -I FORWARD -p udp --sport 53 -m string --algo bm --hex-string "|81 80 00 01 00 00 00 00 00 00|" --from 30 --to 40 -j DROP

至于返回错误IP的应答则有点复杂。AntiDNSPoisoning的思路是通过向伪DNS服务器查询被污染域名,获得错误IP的列表,然后再将返回这些IP的应答都丢掉。这个思路看起来可行,但问题在于如何获得完整的错误IP列表。

以下是我这里找到的错误IP:

  • 159.106.121.75
  • 37.61.54.158
  • 59.24.3.173
  • 203.98.7.65
  • 243.185.187.39
  • 78.16.49.15
  • 46.82.174.68
  • 159.24.3.173
  • 93.46.8.89
  • 243.185.187.30
  • 8.7.198.45

假如说这个列表完备,且在相对较长的一段时间内都没有变动的话,则AntiDNSPoisoning提出的方案可行。不过这两个前提条件是否成立,那就需要比较长的时间来验证了。另外,iptables的string模块是否会带来比较严重的延迟也是一个问题。毕竟按照AntiDNSPoisoning方案的思路,每个DNS查询响应都要比对十几条规则,或许为dnsmasq打个补丁来做这件事要更好一点。

除了返回的IP外,TTL值也可以用来分辨GFW伪造的DNS查询响应。比如从本机ping 8.8.8.8,得到TTL值51,则可以构造出以下规则:

iptables -I INPUT -p udp -s 8.8.8.8 --sport 53 -m ttl --ttl-lt 52 -j DROP
iptables -I INPUT -p udp -s 8.8.8.8 --sport 53 -m ttl --ttl-gt 52 -j DROP
iptables -I FORWARD -p udp -s 8.8.8.8 --sport 53 -m ttl --ttl-lt 51 -j DROP
iptables -I FORWARD -p udp -s 8.8.8.8 --sport 53 -m ttl --ttl-gt 51 -j DROP

本机的TTL为51,则路由器上少跳一次所以是52。在网络环境一定的情况下,TTL一般不会变化,而GFW伪造的应答与正确应答的TTL刚好一样的可能性也很低,所以这个法子也有一定的实用价值。

小结

从不需要安装更多的程序和规则数量两方面考虑,目前我用的是5353端口的OpenDNS。

2012年4月30日星期一

Sync From Twitter To Google Plus

今天收到了Google Voice的一封信,说我的号码已经有很长时间没用过,如果再不用他们就要回收了。本想着四处逛逛,要真找不到什么用处的话,回收就回收吧,谁知竟翻到了一个同步Twitter信息到Google Plus的法子

首先在GV的设置里找Voicemail & Text,启用Text Forwarding。然后发送任意内容的一条短信到号码33669(因为无法直接把GV号码绑定到Twitter,还以为GV不支持短号码),Gmail中会收到一封信,要求你在G+中验证电话号码。接着登陆G+,添加GV号码并完成验证。

回到Gmail,查看刚才那封信的发件人地址。该地址的域名为txt.voice.google.com,用户名格式为:ddddddddddd.33669.xxxxxxxxxx。其中d的部分是你的GV号码,x的部分或许是密钥吧。向这个地址发送邮件,等同于在GV中向33669发送短信,所以我们可以通过向这个地址发送邮件更新G+信息流。

然后是想办法,当我们更新Twitter之后,自动将推文通过email发送到该地址去。原文作者推荐的是ifttt。在ifttt中创建一个新task,内容为:“If new tweet by you then Send an email from Gmail.”To字段写之前找到的那个email地址,Subject写TWITTER2GOOGLEPLUS {{CreatedAt}},Body写{{Text}} +public(通过email更新G+,邮件标题会被忽略,并且默认情况下只向你的圈子共享信息,所以需要在Body中加上+public)。

通过上面的折腾,的确可以实现同步Twitter信息到G+的目的,只是要给ifttt访问Twitter和Gmail帐户的权限,总觉得有那么一点不太放心的感觉…

最后,为了防止Gmail里出现一堆不相干的信息,还要创建两个过滤器。一个收件人写之前找到地址,标题为TWITTER2GOOGLEPLUS,另一个发件人地址为之前找到的地址,标题为SMS from 33669,执行的操作都是删除会话。

以上。

2010年10月18日星期一

SSL证书制作

证书签名方案

使用OpenSSL制作证书其实还蛮简单的,只是证书签名的部分有一点复杂,方法有三:

  1. 交由受浏览器信任的第三方证书颁发机构签名;
  2. 自签名;
  3. 自制CA证书并用其签名。

对于上线运营的网站来说,第一个方案是首选,因为只有这样浏览器才不会报警。过去买证书很贵,现在倒是有免费的了,比如IE和Firefox都内置的StartSSL

不同的证书颁发机构对于证书生成多少都会有自己的要求,所以本文主要讨论后两种方案。

自签名证书

注:下面提到的很多命令都需要一个openssl配置文件,该文件一般名为openssl.cnf。Linux里一般不用管,Windows可使用参数config指定路径,使用环境变量OPENSSL_CONF也可以。

使用如下命令即可生成自签名证书:

openssl req -x509 -newkey rsa:1024 -nodes -days 365 -out self.pem -keyout self.key

req命令表示创建证书,newkey参数表示创建私钥而不是从已存在的文件中读取,nodes参数表示不加密私钥。如果不添加nodes参数,以后每次使用私钥时都必须输入密码(如Apache每次重启)。

输入证书信息时,Common Name需要写域名,支持通配符,如*.domain.tld。

程序运行完成后,self.pem即为完成签名的证书,self.key则为私钥。

使用上述命令创建的证书只能写一个域名匹配字符串,如写了*.domain.tld之后,访问https://domain.tld仍然会报错。如果想在一个证书中指定多个域名匹配字符串,则需要打开openssl.cnf文件,在末尾处添加如下内容:

[ ca_x509v3_more_cn_ext ]
nsComment="OpenSSL Generated Certificate"
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid:always,issuer:always
basicConstraints=CA:true
subjectAltName = DNS:domain.tld,DNS:*.domain.tld

将subjectAltName行修改为需要的内容后保存退出,使用如下命令重新生成自签名证书:

openssl req -x509 -newkey rsa:1024 -nodes -days 365 -out self.pem -keyout self.key -extensions ca_x509v3_more_cn_ext

自制CA证书并用其签名

如需要使用多个证书,每一个都自签名则意味着每一个都需要导入浏览器,这样就很麻烦。自制CA证书并用其签名后,无论制作了多少个证书,都只需要将自制的CA证书导入浏览器即可,相对来说方便些。

上例中用一条命令直接生成了私钥和证书,这次换个方法,分解为两步。

首先,生成自己的个人私钥:

openssl genrsa -des3 -out my.key 2048

des3参数表示使用该算法加密生成的私钥,以后每次使用私钥时都必须输入密码,去掉这个参数则不进行加密。

根据个人私钥生成自签名CA证书:

openssl req -x509 -key my.key -days 911 -new -out my.pem

输入证书信息时,Common Name可以写自己的名字。将该CA证书导入浏览器后,该名字会显示在证书管理器中。

接下来生成服务器的私钥和证书:

openssl req -newkey rsa:1024 -nodes -days 365 -out server_unsigned.pem -keyout server.key

再之后,就可以用个人证书签名服务器证书了:

openssl ca -days 365 -md sha1 -in server_unsigned.pem -out server.pem -cert my.pem -keyfile my.key

如该命令报错找不到index.txt之类的,视openssl.cnf中的配置,则需要做点准备工作:

mkdir demoCA
mkdir demoCA\newcerts
touch demoCA\index.txt
echo 11 > demoCA\serial

index.txt为空,serial随便写一个两位的数字进去。

多个域名的支持问题,跟上面说的一样,添加extensions参数:

openssl ca -days 365 -md sha1 -in server_unsigned.pem -out server.pem -cert my.pem -keyfile my.key -extensions ca_x509v3_more_cn_ext

完成后,server.key和server.pem即为已签名的证书及私钥。如果用在Lighttpd中,将两个文件合并即可。

最后,将my.pem导入至浏览器中“受信任的根证书颁发机构”即可。

其他

如果要去掉私钥的密码保护,可以这样做:

openssl rsa -in my.key -out my_plain.key

如果需要根据私钥生成公钥,可以这样做:

openssl rsa -in my.key -pubout -out my_public.key

证书生成后,可以使用如下命令查看详细信息:

openssl x509 -fingerprint -text -in my.pem

使用证书加密信息:

openssl smime -encrypt -in ptest.txt -out etest.txt my.pem

使用私钥解密:

openssl smime -decrypt -in etest.txt -out dtest.txt -inkey my.key

若需要DER格式的证书,可使用如下命令进行转换:

openssl x509 -in my.pem -outform DER -out my.der

2010年7月6日星期二

手贱

前两天试了试Blogger的导入和导出功能,今天才发现就这么一试导致链接地址全变了。PR什么的我倒是不在乎,可看着也挺不舒服的。Blogger后端没有修改POST URL的功能,API里也没有。等空了找找看有没有什么办法吧,不过暂时只能这么放着了。

要是有人链到我这儿,对不起先。

Update:

折腾了一下,总算是解决了这个问题,部分解决。

首先,打开导出的XML文件,检查每一个entry元素的link子元素,确保href是你想要的。接着写一个脚本,将entry的title子元素改成链接的文件名部分。这里跟直接发帖一样,不改的话Blogger会根据entry的title给你自动生成一个

# coding: UTF-8
require 'rexml/document'

doc = REXML::Document.new(File.open(ARGV[0], 'r'))

posts = {}
doc.root.elements.each('/feed/entry') do |entry|
  # 有5个link的元素才是blog文章
  next if entry.get_elements('link').length != 5
  
  link = entry.elements['link[@rel="alternate"]']
  url = link.attribute('href').value
  posts[url] = entry.elements['title'].text
  url = url[url.rindex('/')+1..-6]
  entry.elements['title'].text = url
end

doc.write(File.open(ARGV[1], 'w'))
File.open(ARGV[2], 'w') { |f| f.write(posts.to_s) }

其次,在Blogger控制台新建一个blog,名字照旧,域名换一个如otnthnew。选择好模板之后,切忌按照向导的提示立刻导入旧帖子。先去设置中,将所有设置改成跟原blog一样。尤其需要注意的是“格式设置”中的“转换断行”选择为“否”,还有“基本”中的“选择帖子编辑器”选择为“旧编辑器”。

最后,导入备份的XML。把原blog的域名改成otnthold,再把otnthnew改成otnth。再然后还是写一个脚本,把帖子标题给改回来。

# coding: UTF-8
require 'gdata'

GMAIL = ''
PWD = ''
BLOGID = 'xxxxxxxxxxxxxxxxxxx'

=begin
因为墙的问题,gdata需要一点小hack。打开lib/gdata/http/default_service.rb,将:

http = Net::HTTP.new(url.host, url.port)

修改为:

http = Net::HTTP::Proxy(ENV['PROXY_ADD'], ENV['PROXY_PORT']).new(url.host, url.port)
=end
ENV['PROXY_ADD'] = '127.0.0.1'
ENV['PROXY_PORT'] = '8118'


posts = eval(File.open(ARGV[0], 'r:utf-8') { |f| f.read })

client = GData::Client::Blogger.new
client.clientlogin(GMAIL, PWD)

url = 'http://www.blogger.com/feeds/#{BLOGID}/posts/default?max-results=10'
idx = 1
while true
  feed = client.get(url + '&start-index=' + idx.to_s).to_xml
  feed.elements.each('entry') do |entry|
    entry.elements.each('link') do |link|
      link = entry.elements['link[@rel="alternate"]']
      entry.elements['title'].text = posts[link.attribute('href').value]

      entry.add_namespace('http://www.w3.org/2005/Atom')
      entry.add_namespace('gd','http://schemas.google.com/g/2005')
      entry.delete_element('thr:total')

      edit_uri = entry.elements['link[@rel="edit"]'].attributes['href']
      response = client.put(edit_uri, entry.to_s)
    end
  end
  
  idx += 10
  break if idx >= feed.elements['openSearch:totalResults'].text.to_i
end

因为blogid已经变了,对于Blogger来说这就是一个全新的blog,会不会有什么严重的后遗症还有待观察。

2010年3月18日星期四

Opera Mini翻墙笔记

一直在用的某一个Opera Mini 4.2修改版突然不能爬墙了。本不想折腾,可实在是被各种“优化”过的皮肤刺激得不轻,于是花了点时间,有了这一篇笔记。

自从Opera Mini国际版服务器封掉所有来自大陆IP的请求后,要用OPM翻墙就需要解决两个问题:首先是找一个,或者自己搭一个中继服务器;其次是将OPM程序中原来的服务器地址改掉。

网上别人搭好的中继服务器很多,几乎全用的是opm-server-mirror。验证一个中继服务器是否可用很简单,只要在服务器地址最后加上“/?test=1”(例如:http://xx.oo.com/opm/?test=1)并用浏览器访问,如显示“Hello Opera Mini Server! Fuck GFW!” 则表示中继服务器工作正常。

要求不高的话,用别人搭好的中继服务器也没啥,可这样会存在一个严重的安全隐患。因为OPM所有的请求和回应都要从中继服务器绕一圈,假若搭建服务器的人心怀不轨,获取用户的各种账号及密码是非常容易的事情。可能的话还是自己弄一个吧,随便找一个国外的支持PHP和cURL的免费空间就成,程序及教程opm-server-mirror都有。

搞定服务器的问题后,接下来则是修改OPM的服务器地址。如果更喜欢官方原版,opm-server-mirror提供了一个OPM服务器地址修改器。这种修改方式的问题在于,一旦中继服务器不再可用,需要用计算机再次修改并重新安装,未免有些麻烦,所以我个人更喜欢使用可自定义中继服务器的修改版。

可自定义服务器的修改版很多,个人推荐如下三个版本:

某些版本如安装出现问题,可尝试寻找一个可用的Socket服务器。比如用JD-GUI反编译这个版本

如需要测试某个修改版或某个服务器,可以用PC上的J2ME模拟器,如MicroEmulator

2010年1月8日星期五

Windows 7 IPv6不完全折腾

按照网上很多人的说法,Windows 7下只需要开一个有管理员权限的控制台,执行类似如下两条命令即可:

netsh interface ipv6 isatap set router isatap.tsinghua.edu.cn
netsh interface ipv6 isatap set state enabled

然而很奇怪的是,ipconfig显示我已经有了一个2001开头的IPv6地址,ipv6.google.com却打不开。试了很多个isatap服务器都不行,正像只没头苍蝇一样在网上乱逛的时候,鬼使神差地敲了一句ping -6 ipv6.google.com。呃,居然有回复?!然后试着在浏览器里访问http://[2001:4860:c004::68],还真的可以打开……

C:\>nslookup www.kame.net
服务器:  google-public-dns-a.google.com
Address:  8.8.8.8

非权威应答:
名称:    www.kame.net
Addresses:  2001:200:0:8002:203:47ff:fea5:3085
          203.178.141.194


C:\>ping www.kame.net

正在 Ping www.kame.net [203.178.141.194] 具有 32 字节的数据:
来自 203.178.141.194 的回复: 字节=32 时间=111ms TTL=45
来自 203.178.141.194 的回复: 字节=32 时间=131ms TTL=45
来自 203.178.141.194 的回复: 字节=32 时间=99ms TTL=45
来自 203.178.141.194 的回复: 字节=32 时间=137ms TTL=45

203.178.141.194 的 Ping 统计信息:
    数据包: 已发送 = 4,已接收 = 4,丢失 = 0 (0% 丢失),
往返行程的估计时间(以毫秒为单位):
    最短 = 99ms,最长 = 137ms,平均 = 119ms

C:\>nslookup ipv6.google.com
服务器:  google-public-dns-a.google.com
Address:  8.8.8.8

非权威应答:
名称:    ipv6.l.google.com
Address:  2001:4860:c004::68
Aliases:  ipv6.google.com


C:\>ping ipv6.google.com
Ping 请求找不到主机 ipv6.google.com。请检查该名称,然后重试。

C:\>ping -6 ipv6.google.com

正在 Ping ipv6.l.google.com [2001:4860:c004::68] 具有 32 字节的数据:
来自 2001:4860:c004::68 的回复: 时间=401ms
来自 2001:4860:c004::68 的回复: 时间=400ms
来自 2001:4860:c004::68 的回复: 时间=401ms
来自 2001:4860:c004::68 的回复: 时间=401ms

2001:4860:c004::68 的 Ping 统计信息:
    数据包: 已发送 = 4,已接收 = 4,丢失 = 0 (0% 丢失),
往返行程的估计时间(以毫秒为单位):
    最短 = 400ms,最长 = 401ms,平均 = 400ms

nslookup能够获得IPv6地址,而且排在IPv4地址的前面,似乎DNS并没有什么问题。然而无论是ping还是浏览器,却都对IPv6地址视若无睹,就好像IPv6根本没有启用一样。

接下来抱着试一试的心情,我又往hosts文件里添加了几个IPv6地址,比如:2001:4860:c004::68 www.google.com

居然,好了?嗯,ping没问题了,浏览器也能正常打开。看起来还是DNS解析的问题,网络应用程序默认情况下无法取得IPv6地址。

可问题究竟出在哪?在网上翻了很久,仍然不明所以。我甚至开始怀疑,是不是自己网络环境的原因(我用没有独立IP的小区宽带,家里还有一个路由器,相当于是内网中的内网),但试着在Ubuntu里装上miredo,同样用Google DNS,同一个ISATAP服务器,一切正常。

看来,只能是Windows 7的设置有问题了。虽然解决办法到现在也没找到,不过至少hosts可用,先将就吧……

用上IPv6之后,我常用的绝大部分网络程序都没出什么问题,只有Privoxy。跑到官网上看了看,最新版的3.0.15是可以支持IPv6的,只是mingw32编译的Windows版还不行,需要修改代码。Socket编程我碰都没碰过,这可不是我擅长的领域,所以试着用Cygwin编译了一个Privoxy,能用。虽然没有GUI,不过那个窗口也没大用,继续将就……

2009年8月15日星期六

Tumblr vs Publr

现在才写似乎有些Out了,不过我的确是最近才开始用类似的东西。因为就是用来贴图而已,所以我只关注了这两家网站关于贴图的相关功能。

因为墙的关系,最先开始用的是Publr。本以为作为Tumblr的后来者,功能方面应该较弱才对,结果用了一段时间发现事实并非如此。Publr可以自定义Theme,网站提供的三款也都是设计优良的作品。发布照片的界面也很好用,能够一次选择多张图片,并且在上传的时候去写文字内容。基本上我介意的核心功能,Publr都能很好地提供。

要说缺点,不能设置Post发布时间算一个,无法调整Photoset顺序也算一个,不过都还可以忍受就是。真正让我起意尝试其他相似服务的原因并不在于功能,而是出于对数据安全性的担心。

Tumblelog,看名字就知道,这一类网站Tumblr肯定才是老大,Publr是否能找到自己的位置?上线有一年了吧,我只用了月余就抓出了三个Bug,用户少到没人发现?API至今还很不完整,站方想要添加的SNS功能也进展缓慢,种种迹象让我觉得至少要找个备份的地方才算保险。

于是我慕名翻墙来到了Tumblr,可是却有那么点失望。Tumblr的功能的确较Publr丰富,创建多个Blog、SNS,等等等等。可是我看了官方网站才知道,发布Photoset的功能七月才上线,无论可用性还是易用性都有不小的缺陷。

Tumblr将单张的Photo和多张的Photoset分成了两种不同的Content类型,假如第一次发布时只选择了一张照片,Post类型即为Photo,以后修改也不能再添加照片并转化为Photoset了。呈现方面,如浏览器安装了Flash插件则Photoset会被显示为一个Flash相册,否则就是所有大图的堆叠,相比Publr点击略所图用Javascript放大的方式差了不少。另外Tumblr的Photoset还有最多十张的限制,上传时必须逐张进行选择,用起来实在有些不太舒服。

综合来看,仍然是Publr更为契合我的需求。至于备份,写了一个Ruby脚本将Photo类型的Content从Publr同步至Tumblr,而Photoset就只能手工处理了。

2009年8月6日星期四

利用GAE实现Twitter短信通知

简介

随着国内Twitter Clone集体被自杀,利用叽歪绑定飞信,通过手机短信获取Twitter更新的法子就失效了,于是我再一次开始折腾。

这次用到的东西包括cocobear写的PyFetion、Yahoo Pipes和Google App Engine。基本思路就是利用GAE的Cron功能定时检查Yahoo Pipes抓取的RSS,如果有新的东西就用PyFetion给自己的手机发短信。

除了Twitter,这个程序可以用来做的事情挺多,比如接收实时天气预报之类,各位可以自由发挥。

安装及使用说明

由于PyFetion、FeedParser等第三方库都采用GPL许可证发布,所以我的代码也使用GPL v2许可证,使用及再发布请留意相关限制。

代码放到Github上了,下载请走这里,点击download即可获得最新源文件的压缩包。

我并没有为本程序单独建立一个代码仓库,目前还整合了杜晓刚GAppProxy等其他程序。用得上的话就不用为本程序单独建立一个GAE了,不然的话放在那里也成,并不影响使用。

下载及解压后需要修改的文件有两个。app.yaml中第一行“application: ogaeo”,将ogaeo改为你的GAE项目名称。另外则是Conf.py中RSS2Fetion的相关配置信息。

默认的RSS只抓取Twitte的replies和direct messages,应该不至于太烦人。据说用飞信给自己发短信有每天600条、每月1000条的限制,如需要自定义抓取来源请留意。

我将Cron任务设置为每5分钟执行一次,实际延迟约在5到10分钟的样子。如需要更改,请查阅cron.yaml文件。

需要GAE申请及上传帮助,请查阅GAppProxy帮助文档。使用中出现问题,请在本页留言。

使用本程序会造成飞信PC及手机客户端掉线,如果你经常使用飞信聊天并且只有一个移动的号码,本程序并不适合你。

如果希望临时关闭本程序,可以采用短信修改飞信密码的办法来实现。编辑短信,内容为新密码,发送至12520050。详情请查阅飞信帮助说明

更新历史

Update 22:36 2009-8-11:

本想偷懒直接用memcache,可是发现memcache无法提供长时间的缓存,所以还是得用数据库。

另外还发现GAE一个问题,pickle反序列化似乎得这样用:pickle.loads(str(dbcache.txt))。

Update 23:56 2009-8-13:

用pickle序列化数据并保存至数据库仍然会有重复发送的问题,而且两次重复发送都在凌晨6点多。找不到问题出在哪里,于是再次修改缓存机制,将RSS永久保存在数据库中。

一定要记住两件事:一、TextProperty不可查询,只能用StringProperty;二、看文档需要仔细些,再仔细些……

Update 14:43 2009-8-17

经过上次修改后没有再出现重复发送短信的情况,问题应该是解决了吧,只是出错的原因还不太确定。

嫌疑集中在Model(Query、GqlQuery)类的get方法上。按照文档的说法,query.get()应该返回数据库中符合查询条件的第一条纪录,没有则返回None。可是用query.get() == None进行条件判断时就会出现重复发送的情况,改用query.count() == 0时则不会。初步判断,有可能是get方法在发生错误(如超时)时,并没有抛出异常所致。

Update 22:57 2009-8-20

上次将get()修改为count()后忘记上传代码了,汗。

Update 23:15 2009-8-30

有人说希望可以用父母的手机申请飞信并给自己的手机发短信,这样就不影响飞信使用。貌似的确会有这样的需求,所以加上。

Update 21:46 2009-9-17

某人提意见,去掉replay里[@自己的用户名]看起来会怪怪的。想想也是,反正省不了几个字符,于是小改一下默认的Pipe。

2009年6月4日星期四

Mobile Over The Cloud

Apple MobileMe和Microsoft MyPhone都只支持特定平台,所以我的手机没法用,features倒是看起来很诱人。

Nokia Ovi用的是SyncML协议,理论上应该很多手机平台都支持。不过同步使用的密码需要以OTA的方式获得,非塞班手机能不能用没试过。支持同步通讯录、日历和记事本,貌似不错,可是服务器经常停机,频繁到影响使用的程度。

Google Sync则SyncML和ActiveSync两种协议都支持,S60上自然是用SyncML。有Google帐户就可以直接使用,能同步通讯录和日历。

因为我还没有忙到需要用计算机管理日程的程度,所以比较关注的只有通讯录一项。Ovi既然是Nokia出的,似乎应该对自家手机支持比较好才对,事实上也不尽然。

我先试了Google Sync,发现其不支持生日和备注字段。接着再试Ovi,生日备注是支持了,可是“手机(家庭)”字段却不会被同步。两家对vCard的支持只是半斤八两,都不算好。

Web端方面,Ovi差Google太多。Ovi的网站虽然比较华丽,但是速度太慢,经常停机,并且功能薄弱——连批量编辑和删除联系人的功能都没有。

个人信息中心这类东西,Google的优势应该比Nokia大很多。毕竟Google有Gmail、Gtalk,除了已经支持的Contacts和Calendar,还有Bookmark、Notebook,有心想做都是现成的。而且用Google,不必担心换了非Nokia非WinMo的手机就没法用。

在Google Sync进一步完善前(或许有得等),跟Ovi搭配着一起用或许是个不错的主意。

另,SyncML协议可以同步的东西其实很多,比如彩信和短信。不过我找了很久,都没有找到一家真正提供彩信同步功能的网站。国内有一家MyTT虽然号称可以支持,但实际上也不行。可以同步短信的倒是有好些,我试过之后发现也就O-Sync尚算可用。可是这家也不支持导出备份,总有一点点担心长期运营的问题。

2009年3月14日星期六

Psiphon2试用

在网上翻到Psiphon2,没仔细看究竟是啥玩意儿,就发了封信到english@sesawe.net(写英文)要邀请。不曾想才过半个小时,就收到了Freerk Ohling的回信。那个时候加拿大应该是半夜才对,莫非Freerk也是宅男夜猫子?

具体怎么用,请到这里去看吧,很简单,我就只说说一天来的使用感想好了。

Psiphon2跟go2一样,其实就是一个在线代理。比如你被分配到的代理地址是https://xx.xx.xx.xx/xxx/,若要访问被墙了的http://fackgfw.cn,那就可以这样用:https://xx.xx.xx.xx/xxx/http://fackgfw.cn。

在线代理有的缺陷Psiphon2自然都有,如只支持http和https协议,以及访问采用AJAX技术的网站可能会有问题等等。优点则是不需要修改系统或浏览器的任何设置,也就是说网吧等地方也能用。

Psiphon2跟别的在线代理相比,最大的不同应该就是速度。我试着从一个被墙的日本网站下载文件,最快能达到30KB/S左右,很不错了已经。而且Psiphon2没有广告,如果能一直维持这样的速度,我会非常非常感恩的。

虽然就目前的使用状况来看,我对Psiphon2挺满意,不过该说的还是要说。基于在线代理的运行机制,你通过Psiphon2所进行的任何操作,对Psiphon2服务器来说都是可见的,Psiphon2完全有能力收集你的访问记录和某些帐户信息。

当然了,用某门某界翻墙同样有类似的问题。被蹂躏了这么久,我个人真是觉得能用就好。而且相比跟某功某志扯上关系的某门某界,Psiphon2或许还更值得信赖一点点。

以下是一些Psiphon2使用小贴士。

javascript:(function(){var proxy = 'https://xx.xx.xx.xx/xxx/';location.href = proxy + location.href;})()

将以上代码存为一个Bookmarklet(记得修改服务器地址),遇到被墙的网站点一下就会自动调用Psiphon2访问。

<script language="JavaScript">
if (document.title == '503 - Connect failed (Privoxy@localhost)') {
  var proxy = 'https://xx.xx.xx.xx/xxx/';
  location.href = proxy + location.href;
}
</script>

上面这个更好一点,存为Maxthon的按钮插件并设置自动运行,或存为Opera、Firefox的用户脚本,被墙时可以自动调用Psiphon2。

上述代码用的是Title来判断是否被墙,因为Javascript似乎没办法获得HTTP Response Code。我用Privoxy,所以判断语句才长这样,不同浏览器不同环境要依据实际情况修改才行。

Update:

还没爽快多久,我被分配到的地址就不能用了。搜了一下发现,中文网络上关于P2的信息突然多出来不少,连我写的这点东西都有人“转载”,甚至还有人直接贴出自己被分配的地址(跟我的一样)。别的no comments,没想到我这里也不如我想象的那么冷清,有那么点意外。

发现问题后给Ohling又写了封信,回信还是一如既往的快,并告诉我说,过几天我就会收到一个新地址。不过那已经是一周以前的事了,到今天我也什么都没收到。以现状来看,P2所掌握的资源估计有限。

除了P2本身出问题,其运行的安全性建立在两个前提之上:一是没人故意捣乱;二是没有小白泄漏地址。仔细想想这两条都难以保证,就不知道P2是不是真的栽在其中之一上。

2009年3月5日星期四

Tips of Hotspot Shield

Hotspot Shield是架还不错的翻墙梯,至少速度还不错。只是广告很烦人,要装客户端也很烦人,而且默认情况下连接成功后所有网络请求都会走Hotspot Shield的线路,没什么必要。

曾试着用Windows自带的拨号工具代替Hotspot Shield客户端,只是没找到怎么样才能向服务器提交CA证书通过IPSec验证,所以尝试失败,客户端还是得装。不过另外两个问题,倒是有办法解决。

先说说比较简单的广告问题。最直接的法子当然是过滤,可是也太麻烦了些。实际上有人发现,使用Opera的时候Hotspot Shield不会添加广告。所以这个问题可以通过伪造User-Agent来实现,比如你要是也用Privoxy的话,可以这样写:

{ +hide-user-agent{Opera/9.64 (Windows NT 5.1; U; Edition IBIS; zh-cn) Presto/2.1.1} }

另外,据说Hotspot Shield针对免费用户也是有流量限制的,每个月3GB,而这个限制可以通过修改网卡的MAC地址绕过。我个人倒是没遇到过流量超限的情况,顺便提一句备用吧。

想实现只有发往特定服务器的请求才使用Hotspot Shield的功能则比较麻烦,需要去设置路由表。

打开C:\Program Files\Hotspot Shield\config\config.hvpn,将“;route-noexec”行最前端的分号去掉并保存。这一设置能让Hotspot Shield在连接成功后不去修改路由表,方便我们自己处理。

执行Hotspot Shield Launch连接服务器并纪录IP地址,该地址可以从Launch弹出的IE窗口中获得。例如某次连接分配到的地址是10.55.160.44,那对应的网关就是将最后一位改为1,即10.55.160.1。

假设现在en.wikipedia.org无法访问,我们先在网上随便找一个可以进行域名解析的网站,例如http://www.hostip.info/,填入域名提交并获得en.wikipedia.org对应的IP地址为208.80.152.2。

打开一个命令提示行窗口,执行该命令:route add 208.80.152.0 mask 255.255.255.0 10.55.160.1

管理路由表还是有点麻烦,而且貌似也没有简单方便的GUI工具可以代劳,想要自动化一点只能自己写脚本,这也是我更喜欢代理服务器的原因。

2009年2月10日星期二

如何开启Live Mail的POP3功能

在网上看到Live Mail,也就是曾经的Hotmail、MSN提供POP3支持的消息,一点也不高兴:该功能只对有限的几个国家的用户开放,显然,不包括中国。

好吧,根据以往的经验,试试能不能冒充一下外国友人,享受非国民待遇。因为某些原因,先试了荷兰,不成,接着试了英国和加拿大,还是不成。心想说微软不至于这么小气吧,于是Google之,找到了这里,照做之下还是不成。

最后才发现,原来是我用以测试的Magic Mail Monitor这个程序有问题。可叹我用了他那么些年,直到正式皈依GMail为止。GMail的POP3貌似是独立的,在Web中删除或归档的信件不会反映在POP3连接中,于是把POP3当作检查新邮件的手段就不好使了。

呃,不废话了,以下是开启Live Mail POP3功能的办法:

  • 用浏览器打开:https://account.live.com/?mkt=en-gb
  • 点击“Registered information”
  • 将Home location和Work location的如下项都改掉
    • Country/region: United Kingdom
    • Postal Code: WC1B 3DG
    • Constituent Country: England
    • Time zone: London, United Kingdom - GMT
  • 保存后,点页面最上边的“Mail”进入Live Mail
  • 右边的“选项”,点一下,把界面改成英文

这样就搞定了,似乎并不需要登出登入。在激活了POP3功能之后,可以把你的个人信息改回去。或者干脆就冒充外国人到底,只改Work location。为了在FF中好看点,顺便偷图一张。

EMail客户端需要设置的参数如下:

  • 用户名:SomeBody@hotmail.com
  • 服务器:pop3.live.com
  • SSL:要且一定要
  • 端口号:995

我终于可以用GMail通过POP3来收取Live Mail的信件,实现天下同G了?很遗憾,可以,也不可以。

跟GMail刚开始提供IMAP功能时的毛病一样,Live Mail目前的POP3功能不是8-bit clean的,未经编码的GBK、UTF8通通有问题。用通俗的话来说就是有可能会乱码,所有中文字符显示为问号。因此暂时还必须在Live Mail中保存原件,或者只把POP3功能当检查新邮件的手段用。

目前开放了POP3功能的国家名单中还有日本,所以这个问题微软肯定早就知道了,等着吧。

另外还有一个不大不小的问题,通过POP3收取的信件不包括junk,也没有选项可以进行设置。

在折腾的过程中还顺便发现Live Mail Web端Bug一枚:

当邮件标题为未编码的GBK字符时,如界面语言为中文则显示正常,否则邮件列表界面中会乱码。点开邮件,只要其Content-type正确,在任何语言的界面下,包括邮件标题都显示正常。

不过无所谓了,我只希望POP3的Bug尽快修复,我就可以早一点跟Live Mail界面上那条硕大的广告说再见了。

2009-3-11 12:54 Update:

8bit clean问题已修复。

2009年1月15日星期四

用手机接收Twitter Replies

本来Twitter只是我用来作为一个自闭宅男自言自语的地方,没事偷着乐而已。可是近来接连被人在那里抓住现行,这下问题就出来了。

先是发现,即使在Notices设置中选择Show me all @ replies,未follow对象@我的消息仍然不会显示在Home Time Line里。继而又发现,没有任何方便的法子获取replies提醒,没email,没im,当然更不会有短信。

要知道,我更新Twitter都是通过叽歪同步的方式,难道我得三不五时用浏览器去访问Twitter @Replies Tab才成?好吧,于是开始折腾。

在经过艰苦卓绝的探索,克服了一系列难关之后,我终于实现了用手机接收Twitter Replies提醒短信的终极目标,完成了一次互联网上的二万五千里长征。

好吧,我不贫了,下面就说具体过程。

据说,过去叽歪和饭否等国内网站,都提供手机短信下行提醒服务。只要想办法弄到Twitter Replies的RSS,通过Feedlr一类的服务广播到帐户A,再用帐户B绑定手机并关注帐户A,就可以达到目的。

只是现在日子不好过,饭否直接取消了短信下行服务,叽歪没取消,可是怎么设置都收不到。还好叽歪支持飞信,通过用帐户B绑定飞信的办法,仍然可以达成目的。

先去叽歪注册两个帐户,Xo和XoJwBot。用Xo绑定飞信帐户,设置获取提醒方式为飞信,并关注XoJwBot,叽歪上的设置就弄好了。如果注重隐私问题,可以将两个帐户都设置为不公开。

然后是想办法获得Twitter Replies RSS。@Replies Tab页最下面有提供RSS连接,可是这个地址需要Auth,所以得这么用:http://[ttUser]:[ttPw]@twitter.com/statuses/replies.rss

接着去Feedlr注册。但在创建广播的时候Feedlr会告诉你,如上地址非法。咋办?如果不想让全世界都知道你的Twitter密码的话,就不要考虑FeedSky一类的法子了,用Yahoo Pipes吧。

Yahoo Pipes用起来不算难,或者说,不算太难。我们还可以顺便在Pipe里把原始RSS中“@User”的部分删掉,以免广播到叽歪时出问题。

最后将Yahoo Pipes输出的RSS用Feedlr广播到叽歪帐户XoJwBot,整个过程就完成了。只要飞信不取消Client离线就发短信的功能,可以干的事还蛮多的,希望这篇东西流传别太广吧。

就为了这么点破事儿,数数注册了几个帐户:一个Twitter、一个Yahoo、一个Feedlr、两个叽歪、一个飞信,还有两个email,还有一部手机和一张中移动的SIM卡……

Update:

出问题乐,收不到短信……

经过排查,问题出在叽歪至飞信的环节。即使我打开了飞信客户端,仍然收不到叽歪发来的信息,从飞信客户端发送更新至叽歪也没反应,看来是叽歪的飞信机器人当掉了。

这么不靠谱,残念……

2009年1月6日星期二

选个Feed来订阅

有一点点矛盾,写Blog的人可能不会喜欢Feed Cache这东西,但读者肯定喜欢。比如我在订阅Feed的时候,一般都会选Cache量最大的地址订阅。

怎么样判断哪个地址的Cache量最大呢?都订阅上然后手工去翻,或者借助服务提供商的API,如果有的话。Google Reader是有的,Bloglines和NewsGator不太清楚,应该也有吧。

我写了一个Google Reader API检查Cache量的小东西,附在文末。在文本框中填入Feed URL,点后面的按钮就可以了,结果会以表格的样式显示在文本框下面。为了图方便,代码用了同步模式获取数据,如果老半天没反应就手动刷新一下页面再试。

Google Reader API目前还没有正式发布,需要先验证,而且还没JSON版本,所以会遇到著名的跨域问题。IE6用户在菜单上选工具、Internet选项,在安全页中点自定义级别,找到其他项下的“通过域访问数据资源”,选提示,确定。这样脚本运行时会出现提示,授权即可。

直接使用IE6的话,先访问Google Reader并登陆,然后在同一个窗口打开本页就可以正常使用了。Maxthon之类的浏览器就随便了,只要登陆过,在新开的选项卡里也可以正常使用。

代码只在IE6中测试过,不好意思。

以下是一些BSP提供的不同Feed地址,列表应该会慢慢增加的吧。其实只要BSP做好转向,啥事都没了。

新浪
http://blog.sina.com.cn/rss/BLOGID.xml
http://blog.sina.com.cn/rss/BLOGNAME.xml
http://blog.sina.com.cn/myblog/index_rss.php?uid=BLOGID
Blogger
http://www.blogger.com/feeds/BLOGID/posts/default
http://BLOGNAME.blogspot.com/feeds/posts/default
http://BLOGNAME.blogspot.com/atom.xml
http://BLOGNAME.blogspot.com/rss.xml
歪酷
http://rss.yculblog.com/BLOGNAME.xml
http://rss.ycool.com/blog/BLOGNAME.xml
BlogCN
http://BLOGNAME.blogcn.com/rss.xml
[404]http://www.blogcn.com/rss.asp?blog=BLOGNAME

2009年1月1日星期四

Feed迷思

Feed,或者叫RSS,总之就是那玩意儿,我现在的生活已经有点离不开了。每当我又不知道该做什么才好的时候,总会打开Feed阅读器看看有啥新东西了没。

我有不止一台机器,也并非完全没有用别人机器的可能,所以一开始对在线阅读器还是挺有兴趣的。不过在尝试使用了一段时间Bloglines之后,我放弃了。

实在是太慢了。Bloglines服务器在国外,本来就不快,还要再加上等待页面重绘的时间,慢得让我无法忍受。我可是至今都还在用AcdSee 2.4的人,图的就是一个爽利。

之后我遇到了国产的GreatNews离线阅读器,曾一度惊为天人。体积小巧,资源占用不多,而且还能绑定Bloglines帐户。GreatNews+Bloglines的组合,我用了很长一段时间。

然而渐渐的,我也发现了GreatNews的不少缺点。首先是与Bloglines的集成度不高,Clippings只是本地操作,无法反映到Bloglines帐户中,所谓社会化功能就更没有了。更重要的是程序本身也有不少问题。Bloglines端的Feed发生302重定向后,GreatNews中新旧地址会同时存在,不会自动删除旧地址。手动删除也不行,因为Clippings是保存在本地的,删除旧地址会一并将Clippings也删掉。最让人无法接受的是,会莫名其妙自动退出。

GreatNews是免费软件,开发者好像也只有一个,缺乏激励的情况下后续乏力也无可指责。随后我换回了FeedDemon,其时该程序已经被NewsGator收购了。

当时的FeedDemon还是共享软件,不过最近已经免费了。被收购后的FeedDemon与NewsGator配合很好,Feed订阅的双向同步都没有问题,Clippings数据在服务器端也同样有保存。一直到最近,FeedDemon都是我日常使用的首选。

不过FeedDemon也不完美就是了。相比GreatNews,FeedDemon的资源占用要大很多。另外当单一Feed在本地未读Posts达到100条时,FeedDemon将不再继续下载新数据,这和我的使用习惯不符,也觉得FeedDemon太过自作聪明。

如果说对FeedDemon还有什么不满,那就是社会化功能太弱了。通过对比不同用户的订阅进行推荐,我觉得是很棒的功能。而NewsGator这方面的表现很差,不知是中文用户太少,还是别的什么缘故,NewsGator推荐给我的Feed一个我有兴趣的都没有。

于是我只好想起来了,就导出FeedDemon的OPML,再导入Google Reader和鲜果,根据推荐新增几个订阅。一直就这么波澜不惊的将就用着,直到Google推出了自己的浏览器Chrome,让我的心思又活泛起来了。

将Chrome作为日常首选,暂时还没可能。不过Chrome真的很快,无论是启动还是加载GMail、Google Reader,都很快。而且Chrome绑定了Google Gears,只要多等一会儿,在Chrome跑使用了Gears的Reader并不太慢,虽然还是比不了FeedDemon。

要不要换?我也不知道,看看再说吧。

Update

试着用了几天Chrome加Reader的组合,发现问题还不少……

  • Chrome的Flash支持非常糟,会占用大量CPU时间甚至造成卡死。只好删掉系统和plugin目录下的npswf32.dll,不用Chrome看Flash。
  • Reader不使用Feed的自定义Icon,找特定BSP的Feed时很不方便。
  • 当抓取Feed出问题的时候,GUI上没有任何直观的提示,必须打开Feed点show details。
  • 只有Stream一种内容呈现方式,滚动条越往下拉,内存占用越大。
  • Feed和Clipping都用Tag来分类,用起来挺不方便的。我个人的解决办法是用英文Tag分类Feed,用中文Tag做Clipping。
  • Clipping时添加Tag必须手工输入,不能点选。针对英文Tag有自动完成和提示,但用中文Tag就很麻烦。
  • Share和Share with note还不就是一回事,感觉有点啰嗦。
  • FeedDemon针对某些Feed,可以显示已有多少条评论,Reader没这功能。

2008年12月24日星期三

Tips of RayFile

安装RaySource之后,该软件会偷偷摸摸地在系统加载项里添加一条peer.exe的记录,记得用Windows优化大师一类的工具将其去掉。

执行RaySource程序,或浏览RayFile网站时,peer.exe也同样会被加载,同时被加载的还有一个PeerAdapter.exe。如当前并没有使用RaySource下载什么东西,这两个进城都可以杀掉。

在已知文件MD5值的情况下,可用如下方式查验该文件是否存在于RayFile服务器中:

http://cachefile.rayfile.com/zh-cn/download/C2DB9C4749C6ECF521FFCA0DD8F62752/

这个地址的最后一段即为MD5值,该地址会被转向至:

http://www.rayfile.com/zh-cn/files/284c6299-4120-11dd-bbb3-00142218fc6e/

而RaySource中所使用的地址,实际上是经过Base64编码过的。例如:

fs2you://Y2FjaGVmaWxlNy5yYXlmaWxlLmNvbS96aC1jbi9kb3dubG9hZC9DMkRCOUM0NzQ5QzZFQ0Y1MjFGRkNBMEREOEY2Mjc1Mi9tc3loLnR0ZnwxNTA0NDQ0MA==/

解码后的内容如下:

cachefile7.rayfile.com/zh-cn/download/C2DB9C4749C6ECF521FFCA0DD8F62752/msyh.ttf|15044440

附上一个JavaScript实现的Base64解码工具

2007年10月6日星期六

Opera中的站点首选项

因为新浪等BSP的图片不允许外链,所以用Google Reader看这样的Feed会很难受。为了解决这个问题,我试着在Opera中,针对www.google.com的站点首选项设置为不发送引用页。但这样设置却起不到预期的作用,还是必须在菜单上修改快速首选项并刷新才行。

注:后来才知道我这是舍近求远,其实只要用HTTPS访问Google Reader就可以了。因为考虑到安全原因,HTTPS规范推荐不发送引用页数据。)

一直都以为是站点首选项和快速首选项的优先级有问题,过了好些日子才想到了另外一种可能。在自己机器上搭了个Web服务器,经测试验证了自己的想法后,才发现原来是自己笨。

Opera中站点首选项针对的是被引用文件所在主机,而非引用页所在的主机。如需要在Google Reader中看新浪Blog的图片,则应该针对album.sina.com.cn设置为不发送引用页,而非www.google.com。

2007年9月19日星期三

Say bye to flickr

flickr被和谐的时候,我多少也觉得有些愤慨。没想到的是,不久之后flickr就从受害者变成了加害者——他们取消了免费账户的原始照片下载权限。

我曾在flickr放了一组很值得留下的照片,而且我以为自己没有留底。flickr此举就代表着,除非我付那25美金的年费,否则就算是我也拿不回自己的原始文件。更过分的是,以往这方面并没有限制,变更服务条款也没有通知我。

一直隐忍着,直到今天在硬盘上乱翻,才在一个角落里意外发现了那一组照片的原始文件。不夸张的说,有种重新取得回忆所有权的感觉。一阵狂喜,接着我删掉了旧的flickr账户,重新注册了一个,并决定以后只看照片,绝不上传。

凭心而论,flickr对免费账户的限制本来就很多,加上这么招人恨的一条不知道是为了什么。不允许外链就是了,连原始文件也不让下载,太过分了些。

2007年9月17日星期一

被某人记得

我有在Facebook上注册过,为了看看有啥好玩的。逛了一圈,没找到继续流连的理由,于是就扔在一边了。若不是今天收到了一封email,告知我某人在Facebook上加我为好友,我都快忘记有这么一回事了。

那是一个曾经很熟的人。登录上去才知道,他也刚注册而已,我是他添加的第一个人。

是不是该感到窃喜?因为还有人记得我。事实上,刚开始我确实有这样的情绪。然而继续在Facebook上翻了翻,我才发现完全不是这么回事。

如果你愿意提交email帐户及密码,Facebook会去读取你的通讯录,并告诉你哪些你认识的人曾经在他们家注册过。我的GMail邀请函就是那位曾经很熟的人发给我的,所以他的通讯录里有我。原来如此。

当然,Facebook这个功能很棒。只是我和那位曾经很熟的人,不可能会再次变熟了。所以我的Facebook上其实还是一个好友都没有,我还是没有找到流连的理由。

2006年12月11日星期一

Zooomr:年轻真好

过去一直在用flickr,前几天因为一个心血来潮的理由,集中体验了一下很热门的几个相册服务,包括Zooomr23hq、Zoto、PBase等等。虽然最后还是觉得flickr最好,而且Zooomr">连第二也排不到,不过仍然觉得这是个很有意思的地方。

这家站最被容易被人口口相传的有这么几点:相册服务的后起之秀,flickr的追赶者;可能会被收购,传言金额在500万美元左右;只有一个(以前的事了)站长兼程序员,当年17岁,今年18岁。不过这些特点跟用户的关系不大,而我对Zooomr的第一印象却好坏各半,感觉这里做得很时髦,却也很粗糙。

时髦在申请账户的时候就可以感觉到了,Zooomr并不自己管理用户认证,而是用了OpenID。所谓OpenID,就像你在MS、Yahoo、Google,只要申请过一个账户,就可以使用该站旗下的所有服务。只不过MS他们的账户只限于自己的旗下网站,OpenID则属于开放的第三方。

站在用户的角度,我对OpenID这东西没什么特别的感觉,好处坏处都有。但对于服务提供商来说,用这种东西可以说是相当大胆的行为。撇开隐私一类的深层问题,假如OpenID服务器down掉了怎么办?用户声称忘记OpenID密码且无法找回,要求你让他进入自己的账户又怎么办?世界是平的,很先锋,可现实问题也不少。后来我才知道,Zooomr现在已经是2.0 beta版了,升级时用户认证就出了问题。以前用的认证方式是Level9、Meetro和Google Account,OpenID和LiveJournal是现在才统一的。

至于粗糙就随处可见了。网站首页是固定宽度的,页面下方有近五分之二是灰色,显然是前景长度不够,CSS也没有调整好。登陆页有部分内容与页脚重叠,也是CSS的问题。删除照片之后,查看次数和Trackbacks不会实时更新,有延迟。照片public还是private不能改,保存无效。虽然能生成个人的Tags云,但无法通过Tag定位和搜索特定用户、相册的照片,也就是说Tag搜索只能是全域的。

还有个非常严重的问题。虽然Zooomr声称支持jpeg、png、tiff等格式,但略缩图都是jpeg的,包括“原始尺寸”。是的,“原始尺寸”,而没有“原始文件”。即使你上传的已经是jpeg格式的图片,Zooomr依然会给你通通转一遍,而且原始文件不保留。我上传了一张103KB、800×600的照片,下回来的文件是184.4KB,EXIF也全没了。[*这意味着就算你是Pro用户,也无法从Zooomr拿你上传的原始文件。*]我认为这是不可接受的设计错误,也是让我判定Zooomr目前不足用的最大理由。

单以这些方面评价,现在的Zooomr恐怕连beta都不够格,可Zooomr却有种让人无法全面否定他的特质。如果把Zooomr当成一件作品,那产生这种特质就应该归功于作者,那位叫做Kristopher Tate的小伙子。所谓的年轻,所谓的稚嫩但富于激情。

在Zooomr的about页上(这也是我唯一发现有指向FAQ链接的页面),Tate大大咧咧地列出了他的开发工具,有LightTPD、Python、Debian等等。这就是个挺典型的programmer作风,类似的表现还有不少。评论和留言支持Markdown,很geek的东西。API用了flickr的标准,连OpenID都用,这个倒不奇怪。只不过API的完成度相当低,自己开发上传程序更顾不上,那就用第三方的jUploadr,开源的。说实在话,我猜这家伙的代码风格不会太好……

如果有兴趣,还可以去读读Zooomr的blog。就我翻过的那几页,Tate更新可算是很勤奋。文字也称得上很可爱:“I want to connect the world with itself — first hand, from your eyes. And, I hope that I am not alone.”他也很喜欢YouTube,正好有人说他handsome,觉得如何你可以自己去看看

一个优缺点鲜明的作品,一个年轻而幸运的男孩儿,这样的用户体验其实是蛮有趣的。不知道这样的business,能够走多远?

Zooomr现在对bloggers免费赠送Pro账户,每月的流量限制是2GB,后来提高到2.5GB,现在又提高到4GB,真有点“想一出是一出”的味道。

blog上有一张地图Zooomr World Map Coverage as of 26.11.2006。原来Zooomr的用户竟然是大陆(似乎是北京,有点不正常,或许跟IP数据有关)和台湾最多……

Zooomr的API实现很不完整,页面上虽然说允许email申请APIKey,但好像没人回复的样子。如果想要的话,其实可以去jUploadr里找,不过目前没什么用就是了。

Zoto打算要全面收费了,说是3.0版正式推出的时候,时间是12月。不过现在12月快过了一半,却也没动静。而且年底是西方传统的促销、折扣、派送期,这会子跟人要钱,前途未卜。其实我觉得Zoto很适合存放照片,就这么倒掉也蛮可惜的。他们家的CEO还写了篇《Why Flickr Sucks Sometimes》,骂也没骂痛快,我只看出了酸葡萄心理。

OpenID的官网上有个列表,看得出现在接受这项服务的网站并不多。不过其中有一个我觉得很惹眼,DeadJournal。“DeadJournal.com is a journal site (much like LiveJournal), but as you will quickly see, not all journals are apple pie and fruitcakes. Here is where you find the journals that nobody else wants to see, or even host.”广告语写得还不错吧,有没有兴趣去逛逛?

好吧,其实写这篇东西的最初动因其实是Zooomr的Terms of Service。其中第4条Rule说:“All users are bound by applicable local laws, including laws regarding pornography and copyright. It is up to individual users to determine for what purposes use of the Web Site would be illicit and illegal in his/her jurisdiction.”貌似他们不禁止色情内容的意思。