bianbian coding life

便便代码人生: 关注技术, 翻译文档, 偶尔动动手

Archive for January, 2008

[原]关于Indy组件(Delphi)实现FTP上传断点续传的方法 (upload resume)

Posted by bianbian on 2008-01-15 09:00


本文Tags: , , ,

Indy不仅支持下载断点续传,也支持上载断点续传,而且不需要对Indy做出改造。
在Blues的blog,他提到可以“通过IDFTP得到服务端已经上传的部分的SIZE,然后通过文件流在本地建立剩余部分的临时文件,然后以APPEND方式上传,传完后删除临时文件,达到上传断点续传的效果”。原文在此:DELPHI ftp 上传断点续传的实现
我再仔细看了Indy的源码,发现不需要临时文件。可以对Blues的方法作出重大改进:
Put()方法第一个参数可以是TStream(实际上,如果是文件名的话Indy会建立Stream,然后再调用Stream的Put方法)。而且如果Append设为True的话,Indy不会去动Stream的Position:

  1. procedure TIdFTP.Put(const ASource: TStream; const ADestFile: string = '';
  2.  const AAppend: boolean = false);
  3. ...
  4. procedure TIdTCPConnection.WriteStream(AStream: TStream; const AAll: boolean = true;
  5.   const AWriteByteCount: Boolean = False; const ASize: Integer = 0);
  6. ...
  7.   if AAll then begin //bianbian注:如果Append,AAll是false
  8.     AStream.Position := 0;
  9.   end;
  10.   // This is copied to a local var because accessing .Size is very inefficient
  11.   if ASize = 0 then begin
  12.     LStreamEnd := AStream.Size;
  13.   end else begin
  14.     LStreamEnd := ASize + AStream.Position;
  15.   end;
  16.   LSize := LStreamEnd - AStream.Position;
  17. ...

也就是说,先把原文件的Stream Seek到Size位置,丢给Indy即可,实现也很简单:

  1. var
  2.   fs: TFileStream;
  3. ...
  4.   fs := TFileStream.Create(FullFileName, fmOpenRead or fmShareDenyWrite);
  5.   fs.Seek(size, 0); //偏移
  6.   FTP.Put(fs, ExtractFileName(FullFileName), True);
  7.   fs.Free;
标签: , , ,

遵守创作共用协议,转载请链接形式注明来自http://bianbian.org 做人要厚道

相关日志

Posted in Delphi, Technology | 1 Comment »

[唉]Delphi怎么没有三目运算符(也叫三元运算符)

Posted by bianbian on 2008-01-13 08:22


本文Tags: ,

虽然自己写了一个iif函数,还是有问题的:

  1. function iif(const bool: Boolean; const ifSucc, ifFail: Variant): Variant;
  2. begin
  3.   if bool then
  4.     Result := ifSucc
  5.   else
  6.     Result := ifFail;
  7. end;

问题是传进的参数事先是已经被计算出值了,就会导致问题:

1)重复计算。比如:如果bool为真,输出txt,否则在之前加几个空格再输出txt
iif(bool, txt, ' ' + txt);
如果bool为真,按三目运算的规则,' ' + txt 是不会执行到的。不过这里做参数,只能重复计算,效率比if else 低

2)避免不了某些会导致异常的代码
原因还是因为参数会事先计算。比如:如果是目录,输出0,否则输出文件最后修改时间:
iif(Isdir(PathFileName), 0, FileDateToDateTime(FileAge(PathFileName)));
如果PathFileName是目录,FileAge()函数会抛出异常。
按三目运算规则,异常的代码是不应该被执行到的;但这里作参数,一旦是个目录每次必定抛异常,还得改成if else

还没想到好的解决办法,难道用Callbak函数回调?太夸张了点。。。。汗。。。。。

标签: ,

遵守创作共用协议,转载请链接形式注明来自http://bianbian.org 做人要厚道

相关日志

Posted in Delphi, Technology | No Comments »

[嗯]新增blog域名: bianbian.org

Posted by bianbian on 2008-01-10 03:43


本文Tags: ,

为了大家容易记住,弄了个顶级域名:bianbian.org
以前的 bianbian.sunshow.net 还是有效,再次感谢sunshow。

标签: ,

遵守创作共用协议,转载请链接形式注明来自http://bianbian.org 做人要厚道

相关日志

