回精華區
作者itoc, 信區: itoc
標題[修正] newbrd.c 免連署的看板申請
時間04/04/05
作者: itoc (League) 看板: plan
標題: [修正] 免連署的看板申請
時間: 2004/03/16 Tue 23:56:53                           Updated: 2005/05/19

※ 引述《yenning.bbs@bbs.seehere.org (yenning)》之銘言:
> 是不是能用成像itoc.twbbs.org的看板連署一樣?

  1. 拔掉 newbrd.c 的所有連署功能,^P 只剩下申請看板
  2. 免連署的看板申請
  3. 尚未開板的顯示 '+',已開板完畢顯示 ' '
     若是 VIP 的申請,在尚未開板前會顯示 '*'
  4. 申請看板時即填入所有資訊,站長按 o 就直接開板完成
  5. 如果做了精華區的 patch,那麼還直接加入 Class
  6. help 沒有改,想寫的人再自己寫 :p

: theme.h

  NECKER_COSIGN、FOOTER_COSIGN、FEETER_COSIGN
  這三個自己改一下,不改也沒差

  指令就只剩下 (r)讀取 (^P)申請 (d)刪除 (o)開板 (E)編輯 (^Q/^O)查詢

: struct.h  HAVE_COSIGN 這一段改成這樣

#ifdef HAVE_COSIGN

/* ----------------------------------------------------- */
/* newbrd.c 中運用的資料結構                             */
/* ----------------------------------------------------- */

typedef struct NewBoardHeader
{
  char brdname[BNLEN + 1];
  char class[BCLEN + 1];
  char title[BTLEN + 1];
  time_t btime;
  time_t etime;
  char xname[32];
  char owner[IDLEN + 1];
  char date[9];
  usint mode;
  int readlevel;
}       NBRD;


#define NBRD_FINISH     0x01    /* 已結案 */
#define NBRD_VIPAPPLY   0x02    /* VIP 的申請 */

#endif  /* HAVE_COSIGN */

: newbrd.c 換成以下
: ----------------------------------------------------
  注意 is_vip_apply() 的部分要自己改寫,當然你也可以直接 return 0,就沒有 VIP
       nbrd_add() 裡面的分類依各站自定
  ----------------------------------------------------
  如果還希望自動加入 Class 分類,那麼參考精華區這篇
  [功能] newbrd.c 連署開板後自動加入 Class
: ----------------------------------------------------

/*-------------------------------------------------------*/
/* newbrd.c   ( YZU_CSE WindTop BBS )                    */
/*-------------------------------------------------------*/
/* target : 連署功能                                     */
/* create : 00/01/02                                     */
/* update : 02/04/29                                     */
/*-------------------------------------------------------*/
/* run/newbrd/_/.DIR - newbrd control header             */
/* run/newbrd/_/@/@_ - newbrd description file           */
/*-------------------------------------------------------*/


#include "bbs.h"


#ifdef HAVE_COSIGN

extern XZ xz[];
extern char xo_pool[];
extern BCACHE *bshm;                /* itoc.010805: 開新板用 */

static int nbrd_add();
static int nbrd_body();
static int nbrd_head();


static int
cmpbtime(nbrd)
  NBRD *nbrd;
{
  return nbrd->btime == currchrono;
}


static int
nbrd_stamp(folder, nbrd, fpath)
  char *folder;
  NBRD *nbrd;
  char *fpath;
{
  char *fname;
  char *family = NULL;
  int rc;
  int token;

  fname = fpath;
  while (rc = *folder++)
  {
    *fname++ = rc;
    if (rc == '/')
      family = fname;
  }

  fname = family;
  *family++ = '@';

  token = time(0);

  archiv32(token, family);

  rc = open(fpath, O_WRONLY | O_CREAT | O_EXCL, 0600);
  nbrd->btime = token;
  str_stamp(nbrd->date, &nbrd->btime);
  strcpy(nbrd->xname, fname);
  return rc;
}


static void
nbrd_fpath(fpath, folder, nbrd)
  char *fpath;
  char *folder;
  NBRD *nbrd;
{
  char *str = NULL;
  int cc;

  while (cc = *folder++)
  {
    *fpath++ = cc;
    if (cc == '/')
      str = fpath;
  }
  strcpy(str, nbrd->xname);
}


static int
nbrd_init(xo)
  XO *xo;
{
  xo_load(xo, sizeof(NBRD));
  return nbrd_head(xo);
}


static int
nbrd_load(xo)
  XO *xo;
{
  xo_load(xo, sizeof(NBRD));
  return nbrd_body(xo);
}


