BBS水木清华站∶精华区

发信人: wxb1 (ben), 信区: Linux        
标  题: [5/8] 呼叫BBC暨主动传真服务 
发信站: BBS 水木清华站 (Fri Jun 11 14:22:51 1999) 
 
以Linux实作 语音/传真/EMAIL/BBC 整合系统 
5.呼叫BBC暨主动传真服务 
 
呼叫BBC 
 
        目前许多ISP都有提供邮件来时,以BBC的方式通知客户的贴心服务(需 
您BBC的厂商和该ISP有合作关系),此处呼叫BBC,事实上并非拨您BBC的号码, 
而是透过BBC厂商提供的网际网路传呼功能,进行呼叫动作,因此目前可传呼的对 
象为中华电信、大众传呼等的客户,至於中华国际传呼虽也提供网上传呼,但我 
并无密码,因此也呼叫无门!目前此系统可呼叫的号码及讯息如下: 
 
BBC 开头   有语音讯息           有传真          有Email to FAX 
0950    [您的代号] VOICE        [您的代号] FAX  [您的代号] EFAX 
0942    [您的代号] VOICE        [您的代号] FAX  [您的代号] EFAX 
0948    [您的代号] VOICE        [您的代号] FAX  [您的代号] EFAX 
095*(数字型不含0950) 
        [您的代号] 55555        [您的代号] 333  [您的代号] 1333 
060     [您的代号] 55555        [您的代号] 333  [您的代号] 1333 
070     [您的代号] 55555        [您的代号] 333  [您的代号] 1333 
 
注:中华电信需有HINET拨接密码,才可传呼,且可送简讯至大哥大手机,其BBC 
呼叫每次一元,大哥大为2.5元! 
 
呼叫BBC的bash script副程式如下: 
 
CallBBC() 

        # 抓取BBC号码 
        read userReg < ${MAINPATH}conf/$1.reg 
        bbc=`$ECHO $userReg | cut -d"," -f8,8 -s` 
        if [ $bbc ]; then 
                # 写入记录档 
                logstr=`$DATE "+%D %T,User:$1,$bbc"` 
                $ECHO $logstr >> $BBCLOGFILE 
                # 执行BBC呼叫(bbc.pl  PERL语言) 
                ${MAINPATH}bin/bbc.pl "$bbc" "$1+$2" 
        fi 

 
在前几篇中未填入的 ----------------- Call BBC-------------------- 段落 
加入以下的呼叫: 
 
CallBBC $UserID "VOICE"   // 语音段落 
 
CallBBC $UserID "FAX"     // 传真段落 
 
CallBBC副程式中的bbc.pl 主要的工作是根据BBC号码分辨其是哪一家的BBC,是 
文字形或数字形的BBC,再决定如何呼叫! 
 
#!/usr/bin/perl 
# bbc.pl 
 
