Thursday, December 28, 2006

Configuring fetchmail to work with gmail

Gmail uses the POP3-over-SSL protocol, which encrypts your messages, to pop your mails. Thus, we should get a legel certificate for verification. You can use any legal certificates, here we will grab Google's own cerificate and authenticate it.

  1. Get gmail's own cerificate:
    $ openssl s_client -connect smtp.gmail.com:995 -showcerts
    Which will output such below:
    CONNECTED(00000003)
    depth=0 /C=US/ST=California/L=Mountain View/O=Google Inc./CN=pop.gmail.com
    verify error:num=20:unable to get local issuer certificate
    verify return:1
    depth=0 /C=US/ST=California/L=Mountain View/O=Google Inc./CN=pop.gmail.com
    verify error:num=27:certificate not trusted
    verify return:1
    depth=0 /C=US/ST=California/L=Mountain View/O=Google Inc./CN=pop.gmail.com
    verify error:num=21:unable to verify the first certificate
    verify return:1
    ---
    Certificate chain
    0 s:/C=US/ST=California/L=Mountain View/O=Google Inc./CN=pop.gmail.com
      i:/C=US/O=Equifax/OU=Equifax Secure Certificate Authority
    -----BEGIN CERTIFICATE-----
    MIIC3TCCAkagAwIBAgIDBZIAMA0GCSqGSIb3DQEBBQUAME4xCzAJBgNVBAYTAlVT
    MRAwDgYDVQQKEwdFcXVpZmF4MS0wKwYDVQQLEyRFcXVpZmF4IFNlY3VyZSBDZXJ0
    aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDUxMTE1MjEyMjQ0WhcNMDcxMTE2MjEyMjQ0
    WjBoMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMN
    TW91bnRhaW4gVmlldzEUMBIGA1UEChMLR29vZ2xlIEluYy4xFjAUBgNVBAMTDXBv
    cC5nbWFpbC5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMP8LCYiLGJ/
    RihwcOi1V/zHVTw0Gfu+mI141Vjuuj2DtQoav8emwlXbu8gZoKP9GeMWpX1Vo9qN
    4gkslIToHmDnIwGjcaEAfpdhSR9g54Kf5Y7BEXVyco6mTIlpe9vsbV0dmB1FvLP2
    1N09dkUJfi7V0fjb8mcn3QYu6+6QNoxPAgMBAAGjga4wgaswDgYDVR0PAQH/BAQD
    AgTwMB0GA1UdDgQWBBTdASsopgao1m8hcEg0cDZhucltljA6BgNVHR8EMzAxMC+g
    LaArhilodHRwOi8vY3JsLmdlb3RydXN0LmNvbS9jcmxzL3NlY3VyZWNhLmNybDAf
    BgNVHSMEGDAWgBRI5mj5K9KylddH2CMgEE8zmJCf1DAdBgNVHSUEFjAUBggrBgEF
    BQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQEFBQADgYEAln3/pVqYnUXA1TVGzOqX
    LFhohGxpuNkr1UJnQmYxmZeB07uPBYRX8c0JXEKs29TmAHRsLhmp8kF36F11Dxgi
    Xm/Y8I9zgWHoMj7SL3Ve/u8K8K7XcUyUuaWmldLQAREafpFy+f+KYHGuAVh8hjy6
    XyPlMCqj+PNp8QXjgOcgO68=
    -----END CERTIFICATE-----
    ---
    Server certificate
    subject=/C=US/ST=California/L=Mountain View/O=Google Inc./CN=pop.gmail.com
    issuer=/C=US/O=Equifax/OU=Equifax Secure Certificate Authority
    ---
    No client certificate CA names sent
    ---
    SSL handshake has read 891 bytes and written 314 bytes
    ---
    New, TLSv1/SSLv3, Cipher is DES-CBC3-SHA
    Server public key is 1024 bit
    Compression: NONE
    Expansion: NONE
    SSL-Session:
       Protocol  : TLSv1
       Cipher    : DES-CBC3-SHA
       Session-ID: C376985C4DAFD52F21A89E42FB9D36DA0458F3A6F1D97E9615A0793DE2C2163C
       Session-ID-ctx:
       Master-Key: 74C5BE3ACBEE15367F1D7ADCD91B478B0FD81FC9EDB56D8698C1DCAEE09CAEECCE58C557308CBE0C049EFB50D1EB2829
       Key-Arg   : None
       Start Time: 1167236180
       Timeout   : 300 (sec)
       Verify return code: 21 (unable to verify the first certificate)
    ---
    +OK Gpop ready for requests from 210.77.27.77 f57pf402492pyh
    

    Then, the Gmail's certificate is just the content between -----BEGIN CERTIFICATE----- and -----END CERTIFICATE-----. Prepare a directory to save your certificates, for example, ~/.certs/. Copy such content and save into the file ~/.certs/gmail.pem

  2. Get the Fingerprint of the certificate, run the command below:
    $ openssl x509 -fingerprint -md5 -noout -in gmail.pem
    MD5 Fingerprint=59:51:61:89:CD:DD:B2:35:94:BB:44:97:A0:39:D5:B4
    

  3. Rehash the gmail certificates:
    $ c_rehash ~/.certs
    Doing /home/nini/.certs/
    gmail.pem => 7f549ca4.0
    

  4. Now, the configuration of POP3-over-SSL has mostly completed. Verfiy whether everthing is ok by the following commands:
    $ openssl s_client -connect pop.gmail.com:995 -CApath ~/.certs -quiet
    depth=1 /C=US/O=Equifax/OU=Equifax Secure Certificate Authority
    verify return:1
    depth=0 /C=US/ST=California/L=Mountain View/O=Google Inc./CN=pop.gmail.com
    verify return:1
    +OK Gpop x99xx9999xxx ready.
    CAPA
    +OK Capability list follows
    USER
    RESP-CODES
    EXPIRE 0
    LOGIN-DELAY 300
    X-GOOGLE-VERHOEVEN
    .
    USER username@gmail.com
    +OK send PASS
    PASS password
    +OK Welcome.
    CAPA
    +OK Capability list follows
    USER
    RESP-CODES
    PIPELINING
    EXPIRE 0
    LOGIN-DELAY 300
    TOP
    UIDL
    X-GOOGLE-VERHOEVEN
    .
    QUIT
    +OK Farewell.
    read:errno=0
    

  5. Then, configure your ~/.fetchmailrc file, here is a good example:
    poll pop.gmail.com with proto POP3 uidl
        username "username@gmail.com" there with password "password" is "nini" here
        options keep ssl sslfingerprint
        '59:51:61:89:CD:DD:B2:35:94:BB:44:97:A0:39:D5:B4'
        # sslcertck sslcertpath "/home/nini/.certs"
        mda "/usr/bin/procmail -d %T"
    

    If your fetchmail is not running as a deamon but a crontab task, use the configuration file above and make sure the line contained sslcertpath is commented. Otherwise, you might occour the error:

    fetchmail: Server certificate verification error: unable to get local issuer certificate
    25424:error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed:s3_clnt.c:894:
    fetchmail: SSL connection failed.
    

    Perhaps, this has exposed a slight difference in logging behaviour between daemon mode and single instance mode. you can test it with the command:

    $ fetchmail -d0 -v pop.gmail.com
    