static char
nbrd_attr(nbrd)
  NBRD *nbrd;
{
  /*         已開板完成用 ' '
     未開板的一般人申請用 '+'
     未開板的VIP申請用 '+' (一般使用者看到)
     未開板的VIP申請用 '*' (只有站長可見)
   */
  usint mode;

  mode = nbrd->mode;
  return mode & NBRD_FINISH ? ' ' :
    (HAS_PERM(PERM_ALLBOARD) && (mode & NBRD_VIPAPPLY) ? '*' : '+');
}


static void
nbrd_item(num, nbrd)
  int num;
  NBRD *nbrd;
{
  prints("%6d %c %-5s %-13s %-13s[%s] %.*s\n",
    num, nbrd_attr(nbrd), nbrd->date + 3, nbrd->owner,
    nbrd->brdname, nbrd->class, d_cols + 29, nbrd->title);
}


static int
nbrd_body(xo)
  XO *xo;
{
  NBRD *nbrd;
  int num, max, tail;

  max = xo->max;
  if (max <= 0)
  {
    if (vans("要新增連署項目嗎(Y/N)?[N] ") == 'y')
      return nbrd_add(xo);
    return XO_QUIT;
  }

  nbrd = (NBRD *) xo_pool;
  num = xo->top;
  tail = num + XO_TALL;

  if (max > tail)
    max = tail;

  move(3, 0);
  do
  {
    nbrd_item(++num, nbrd++);
  } while (num < max);
  clrtobot();

  /* return XO_NONE; */
  return XO_FOOT;        /* itoc.010403: 把 b_lines 填上 feeter */
}


static int
nbrd_head(xo)
  XO *xo;
{
  vs_head("申請看板", str_site);
  outs(NECKER_COSIGN);
  return nbrd_body(xo);
}


static int
is_vip_apply()                /* 是不是 VIP 的申請 */
{
  char *str, email[80];

  // 以下這一段要由各站自定 
  if (HAS_PERM(PERM_VALID))
  {
    str_lower(email, cuser.email);

    /* 檢查 .ee##(g)@nctu.edu.tw */
    if (str = (char *) strchr(email, '.'))
    {
      if (*(str + 1) == 'e' && *(str + 2) == 'e' &&
        (!strcmp(str + 5, "@nctu.edu.tw") || !strcmp(str + 5, "g@nctu.edu.tw")))
      {
        return 1;
      }
    }

    /* 檢查 u##11###@cc.nctu.edu.tw */
    if (strlen(email) == 23)
    {
      if (email[0] == 'u' && email[3] == '1' && email[4] == '1' &&
        !strcmp(email + 8, "@cc.nctu.edu.tw"))
      {
        return 1;
      }
    }
  }
  // 以上這一段要由各站自定

  return 0;
}