Posted in Uncategorized | 1 Comment »

[原]qmail+vpopmail+maildrop+SpamAssassin遇到的错误及解决

Posted by bianbian on 2008-01-05 12:28


本文Tags: , , , ,

这几天这是多灾多难,修复烂系统真是考验人阿。。。。。。下面把Qmail的错误及解决汇总一下:

■ qmail-1.03的编译出现问题
../load auto-str substdio.a error.a str.a
/usr/bin/ld: errno: TLS definition in /lib/libc.so.6 section .tbss
mismatches non-TLS reference in substdio.a(substdo.o)
/lib/libc.so.6: could not read symbols: Bad value
collect2: ld returned 1 exit status
make: *** [auto-str] Error 1

后来搜了一下,在哪说的忘记了,是因为gcc版本高了以后对extern int errno这种写法不自动修正了。解决办法:
grep “extern int errno”
把所有grep出来的地方的”extern int errno”换成 #include

试了一下,果然解决。
原文找到了:http://www.webservertalk.com/archive66-2006-3-1441516.html
[bianbian补注]:其实这个错误再打个errno的patch就可以解决的。。。

■ Sorry,_message_has_wrong_owner._(#4.3.5)
queue队列损坏,删除/var/qmail/queue目录,重新make setup check生成目录

■ Sorry,_no_mailbox_here_by_that_name._(#5.1.1)
修改了/var/qmail/control/locals文件,所以,虚拟域名就无效了。
把locals文件清空,就不会出现这个问题了。

■ qmail能发不能收, qmail_has_prog_delivery_but_has_x_bit_set
连自己域内发给自己的都收不到。一般是.qmail-default的权限问题。查看日志会发现:
deferral: Uh-oh:_.qmail_has_prog_delivery_but_has_x_bit_set._(#4.7.0)
前面我抱怨过了,给我的网站恢复数据居然是NTFS的,导致所有文件权限丢失。详见抱怨贴
一定要去掉 /home/vpopmail/domains/域名/.qmail-default 的x权限
即 chmod -x /home/vpopmail/domains/域名/.qmail-default

■ 454 oops, unable to write pipe and I can’t auth
详见:[原] qmail打了smtpd-auth补丁后454 oops, unable to write pipe and I can’t auth

■ pop3 遇到 -ERR this usr has no $HOME/maildir
supervise/qmail-pop3d/run里启动pop3d的脚本可能有错,应该是:
#!/bin/sh
PATH=/var/qmail/bin:/usr/local/bin:/usr/bin:/bin
export PATH
QMAILDUID=`id -u vpopmail`
NOFILESGID=`id -g vpopmail`
exec tcpserver -H -R -v -c100 -u “$QMAILDUID” -g “$NOFILESGID” 0 110 qmail-popup nju.org.cn \
/home/vpopmail/bin/vchkpw \
/var/qmail/bin/qmail-pop3d Maildir 2>&1

■ 解决qmail经常收到投递失败的邮件
这一段部分来自:http://blog.5ilinux.com/archives/2006/04/qmailerror.html
首先说明一下<>和<#@[]>都是系统bouce信件信封(envelope)上的寄信人地址
这两种信都是系统产生的,区别在于<>往往是系统single bouce的地址,而<#@[]>则是系统double bounces或者triple bouces的地址
系统用这两种地址是为了避免邮件回路(mail loops)
来自<#@[]>一般都是系统的double bounces
要去掉这些double bounces可以有一种简单的办法
其原理是产生一个nobody的地址,发往这里的信件都会被丢弃,这样double bouces就不会烦你的postmaster了
具体步骤如下:
echo “#” > /var/qmail/alias/.qmail-doublebounceto (或者直接丢弃:echo “| cat > /dev/null” … )
echo “doublebounceto” > /var/qmail/control/doublebounceto

■ 垃圾邮件太多
1)装上发信黑名单 CBL: http://anti-spam.org.cn
2)装上maildrop和垃圾邮件过滤器 SpamAssassin: http://spamassassin.apache.org/
简单点,直接用perl的cpan安装:cpan Mail::SpamAssassin
这里有具体方法:
Getting SpamAssassin, MailDrop, VPopmail and qmail to play friendly
用 qmail + vpopmail + maildrop + spamassassin 实现邮件过滤的方案

其实我觉得老外的那个办法更好,直接改.qmail-default一个文件就行了。结合两者长处,我写了一个又支持用户自定义黑白名单,又不需要到处放.mailfilter的方法:

.qmail-default
|/usr/local/bin/maildrop ./.mailfilter

.mailfilter
VPOP="| /home/vpopmail/bin/vdelivermail '' bounce-no-mailbox"
VHOME=`/home/vpopmail/bin/vuserinfo -d $EXT@$HOST`

#check dir
`test -d $VHOME/Maildir/`
if( $RETURNCODE != 0 )
{
    echo "Sorry,_no_mailbox_here_by_that_name."
    EXITCODE=77
    exit
}

#blacklist
#
`test -f $VHOME/.blacklist`
if ($RETURNCODE==0)
{
    $DOMAIN=`expr $SENDER : '.*@\(.*\)'`
    if ($SENDER ne '' && (lookup($SENDER, "$VHOME/.blacklist") || lookup($DOMAIN, "$VHOME/.blacklist")))
    {
        #to "$VHOME/Maildir/.Trash/"
        to /dev/null
    }
}

#whitelist
#
`test -f $VHOME/.whitelist`
if ($RETURNCODE==0)
{
    if ($SENDER ne '' && lookup($SENDER, "$VHOME/.whitelist"))
    {
        to "$VHOME/Maildir/"
    }
}

#spamassassin
#
if ($SIZE < 262144)
{
    exception {
        xfilter "spamc -f -u $EXT@$HOST"
    }
}
else
{
    exception {
        to "$VHOME/Maildir/"
    }
    exception {
        to "$VPOP"
    }
}

if (/^X-Spam-Flag: *YES/)
{
    ADDQUOTA = " $SIZE 1"
    `echo $ADDQUOTA >> $VHOME/Maildir/maildirsize`
    to “$VHOME/Maildir/.Trash/”
}
else
{
    exception {
        to “$VHOME/Maildir/”
    }
    exception {
        to “$VPOP”
    }
}

■ 加入maildrop作为投递程序后的可能错误
maildrop:_Cannot_have_world/group_permissions_on_the_filter_file_-_for_your_own_good./
.mailfilter必须是0600属性

failure: Unable_to_execute_/sbin/nologin/Unable_to_execute_/sbin/nologin/
或者
Sorry,_no_mailbox_here_by_that_name._(#5.1.1)
如果编译maildrop的时候设置了vpopmail作为uid来跑,即
./configure –enable-maildrop-uid=vpopmail \
–enable-maildrop-gid=vchkpw –enable-maildirquota –without-db \
–with-trashquota
必须给vpopmail一个shell,默认好像是/sbin/nologin,修改/etc/passwd,改为/bin/bash即可

标签: , , , ,

遵守创作共用协议,转载请链接形式注明来自http://bianbian.org 做人要厚道

相关日志

Posted in Linux, Technology | No Comments »

[原] 解决 libXp.so.6 找不到的问题

Posted by bianbian on 2008-01-04 03:53


本文Tags: , , ,

error while loading shared libraries: libXp.so.6: cannot open shared object file: No such file or directory.

俺英文写得超级烂了,随便看看吧。一般服务器上都不装X环境的,不过有些变态的程序却要用到X环境的组件:比如java写的Tidy,oracle的安装程序。一般遇到这种情况,偷懒的人都直接rpm或apt-get到libXp.so.6来装。不过我喜欢什么都在自己的掌握中,不喜欢装到哪都不知道的感觉(Slackware甚至不支持rpm,我太欣赏了)。其实libXp.so.6只是XFree86的一个很小的库,根本没必要装整个X。自己动手,乐趣多多的解决办法:
lynx http://ftp.xfree86.org/pub/XFree86/
1)到 http://ftp.xfree86.org/pub/XFree86/,找到最新版本点进去,现在是4.7.0。
2)如果对自己系统不熟悉,可以先下个Xinstall.sh。然后运行 sh Xinstall.sh -check
他会告诉你下哪个编译好的版本适合你的系统。我的是”Linux-ix86-glibc24″。
然后点binaries进去,不研究源码,只是拿来用,就下预编译的好了。接着点“Linux-ix86-glibc24”。
3)这有很多tar,注意:你只要下Xbin.tgz就够了(现在是6.6M)
4)tar zxf Xbin.tgz -C /usr/X11
5)vi /etc/ld.so.conf,加入/usr/X11/lib
6)ldconfig
完毕。

