作者lzch.bbs@lzch.twbbs.org (喔耶) 看板: plan
標題[功能] dict.c Yahoo! 線上字典
時間1417 (2006/03/13 Mon 13:03:08) Updated: 2006/03/13
: src/game/Makefile
SO = ...... tetris.so dict.so
.o.so: ; ...... .so -L../lib -ldao -L/usr/local/lib -liconv
freebsd:
@$(MAKE) CC=gcc ...... -I../include -I/usr/local/include" $(SO)
: src/game/dict.c 新增此程式
/*-------------------------------------------------------*/
/* dict.c (YZU WindTopBBS Ver 3.02 ) */
/*-------------------------------------------------------*/
/* target : Yahoo 線上字典 */
/* create : 01/07/09 */
/* update : / / */
/* author : statue.bbs@bbs.yzu.edu.tw */
/* change : hialan.bbs@venice.twbbs.org */
/* change : lzch.bbs@snow.ice.ntnu.edu.tw 20060313 */
/*-------------------------------------------------------*/
#if 0
普通
http://tw.dictionary.yahoo.com/search?p=hello
#endif
#include "bbs.h"
#include "iconv.h"
#ifdef HAVE_NETTOOL
#define mouts(y,x,s) { move(y,x); outs(s); }
#define HTTP_PORT 80
#define SERVER_yahoo "tw.dictionary.yahoo.com"
#define CGI_yahoo "/search?p="
#define REF "http://tw.dictionary.yahoo.com/"
static int
encode_from_utf8_to_big5_and_more_out(server, s)
char *server;
char *s;
{
FILE *fin, *fout;
char *encFrom = "UTF-8", *encTo = "BIG-5";
char fname_utf[64], fname_big[64];
char bufin[1024], bufout[1024], *sin, *sout;
int lenin, lenout, i;
iconv_t c_pt;
sprintf(fname_utf, "tmp/%s.yahoo_dict", cuser.userid);
sprintf(fname_big, "tmp/%s.yahoo_dict.for_more", cuser.userid);
if ((fin = fopen(fname_utf, "rt")) == NULL) {
return -1;
}
if ((fout = fopen(fname_big, "wt")) == NULL) {
return -1;
}
if ((c_pt = iconv_open(encTo, encFrom)) == (iconv_t)-1) {
return -1;
}
while( fgets( bufin, 1024, fin ) != NULL ){
lenin = strlen(bufin);
lenout = 1024;
sin = bufin;
sout = bufout;
iconv( c_pt, &sin, &lenin, &sout, &lenout );
for( sin++, lenin--; lenin > 0; sin++, lenin--){
iconv( c_pt, &sin, &lenin, &sout, &lenout );
}
bufout[1024-lenout] = '\0';
/* skip DJ: []*/
if( !strncmp( bufout, " DJ: []", 7 )){
continue;
}
/* skip KK: []*/
if( !strncmp( bufout, " KK: []", 7 ) ){
continue;
}
/* 遇到標題 */
if( !strncmp( bufout, "lzch_h200000000", 15 ) ){
/* 把後面的字忽略掉 (在一大堆空白後面) */
for( i = 0; strncmp( &bufout[i], " ", 3 ) != 0 && i < 1024; i++ )
;
bufout[i] = '\n';
bufout[i+1] = '\0';
fprintf( fout, "\n%s", bufout+15 ); /* 給標題一個 enter */
/* 單字與解釋的分隔線 */
for( i = 0; i < 39; i++ ){
fprintf( fout, "─" );
}
fprintf( fout, "\n" );
continue;
}
/* 遇到譯詞 */
if( !strncmp( bufout, "lzch_explain000", 15 ) ){
fprintf( fout, "※ %s", bufout+15 );
continue;
}
/* 遇到詞性 */
if( !strncmp( bufout, "lzch_pcixin0000", 15 ) ){
bufout[strlen(bufout) - 1] = '\0';
fprintf( fout, "> > %s < <\n", bufout+15 );
continue;
}
/* 普通的輸出 */
fprintf( fout, "%s", bufout );
}
fprintf(fout, "\n\n--\nYahoo!奇摩字典\nhttp://%s%s\n\n", server, s + 4);
fclose(fout);
more(fname_big, NULL);
unlink(fname_big);
iconv_close(c_pt);
fclose(fin);
fclose(fout);
return 0;
}
static void
url_encode(dst, src) /* URL encoding */
uschar *dst; /* Thor.990331: 要 src 的三倍空間 */
uschar *src;
{
for (; *src; src++)
{
if (*src == ' ')
*dst++ = '+';
else if (is_alnum(*src))
*dst++ = *src;
else
{
register cc = *src;
*dst++ = '%';
*dst++ = radix32[cc >> 4];
*dst++ = radix32[cc & 0xf];
}
}
*dst = '\0';
}
static void
write_file(sockfd, fp)
int sockfd;
FILE *fp;
{
static char pool[2048];
int cc, i;
char *xhead, *xtail;
int show, start_show;
int space; /* 在 html 中,連續的 space 只會算一次 */
char *start_str[] =
{
"<blockquote>",
NULL
};
char *stop_str[] =
{
"<div id=\"morevoc\">",
"<div id=\"emlist\">",
"</blockquote>",
"document.write(\"",
NULL
};
char *newline_str[] = /* 取代換行字元的符號 */
{
"<br>",
"</td>",
"<h2>", /* 查尋的單字 lzch_h200000000 */
"<div class=chinese>", /* 中文發音 */
"<div class=peng>", /* 英文例句 lzch_peng000000 */
"<div class=pchi>", /* 英文例句的翻譯 lzch_pchi000000 */
"<div class=pexplain>", /* (英)中譯 (中)英譯 lzch_explain000 */
"<div class=ptitle>", /* 中文字典裡的英文相關單字,英文字典裡的音標 */
"<div class=pcixin>", /* 詞性 lzch_pcixin0000 */
NULL
};
/* parser return message from web server */
xhead = pool;
xtail = pool;
show = 1;
start_show=0;
space = 0;
for (;;xhead++)
{
if (xhead >= xtail)
{
xhead = pool;
cc = read(sockfd, xhead, sizeof(pool));
/* lzch test */
/* for( i = 0; i < 2048; i++ ){ fputc( pool[i], lzch ); } */
if (cc <= 0)
break;
xtail = xhead + cc;
}
if (!start_show)
{
for (i = 0; start_str[i] != NULL; i++)
{
if (!str_ncmp(xhead, start_str[i], strlen(start_str[i])))
{
start_show = 1;
xhead += strlen(start_str[i]);
break;
}
}
}
else if (start_show)
{
for (i = 0; stop_str[i] != NULL; i++)
{
if (!str_ncmp(xhead, stop_str[i], strlen(stop_str[i])))
{
start_show = 0;
xhead += strlen(stop_str[i]);
break;
}
}
}
if (!start_show)
continue;
for (i = 0; newline_str[i] != NULL; i++)
{
if (!str_ncmp(xhead, newline_str[i], strlen(newline_str[i])))
{
fputc('\n', fp);
if( !strncmp( xhead, "<h2>", 4 ) ){
fprintf( fp, "lzch_h200000000" ); /* 標記此為標題 */
}
else if( !strncmp( xhead, "<div class=pcixin>", 18 ) ){
fprintf( fp, "lzch_pcixin0000" ); /* 標記此為詞性 */
}
else if( !strncmp( xhead, "<div class=pexplain>", 20 ) ){
fprintf( fp, "lzch_explain000" ); /* 標記此為譯詞 */
}
else if( !strncmp( xhead, "<br>\n<li>", 9 ) ){
fprintf( fp, "lzch_explain000" ); /* 標記此為譯詞 */
}
else if( !strncmp( xhead, "<div class=peng>", 16 ) ){
}
else if( !strncmp( xhead, "<div class=pchi>", 16 ) ){
}
else if( !strncmp( xhead, "<div class=ptitle>", 18 ) ){
}
xhead += strlen(newline_str[i]);
space = 0;
break;
}
}
/* 標籤略過 */
cc = *xhead;
switch(cc)
{
case '<':
show = 0;
continue;
case '>':
show = 1;
continue;
case '\n':
case '\r':
continue;
case ' ':
if (space)
continue;
space = 1;
}
if (show)
fputc(cc, fp);
if (cc != ' ')
space = 0;
}
fputc('\n', fp);
}
static int
http_conn(server, s)
char *server;
char *s;
{
int sockfd;
FILE *fp;
char fname[64], *str;
if ((sockfd = dns_open(server, HTTP_PORT)) < 0)
{
vmsg("無法與伺服器取得連結,查詢失敗");
return 0;
}
else
{
mouts(22, 0, "正在連接伺服器,請稍後(按任意鍵離開).............");
refresh();
}
write(sockfd, s, strlen(s));
shutdown(sockfd, 1);
sprintf(fname, "tmp/%s.yahoo_dict", cuser.userid);
fp = fopen(fname, "w");
str = strchr(s + 4, ' ');
if (str)
*str = '\0';
write_file(sockfd, fp);
fclose(fp);
close(sockfd);
if( encode_from_utf8_to_big5_and_more_out( server, s ) == -1 ){
more(fname, NULL);
}
/* more(fname, NULL);*/
unlink(fname);
return 0;
}
static void
yahoo_dict(word)
char *word;
{
char atrn[256], sendform[512];
char ue_word[90];
url_encode(ue_word, word);
sprintf(atrn, "%s", ue_word);
sprintf(sendform, "GET %s%s HTTP/1.0\n\n", CGI_yahoo, atrn);
http_conn(SERVER_yahoo, sendform);
}
int
main_dreye()
{
char word[30];
while (1)
{
clear();
move(0, 23);
outs("\033[1;37;44m◎ Yahoo! 線上字典 v0.1 ◎\033[m");
move(3, 0);
outs("此字典來源為 Yahoo! 線上字典。\n");
prints("WWW: %s\n", REF);
outs("author: statue.bbs@bbs.yzu.edu.tw\n");
if (!vget(8, 0, "查詢字彙:", word, 30, DOECHO))
break;
yahoo_dict(word);
}
return 0;
}
#endif /* HAVE_NETTOOL */
==
我的 OS 是 freebsd 6.0 release
linux 改 Makefile 的方法可能不太一樣...
code 寫的不是很好,總之方法是用 iconv() 把 yahoo 字典的編碼轉成 big5
有興趣的再自己改吧 :)
還是有 bug 的.. 只是我不太知道是為什麼?? (不會改啦...)
http://xcin.linux.org.tw/i18n/pc2000/p4/node2.html
http://netlab.cse.yzu.edu.tw/~statue/freebsd/zh-tut/converter.html#ICONV
http://opensvn.csie.org/pttbbs/tags/stable.rc/docs/FAQ
--
□ Origin: lzch.twbbs.org □ From: 140.122.37.121