blog mail me! feed

实现Github的代码仓库权限控制.

Github这个social coding的代码托管网站风骚得总有让人push, 攒蓝条的冲动.
以上是题外话.

最近回头去, 把以前断断续续没写完的Project gitar(web端的多用户仓库管理界面)继续拾起来开发,
也遇到了些问题: 比如, 如何实现github那样的, 对用户的公共仓库进行权限控制,
今天仔细翻了翻sshd和git的文档, 终于找到了一个解决方法.

[1] 修改sshd_config, 将PermitUserEnvironment设置为yes, 以保证能够在authorized_keys文件中, 对环境变量进行设置.

[2] 对于每个用户提交的RSA公钥, 在其

ssh-rsa AA….== foo@bar

的前面, 加上

environment=”GITAR_USER=username”

这样用户通过了公钥认证后, 当前的session的环境变量中, 即保存了用户的gitar用户名.

[3] 使用git hooks, 匹配环境变量 $GIT_DIR 路径中所包含的用户名信息, 和$GITAR_USER 中的当前用户名,
用户名不匹配时, 即通过产生不为0的exit code, 终止远端的push操作.

[4] 当然Github中还可以添加collaborators, 也可以对特定仓库添加public keys, 可以通过扩充用户session的环境变量来实现目的.
或者, 也可以使用shell脚本调用一个python脚本, 将 $GITAR_USER 的值与数据库中的collaborators进行比对.

e 1.0.35

github把最新的e-texteditor源码拖了下来, 然后抱着试探的心理编译了一次.
上次编译出来的e-texteditor可用性太差了, Bundles基本没法用, 还有各种莫名其妙的崩溃.

上次把external文件夹里的各种stuff搞定后, 这次编译顺利多了,
除了几个cpp文件存在重复定义的函数需要清理.

不得不说社区力量还是很强大的,
1.0.35的e在Linux下稳定多了, Bundles基本可用不会出什么问题了,
(貌似对于有空格一些Bundles, 对于TAB的支持还是不是很好)
只是偶尔还是会出现行显示重叠问题 -.-#

总的来说, 现在的e在Linux下还有一堆让人很不舒服的小bug,
不知道什么时候才能真正的可用…
也许没事可以自己试着看能不能修复几个… (痴人说梦级YY)

p.s. Ubuntu下我的笔记本掌托好热啊啊啊!!! 比Windows下热多了,
电源管理还是有问题… 不知道其他的发行版如何…

p.s.2 论文拖了一天了, 结果一个字都没写, 该死的破学校,
Elsevier都不买, 搞得我就找了个借口, 肆意的procrastinating..

e On Ubuntu

今天又尝试着编译了一次 e texteditor
Debug+Release加起来差不多一共编译了2小时多,
中途还有无数次的ld或者gcc的错误.
最后自己把Bundles从svn拖下来打包运行后发现, 目前的e在Linux上太脆弱了.
至少在我的GTK上, 试用的效果很糟糕.

先是因为没有Ruby产生的Segmentation Error.
继而是各种Bundles无法正常运行.
if [tab]的结果是condition被highlight但是光标失去焦点了, 无法修改,
必须用鼠标再点下屏幕上某个位置, 才能继续输入.

