2008-04
19

fcicq最近在IPA上看到一篇安全相关的文章, 它的最末尾有个checklist,于是催我把它翻译了。前几天比较忙,周末没什么事儿了,就翻译一下吧。

原文的标题是如何让网站更安全。 这里仅翻译文章最后的一个checklist。

2008/4/20更新:fcicq倒是神速啊,马上就把具体的应用策略扔出来了 :D 参考:PHP 实践 Security Checklist

阅读全文 »

2008-03
27

今天继续翻译代码布局的这一部分。有些很明显的条目,就不翻译了,看看代码就应该明白是什么意思。

阅读全文 »


2008-03
20

margin和padding的意义相信大家都很清楚,可是在具体应用中, 到底应该使用哪一个,就比较难于判断了。 这篇文章 说得挺清楚的,在这里翻译一下,供参考。

何时应当使用margin

  • 需要在border外侧添加空白时。
  • 空白处不需要背景(色)时。
  • 上下相连的两个盒子之间的空白,需要相互抵消时。如15px + 20px的margin,将得到20px的空白。

何时应当时用padding

  • 需要在border内测添加空白时。
  • 空白处需要背景(色)时。
  • 上下相连的两个盒子之间的空白,希望等于两者之和时。如15px + 20px的padding,将得到35px的空白。

浏览器兼容性问题

在IE 5.x、IE6中,为float的盒子指定margin时,左侧margin可能会变成两倍的宽度。 通过改用padding或指定盒子为display:inline可以解决。



2008-03
18

今天在写代码时遇到一个很奇怪的问题。我写的这样一个函数:

sub parse {
  my $self = shift;
  my $header = shift;
  my $charset = shift;
  
  # 其它处理
  # ...
}

至于如何调用,则是先通过 MIME::Parser 模块解析邮件, 然后调用解析结果中的 MIME::Head::get 函数来获得邮件头的值, 再将其结果传递给 parse 函数:

print $self->parse($head->get("Cc"), "GB2312");

通常都没有问题,在parse函数中,$header取到 Cc 邮件头,而 $charset 取到 "GB2312"; 但当一封邮件中不存在Cc时,就会出现一件怪事: $header 变量竟然取到了第二个参数 "GB2312" 的值!

在 parse 中将 @_ 打出来,发现当Cc邮件头取不到时,第一个参数就“消失”了, 参数列表就变成了 ("GB2312")。按照常理,参数列表应该是 (undef, "GB2312")才对啊。

百思不得其解中,偶然看到 MIME::Head::get 的文档中这样说:

  • If a numeric INDEX is given, returns the occurence at that index, or undef if not present:
  • If no INDEX is given, but invoked in a scalar context, then INDEX simply defaults to 0:
  • If no INDEX is given, and invoked in an array context, then all occurences of the field are returned:

上面的调用属于没有 INDEX 的情况,莫非parse函数的参数列表提供了一个列表环境, 导致MIME::Head::get返回了一个数组?

于是强制为它提供一个标量环境,结果就正常地得到了 (undef, "GB2312")。

print $self->parse(scalar $head->get("Cc"), "GB2312");

看来果然是上下文环境造成的问题。parse函数的第一个参数期待一个常量, 而函数的参数列表却是一个列表环境,再加上MIME::Head::get在列表环境中返回数组, 这样就会导致两种错误:

  • 如果不存在Cc,则参数列表为("GB2312"),$header = "GB2312";
  • 如果存在多个Cc,则参数列表为("Cc-val1", "Cc-val2", "Cc-val3", "GB2312"), $charset="Cc-val2"。

两种情况都十分荒谬。

对Perl的上下文不熟悉的人,这里可要特别注意啊。



2008-03
11

继续翻译Perl最佳实践的2.9~2.12。

阅读全文 »


2008-03
08

停止已久的《Perl Best Practices》翻译今天重新开始了。继续讲代码布局。

阅读全文 »


2008-03
07

最近遇到的一个任务是要将散落在系统各个文件中的 use lib '/opt/mysoft/lib'; 这样的绝对路径引用改成相对路径, 以便整个系统能够轻易地移动到其他的目录中。系统是工作在Apache2 + mod_perl 下的,cgi程序位于 /opt/mysoft/cgi-bin 下。

初看起来似乎很容易:

use lib '../lib';    # 错误!

但实际尝试一下就会发现,这里的 '..' 似乎找错了位置。当前目录并不是cgi程序所在的 /opt/mysoft/cgi-bin。 经过一番实验后,发现在 use lib 时,当前目录居然是在 / 下!这样这条路就走不通了。

另一个想法是通过 $0 获取到CGI程序的路径,再根据此路径来找到 lib 目录不就可以了么?

$dir = dirname $0;
use lib "$dir/../lib";     # 错误!

print "$_\n" for @INC;

实际运行就会发现,这一招也行不通。原因是use lib是在编译时执行的。编译时代码并没有被执行, 因此 $dir 变量为空(甚至都不存在),于是就成了 use lib "/../lib",当然不正确了。 这样看来 use lib 似乎必须要书写完整路径了。