Use esmtp over smtp server

  1. Edit the configuration file ~/.esmtprc:
    hostname = smtp.gmail.com
    username = "username@gmail.com"
    password = "password"
    starttls = enabled
    
  2. $ chmod 0710 ~/.esmtprc
  3. If you use mutt as your mail client, then modifiy ~/.muttrc
    ~/.muttrc

    set envelope_from set sendmail="/usr/bin/esmtp -v -X ~/.esmtplog" my_hdr From: "username@gmail.com" my_hdr Reply-To: "username@gmail.com" set sendmail_wait=0

Reference:

Monday, December 25, 2006

Nautilus挂载Windows分区后部分中文乱码的解决办法

最近因为Beryl的吸引,放下了使用已久的fvwm投入了gnome的阵营 :) 看我下边的一篇文章:

发信人: Jun (无语话凄凉), 信区: Linux
标  题: beryl还是搭配gnome工作好些
发信站: BBS 科苑星空站 (Wed Dec 20 12:23:46 2006), 站内

3d桌面出来后就开始抛弃了fvwm跟风了。觉得gnome是个臃肿的庞然大物,
所以一直裸用beryl的,但是发觉它独立工作还有不少缺憾,比如fx卷屏的
时候X占用CPU很高,并且时常有崩溃的情况,休眠后恢复常常X挂掉。

最近编译了gnome-light,然后搭配beryl-0.1.2,发觉使用流畅多了,并且
挺稳定。对于边角(decoration)的修饰很漂亮,避免视觉的厌烦。一系列的
工具很好用,最赞的是eog, evince,nautilus和rhythmbox快速稳定,非常
适合桌面应用。以前 gqview处理中文路径有问题,acroread很臃肿,卷屏
迟钝,rox虽然小巧精悍,细节上,比如缩略图和指定mine-type总有些不如
nautilus顺畅,xmms的中文绝对考rp,audacious类似winmap的古老的两截
窗口使用上远比不上rhythmbox的foobar 样式方便直接,并且无法
minimize into systray bar。