而运行某些弹出Tooltip的Bundle更是直接就让e对键盘没任何响应了,
只能把e关闭掉. (-____-#)

上周还尝试了下Linux下的Textmate的另一个alternative,
也是完全兼容Textmate Bundles的redcar,
不过ruby的运行效率… redcar的启动时间不说, 运行起来感觉打字都觉得一顿一顿的.
一个撤销工作要执行2~3s.

看来还是老老实实用vi算了…

最后放个编译好的deb包:
http://tremblefrog.org/e-1.0-31.deb

最近干的无聊事儿.

花了几个小时才把209上的FreeRadius + PopTop + PPPD VPN用户验证做好.
因为MySQL是编译安装的缘故, 所以相关lib和include一直没有链接上,  rlm_sql_mysql根本就没有编译.
调试了半天发现验证无法进入sql{}, 最后仔细检查了configure的输出才发现. -____-#

装pptpd的时候把原来apt-get的整套pppd, pptpd都卸载了, 结果pptpd的logwtmp.so不支持2.4.4的pppd;
最后又发现不知道什么时候往radgroupreply里加了条Account-Type := Local的值, 导致验证最后会出错.

这是其一.

其二是继续在FreeRadius的rlm_sql模块上, 自己写了一个做VPN流量控制的功能.
可以通过username和其所属的group做特定限制的流量认证, 超过流量则返回Reject响应.
好久不写C代码了, 在指针上出了一堆莫名其妙的错误, 最后终于是当复习了一次C语言, 汗 -____-#

其实代码很短, 也就几十行, 我也居然就花了几个小时来调试该死的各种指针的错误…
太菜了. 不过最后的效果还不错.

其三是基于Sonic大神的VPN管理前台修改了下, 自己又加了些查看VPN使用记录和流量的功能,
提供了一个相对功能完善的用户前台. 

虽然觉得自己很囧, 写个C代码写成这个破样儿, 不过真正弄完还是觉得不错 -____-#.
未来的考虑是:
1. 修改pppd的代码, 让其可以在线判断流量限制, 从而实现超过限制则断网. (好狠毒 -__-#)
2. 考虑从sql模块中剥离出流量限制的代码, 做一个新的模块.
3. 改天把笔记补上来.

在写tuna前的一点架构思考.

  1. 需要断点续传吗?
    断点续传需要HTTP服务器的支持, 之前是est大神实现的s1完成的对PUT协议的支持.
    client可以通过Google Gears, 不过服务器端还有很多可以考虑的地方.

    首先, 如何识别一个需要resume的upload request呢?
    我想用cookie应该是比较好的方法, 每次用户提出一个上传请求, 就建立一个cookie, 上传完成后删除此cookie.
    这样避免了在最初的demo中, 使用随机的nonce带来的关闭浏览器就无法继续的bug.

  2. 如何实现?
    我想把判断abortive的上传的部分交给前台和cookie去做, 而不是在nginx内部实现.
    否则不仅仅会使得开发效率降低, 而且还得额外引入SQLite的代码, 有些古怪.

    nginx的module应该是只负责处理PUT请求就可以了, 如果发现一个不存在的续传请求,
    简单的抛出 400 Bad Request就ok.

  3. 目标?
    tuna的目标是实现一个类似rapidshare这种下载站, 每个文件有一个默认的expiration,
    下载可以推迟这个deadline.

    下载被理解为一个dormforce id所发起的一个成功的GET行为.
    一个dormforce id在不同IP产生的多次request均计算为一次.

  4. 架构?
    准备采用nginx + php-fpm + php + mysql 实现, 因为是服务器上已经有的生产环境.

    从209的那块新的SCSI硬盘上再单独划出一个逻辑卷做repository,
    这样管理起来灵活方便些.

    nginx 挂上 upload module 和 accesskey module, 用作大文件上传的hash, 和防盗链的控制.
    下载的时候用php通过X-SendFile提供访问控制和请求转发.
    因为upload module把文件的文件名都命名为了数字格式, 没有extension,
    所以需要php提供Content-Type和Content-Disposition头.

    防盗链这块, 用referer做第一级的过滤.
    第二级用accesskey, 使用在GET参数里的nonce值, 请求文件, IP做一个MD5的accesskey保证这个地址在一个时间戳上, 对应一个文件和一个IP是唯一的.
    第三级在php这里, 判断这个做nonce值的timestamp是否已经过期(比如300s), 如果okay则放行.

整体上应该大体就是这样.
唯一需要更改的地方就是让nginx的upload module支持PUT协议和续传.
中间需要改的地方还需要仔细看下.

修复nginx的upload module不支持0.7.x的bug

今天准备装上nginxupload module做些测试的, 结果发现自己的nginx 0.7.44下,
upload module没法通过编译, 问题出错在ngx_http_upload_module.c的1152行左右.

ngx_conf_merge_path_value(conf->store_path,
                              prev->store_path,
                              NGX_HTTP_PROXY_TEMP_PATH, 1, 2, 0,
                              ngx_garbage_collector_temp_handler, cf);

查看 ngx_conf_merge_path_value()的定义发现新的nginx中这个函数的变化很大,
改为了: char *ngx_conf_merge_path_value(ngx_conf_t *cf, ngx_path_t **path, ngx_path_t *prev, ngx_path_init_t *init);

所以修改为了下代码:


static ngx_path_init_t  ngx_init_temp_path = {
    ngx_string(NGX_HTTP_PROXY_TEMP_PATH), { 1, 2, 0 }
};
	// for nginx 0.7.x, hack by killkeeper
	ngx_path_t *_path = ( ngx_path_t *) malloc( strlen(NGX_HTTP_PROXY_TEMP_PATH) );
	memcpy ( _path, &NGX_HTTP_PROXY_TEMP_PATH, strlen(NGX_HTTP_PROXY_TEMP_PATH) );

	ngx_conf_merge_path_value( cf, &_path, prev->store_path, &ngx_init_temp_path);

本来想加一个预编译头的, 不过发现nginx没有定义NGX_VERSION类似的的这种宏,
就算了.

恩, 目前编译是通过了, 明天具体测试下工作正常不.

一个wpmu的hack, 用nginx代替php处理静态文件.

wpmu使用php处理静态文件的模式一直让我很不舒服,
结果今天研究了N久如何绕开php来做静态文件的处理.

先选取了自己以为最简单的实现方法, 用squid做反向代理.
装上了squid 3.1, 发现网上的config教程都是2.6的, 完全不适用,
研究了manual后, 配好了反向代理,
接着, 尴尬的事情就发生了, 因为是本地做反向代理,
无疑通过nginx来进行proxy_pass的结果就是死循环…

nginx –[proxy_pass]–> squid –[http request]–> nginx –[proxy_pass]–> squid…

太糟糕了, 要解决这个问题只有通过实现两个virtual server, 并且重写host来实现反向代理.
庞大的工程. 遂放弃.

后来转向nginx的X-SendFile功能,
原理是捕捉到特定的X-Accel-Redirect头后,
通过实现一个内部的location, 来完成一个重定向.

不过事情没有这么简单, 现有栋力博客的重写规则是:
rewrite ^.*/files/(.*) /wp-content/blogs.php?file=$1;

而静态路径里也含有 /files/ , 所以会被同时重写, 最后返回一个500 Internal Error,
并且这个error是没法通过FireBug或者日志来trace的.
研究了下nginx的判断逻辑, 加了一条URL判断后终于搞定.

详细的步骤如下:
Read the rest of this entry »

服务器升级.

目前去年5月几经折腾买入的二手Hitachi服务器工作一切良好,
就是36G的硬盘有点小.
索性周二在淘宝上订了块二手Maxtor 174g 10000r SCSI硬盘, 310, 
周四早上去机房, 把硬盘插好, 顺利的自检通过.

本想跑个badblocks检查下坏道, 无奈忘了加-s 参数也忘了用& 让它在后台跑,
10分钟后putty就被润新脆弱的网速折磨挂了, 坏道检测也就中止了-___-.

接着把原来的FAT32分区全部删掉(哦, 数据删光了, 某b还念念不忘有没有点秘密的玩意儿)
整个盘重新做成了Linux LVM,
打算着格式化为reiserfs, 这样配合LVM可以在线的扩充逻辑卷容量,
嗯… 很悲惨的发现内核里没reiserfs -____-#

又转而试图作成ext4, 结果用mount -t ext4 也mount不上, 郁闷(有牛人解释下咩?).
最后还是做成ext3; 把htdocs全部迁移; nginx配置修改好,
就基本完成平滑迁移了.

话说等考完G了重做一次Debian, 把reiserfs扔内核里去.

唔, Linux…

Python写的pyMono Bot跑的很欢畅, 自从给xmpppy库里加上了一个每180s发送一次空包的hack后,
几乎没掉过线了, 不过倒是有些古怪的Exceptions经常把bot轰杀至渣.

因为错误处理写得很简单, 所以今天顺便看了下shell的文档,
写了个小shell程序, 挂在cron里, 每小时一次检查bot是否挂掉了.

anyway, I love this way of handling things.