Usually we don’t install X-Window on a Server, unfortunatelly some programs maybe use lib of XFree86, like oracle-installer, java-Tidy, etc. Some guys may use rpm or apt-get to fetch libXp.so.6, but I don’t like that. So lets do it:
1) lynx http://ftp.xfree86.org/pub/XFree86/ , choose lastest version, (now is 4.7.0)
2) if you don’t know much about your system(glibc, arch…), you can download “Xinstall.sh”, and
run “sh Xinstall.sh -check”. It will tell which binary-version you should choose, such as “Linux-ix86-glibc24″
3) ok, click binaries -> Linux-ix86-glibc24, now URL is : http://ftp.xfree86.org/pub/XFree86/4.7.0/binaries/Linux-ix86-glibc24/
You only need download Xbin.tgz (now only 6.6M)
4) tar zxf Xbin.tgz -C /usr/X11
5) vi /etc/ld.so.conf, add “/usr/X11/lib”
6) ldconfig

标签: , , ,

遵守创作共用协议,转载请链接形式注明来自http://bianbian.org 做人要厚道

相关日志

Posted in Linux, Technology | 1 Comment »

[原] qmail打了smtpd-auth补丁后454 oops, unable to write pipe and I can’t auth

Posted by bianbian on 2008-01-03 04:22