$PATH="/user/home/message/bin/"; 
#================================================ 
$number=$ARGV[0]; 
$message=$ARGV[1]; 
$ok=0; 
if ($number=~/^0948(.+)/) { 
        # 大众 0948 
        system("${PATH}fitelbbc.pl $number $message"); 
}elsif ($number=~/^0950(.+)/) { 
        # Hiair 中英文 
        system("${PATH}hinetbbc.pl $number $message"); 
}elsif ($number=~/^0942(.+)/) { 
        # Hiair 中英文 
        system("${PATH}hinetbbc.pl $number $message"); 
}elsif ($number=~/^095(.+)/) { 
        $ok=1; 
}elsif ($number=~/^060(.+)/) { 
        $ok=1; 
}elsif ($number=~/^070(.+)/) { 
        $ok=1; 

 
# ok=1 为数字形BBC,将讯息转为数字 
if ($ok==1) { 
        $message =~ s/VOICE/55555/g; 
        $message =~ s/EFAX/1333/g; 
        $message =~ s/FAX/333/g; 
        # Hiair 数字 
        system("${PATH}hinetbbc.pl $number $message"); 

 
fitelbbc.pl 与 hinetbbc.pl 都是先把要送过去的资料处理编排好後,再模拟浏 
览器,利用HTTP POST Method的方式,将资料送出,若您不了解HTTP协定,可参 
考相关资料,或是在Linux上架起 sniffit 软体,实际捕捉传送的DATA,再依样 
画葫芦即可。以下为fitelbbc.pl原始码,hinetbbc.pl就省略了! 
 
#!/usr/bin/perl 
# fitelbbc.pl 
$FILE="/tmp/fitelbbc.txt"; 
#================================================ 
$number=$ARGV[0]; 
$message=$ARGV[1]; 
($sec, $min, $hour, $day, $mon, $year) = localtime(time); 
$mon=$mon+1; 
$year=$year-11; 
if ($number=~/^0948(.+)/) { 
        # 大众网上传呼时 "0948"不需敲入 
        $number=$1; 

# $query_str 是主要传过去的部分 
$query_str="svc_no=$number&pwd_in=%ABP%BEP%B4%C1%B6%A1%A1A%A4%F0%BB%DD%BF%E9%A4J 
&i 
sp_code=1&s 
ender_name=+&reminder_option=OFF&year=$year&month=$mon&day=$day&hour=00&min=00&m 
essage=$messag 
e"; 
$query_len=length($query_str); 
#print "$query_len,$query_str\n"; 
 
# 大众网站 
$them='www.fitel.net.tw'; 
$port=80; 
$AF_INET=2; 
$SOCK_STREAM=1; 
$sockaddr='S n a4 x8'; 
($name,$aliases,$proto)=getprotobyname('tcp'); 
($name,$aliases,$port,$proto)=getservbyname($port,'tcp') unless $port=~/^\d+$/; 
($name,$aliases,$type,$len,$thataddr)=gethostbyname($them); 
$that=pack($sockaddr,$AF_INET,$port,$thataddr); 
if (socket(SOCK,$AF_INET,$SOCK_STREAM,$proto)) { 
#  print "socket OK!\n"; 

else {die $!;} 
if (connect(SOCK,$that)) { 
#  print "connect OK!\n"; 

else {dis $!;} 
select(SOCK); $|=1; select(STDOUT); 
 
print SOCK <<SEND_END; 
POST /cgi-bin/internetpage.exe HTTP/1.0 
Referer: http://www.fitel.net.tw/html/svc03.htm 
Connection: Keep-Alive 
User-Agent: Mozilla/4.03 [en] (WinNT; I) 
Host: www.fitel.net.tw 
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */* 
Accept-Language: en 
Accept-Charset: iso-8859-1,*,utf-8 
Content-type: application/x-www-form-urlencoded 
Content-length: $query_len 
 
$query_str 
SEND_END 
 
# 接收POST之後回传的DATA(并未利用) 
open (MYFILE,"> $FILE") || die "Can't open file:$!\n"; 
do { 
        $recv=<SOCK>; 
#       print "$recv"; 
        print MYFILE "$recv"; 
} while( length($recv)>0); 
close(SOCK); 
close (MYFILE); 
 
传真额外服务 
 
        此系统所谓的传真额外服务,操作方式为:当输入[代号],听完"留言请 
按「1」,送传真请按「2」……"後,尚可按「5」,仍後会听到"请输入服务代码 
",目前可输入以下代码收取传真: 
10:统一发票号码 、 11:今日天气 、 12:明日天气 、 13:一周天气 、 14:卫星 
云图 
 
        其作法也是在网际网路上,定时抓取以上的相关资料(仍是用HTTP), 
转换成传真格式,等待客户拨接进来後传送出去。 
        统一发票在网路上许多地方都有提供,比较讨厌的是其格式皆为HTML, 
需加以转换後(去除其中TAG),变为纯文字後,再转为传真格式;其余几项皆为 
中央气象局的资料,其本身就有纯文字的档案,故不需再做处理;卫星云图是GIF 
的格式,仍须用到前篇所述的PBMPLUS工具软体做转换: 
GIF -(giftoppm)a PPM -(ppmtopgm)a PGM -(pgmtopbm)a PBM -(efix)aTIFFG3 
 
giftoppm $GIFFILE | ppmtopgm | pgmtopbm | efix -i pbm -o tiffg3 -d 0.5,0.5 -s 2, 
1 -p 4,6 -n $FAXOUT4 
 
以下为统一发票的抓取范例,天气部分因为颇为类似就省略了! 
 
#!/usr/bin/perl 
$FILE1='/tmp/ultra1.htm'; 
$FILE2='/tmp/ultra1.txt'; 
$FAXOUT='/user/home/message/fax/ultra/ultra1.%03d'; 
 
$GetStr = "GET /hinet_v3/invoice.htm HTTP/1.0\nPragma: no-cache\n"; 
 
$them='www.hinet.net'; 
$port=80; 
$AF_INET=2; 
$SOCK_STREAM=1; 
$sockaddr='S n a4 x8'; 
($name,$aliases,$proto)=getprotobyname('tcp'); 
($name,$aliases,$port,$proto)=getservbyname($port,'tcp') unless 
$port=~/^\d+$/; 
($name,$aliases,$type,$len,$thataddr)=gethostbyname($them); 
$that=pack($sockaddr,$AF_INET,$port,$thataddr); 
 
if (socket(SOCK,$AF_INET,$SOCK_STREAM,$proto)) { 
#  print "socket OK!\n"; 

else {die $!;} 
if (connect(SOCK,$that)) { 
#  print "connect OK!\n"; 

else {dis $!;} 
 
select(SOCK); $|=1; select(STDOUT); 
print SOCK $GetStr; 
print SOCK "Accept: */*\n\n"; 
open (MYFILE,"> $FILE1") || die "Can't open $FILE:$!\n"; 
do { 
        $recv=<SOCK>; 
        $recv =~ s/\r//g; 
#       print "$recv"; 
        print MYFILE "$recv"; 
} while( length($recv)>0); 
close(SOCK); 
close (MYFILE); 
 
open (NEWS,"< $FILE1") || die "can't open input $FILE1:$!\n"; 
open (OUT,"> $FILE2") || die "can't open out $FILE2:$!\n"; 
 
$cont_do=0; 
while($line=<NEWS>) { 
        if ($cont_do!=0) { 
           last if $line=~/<\/table>/ ; 
           if ($line =~ /<\/tr>/) { 
                print OUT "-----------------------------------------"; 
           }else { 
                $line =~ s/<br>//; 
                $line =~ s/<tr>//; 
                $line =~ s/<\/td>//; 
                $line =~ s/<\/a>//; 
                $line =~ s/<\/font>//; 
                $line =~ s/<font(.*)>//; 
                $line =~ s/<a (.+)>//; 
                $line =~ s/<td(.*)>//; 
                $line =~ s/        //; 
                $pos = (40-length($line))/2; 
                $space=''; 
                for ($n=0;$n<$pos;$n++) { 
                        $space .= ' '; 
                } 
                #  "功"字冲码,再加一"|" 
                if ($line =~ /^(特|头|二|三|功||五|六)$/) { 
                        print OUT "                $1"; 
                }elsif ($line =~ /^奖$/) { 
                        print OUT "    $line"; 
                }else{ 
                        print OUT "$space$line"; 
                } 
           } 
        }elsif ($line=~/<table/) { 
                $cont_do = 1; 
        } 

print OUT "\n*本号码单若有编排错误,请以财政部记录为准*\n"; 
close(NEW); 
close(OUT); 
system("/usr/bin/efix -i text -o tiffg3 -n$FAXOUT < $FILE2"); 
system("/bin/rm -f $FILE1"); 
system("/bin/rm -f $FILE2"); 
exit(0); 
 
不论网上传呼,或传真额外服务,都是利用网路上的现成资源,虽然颇为便利, 
但请注意是否侵权,另外因来源受制於他人,所以若其格式变动,几乎您也需跟 
著修改才行! 
 
主动传真服务 
 
        主动传真的第一步,就是当有传真或EMAIL转传真进来时,将传真格式的 
档名做一份复制到特定的目录,其程式码如下: 
                        # 加入answer (bash script) Write to Callout段落中 
# 抓取传真号码 
                        FAXphone=`$ECHO $userReg | cut -d"," -f7,7 -s` 
                        # 看看是否有设定要主动传真 
doFAX=`$ECHO $userReg | cut -d"," -f12,12 -s` 
                        if [ $FAXphone ]; then 
                           if [ "$doFAX" = "1" ]; then 
                                # Append 传真档名至特定目录下的UserID档名中 
                                $ECHO -n "$faxfiles " >> "${CALLOUT_PATH}${UserI 
D}" 
                                # 改变此档属性,以便过期或传完後可将其删除 
                                chmod go+w "${CALLOUT_PATH}${UserID}" 
                           fi 
                        fi 
 
 
先前提过的mail2fax程式,也需将这部分加入 
 
# 加入 mail2fax(Perl语言) 段落中 
# ------------------------ Write to Callout-------------------------- 
 
if ( $FAXphone ne '' ) 

        if ( $doFAX eq '1' ) { 
                open(FF,"/usr/bin/find $FaxFile.* -printf \"%p \" | "); 
                $fileout = <FF>; 
                close(FF); 
                open(W,">> " . "${CALLOUT_PATH}$id"); 
                print W "$fileout" ; 
                close(W); 
                chmod(0666,"${CALLOUT_PATH}$id"); 
 
        } 

 
一台PC有两个COM PORT,您可再接一电话线及传真数据机做主动传真服务,但因 
我仅有一条电话线,所以作法为利用空闲时间,侦测有无主动传真要送! 
也就是一段时间无人拨接进来,则去察看一下,有无传真要送出! 
 
# Slect voice mode. 
$VMCP -c"$AT_VOICE" -wOK 
 
# 此处原来的参数为 -t0,表示一直等待,现改为 -t180,等三分钟 
$VMCP -t180 -c"$AT_WAITRING" -wRING 
 
#--------------------------------FAX Callout------------------------------ 
if [ $? -eq 100 ]; then 
        # $? -eq 100 表示上式VMCP 三分钟Timeout 
        FaxCallOut 
fi 
#--------------------------------------------------------------------------- 
 
FaxCallOut 副程式如下: 
 
FaxCallOut() 

        faxout=`$FIND ${CALLOUT_PATH}* -printf "%f "` 
        if [ `$ECHO -n $faxout | $WC -w` -gt "0" ];  then 
                for FILE in $faxout 
                do 
                        read faxfiles < ${CALLOUT_PATH}$FILE 
                        if [ `$ECHO -n $faxfiles | $WC -w` -gt "0" ]; then 
                           read userReg < ${MAINPATH}conf/$FILE.reg 
                           faxphone=`echo $userReg | cut -d"," -f7,7 -s` 
                           if [ $faxphone ]; then 
                              $VMCP -c"$AT_FAX" -wOK 
                              /usr/bin/efax -d /dev/$TTYS -t"$faxphone" $faxfile 

                              if [ $? -eq 0 ]; then 
                                  $RM -f ${CALLOUT_PATH}$FILE 
                              fi 
                           fi 
                        fi 
                done 
        fi 
        # 执行结束再把控制权转移至原程式 
        exec ${MAINPATH}bin/answer 

 
若您PC上接了数台数据机,请小心不要同时做Callout(可利用LOCK FILE的方式 
),否则可能同时拨一样的电话,不然就需将FaxCallOut副程式修改一下,避免 
此情形发生! 
 
结尾 
 
        本篇讨论如何呼叫BBC、传真额外服务、及主动传真服务,透过这些功能 
,可使讯息的流传更为便利,也愈容易掌握所需的资讯。接下来的一篇将讨论如 
何进行群组传送,以及建立基地台,分区转送的功能。 
 
撰文:朱先宇   1998/12/17 
EMAIL: hybj@ms1.hinet.net 
 
-- 
just a test 
 
※ 来源:·BBS 水木清华站 bbs.net.tsinghua.edu.cn·[FROM: 202.116.130.100] 

BBS水木清华站∶精华区