One App A Year - For Mailr

好吧,我又用好吧作为开篇语了,其实是不知道说什么好了。这是一个拖了一年的难产 app,大概是一年又一周前,我和 @mockee 还站在梧桐前面的公交车站,在我百般无聊地唐僧着啊好闲啊没事干啊想做点什么啊的场景下,Mockee 以一种温拿的口气说其实吧我早就想怎么怎么的了。

于是诞生了 Mailr,第一个 commit,2011 年 11 月 14 日。

可是故事并没有像想象的那样顺利地开展下去,后面的日子里,我们都被其他的事当然对公司来说是正事的事搅得一团乱麻,于是交互设计开发三三落下。在这段时间里,连原生豆邮都加上了未读和垃圾豆邮的功能,连豆瓣的 API 都改成了先进的第二版,连 Diablo III 都更新到 1.05,连五环的房子都涨上了 35,000.00 这样对草民来说无比惊人的数字,连我都沿太平洋溜达了一圈回来刷新了个人所谓的发达国家游览记录,Mailr 还是一直难产,应该说,是停产。

所以,直到临近证书过期,才突然醒悟,其实我们还是在怨念着这个小东西的。

2012 年 10 月 21 日,1.0.0 的 tag 终于被打上。

2012 年 11 月 2 日,Mailr 1.0.0 正式登台。

这个的结果怎么样,渥太华,至少做了个自己会用的东西,然后正好可能会有人也喜欢用,那就好了。

最后,@mockee @tifa 大家辛苦了,并且,多谢包容我的拖延……

迟来的年终总结

纪大了人就是懒啊,去年一整年Blog的更新频率是低得可怜,Bye Bye 2010这篇现在居然还在第一页。年底总结本来在公历年底就该写了,无奈项目各种赶工,于是只好厚着脸皮拖到农历年底才开始磨蹭出这篇东西。

先按照以往的模式,总结一下吧。

  1. 暂别Python,拾起ObjC,走着路边地摊无证程序员的道路
  2. 终结2年没出游的真空,亚龙湾晒太阳切西瓜
  3. 告别水上谈兵,亲身10米试水,确实感觉不错。不过按目前的安排,好友4月的马来潜水邀约估计是不得行了
  4. 填补核磁共振的体验空白,完美诠释多年来脖子长的困惑,果然必须开始研习程序员最后一道宝典《颈椎病恢复指南》了
  5. 告别各类Hardcore游戏,全面被iOS攻占,只能在年末,追忆那些年我们一起玩过的游戏

好吧,发现自己已经越来越记不住事了,零零散散地才挤出这么几条,看来今年需要借助一些辅助手段来记录生活了,打算先试试石头推荐的olive还是啥的什么。

最后再说一下iOS吧,这小半年基本就在和它较劲了。这次是完全从零开始的任务,不过还好有各位大cow指点,终于能赶在春节前上架了。现在的bug还有很多,2%的崩溃率足以说明问题了,但希望大家能继续支持豆瓣阅读,让方舟在2012年飘起来吧。

~fin~

更换域名

名中间多了一个-一直心里不爽,加上最近域名认证甚嚣尘上,原来的j-lite.net也被强制停止解析了一阵子,所以干脆,换了新域名,从此,请各位用jsome.net来访问本站,原域名只作跳转用。

以上。

emacs sudo编辑远端文件

在之前的一篇文章里提到过在Emacs下使用sudo的方法。这个解决了我很多本地编辑的问题。但是我还是抛不开vi,因为一直没有解决服务器上需要sudo才有权限的文件编辑问题。

现实中这是一个很普遍的现象,就是在服务器上关闭了root或者其他用户的ssh登陆权限,是通过一般用户登陆以后通过sudo等方式获得权限后才能进行进一步的文件编辑。而如果直接使用sudo,用比如/sudo:user@host:filepath的方式来打开文件,Emacs会报错说这是一个远端文件,不能使用sudo来进行操作。就因为这提示,导致我一直以来对于这样的情况只能乖乖地开个shell跑到服务器上面去用vi编辑,编辑过程中的各种不爽在此不表……

不过当最终忍受不住这种只能用vi的寂寞后,终于下定决心看一下tramp的手册,结果很好,发现了这么一章内容――Connecting to a remote host using multiple hops,原来tramp是可以通过设置代理的方式来编辑那些无法直接访问到的文件的。代理可以是各种Inline method,也可以是Gateway method。所以通过ssh做跳板再sudo是完全可行的。

设置的格式是(host user proxy),其中proxy可以使用%u%h来通配输入的用户名和主机名。详细情况感兴趣的童鞋可以细看手册,这儿就只贴出满足我的需求的代码了:

(add-to-list 'tramp-default-proxies-alist
             '(nil "\\`user\\'" "/ssh:%h:"))

经过这样的设置,就可以直接使用/sudo:user@host:filepath来编辑那些远端需要sudo的文件了。所以,泡杯茶,扔掉vi吧 : )

在Finder中启动当前目录的iTerm

阵子看了个利用Automator给Finder加上自动切换显示隐藏文件的方法,觉得这方法还不错。早想给Finder加上一个打开当前路径的终端的功能了,于是就撒手开干。

