八卦编程

代码片断啊,类库推荐啊,语言学习心得啊,所有一个程序员碰得到的东西,都归这儿。欢迎各位同行肆无忌惮的踩。

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原来形同虚设呀⋯⋯

Updated: 呃,仔细研究以后才发现一开始并没有理解 CRSF 究竟是为了防什么,乌龙了一把,咳咳咳……

继续阅读

豆瓣电台重播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迁移指南

继续阅读

解决Xcode莫名崩溃的问题

前面的一篇博文里面我提到了我的Xcode每次开启必然会报错崩溃的问题。报错信息如下:

Uncaught Exception:
  -[NSCFArray length]: unrecognized selector sent to instance 0x2006354a0

这事在网上寻觅许久未果,本来就想算了的。突然最近有同事发现Mail也会这样莫名其妙的崩溃,在多方尝试下,发现只要关掉公司的vpn就没事了,进而又发现只要不使用vpn推送的DNS信息就可以了。于是自然就想到难道这就是导致我的Xcode罪魁祸首,一试,果然如此,我勒个去 = =

员外前阵子发了一个关于Snow Leopard诡异的DNS问题的文章,里面也提到了这个问题,所以这是雪豹自己的bug。可是,DNS服务是必须要用的,如果自己加Hosts,必然会有更新不及时的情况,那怎么办呢? 所以在关闭DNS推送后,还需要做点手脚才行。

Magic是由resolver来完成的,具体使用可以参考man 5 resolver。这儿就只说应用了。

# /etc/resolver/x.com
nameserver 10.10.10.10
nameserver 8.8.8.8

这样就为x.com的子域指定了使用这两个DNS来解析。嗯,尝试的顺序是从上往下的,最多支持3个DNS,如果有不连接VPN的时候,别忘了在DNS最后加上一个公网可用的DNS,免得在这种情况下不能访问。

OK,如此手术一番,Xcode终于活了。

做了个豆瓣RT的油猴脚本

友问有没有什么插件能够快速转发广播里的“我说”,我想,这个用油猴是最简单的了,于是顺手写了一个,需要的童鞋自取吧。

由于不知为啥油猴的require标记无效,所以还是用了网上找的在油猴中使用jQuery的办法,土就土点吧,反正能用了。

现在只在首页及下面的分页有效,有其他需求的,比如到某人的miniblog页面下去RT暂时就不做了,取id忒麻烦……

// ==UserScript==
// @name           douban rt
// @namespace      www.douban.com
// @include        http://www.douban.com/
// @include        http://www.douban.com/?*
// ==/UserScript==

// Add jQuery
(function(){
    if (typeof unsafeWindow.jQuery == 'undefined') {
        var GM_Head = document.getElementsByTagName('head')[0] || document.documentElement,
            GM_JQ = document.createElement('script');

        GM_JQ.src = 'http://img3.douban.com/js/packed_jquery.min1.js';
        GM_JQ.type = 'text/javascript';
        GM_JQ.async = true;

        GM_Head.insertBefore(GM_JQ, GM_Head.firstChild);
    }
    GM_wait();
})();

// Check if jQuery's loaded
function GM_wait() {
    if (typeof unsafeWindow.jQuery == 'undefined') {
        window.setTimeout(GM_wait, 100);
    } else {
        letsJQuery(unsafeWindow.jQuery);
    }
}

// All your GM code must be inside this function
function letsJQuery($) {
    $(function(){
        $.grep($(".mbtr"), function(e, i){
            if ($(e).find("span.pl").text().lastIndexOf("说:") > 0) {
                $(e).find(".quote").append('<a href="##" class="j_dbrt">RT</a>');
            }
        })});
    $(".j_dbrt").live("click", function(){
        $($("#db-talk").find("textarea").focus()[0]).val($(this).parent().parent().text().replace(/ [^ ]*\s+RT$/, ''));
        return false;
    });
}

Updated 上传到userscripts了,有兴趣的去安装吧 http://j-lite.net/r/douban_rt

Django 1.2.3 released

吧,上周临行前Django升级到1.2.2,当时立刻就作了更新,想着可以安份一阵子了,结果DSF居然趁着我们在青岛happy的时候,发布了1.2.3……

本次更新主要是给1.2.2擦屁股,解决如下问题:

  • 1.2.2更新的CSRF语句处理非ASCII响应存在问题。
  • 1.2.2更新后部分表单,特别是admin中的用户编辑表单出现问题。
  • 1.2.2打包时包依赖不正确(我汗= =|||)

好吧,下面是更新时间,更新Django请猛击这里,更新文档请猛击这里。更新完了的和不想更新的,洗洗睡吧。

Django 1.2.2 released

Django发布了一个新的安全更新。这次修改主要解决自1.2引入的CSRF防御系统的安全漏洞,新引入的{% csrf_token %}由于对cookie的依赖过于明显,攻击者可以比较容易的通过修改cookie内容达到XSS攻击的目的。

由于这部分功能是在Django 1.2引入的,所以只对trunk和1.2.X版本有影响。如果你正在使用的Django是你hack过的版本,你可以参考changeset13698(for trunk)或者changeset13699(for 1.2)来修改你正在使用的Django。当然,如果没做啥改动,那么还是直接更新成新的release版本1.2.2比较方便了 XD

另外,毕竟这是一次新的release,我把django-doc也更新了一下,有需要的童鞋可以去这个地址下载最新编译好的html文档。