static int
nbrd_add(xo)
  XO *xo;
{
  int fd, readlevel;
  char *dir, fpath[80], path[80], *plevel;
  char *brdname, *title;
  FILE *fp;
  NBRD nbrd;

  if (!cuser.userlevel)
    return XO_NONE;

  memset(&nbrd, 0, sizeof(NBRD));

  brdname = nbrd.brdname;
  title = nbrd.title;

  if (!vget(b_lines, 0, "英文板名:", brdname, BNLEN + 1, DOECHO))
    return XO_FOOT;

  if (brd_bno(brdname) >= 0)
  {
    vmsg("已有此板");
    return XO_FOOT;
  }

  if (!valid_brdname(brdname))        /* itoc.020726: 檢查板名是否合法 */
  {
    vmsg("板名不合法");
    return XO_FOOT;
  }

  // 以下這一段要由各站自定 
  switch (vans("看板分類:1)個人 2)寢板 3)班板 4)黨羽 5)營隊 6)其他 [Q] "))
  {
  case '1':
    plevel = "個人";
    break;
  case '2':
    plevel = "寢板";
    break;
  case '3':
    plevel = "班板";
    break;
  case '4':
    plevel = "黨羽";
    break;
  case '5':
    plevel = "營隊";
    break;
  case '6':
    plevel = "??";    /* 讓站長自己手動改 */
    vmsg("請於補充事項中註明您要的看板分類");
    break;
  default:
    return XO_FOOT;
  }
  // 以上這一段要由各站自定 

  strcpy(nbrd.class, plevel);

  readlevel = vans("看板屬性:1)公開 2)秘密 3)好友 [Q] ") - '0';
  switch (readlevel)
  {
  case 1:
    plevel = "公開";
    break;
  case 2:
    plevel = "秘密";
    break;
  case 3:
    plevel = "好友";
    break;
  default:
    return XO_FOOT;
  }

  if (!vget(b_lines, 0, "看板主題:", title, BTLEN + 1, DOECHO))
    return XO_FOOT;

  dir = xo->dir;
  if ((fd = nbrd_stamp(dir, &nbrd, fpath)) < 0)
    return nbrd_head(xo);
  close(fd);

  vmsg("還有要補充什麼嗎?[例如轉信、諂媚站長的話...:p]");
  sprintf(path, "tmp/%s.nbrd", cuser.userid);        /* 連署原因的暫存檔案 */
  fd = vedit(path, 0);
  if (fd)
  {
    unlink(fpath);
    vmsg(msg_cancel);
    return nbrd_head(xo);
  }

  strcpy(nbrd.owner, cuser.userid);
  nbrd.readlevel = readlevel;
  nbrd.mode = is_vip_apply() ? NBRD_VIPAPPLY : 0;
  rec_add(dir, &nbrd, sizeof(NBRD));

  fp = fopen(fpath, "a+");
  fprintf(fp, "作者: %s (%s) 站內: 看板申請\n", cuser.userid, cuser.username);
  fprintf(fp, "標題: [看板申請] %s\n", brdname);
  fprintf(fp, "時間: %s\n\n", Now());
  fprintf(fp, "英文板名:%s\n", brdname);
  fprintf(fp, "看板分類:%s\n", nbrd.class);
  fprintf(fp, "看板主題:%s\n", title);
  fprintf(fp, "板主名稱:%s\n", nbrd.owner);
  fprintf(fp, "看板屬性:%s\n\n\n", plevel);
  f_suck(fp, path);
  unlink(path);
  fprintf(fp, "\n--\n□ 本文章由 %s 從 %s 申請\n", cuser.userid, fromhost);
  fclose(fp);

  vmsg("請等待站長開板");
  return nbrd_init(xo);
}


static int                        /* 1:開板成功 */
nbrd_newbrd(nbrd)                /* 開新版 */
  NBRD *nbrd;
{
  BRD newboard;
  ACCT acct;

  memset(&newboard, 0, sizeof(BRD));

  /* itoc.010805: 新看板預設 battr = 不轉信; 看板板主為提起連署者 */
  switch (nbrd->readlevel)
  {
  case 2:       /* 秘密 */
    newboard.readlevel = PERM_SYSOP;
    newboard.battr = BRD_NOTRAN | BRD_NOSTAT | BRD_NOVOTE;
    break;
  case 3:       /* 好友 */
    newboard.readlevel = PERM_BOARD;
    newboard.battr = BRD_NOTRAN | BRD_NOSTAT | BRD_NOVOTE;
    break;
  default:      /* 公開 */
    newboard.postlevel = PERM_POST;
    newboard.battr = BRD_NOTRAN;
    break;
  }
  strcpy(newboard.brdname, nbrd->brdname);
  strcpy(newboard.class, nbrd->class);
  strcpy(newboard.title, nbrd->title);
  strcpy(newboard.BM, nbrd->owner);

  if (acct_load(&acct, nbrd->owner) >= 0)
    acct_setperm(&acct, PERM_BM, 0);

  if (brd_new(&newboard) < 0)
    return 0;

  vmsg("新板成立,記著加入分類群組");
  return 1;

}


static int
nbrd_open(xo)
  XO *xo;
{
  NBRD *nbrd;

  if (!HAS_PERM(PERM_ALLBOARD))
    return XO_NONE;

  nbrd = (NBRD *) xo_pool + (xo->pos - xo->top);

  /* itoc.030519: 避免重覆開板 */
  if (brd_bno(nbrd->brdname) >= 0)
  {
    nbrd->mode = NBRD_FINISH;
    currchrono = nbrd->btime;
    rec_put(xo->dir, nbrd, sizeof(NBRD), xo->pos, cmpbtime);
    vmsg("已有此板");
    return nbrd_init(xo);
  }

  if (nbrd->mode & NBRD_FINISH)
  {
    vmsg("已完成開板");
  }
  else
  {
    if (vans("請確定開啟看板(Y/N)?[N] ") == 'y')
    {
      if (nbrd_newbrd(nbrd))
      {
        nbrd->mode = NBRD_FINISH;
        currchrono = nbrd->btime;
        rec_put(xo->dir, nbrd, sizeof(NBRD), xo->pos, cmpbtime);
      }
      return nbrd_init(xo);
    }
  }
  return XO_FOOT;
}