决定还是转入gnome-light+beryl的桌面应用了,稳定/流畅/易用/类似
MACOSX的操作方式就是王道哇,非常棒。

--

※ 来源:·BBS 科苑星空站 kyxk.net·[FROM: 210.77.27.*]

接下来是正题,由于fm换成了nautilus,输入法换成了scim,所以遇到了不少问题。比如令人头疼的是nautilus显示从windows的fat32挂载上来分区中的中文文件名有一部分是正常的,然而有一部分却是乱码,google一下,网络上有不少人遇到过这样的问题,却最后没有合适的解答,我折腾了许久才发觉原来是变量G_FILENAME_ENCODING设置的问题,在.gnomrc里边被设置为GBK了,而我是UTF-8的locale,所以导致了这样的恶心问题。

一个题外话是,中国之所以linux桌面推广比较成问题,我觉得单这些混乱的locale设置、中文字体配置就够人头大了。从4、5年前接触使用linux到现在,一直面临着这种问题,Emacs中文配置、输入法配置,等等。比如FreeBSD下到现在还是只能用LC_CTYPE=zh_CN.eucCN,用UTF-8的话,总会有程序在中文上让你恶心,Linux下已经可以全面采用UTF-8了。下边贴一下我的一些关键配置文件,包括.xprofile, gnome-start.sh:

.xprofile

关于X的个人配置可以放到这里边,至于为什么,可以读一下类似/etc/X11/gdm/Xsession这个文件,用gdm启动的X环境的启动脚本。当然你可以把配置放到/etc/X11/xinit/xinitrc.d诸如此类地方,不过那需要有root权限并且是影响所有登录用户的,我觉得不利于备份,不喜欢 :)

#!/bin/sh

export LANG=en_US.UTF-8
export LC_CTYPE=zh_CN.UTF-8

export XIM_PROGRAM="scim"
export XIM="scim"
export XMODIFIERS="@im=SCIM"
export GTK_IM_MODULE="scim"
export QT_IM_MODULE="scim"

export G_FILENAME_ENCODING=UTF-8
export G_BROKEN_FILENAMES=1
export GDK_USE_XFT=1

export OOO_FORCE_DESKTOP=gnome

gnome-start.sh

在gnome的session中可以加入gnome-start.sh这个脚本,然后把你所想要启动的程序放到这个脚本里边:

#!/bin/sh

# exec fcitx &
exec xmodmap ~/.Xmodmap &

# exec gkrellm2 &

exec tpb -d &

scim -d

dbus-launch beryl-manager
exec beryl --indirect-rendering --strict-binding --replace dbus settings

这里我把thinkpad的热键程序tpb、输入法scim和beryl的启动脚本都写进入了。

.gtkrc-2.0

这里可以放置对于gtk2的个性设置,比如图标、字体之类

include "/usr/share/themes/Clearlooks/gtk-2.0/gtkrc"

style "user-font" {
font_name = "Sans 12"
}

widget_class "*" style "user-font"

gtk-font-name="Sans 12"

include "/home/nini/.gtkrc.mine"

.gtkrc.mine

个性化图标设置
gtk-icon-theme-name = "nuoveXT-1.6"

其实这个变量对nautilus是没有效果的,对rox有用。

Thursday, December 14, 2006

mysql database backup and optimizing

Backup database

It is recommended to use mysqldump to backup, instead of duplicating the data directory directly. Frequently, we can set a schedule to complete this task by crontab. Here is an example:

15 4 * * * /home/mysql/bin/mysqldump -S/data/app_1/mysql.sock -umysql db_name | gzip -f>/path/to/backup/db_name.`data +\%w`.dump.gz
Some notes:
  1. In the crontab, '%' should be converted into '\%'.
  2. Choose a proper time to do backup tasks, such as 4:00~6:00 am, depended by your log statistics.

You can backup firstly at your local host, and then transfer into your remote backup server. You can also backup at a remote server directly,and your command will become:

/home/mysql/bin/mysqldump -h mysql_database_ip -umysql db_name | gzip -f>/path/to/backup/db_name.`data +\%w`.dump.gz

