回精華區
作者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
精華選讀←離開[主題上]主題下(k)上篇(j)下篇S/a搜尋 G串列 TAB精華 ↑↓捲 Pg/Space翻