static int
nbrd_browse(xo)
  XO *xo;
{
  int key;
  NBRD *nbrd;
  char fpath[80];

  /* itoc.010304: 為了讓閱讀到一半也可以加入連署,考慮 more 傳回值 */
  for (;;)
  {
    nbrd = (NBRD *) xo_pool + (xo->pos - xo->top);
    nbrd_fpath(fpath, xo->dir, nbrd);

    if ((key = more(fpath, FOOTER_COSIGN)) < 0)
      break;

    if (!key)
      key = vkey();

    switch (key)
    {
    case KEY_UP:
    case KEY_PGUP:
    case '[':
    case 'k':
      key = xo->pos - 1;

      if (key < 0)
        break;

      xo->pos = key;

      if (key <= xo->top)
      {
        xo->top = (key / XO_TALL) * XO_TALL;
        nbrd_load(xo);
      }
      continue;

    case KEY_DOWN:
    case KEY_PGDN:
    case ']':
    case 'j':
    case ' ':
      key = xo->pos + 1;

      if (key >= xo->max)
        break;

      xo->pos = key;

      if (key >= xo->top + XO_TALL)
      {
        xo->top = (key / XO_TALL) * XO_TALL;
        nbrd_load(xo);
      }
      continue;

    case 'h':
      xo_help("cosign");
      break;
    }
    break;
  }

  return nbrd_head(xo);
}


static int
nbrd_delete(xo)
  XO *xo;
{
  NBRD *nbrd;
  char fpath[80];

  nbrd = (NBRD *) xo_pool + (xo->pos - xo->top);
  if (strcmp(cuser.userid, nbrd->owner) && !HAS_PERM(PERM_ALLBOARD))
    return XO_NONE;

  if (vans(MSG_DEL_NY) != 'y')
    return nbrd_head(xo);

  nbrd_fpath(fpath, xo->dir, nbrd);
  unlink(fpath);

  rec_del(xo->dir, sizeof(NBRD), xo->pos, NULL);
  return nbrd_init(xo);
}


static int
nbrd_edit(xo)
  XO *xo;
{
  if (HAS_PERM(PERM_ALLBOARD))
  {
    char fpath[64];
    NBRD *nbrd;

    nbrd = (NBRD *) xo_pool + (xo->pos - xo->top);
    nbrd_fpath(fpath, xo->dir, nbrd);
    vedit(fpath, 0);
    return nbrd_head(xo);
  }

  return XO_NONE;
}


static int
nbrd_uquery(xo)
  XO *xo;
{
  NBRD *nbrd;

  nbrd = (NBRD *) xo_pool + (xo->pos - xo->top);

  move(1, 0);
  clrtobot();
  my_query(nbrd->owner);
  return nbrd_head(xo);
}


static int
nbrd_usetup(xo)
  XO *xo;
{
  NBRD *nbrd;
  ACCT acct;

  if (!HAS_PERM(PERM_ALLACCT))
    return XO_NONE;

  nbrd = (NBRD *) xo_pool + (xo->pos - xo->top);
  if (acct_load(&acct, nbrd->owner) < 0)
    return XO_NONE;

  move(3, 0);
  acct_setup(&acct, 1);
  return nbrd_head(xo);
}


static int
nbrd_help(xo)
  XO *xo;
{
  xo_help("cosign");
  return nbrd_head(xo);
}


static KeyFunc nbrd_cb[] =
{
  XO_INIT, nbrd_init,
  XO_LOAD, nbrd_load,
  XO_HEAD, nbrd_head,
  XO_BODY, nbrd_body,

  'r', nbrd_browse,
  'd', nbrd_delete,
  'E', nbrd_edit,
  'o', nbrd_open,

  Ctrl('P'), nbrd_add,
  Ctrl('Q'), nbrd_uquery,
  Ctrl('O'), nbrd_usetup,

  'h', nbrd_help
};


int
XoNewBoard()
{
  XO *xo;
  char fpath[64];

  sprintf(fpath, "run/newbrd/%s", fn_dir);
  xz[XZ_COSIGN - XO_ZONE].xo = xo = xo_new(fpath);
  xz[XZ_COSIGN - XO_ZONE].cb = nbrd_cb;
  xo->key = XZ_COSIGN;
  xover(XZ_COSIGN);
  free(xo);

  return 0;
}
#endif        /* HAVE_COSIGN */


--
□ 本文章由 itocitoc.Dorm11.NCTU.edu.tw 發表
精華選讀←離開[主題上]主題下(k)上篇(j)下篇S/a搜尋 G串列 TAB精華 ↑↓捲 Pg/Space翻