Example to optimize a forum

  1. Use Webalizer to replace the database statistics.
  2. Firstly, Use the command "top" to check the load of cup and memory. For example the load of cup is 80%, and memory is 10MB, which means the index cache of database has exhausted. So, modified the startup arguments, add "-O key_buffer=32", such as:
    /home/mysql/bin/safe_mysqld --user=mysql --pid-file=/path/to/mysql.pid \
    --datadir=/path/to/data --port=3402 --socket="$rundir"/mysql.sock \
    -O max_connections=500 -O wait_timeout=600 -O key_buffer=32M &
    

    Wait a few minutes, until the database runs steadily. And check the load of cpu and memory again. Assign more memory for index caches, until the load cpu decreases below 10%. For a database application, it takes more effects to assign spare memory to database other than web application, because faster mysql query processes will accelerate the web application and save the resources of concurrency web services.

  3. Run the command "show processlist" to stat the most frequent sql query statment. Run "show processlist" every minute by crontab, and log the results.
    * * * * * (mysql -uuser -ppassword < ~/show_processlist.sql >> ~/mysql_processlist.log)
    

    The content of show_processlist.sql contains only one command: show processlist; For example, filter the log and find the statements containing "where":

    grep where mysql_processlist.log
    

    If death locks exist, review the bad sql design. If search processes are slow, index the fields of "where" statements. If order processes are slow, index the fields of "order by" statements. If the query processes containing "%like%" are slow, recommend to deny them or find other text indexing method.

  4. If some databases are extremely frequently used, try to assgin different ports for each database.

Compile and install

Some tips:
  • Install the stable version as last as possible,
  • Donot compile with the option "--with-charset=xxx", which will make trouble.
  • Donot compile with innodb, which is often used in the support of enterprise, and slower than MYISAM.

    ./configure --prefix=/home/mysql --without-innodb
    make
    make install
    

    Reference: http://www.chedong.com/tech/mysql.html

Tuesday, December 12, 2006

Let iframe auto-adjust its height

Iframe, especially no-border iframe, can integrate with a webpage seamlessly, and can update one part of this page without refresh. However, the size of a iframe usually can not adjust as arbitrarily as a layer. Now, we can use a javascript function below, to let iframe adjust its height automaticly.

function SetCwinHeight(){
  var cwin=document.getElementById("cwin");
  if (document.getElementById){
      if (cwin && !window.opera) {
          if (cwin.contentDocument && cwin.contentDocument.body.offsetHeight)
              cwin.height = cwin.contentDocument.body.offsetHeight;
          else if(cwin.Document && cwin.Document.body.scrollHeight)
              cwin.height = cwin.Document.body.scrollHeight;
      }
  }
}

Then, add html code of iframe. Donot foreget the attribute "onload". Of course, the id of iframe should match "cwin" in the function SetCwinHeight:

<iframe width="778" align="center" height="200" id="cwin" name="cwin" onload="Javascript:SetCwinHeight()" frameborder="0" scrolling="no"></iframe>

In the end, recommend a function used to get the object of a html element.

function GetObj(objName){
    if(document.getElementById){
        return eval('document.getElementById("' + objName + '")');
    }else if(document.layers){
        return eval("document.layers['" + objName +"']");
    }else{
        return eval('document.all.' + objName);
    }
}

Monday, December 04, 2006

send attachments via mail app under console

If your mail server support 8-bit mode, you can directly use such commands:

    cat <attachment-file> | mail -s <subject> <email-address>

However lots of mail servers donot support 8-bit mode, so you'd better use the uuencode command. Firstly, prepare your mail, for example, named mymail, then,

    uuencode <attachment-file> <attachment-file> >> /tmp/mymail
Or
   cat <attachment-file> | uuencode <attachment-file> >> /tmp/mymail

Then, edit /tmp/mymail, and add your mail content before the attachment. After complete it, send it.

    cat /tmp/mymail | mail -s <subject> <mail-address>

Or directly:

    uuencode <attachment-file> <attachment-file> | mail -s <subject> <mail-address>

When received this mail, copy the content which belongs to mymail and save it into themail.uue. If the receiver reads it under MS Windows, he can unzip it with winzip 7.0 and acquire the attachment. If he under Linux, just use uudecode to restore the attachment:

    uudecode -o <attachment-file> themail.uue

If several files need to be dealed, i suggest you zip them into one package, and the attachment filename just is this package's filename.

There are some other ways, using mutt command:

    mutt -s "title" -a /dir/file1 mail@address

This command will call your editor to edit the mail content, thus you can firstly prepare your content, such as mailcontent.txt, to avoid to call the editor:

    cat mailcontent.txt | mutt -s "title" -a attachfile1 mail@address

Friday, December 01, 2006

urlencode and urldecode in Perl

If you are looking for PHP's urlencode/urldecode equivalent in Perl, you won't find any. But here's what you can do:

Encode:
$str =~ s/([^A-Za-z0-9])/sprintf("%%%02X", ord($1))/seg;
Decode:
$str =~ s/\%([A-Fa-f0-9]{2})/pack('C', hex($1))/seg;

from: http://melecio.org/node/76

Another choice:

use URI::Escape;
uri_escape($val);
uri_unescape($val);