2011年9月22日星期四

Blog搬家了

在有了VPS之后,多年以来的把Blog架设到自己服务器上的夙愿终于满足了。
新的网站地址:http://www.henryhu.net
新的Blog地址:http://blog.henryhu.net

以后技术方面的帖子,在那边会扔到技术分类下,不再单开技术Blog了……

2011年8月14日星期日

关于XIM的那些输入模式

我一直弄不清楚,over-the-spot, on-the-spot, off-the-spot, root-window这帮东西到底有啥区别
今天查了某oracle资料:http://download.oracle.com/docs/cd/E19504-01/802-7789/6ibcsnfb8/index.html

首先这些都是预编辑内容的模式,就是那些你打了但是还没确认的那些字的显示方法……
貌似over-the-spot是在光标处会出现当先的预编辑内容,但是不会把原有内容自动后移,因此新内容显示起来会覆盖在老的上面。确认之后,新的会把老的挤到后面去。
on-the-spot也是在光标处出现预编辑内容,但是会在预编辑,也就是还没确认的时候就把老内容挤到后面去。
off-the-spot貌似是在窗口左下角之类的位置出一个窗口自己显示预编辑内容,反正应用程序不用关心……
root-window据说会在屏幕底下划出一块来显示预编辑内容,莫非是类似从前dos的输入法…… X上没见过。

反正前两个都要程序管,第三个要输入法自己画。

搞这个是因为,今天实现了GeManX对于输入法预编辑的支持,顺路看了看这方面资料…… 因为新ibus好像不关心你程序自己说自己支不支持预编辑,他总是认为你支持,这就导致本来不支持的GeManX没地方显示预编辑内容了……

另,有人知道gtk_im_context_get_preedit_string()返回的东西啥编码么?一定是UTF-8?根据locale?

2011年2月15日星期二

Android市场无法开始下载的问题以及解决

在学校的时候,Android市场上的东西下的好好的。回家之后,虽然能显示开始下载,但是从来也不会真的开始……
一开始以为某地被屏蔽,于是开始抓包。但是确定开始下载的时候,连SYN都没有……
去往上查,说要允许5228端口。但是根据抓包的情况,一直只有到mtalk.google.com:5228的连接,怎么看都是GTalk的事情。
其实这里是被误导了,导致我继续研究了好几天也没有结果。
今天猜测是不是这两者有关联。于是研究了5228的情况。在学校可以连mtalk.google.com:5228,在家连不上,看来是这个糟糕的有线通的问题。
于是搞了个变通的办法:改hosts,把这个地址指向我的笔记本,然后在笔记本上用ssh把这个端口通过ssh隧道forward到目的地去,隧道出口在学校,因此就可以连上了。
搞完之后一试,果然能上GTalk了。出乎意料的是,数秒之内,那些下载都开始了……
这是什么意思……………… 你个android市场是要验证用户身份,但是为啥和GTalk捆绑在一起………………
反正最后是可以下了……

2010年8月9日星期一

原来 divert 还要指定ipv4...

最近发现本子的IPv6不能用了…… 一开始还以为是学校路由器有问题
后来发现win下可以用…… 另外,刚开机可以用……
而且ping6的同时tcpdump会导致系统死锁…… 所以怀疑是软件问题
之后想起来,最近为了让新买的Desire能上网,让本挂在无线网上面,设置成了网关…… 还带NAT的……
启动那个脚本之后,果然IPv6就挂了……
删掉
divert 8668 ip from any to any via msk0
之后,果然就好了……

但是我指定的明明是ip,应该是IPv4吧……
去往上搜,搜到了FreeBSD 6的Errata,里面说,因为divert套接字不支持IPv6,所以指定ip的话,IPv6的包会被丢掉…… 要指定ip4这样……
原来ip指的是所有IP包么!
改成
divert 8668 ip4 from any to any via msk0
果然就一切正常了…… 不能想当然啊……

另外,这个问题FreeBSD 6就有了,到现在divert套接字还是老样子么…… 真是没人干活啊…… 至少对于divert和v6特殊处理一下么……

2010年4月29日星期四

给lftp报了一个bug

学校用的proftpd,为了照顾windows用户,设置了UseEncoding GBK GBK
这样,proftpd返回的FEAT里面,有LANG,没有UTF8。
但是lftp只要知道服务器支持LANG,就会发个LANG过去。只要收到LANG的回复,就认为服务器用的UTF-8……
虽然LANG和UTF8都是RFC 2640定义的,但是支持LANG不一定就是UTF8啊……
所以发了个patch给作者,不知道他会不会管……
--- src/ftpclass.cc.orig        2010-04-29 17:20:28.000000000 +0800
+++ src/ftpclass.cc     2010-04-29 17:20:42.000000000 +0800
@@ -4100,8 +4100,11 @@
    case Expect::LANG:
       if(is2XX(act))
       {
-        conn->utf8_activated=true;
-        conn->SetControlConnectionTranslation("UTF-8");
+                 if (conn->utf8_supported)
+                 {
+                         conn->utf8_activated=true;
+                         conn->SetControlConnectionTranslation("UTF-8");
+                 }
       }
       else if(act==530)
         conn->tune_after_login=true;