本文Tags: ,

qmail打了smtpd-auth补丁后454 oops, unable to write pipe and I can’t auth 的解决:

我打的补丁是qmail-smtpd-auth-043_tgz.bin,google了N久也没找到好办法。幸好我备份了一个qmail-smtpd.c,对比打过补丁后的qmail-smptd.c,发现传入参数处理被改变了,不需要加域名。解决方法就是把 smtpd的run里:
/var/qmail/bin/qmail-smtpd domain.com /home/vpopmail/bin/vchkpw /bin/true 2>&1
的domain.com去掉,即:
/var/qmail/bin/qmail-smtpd /home/vpopmail/bin/vchkpw /bin/true 2>&1

网上还有盛传的一篇文章说的是用户和组设置的问题:
我估计是针对qmail-smtpd-auth-0.31的补丁版本的。
http://blog.5ilinux.com/archives/2006/04/qmailerror.html

454 oops, unable to write pipe and I can’t auth (#4.3.0)

这个错误是在你打了smtp auth的补丁之后,却发现不能正常auth,输入了正确的用户名密码还是提示不正确。可以通过下面的命令来测试。

[root@caph qmail-smtpd]# telnet localhost 25
Trying 127.0.0.1…
Connected to localhost.
Escape character is ‘^]’.
220 xxx.com ESMTP
ehlo
250-xxx.com
250-PIPELINING
250-8BITMIME
250-SIZE 104857600
250 AUTH LOGIN PLAIN CRAM-MD5 //显示这个通常表示你已经打好了补丁,不过这个是可以通过修改qmail-smtp.c文件来定制的。
auth login
334 VXNlcm5hbWU6
awefaq23rasdf
334 UGFzc3dvcmQ6
awefwaef
454 oops, unable to write pipe and I can’t auth (#4.3.0)
quit
221 xxx.com
Connection closed by foreign host.

出现了这种问题是因为smtp运行脚本没有设置正确的用户所致。将你的smtp的tcpserver命令的运行用户和组指定一下。

QMAILDUID=`id -u vpopmail`
QMAILDGID=`id -g vpopmail`

/usr/local/bin/tcpserver -v -H -R -l “$LOCAL” -x /etc/tcp.smtp.cdb -c “$MAXSMTPD”
-u “$QMAILDUID” -g “$QMAILDGID” 0 smtp /usr/local/bin/rblsmtpd -r relays.ordb.org
/var/qmail/bin/qmail-smtpd
/home/vpopmail/bin/vchkpw /bin/true /bin/cmd5checkpw /bin/true 2>&1

不需要修改~vpopmail/bin/vchkpw的属性。

qmail的作者真牛,觉得自己写得很好了,再也不更新。导致现在patch漫天飞啊,苦了俺们了。。。
http://www.shupp.org/toaster/?page=toc

标签: ,

遵守创作共用协议,转载请链接形式注明来自http://bianbian.org 做人要厚道

相关日志

Posted in Linux, Technology | 1 Comment »