CPAN文档的解释如下:

lib - manipulate @INC at compile time

实际上 use lib 可以理解为 BEGIN { unshift @INC, '/opt/mysoft/lib'; }。 BEGIN段的内容在这一段编译结束后立即执行。

回到本来的问题上,如何能避免在系统中使用绝对路径? 其实使用mod_perl的功能一次性地指定好@INC,那么在CGI和pm模块中就无需再use lib了。

在mod_perl的官方文档中有关于如何调整@INC的说明。

一种方法是在 startup.pl 中书写完整路径:

use lib '/opt/mysoft/lib';

令一种方法是直接在httpd.conf中修改@INC:

PerlSwitches -I/opt/mysoft/lib

这样虽然不能完全避免绝对路径,但至少在产品代码中可以不再使用 use lib 了。


同样地,use 也是在编译时执行的。(参考)use Module;相当于

BEGIN { require Module; Module->import( LIST ); }

程序代码中的所有use指令都会在代码执行前被执行,因此use不论放在哪里,效果都是一样的。因此

if ($use_first_lib) {
  use FirstLib;
  ...
}
else {
  use SecondLib;
  ...
}

这样的代码是毫无用处的,不论$use_first_lib的值如何,FirstLib和SecondLib都会被加载。



2008-03
06

最近发现gentoo下pidgin经常会不能输入,表现在输入法切换不出来,甚至无法输入英文字母。没办法只能重启pidgin。不过今天突然发现了问题的所在。那就是,从聊天窗口用Alt-Tab键切换到好友列表窗口,再用Alt-Tab切换回来,这时一切键盘输入就都不管用了。解决方法也很简单:再用Alt-Tab切换一次,就行了。另外为避免出现这种情况,建议没事儿时把好友列表窗口关掉。


2008-03
05

前几天的这篇文章fcicq同学挑毛病,建议不要使用内核自带的ntfs, 而是使用ntfs-3g+fuse。查了一下,ntfs-3g可以完美支持ntfs分区的读写操作, 的确要比内核自带的ntfs好得多。

试试看。安装方法不难,直接emerge即可,它会自动安装 sys-fs/fuse:

# emerge ntfs-3g

我用的是gentoo 2007.0,内核版本2.6.23-gentoo-r8,还需要编译内核的FUSE支持:

# cd /usr/src/linux
# make menuconfig
勾选 File systems --->  <M> Filesystem in Userspace support
# make modules_install
# modprobe fuse

之后当然可以再打开 /etc/modules.autoload.d/kernel-2.6,把fuse加进去。

然后就可以mount ntfs分区了:

# mount -t ntfs-3g -o locale=zh_CN.UTF-8,silent /dev/sda6 /mnt/wine

进入分区后试试读写,均没有问题。

后来看了看ntfs-3g的官方主页的FAQ, 发现竟然允许大小写不同的同名文件,还有特殊字符(如\、?等Windows中不允许的字符)。 作者的理由是NTFS支持POSIX风格的文件名,也支持DOS、Windows格式的文件名, 为保持最大的兼容性,ntfs-3g就选择了POSIX——所以就出现上面这种现象了。 尝试者建立 ABC、abc、ab?c、abc\d等文件,均建立成功,重新启动到windows下试图打开这几个文件, 结果出现了问题:ABC正常打开,但一旦保存,ABC就会丢失,只剩下abc(因为同名),估计有可能需要chkdsk了; ab?c、abc\d文件无法保存、改名和删除。只能回到linux下面操作。

看来作者又是一个十足的协议派……为保险起见,还是先ro吧。

最后的/etc/fstab为:

/dev/sda6       /mnt/wine    ntfs-3g    auto,ro,locale=zh_CN.UTF-8,silent    0  0


2008-03
04

今天在配置nvidia的显卡时出现了一个很头疼的问题。

按照官方网站上的文章, 一步步地顺利地安装好了显卡驱动:

# 先配置内核,详情参考官方文档,省略
# USE=gtk emerge nvidia-drivers
# modprobe nvidia
# update-modules
# eselect opengl set nvidia
# 然后修改xorg.conf,略
# startx

结果startx时出现了这样的错误:

Backtrace:
0: X(xf86SigHandler+0x84) [0x80cca34]
1: [0xffffe420]
2: X(main+0x2af) [0x807067f]
3: /lib/libc.so.6(__libc_start_main+0xd8) [0xb7db5838]
4: X(FontFileCompleteXLFD+0xa1) [0x806fb81]

Fatal server error:
Caught signal 11.  Server aborting

查了半天资料未得到结果,后来想起我曾经安装过nVidia官方网站提供的驱动, 会不会是和portage的驱动冲突呢?于是卸载掉官方驱动:

# sh NVIDIA-Linux-x86-169.09-pkg1.run --uninstall

然后重新emerge:

# emerge nvidia-drivers

这样就可以顺利地启动X了。