2010年4月18日星期日

关于ssh中的Vim鼠标不好用的问题

只要在.vimrc里面,加上
set ttymouse=xterm2
就可以了……
基本上就是让那边的vim知道,这边发的对应于鼠标动作的转义序列是什么格式的,就可以了……
另外,貌似直接在rxvt-unicode里面连ssh再vim是没有问题的,但是在rxvt-unicode里面开screen再连ssh再开Vim就有问题。看来screen在termcap/terminfo方面还是有些问题…… 有待研究……

2010年2月16日星期二

折腾

折腾了几天,搞了各种事情
* 升级Avant Window Navigator到trunk(0.3.9)
有一大堆的事情,比如说:
# bzr up之后,有冲突,干脆全部干掉重来。发现configure有问题,引用了莫名其妙的ac_python_version变量,这个东西哪里都没有。只好手动改成2.6。
# 引用了libdesktop-agnostic,ports里没有,上网去发现貌似也在launchpad上边,可能也是awn这群人搞的,遂bzr co下来
# 结果编译的时候有诸多问题,上网去,发现有bug-report,说是vala版本太新,而且他还branch了一个various-fixes分支出来
# 第一次听说vala,貌似是利用gobject这套系统,配合一个类似于C#的语言,给C以面向对象能力。编译的时候先弄成C再编译
# 再bzr co了那个fixes branch,终于好了。回头对付awn,还算比较容易
# 新版多了个curve模式,貌似速度也好不少,稳定性也是,看来这个rewrite还不错
* 升级awn-extras
也有不少事情:
# 发现里面的各个菜单组件都或者崩溃或者没有程序菜单,追溯到python-gmenu,最后看调试信息,发现没有applications.menu文件
# 本来想生成一个完了,但是下了个菜单编辑工具alacarte,发现这个里面已经有程序菜单了…… 而且gnome-panel也有…… 标准不统一啊……
# 之后再查资料,发现说XDG这套标准允许有前缀,并且通过locate得知有一个gnome-applications.menu在恰当的地方
# 最后通过把XDG_MENU_PREFIX设为gnome-解决
# 之后又是发现那个Media Player Applet不能放大的(不是文件大小)视频。怀疑和之前totem的问题一样
# 看代码发现用的playbin这个gstreamer组件,直接gst-launch,果然出错,而且信息和totem的一样
# 上网搜了一下,有人说totem的pkg-message里说了这个问题,果然有…… 用了就好了
# 说明这个问题不只totem有,用gstreamer的都有…… 为啥默认的那些shm的参数那么小……
* xps文件查看
上两天有人发来xps文件,不能看…… 去网上下了XPS Essentials装,结果wine运行说有gdiplus的函数没实现…… 搜了之后,发现新版wine实现了,遂下载新版,结果换了一个函数…… 只好拷了一个gdiplus.dll过来,运行倒是可以,就是换页要好几秒……
于是去网上找开源解决方案,找到ghostxps,后来发现就是ghostscript那个公司做的。直接转pdf,10M的xps变成了5xxK,但是里面图片质量很差。
去网上看了一下,对latex转pdf有人说应该先转ps再ps2pdf,应该是同理。但是直接转出来的ps竟然有4xxM…… 再转pdf,有17M,还能忍受,质量很好
* skype
bsd ports里面那个skype是static的2.0.0.72-oss版,我输入不了中文,遂尝试新版。
结果新版2.1.0.xx的dynamic版都会卡死在futex系统调用上,而static版不但不能输入中文,还没有声音……
搜索得知,新版用了pulse,遂用rpm安装alsa的pulse插件,linux的pulse库等,结果运行时说shm_open没有实现…… 还是不行
又尝试装了alsa的oss插件,并且设为默认,这次终于有声音了,但是…… 不能录音……
最后还是回归老的了……
* 自动挂载
本来我山寨了一个自动挂载脚本,利用devd的CDEV建立事件,在ntfs/*和msdosfs/*出现的时候,自动挂载到/mnt/*
结果现在有了iPod,就有问题了:我一般只是想充电而已
于是要挂载自动camcontrol eject,问题是CDEV事件不包括设备名,只有label。在找不到反查工具的情况下,只好自己从label查设备
大致上就是一个枚举,利用gpart结果得到所有设备,然后用glabel得到上面的label,并且进行匹配,符合的就是对应设备。
搞的时候发现,glabel status的第一行输出一直是Name Status Components,而Name下面显示的就是label,而且Name的最后一个字母严格和label最后一个字母对齐,通过这个,可以保证从输出结果得到的label是完整的label,不多不少。
现在碰见iPod就会自动卸载了,真不错……
* easytag的崩溃问题
本来easytag给某些歌写tag的时候,总是崩溃。
这两天研究一下,发现都是不正常的ape tag引起的。虽然easytag本身只写id3 tag,但是他写的时候,会先清除ape tag,而要清除就要先解释,于是就挂了…… 我搞了py-apetag下来,结果删tag的时候也说不能解释……
你们删除tag就不会简单地先删掉再建一个空的么…… 非要解释……
最后手动把文件结尾APETAGEX开始的东西全干掉,世界清静了……

感想:
# gstreamer好强大,我视频库里那些视频都可以放…… 虽然对字幕的支持还是令人怀疑
# 发现一个好东西,gst-editor,类似于windows里directx开发包里那个编辑directshow filter图的那个东西,这里是编辑gstreamer 组件图,还能直接调试,虽然偶尔会崩溃……(这个东西现在其实在google code上,不在gstreamer官网上)
# 下东西发现freebsd默认perl版本改成5.10了,择日升级吧…… 好多包……
# 发现labyrinth这个mind map工具不错,操作简单,功能基本上够用,速度快

2010年2月9日星期二

Hacking FreeBSD to change manual page width

I don't like the fixed width of manual pages, since I have such a wide terminal, but the man pages only occupied the left part.
By inspecting the process launched, it seems like that there are several processes related:
sh -c (cd /usr/share/man/en.UTF-8 ; /usr/bin/zcat /usr/share/man/en.UTF-8/man1/ls.1.gz | /usr/bin/tbl | /usr/bin/groff -S -Wall -mtty-char -man -Tutf8 | /usr/bin/col | less)
I tried to skip the most processes, and simplify the calling sequence, and finally I found that the most important process is groff.
After unzipped the ls.1.gz, I found that there's no clear marks of line ending. This encouraged me, since this makes possible to adjust the output width in later steps.
I did some experiments, and I found that the -man and -Tutf8 arguments are critical to the page width. I read the man page of groff, and found that if -Tutf8 is specified, then groff use grotty as postprocessor. I turned to the man page of grotty, but found nothing useful. However, the man page of groff_man supplied useful information: -rIN seems hopeful.
However, when I tried -rIN=130, the output is nothing different from the original. Finally, I turned to Google, and found this post: http://www.cygwin.com/ml/cygwin/2004-11/msg01003.html
So I know that first I should use -rLL and -rLT, and secondly I should use 130n instead of 130.
After adding these to the command line, the output looked like what I wanted. I want to automate the process, so I tried a method similar to the one in the post: changing the source of man by hand.
I greped and found /usr/src/gnu/usr.bin/man/Makefile.inc is the source of the command arguments. However, changing this is not so easy, since it would be interpreted by sed, and then by sh. So I changed /usr/src/gnu/usr.bin/man/lib/config.h instead. With some experiments, finally it worked. I added  -rLL=`echo $MANWIDTH`n -rLT=`echo $MANWIDTH`n into #define NROFF.
The last thing to do is to set MANWIDTH. I Googled about finding terminal width, and found this:
http://markmail.org/message/3gui7ymobsj65mje#query:get%20terminal%20width+page:1+mid:t6hhk3dmnfjyg52b+state:results
It is said that `tput cols` would do the work, and really it worked.
So I added setenv MANWIDTH `tput cols` into ~/.cshrc, and everything worked like a charm~
Now I can fully utilize my screen width!~

2010年2月7日星期日

关于func_get_args()的小错

今天帮同学部署一个小网站,用了php,还有ajax。结果在他们本机调试很好,我弄到服务器上面,就出了问题:
Fatal error: func_get_args(): Can't be used as a function parameter in ...
这个很奇怪,搜了一下,貌似其实是php的一个限制(bug?),可以参见http://bugs.php.net/bug.php?id=34120
貌似是实现的问题,func_get_args()这个东西不能直接用在函数的参数里面(其实文档这么说,用作第一个参数还是可以的…… 第二个就不行了)。必须要先把它赋给一个变量,然后再作为函数参数。
For example,根据文档,这两个都不行:
a(func_get_args(0));
b(1, func_get_args(0));

但其实,第一个是可以的,第二个会出上面那个错。
改成
$x=func_get_args(0);
a($x);
b(1,$x);
就可以了。
同学说他们的php是5.3.1,服务器上是5.2.12,大概5.3搞定了这个事情吧……

2010年2月3日星期三

终于有图标了

如果你用的是Unix类系统,并且还是非标准桌面(例如LXDE一类……)
并且发现,你启动file-roller,pcmanx,nautilus等的图标都很奇怪或者没有
那么可能是这个问题:系统不知道用啥图标,或者找不到图标
去/usr/local/share/icons(Linux同学们可能没有local)
看看有哪几个是有不少图片的,并且有index.theme的,可能就可以作为图标主题
然后在~/.gtkrc-2.0里面加上:
gtk-icon-theme-name="<目录名>"
就会有图标了……
如果试了都不成,就去装gnome-icons-这个样子的软件包再看看吧……
之前我发现是gnome-settings-daemon运行之后就会有图标
但是我又不喜欢一切都由gnome控制面板一类的设置,gtk-chtheme多好
终于pcmanfm启动的时候,给了个提示,解决了问题……
PS. PCManFM作者还写了PCManX,貌似和LXDE还有关系,真nb……

2009年12月14日星期一

通过IPv6方式访问blogspot的方法

既然GFW短期之内还不会延伸到IPv6上,而GFW对blogspot的封禁看来会一直持续下去,这里给出一个通过IPv6访问blogspot的方法:
在你已经通了IPv6的情况下,其实很简单:在上blogspot的时候,把代理设为ipv6.google.com,端口为80,协议为HTTP。
当然,总是改代理很麻烦。因此可以用各种插件来达到自动切换代理,比如我用的FoxyProxy:
装好之后,在选项里,新建代理服务器,在第二页输入ipv6.google.com和80,在第三页新增URL模板,名字随便起,URL模板写*blogspot.com*,选白名单/通配符,确定,就可以了。也可以再加一个模板,*blogger.com*。
假如大家都会用这个办法了,那原来的Live Space就可以考虑不更新了……

2009年11月19日星期四

利用 bcdedit 解决 Vista 启动问题

前一段时间,把系统原来的还原分区(一个NTFS)清了,在那里装了FreeBSD 8/amd64。之后发现,FreeBSD的分区引导记录很不行,他只找活动分区启动,而不管自己是哪个分区的引导记录(大概也不知道……),所以从原来的BSD切换到新装的很麻烦,要手动改活动分区。于是就装了个grub4dos,折腾了半天终于好了。装完之后,尝试新菜单,发现Vista进不去了…… 提示大概是这样的:\Windows\system32\winload.exe 文件未找到或者已损坏 错误0xc000000e。试了一下,发现Vista启动菜单里面其他的项目也用不了了。
想了一下,多半是干掉那个还原分区之后,Windows所在的分区成了第一个Windows能够认出来的分区,于是这个Boot Loader分不清楚了,不能在老地方找到这个文件了……
先尝试把那个新装了BSD的分区类型改成NTFS,结果Windows还是不认…… 改回去之后,我想只好手动修改启动数据库了。Vista的启动数据库,不像XP就是根目录下面有一个boot.ini,而是在根目录下面\Boot\BCD这个文件里面,还是个二进制文件…… Windows就给了一个bcdedit来弄。
因为进不了Vista,我尝试着用虚拟机里的XP来跑。这个虚拟机同时也把主机的真实硬盘作为第二块硬盘挂在上面。
启动虚拟机,尝试了一下,bcdedit竟然能用,于是拷到WinXP这边来。主机Vista所在的盘在虚拟机里面是D盘,所以在运行bcdedit的时候,后面都要加上/store d:\boot\BCD 。
改的过程其实很少。bcdedit原来那些命令也都能用。
命令里面某一项的GUID,可以通过直接运行 bcdedit /store d:\boot\BCD 来了解,最上面{xxxxxxxx-.....}那个就是了,一串很长的十六进制数。默认项这个可以用{default}代替。
首先,把默认项指定成Vista(原来是老BSD):
bcdedit /store d:\boot\BCD /default <Vista项的GUID>
然后设置默认项设备为分区d(一开始我设了c,结果还是不行…… Windows还是把那个算进去了么……)
bcdedit /store d:\boot\BCD /set {default} device partition=D:
bcdedit /store d:\boot\BCD /set {default} osdevice partition=D:
这就好了。
效果不用重启都能看见。还是利用虚拟机,qemu或者VirtualBox都可以,直接挂主机硬盘,Vista果然跑起来了…… 不过一会儿就蓝屏了……

2009年9月17日星期四

WordPress 多层菜单

下了个主题,发现只支持一级菜单……
去网上,先找了一个Multi-level Navigation插件,但是主题不配合……
继续找,找到那么一篇文章:
WordPress Multi-Level Drop Down menu using jQuery | SEOAdsenseThemes.com
弄到WP里面去,竟然就好了……
其实就是加:
<script type='text/javascript'>
jQuery(document).ready(function() {
jQuery("#dropmenu ul").css({display: "none"}); // Opera Fix
jQuery("#dropmenu li").hover(function(){
jQuery(this).find('ul:first').css({visibility: "visible",display: "none"}).show(268);
},function(){
jQuery(this).find('ul:first').css({visibility: "hidden"});
});
});

</script>
<style type="text/css">
#dropmenu, #dropmenu ul {list-style-type:none; list-style-position:outside; position:relative;z-index:300; width:100%;}
</style>
到HTML页面的head部分里面,然后把原来的
<?php wp_list_pages('title_li=&depth=10'); ?>
换成
<ul id="dropmenu">
<?php wp_list_pages('sort_column=menu_order&title_li='); ?>
</ul>
就行了……

2009年6月2日星期二

gdb的出错消息

一直以来,运行gdb,之后输入 attach <PID>,会收到一些错误消息:
> gdb
GNU gdb 6.1.1 [FreeBSD]
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "i386-marcel-freebsd".
(gdb) attach 7590
Attaching to process 7590
/usr/src/gnu/usr.bin/gdb/libgdb/../../../../contrib/gdb/gdb/solib-svr4.c:1443: internal-error: legacy_fetch_link_map_offsets called without legacy link_map support enabled.
A problem internal to GDB has been detected,
further debugging may prove unreliable.
Quit this debugging session? (y or n) n

/usr/src/gnu/usr.bin/gdb/libgdb/../../../../contrib/gdb/gdb/solib-svr4.c:1443: internal-error: legacy_fetch_link_map_offsets called without legacy link_map support enabled.
A problem internal to GDB has been detected,
further debugging may prove unreliable.
Create a core file of GDB? (y or n) n
Reading symbols from /usr/local/kde4/bin/dolphin...(no debugging symbols found)...done.
....
Loaded symbols for /usr/local/kde4/lib/libkfontinst.so.5
Reading symbols from /libexec/ld-elf.so.1...done.
Loaded symbols for /libexec/ld-elf.so.1
[Switching to Thread 0x2dd6b260 (LWP 100239)]
0x29be3243 in select () from /lib/libc.so.7
(gdb)
一直也不知道是什么道理…… 今天去网上查,终于看见一个说法:
需要attach的话,只能运行 gdb -p <PID> <exec file>
也就是说,要提供原来的可执行文件,才能attach到一个现有process……
我试了一下,的确好了:
> gdb -p 7590 /usr/local/kde4/bin/dolphin
GNU gdb 6.1.1 [FreeBSD]
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "i386-marcel-freebsd"...(no debugging symbols found)...
Attaching to program: /usr/local/kde4/bin/dolphin, process 7590
Reading symbols from /usr/local/kde4/lib/libkio.so.7...(no debugging symbols found)...done.
Loaded symbols for /usr/local/kde4/lib/libkio.so.7
......
Reading symbols from /libexec/ld-elf.so.1...done.
Loaded symbols for /libexec/ld-elf.so.1
[Switching to Thread 0x2dd6b260 (LWP 100239)]
0x29be3243 in select () from /lib/libc.so.7
(gdb)
貌似这个问题,在GDB里面很早就修正了。FreeBSD随系统自带的GDB还是6.1.1,ports里倒是提供了一个6.6,但是不支持调试多线程的程序…… 不知道啥时候这个事情能够解决……

2009年4月19日星期日

Joomla 热门新闻的有效期

     热门文章上的内容,是完全按照新闻点击次数排的。虽然原来发布的时候有个失效时间,但是大部分人懒得写,导致很旧的但是点击量大的新闻会长时间排在顶上,违背了新闻和热门的意思。
     因为这个原因,我想说不定能够设置一下,比如只显示两个月的新闻。但是看了一下那个热门新闻模块(mod_mostread),设置很简单,没这方面内容。
     于是只好改代码了么…… 打开/joomla/modules/mod_mostread.php,看见如下代码:
  • case 1:
  • default:
  • //Content Items only
  • $query = "SELECT a.id, a.title, a.sectionid, a.catid"
  • . "\n FROM #__content AS a"
  • . "\n LEFT JOIN #__content_frontpage AS f ON f.content_id = a.id"
  • . "\n INNER JOIN #__categories AS cc ON cc.id = a.catid"
  • . "\n INNER JOIN #__sections AS s ON s.id = a.sectionid"
  • . "\n WHERE ( a.state = 1 AND a.sectionid > 0 )"
  • . "\n AND ( a.publish_up = '$nullDate' OR a.publish_up <= '$now' )"
  • . "\n AND ( a.publish_down = '$nullDate' OR a.publish_down >= '$now' )"
  • . ( $access ? "\n AND a.access <= $my->gid AND cc.access <= $my->gid AND s.access <= $my->gid" : '' )
  • . ( $catid ? "\n AND ( a.catid IN ( $catid ) )" : '' )
  • . ( $secid ? "\n AND ( a.sectionid IN ( $secid ) )" : '' )
  • . ( $show_front == "0" ? "\n AND f.content_id IS NULL" : '' )
  • . "\n AND s.published = 1"
  • . "\n AND cc.published = 1"
  • . "\n ORDER BY a.hits DESC"
  • ;

  • 那个case 1对应选项里的“只显示内容项目”,下面明显在构造SQL查询语句。<br />搜了一下,MySQL有个函数,DATEDIFF(),返回两个日期差的天数,这不是正好么。<br />在其中插入一句判断:
  • . "\n AND ( DATEDIFF('$now', a.created) <= 60 )"
  • 于是问题解决~ 这种脚本语言还真是容易学容易用……

    2009年4月1日星期三

    FireBoard的登录跳转

    最近在一个Joomla上架论坛,用着FireBoard。这个东西有个毛病,就是登录之后跳转到主页,而不是到论坛,看着很不行。
    为了解决这个问题,回去看代码。FireBoard那个登录链接在template/default/plugin/profilebox/profilebox.php里面生成的,原来是这样:

    $loginlink = sefRelToAbs('index.php?option=com_login&amp;Itemid=' . $Itemid));

    我想先把返回地址传过去。于是改成:

    $loginlink = sefRelToAbs('index.php?option=com_login&amp;Itemid=' . $Itemid . "&return=" . sefRelToAbs('index.php?option=com_fireboard'));

    接下来看看/joomla/components/com_login/login.html.php:

    $return = $params->get('login');

    以及:

    <form action="<?php echo sefRelToAbs( 'index.php?option=login' ); ?>" method="post" name="login" id="login">

    看来是转到index.php进行登录工作。再看看index.php:
  • // frontend login & logout controls
  • $return = strval( mosGetParam( $_POST, 'return'));
  • $message = intval( mosGetParam( $_POST, 'message', 0 ) );
  • if ($option == 'login') {
  • $a = $return;
  • $mainframe->login();
  • $return = $a;
  • // JS Popup message
  • ......
  •  
  • if ( $return && !( strpos( $return, 'com_registration' ) || strpos( $return, 'com_login' ) ) ) {
  • // checks for the presence of a return url
  • // and ensures that this url is not the registration or login pages
  • mosRedirect( $return );
  • } else {
  • mosRedirect( $mosConfig_live_site .'/index.php' );
  • }
  •  
  • 看来原来就有跳转的代码。这样就好办了。
    我原来尝试在那个login链接后面加&return=xxx,但是试了一个晚上,一点用都没有。
    后来才发现,貌似是那个$return的变量在起作用。
    最后,修改com_login/login.html.php:
    把原来的$return=xxx改成:

    $return_old = $params->get('login');
  • $return = strval(mosGetParam($_REQUEST, 'return', $return_old));

  • 终于,问题解决,FireBoard登录之后,又跳转回FireBoard了~
    其实看原来那个$return=$param->get啥的,应该是有更好的办法的,但是这样也挺通用的,就行了吧……

    2009年3月10日星期二

    新的键盘 & usbhidaction

    从同学那边借了一个键盘用,反正他有好几个键盘,这个放在旁边也不用。型号是 Microsoft Natural Ergonomic Keyboard 4000,很大的一个键盘,还是人体工程学设计的。
    装载ukbd和uhid模块,插上键盘,显示出来两个设备: ukbd0 和 uhid0。
    貌似ukbd0马上就被Xorg接受了,插上后按键就能够被Xorg接收到。
    而那个uhid0,貌似就是用来发送特殊键的了。这个键盘上有不少特殊键,比如一对滚轮一样的Zoom键,Back/Forward, 控制音量和播放器的,启动程序的,以及可以自定义的特殊键。
    研究了一下,有两个现成的工具。usbhidctl能够接受并显示 uhid 设备发过来的信息,而 usbhidaction 能够根据预先指定的配置文件,在接收到 uhid 设备的时候,执行对应的程序。
    其实 FreeBSD 自带的 usbhidctl 和 usbhidaction 都有问题,他们对于 Report ID 这个HID设备的参数没有处理好。
    一个HID设备允许其上的各个组件利用同一个接口发送信息,而这些信息就通过 Report ID 区分。在信息格式描述符中提到 Report ID 的设备,在发出来的数据包的前面会多一个字节,就是这个数据包所属部分的Report ID。
    usbhidaction没有处理这个多出来的字节,导致它每次都少收一个字节,然后再收一个一字节的包…… 改了就好了。但是这个修改其实涉及到libusbhid,因此光修改usbhidaction还不行。但是要把这整个需要修改的地方做成patch提交,还要花一些功夫。
    于是我改了一下 usbhidaction 和 usbhidctl,还有libusbhid,临时把 Report ID 指定为1,并且根据描述符的处理结果决定接受的字节数。原来的 usbhidaction 默认的 Report ID 是用一个ioctl获取的,这个令我难以理解…… 不是可以有不止一个么…… 关于这个,我发了封信给freebsd-stable,但是没人回…… 看来还是需要完整的patch才比较容易得到接受。
    顺便贴一下我现在用的 usbhidaction 的配置文件。我改了devd.conf使得插入键盘的时候自动运行之,效果还是不错的。
     1 # Volume Control: Up, Down & Mute
     2 Consumer:Unassigned     233  0   /usr/sbin/mixer vol +3
     3 Consumer:Unassigned     234  0   /usr/sbin/mixer vol -3
     4 Consumer:Unassigned     226  0   /usr/sbin/mixer vol 0
     5 # Pause or Play
     6 Consumer:Unassigned     205  0   /usr/local/bin/mpc toggle &
     7 #                                alt+F11
     8
     9 # Calculator
    10 Consumer:Unassigned     402  0   su henryhu -c "/usr/bin/env DISPLAY=:0 tiemu &"
    11
    12 # Back & Forward
    13 Consumer:Unassigned     548  0   su henryhu -c "/usr/bin/env DISPLAY=:0 /usr/local/bin/xdotool key alt+Left"
    14 Consumer:Unassigned     549  0   su henryhu -c "/usr/bin/env DISPLAY=:0 /usr/local/bin/xdotool key alt+Right"
    15
    16 # Zoom Up & Down
    17 Consumer:Unassigned     557  0   su henryhu -c "/usr/bin/env DISPLAY=:0 /usr/local/bin/xdotool click 4"
    18 Consumer:Unassigned     558  0   su henryhu -c "/usr/bin/env DISPLAY=:0 /usr/local/bin/xdotool click 5"
    19
    20 # 1 .. 5
    21 Consumer:Consumer_Control.Microsoft:0xff05  1   0   su henryhu -c "/usr/bin/env DISPLAY=:0 /usr/local/bin/xdotool key ctrl+Up"
    22 Consumer:Consumer_Control.Microsoft:0xff05  2   0   su henryhu -c "/usr/bin/env DISPLAY=:0 /usr/local/bin/xdotool key ctrl+a 1"
    23 Consumer:Consumer_Control.Microsoft:0xff05  4   0   su henryhu -c "/usr/bin/env DISPLAY=:0 /usr/local/bin/xdotool key ctrl+a 2"
    24 Consumer:Consumer_Control.Microsoft:0xff05  8   0   su henryhu -c "/usr/bin/env DISPLAY=:0 /usr/local/bin/xdotool key ctrl+a 3"
    25 Consumer:Consumer_Control.Microsoft:0xff05  16  0   su henryhu -c "/usr/bin/env DISPLAY=:0 /usr/local/bin/xdotool key ctrl+Down"
    26
    27 # My Favorites
    28 Consumer:Unassigned     386  0   su henryhu -c "/usr/bin/env DISPLAY=:0 /usr/local/bin/xscreensaver-command -lock"
    29 #/usr/local/bin/sudo -u henryhu /usr/local/bin/xdotool key ctrl+alt+l >& /var/log/xdotool.log
    30
    31 # Web/Home, Search & Mail
    32 Consumer:Unassigned     547  0   su henryhu -c "/usr/bin/env DISPLAY=:0 firefix &"
    33 Consumer:Unassigned     545  0   su henryhu -c "/usr/bin/env DISPLAY=:0 firefox http://www.google.com &"
    34 Consumer:Unassigned     394  0   su henryhu -c "/usr/bin/env DISPLAY=:0 firefox http://www.gmail.com &"
    35


    2009年2月25日星期三

    英语46级查分的程序

    昨天46级能够查分了,研究了一下……
    主页面调用了一段javascript,验证码竟然是本地验证的…… 这个不说,其实最后查分就是通过XMLHttpRequest直接查…… 就没什么加密一类的事情……
    之后找了一下,好像XMLHttpRequest这个东西还只有Javascript里面才有,python用起来还不方便…… 用FireBug试了一下,因为这个查分系统的请求里面没有数据,所以这个请求其实很简单,拿urllib糊弄一下就好了……
    另外关于FireFox里面不能查的问题,貌似是FireFox的XMLHttpRequest在send(null)的时候HTTP头里面没有Content Length字段,其实send("")就可以了……
    另外,最后这个系统还检查一下Referer,至少不是什么都不干……


     1 import urllib
     2 import urllib2
     3
     4 id = "Your ID"
     5 t = "4"
     6 url = 'http://cet.99sushe.com/cetscore_99sushe0902.html?t=' + t + '&id=' + id
     7 values = {}
     8 headers = { "Referer" : "http://cet.99sushe.com" }
     9
    10 data = urllib.urlencode(values)
    11 req = urllib2.Request(url, data, headers)
    12 response = urllib2.urlopen(req)
    13 the_page = response.read()
    14 result = the_page.split(',')
    15
    16 print "Listening :",result[0]
    17 print "Reading   :",result[1]
    18 print "Mixed     :",result[2]
    19 print "Writing   :",result[3]
    20 print "Total     :",result[4]
    21 print "School    :",result[5].decode('gb2312')
    22 print "Your Name :",result[6].decode('gb2312')
    23 print "Name1     :",result[7].decode('gb2312')
    24 print "Name2     :",result[8].decode('gb2312')
    25 print "Name3     :",result[9].decode('gb2312')

    2009年1月29日星期四

    关于A20地址线的那些事情

    从前在BIOS里面见过关于A20地址线的选项,后来启动FreeDOS什么的时候好像也见过A20的事情,一直不知道是干嘛的……
    后来某天看BSD loader代码的时候,看见启用A20地址线的事情…… 于是去wiki上查了一下,原来是这么回事……
    8086那个时候,地址线只有20位,叫做A0~A19,也就是没有A20地址线的。2^20=1M,因此那时能够访问的内存范围是1M。
    那个时候也分段,地址由段寄存器左移4位,加上基地址,得到物理地址。
    段寄存器和基地址都是16位的,这样就能够访问20位的空间了。但是有个问题……
    段寄存器最大FFFF,基地址也是。所以地址最大是FFFF:FFFF,但是FFFF左移四位得到FFFF0,加上FFFF,得到10FFEF,也就是FFFFF+FFF0。但是物理内存只有1M,最大物理地址范围应该是0~FFFFF,因此多了FFF0,超出了物理地址范围。
    这样,访问到超出范围的时候,8086会自动做一个处理,把高位的1删掉,也就是10xxxx->xxxx,然后返回对应位置。

    按理来说,这是个bug,8086应该返回个错误啥的。但是,既然这已经是事实了,有的程序就开始用这一点,来访问0~FFEF的内存范围,差不多是前64K少一些的范围。这就为日后的新CPU出了难题……

    80286,80386等等更NX的处理器出现了,他们支持访问更大的内存范围。自然,10xxxx和xxxx也就指向了不同的地方。但是,跑那些用到从前bug的老程序的时候,就出问题了…… 改了10xxxx的xxxx不变,导致乱七八糟的问题……
    IBM他们就脑残了一下,说,我们在A20地址线(也就是那个1的位置……)装个开关吧~ 然后又脑残一下,看见键盘控制器正好有一根线空着,就说,我们让键盘控制器来管这个开关吧~
    于是,著名的Gate A20就这么产生了……
    打开:输出0xd1到0x64端口,等8042(键盘控制器)空了,再输出0xdf到0x60端口

    保护模式的操作系统,自然都需要访问1M以上的内存,而且不希望某一位地址一直是0。所以保护模式的操作系统启动步骤之一,就是打开A20。
    但是,IBM那些人们没想到,日后有些环境需要频繁切换A20端口,而键盘控制器是如此之慢…… 他们当初认为,这个切换发生频率很低,因此慢一点没关系……

    于是就有了Fast Gate A20的事情。利用0x92端口,读入之后,把第二位改成1,然后写回去,能快一点。
    但这个引起了新的bug。毕竟只有某些系统支持0x92端口的这个用发,而有些系统…… 改了0x92会导致没有显示之类的,所以有危险……
    后来么,intel也不爽了,就搞了个0xee端口,读打开A20,写关闭…… 速度比从前更快了……

    于是,这样就有了3中方法,由慢到快。某些程序就一个一个试,试了一个验证一下。
    但是,缓存又来捣乱。有的系统虽然开了A20,还是会把几个字节缓存起来,10xxxx和xxxx一样……

    总的来说,A20就是个麻烦的事情,当初搞个BIOS调用之类的也就over了么…… 不过现在的新的系统,基本上都没有A20的问题了,虽然打开A20还是系统启动的必要步骤之一……
    参见A20 - a pain from the past

    2009年1月27日星期二

    80x86 保护模式 内存访问 学习总结

    话说这个80286搞出来的保护模式,又是分段又是分页,从前没好好研究过,从来就没有搞清楚过……
    家里翻到一本老教材,《微型计算机技术及应用——从16位到32位》,里面讲80386的章节,终于基本上讲清楚了……
    假设现在是即分段又分页的情况……

    首先,程序里面引用一个地址,其实指的都是逻辑地址。这样的引用需要两部分数据:段选择子以及段内偏移量。
    然后么,段选择子基本上就放在老的段寄存器里面,不过现在是起一个索引的作用。
    段选择子其实分几部分。总共16位,前13位是个索引,接下来1位指定是到LDT还是GDT里面找。最后两位是特权级。
    LDT和GDT,一个是局部描述符表,一个是全局描述符表,反正是两张表,存了一大堆的段描述符。表的位置放在LDTR和GDTR两个寄存器里面。
    现在研究内存访问,所以只讨论存储段描述符,每个8个字节,包括了段的开始地址(32位)、界限(20位),还有一堆标志什么的。
    用前面那个索引,从LDT或GDT里面找到描述符,然后就有了段基地址。之前需要检查偏移量符合界限,以及其他各种权限之类的检查。
    最后加上偏移量,我们就得到了线性地址~ 分段部分完成~

    然后,线性地址有32位。把它分为3段:10位,10位,12位。
    系统有一堆控制寄存器,其中,CR3里面,保存着页目录的基地址。
    页目录也是一个表,每项4个字节,每个里面都有一个页表基地址…… 当然还有一堆别的东西,什么权限、标志之类的……
    线性地址的第一段,10位,就是这个表的索引。把它乘以4(每项4个字节么……),加上CR3里面的基地址,就有了页表的基地址……
    页表的结构也差不多,也是4个字节一项。用线性地址第二段,10位,乘以4,加上页表基地址,就有了页基地址……
    最后,拿第三段,12位,加上业基地址,终于…… 我们得到了物理地址!

    接下来么,做一些数学计算。
    页内偏移量(线性地址第三段)有12位,2^12=4*1k=4k,和一页大小为4k吻合~
    线性地址前两段,每段10位,对应的表可以有1k项。所以,经过这两级,可以索引1M个页。每个页4k那么大,所以…… 总共4G。
    其实这个计算很NC对吧…… 总共32位,没有1位浪费,全都用来索引的情况下,当然可以索引2^32=4G……
    然后,一个页表有多大呢?一项4字节,共1024字节,所以一个页表4k大。总共1k个页表,所以页表总共占4M那么多地方。
    页目录表么,就4k大啦,比起页表也不算什么……
    然后,段的界限只有20位,2^20=1M,难道一个段只有1M那么大?其实剩下的标志里面有一个粒度位G,能够指定界限以1字节还是4k为单位。
    以4k为单位的时候,就能有1M*4k=4G那么大的段,这个就很完美了么~
    段选择子有16位,因此最多有2^16=65536个段,真多……

    然后,这样n级转换不是很慢么,所以系统里还有转换缓冲区。貌似这个区操作系统还可以控制,让哪些转换结果留在缓冲里面,这样下次碰见一个逻辑地址就不用多级转换了……
    另外,程序用到段选择子的时候,必然都在6个段寄存器里。所以,每次把东西扔到段寄存器里面去,CPU就把对应的段描述符装到一个隐藏的寄存器里面,这样,大部分时间就不用去查LDT/GDT之类的了……