打开Automator,新建服务,服务接受设为 没有输入 ,位置设为 Finder ,从左侧的资源库中找出 运行AppleScript ,拖到右侧,然后保存为 Open iTerm Here 。这时候切换到Finder,便会发现服务子菜单里面多出了一个 Open iTerm Here 的菜单。OK,基础工作完成,下面就是码代码的时间。

在刚刚创建的AppleScript的输入框中输入如下代码,

on run {input, parameters}

  tell application "Finder"
    try
      set currFolder to (folder of the front window as alias)
    on error
      set currFolder to (path to desktop folder as alias)
    end try
    set currPath to POSIX path of currFolder
  end tell

  tell application "iTerm"
    activate
    tell the first terminal
      launch session "Default Session"
      tell the last session
        write text "cd " & quoted form of currPath
      end tell
    end tell
  end tell

  return input

end run

这段AppleScript会获取将当前最前面的Finder地址,如果获取不到,则返回桌面店址,然后通知iTerm的第一个窗口新建标签并跳到这个目录去。为啥是iTerm的第一个窗口? 因为我一般只开一个而已…… 各位童鞋可以根据自己需要作调整。

好了,这时候按一下编辑器的运行,看看是不是正常工作了。一般是没问题的,因为我现在在用的就是这段 = =|||

嗯,大功告成,这时候在Finder中选择这个服务,一切便都如我们所愿了。最后,为了避免每次都要去点菜单,再去键盘设置里改一下快捷键。最理想当然就是用 command+T 了,不过这个快捷键被加入边栏这渣占用了,既不能被服务的快捷键覆盖,又找不到取消这种系统快捷键的方法,于是只好把加入边栏改成一个不常用的键组合,这才一切OK。

Django的CSRF原来形同虚设呀⋯⋯

在搞Django 1.3和Uploadify的整合时,被莫名其妙的302困扰,在苦思之后突然发现,原来Uploadify发送请求时是不会发送Cookie信息的。火急火燎地弄了个middleware来将POST中对应字段写到request.COOKIES去。这样一搞,302倒是ok了,但403倒跑了出来。使用抽插,哦不,抽查法找到是Csrf的验证问题,于是天真地把csrfmiddlewaretoken塞到POST里,可是403依旧。甚是火大。

只好乖乖地看源码,看看Django是如何做CSRF验证的。Django是在CsrfViewMiddleware中进行的相关验证,验证过程很简单,从Cookie中拿出token,然后从POST中拿出csrfmiddlewaretoken,然后块俩做一个字符匹配,就哦了。于是明白了,不就再传个cookie嘛,但突然一想,不对呀,csrfmiddlewaretoken的值就是从cookie里拿的,再传同一个值来做验证,这不是和没验证没啥区别么……

于是做了一个试验,结果确实如此,这下Django悲剧了……

实验项目可以在这个地址下载,运行runserver后,用curl来验证

直接GET,无障碍

curl http://127.0.0.1:8000

强制GET,无障碍

curl -G -d test=test http://127.0.0.1:8000

POST,403了,ms没问题?

curl -d test=test http://127.0.0.1:8000

POST,随便加上csrf,靠!!居然过了!!!

curl -d "test=test;csrfmiddlewaretoken=1" -b csrftoken=1  http://127.0.0.1:8000

归根结底,还是这个验证方法有问题,起码post中的token和cookie中的token是用secret_key做过变幻的,这样才能避免伪造,否则,神马都是浮云~~ 望天

P.S. 报bug去了,#15845。不知他们会采用我说的方法不⋯⋯

Updated: 呃,一般情况下大约是不会有问题的,因为这只是可以任意伪造csrf_token,但通常还有需要csrf保护的地方也会需要sessionid来作用户验证。这篇的问题就可以暂时忽略了。

豆瓣电台重播Bookmarklet

从电台支持单曲推荐以后,以前的那个和你喜欢的音乐不期而遇的口号就逐渐变成泡沫了。当发现可以听任意条目页上的可加心曲目时,种种神秘感便都烟消云散了,这样不好,不好。不过,有一个功能倒是挺实用的,那就是重播当前歌曲,反正都不小心让我遇上了,那多听两遍总没啥问题吧…… 于是,就诞生了如下的bookmarklet,需要的童鞋自己领用吧。

豆瓣电台 - 重播当前曲目

这颠倒的日子

吧,一年一次不负责任日来了,跟风改了主页风格,各位慢慢看,别晕。

继续阅读

Django 1.3新特性

阵子出去度假了,回来发现Django 1.3终于发布了。这次发布包含了少量新功能和大量的bugfix,具体的下文会说明。这次升级对Python版本的最低要求提高至2.4,另外这将是最后一个支持2.4的Django版本了,各位有能力有需求的同志请果断更新。

1.3带来了什么?

类视图 (Class-based views)

本次更新加入了一个新的框架来支持类视图,这将意味着更高的代码重用率和开发效率。新的Generic View基类在提供了易用性和扩展性的同时,还对原先的函数式generic view提供了完整的模拟支持。

扩展链接:
通用类视图
新旧Generic View迁移指南

继续阅读

嗨,新年快乐

虎年的尾巴上,我这个很挫的blog还是更新一下吧,祝大家新年快乐,万事顺利,最关键的,还是看图吧。

新年快乐