荔园在线

荔园之美,在春之萌芽,在夏之绽放,在秋之收获,在冬之沉淀

[回到开始] [上一篇][下一篇]


发信人: hace.bbs@hace.dhs.org (半边海), 信区: InstallBBS
标  题: [转载]实现 `个人文章阅读' v0.2 [1]
发信站: 半边海BBS (Mon Apr  7 18:35:24 2003)
转信站: SZU!news.tiaozhan.com!news.bjsing.net!SCUT-x12

【 以下文字转载自 sysop 讨论区 】
【 原文由 hace 所发表 】

            实现 `个人文章阅读' v0.2 [1]

$$ 2003.04.07   hace  $  BBS 版本: firebird2000 v1106 $$

1. 实现方法

    首先在 /home/bbs 中创建目录 PersonalPost ,即 /home/bbs/PersonalPost
    然后创建目录 /home/bbs/PersonalPost/?/   ?为A到Z
    每个人的文章放到目录 /home/bbs/PersonalPost/?/userid/ 中
    如 hace 的文章将放到 /home/bbs/PersonalPost/H/hace/ 中
    每发表一篇文章需要记录时,
        就用symlink()做链接到 /home/bbs/PersonalPost/?/userid/
        如发表了 /home/bbs/boards/sysop/M.1049382934.A 后,
        将在目录 /home/bbs/PersonalPost/?/userid/ 中创建链接
            M.1049382934.A 文件,让它指向
                /home/bbs/boards/sysop/M.1049382934.A
    目录 /home/bbs/PersonalPost/?/userid 中的文件读取跟精华区一样,
        用的是 .Names 来索引.

2. 代码更改.

    a) 修改 munu.ini
        先修改 /home/bbs/etc/menu.ini ,在特别服务那增加一行:
        @Hace_post   12,29, PERM_POST,   "Hace_post", "(H) 个人文章"
             ~~~~~~ 这两个数字是定位的,没什么关系.
        然后在comm_lists.c中的 MENU sysconf_cmdlist[]
        增加一行如下,前面有++的为增加的:

        MENU sysconf_cmdlist[] = {
            {"domenu", domenu, 0},
        ++  {"Hace_post",hace_post,0},
            //....
            //....
        }
    b) 增加文件 hace_post.c ,内容如下

/* hace_post.c */

#include "bbs.h"
int hace_post(void){
        char path[512],lookid[IDLEN + 6];
        modify_user_mode(PERSONALREAD);
        refresh();
        move(1,0);
        clrtobot();
        prints("您想看谁的文章:\n<输入使用者代号, 按空白键可列出符合字串>\n");
        move(1,16);
        usercomplete(NULL,lookid);
        if(!getuser(lookid) || lookid[0]==0){
                presskeyfor("经查实,无此ID...",2);
        }else{
                sprintf(path,"%s/%c/%s",PerPostPath,toupper(lookid[0]),lookid);
                a_menu("",path,0,-2003);
        }
        clear();
        return 1;
}

    c) 修改 Makefile
        对 CFILE 增加 hace_post.c ,对 COBJS 增加 hace_post.o

    d) 修改 bbs.h
        在 bbs.h 中加上一行:
        #define PerPostPath     "/home/bbs/PersonalPost"

    e) 修改 modetype.c
        在 char *ModeType(mode) 中加上:(前有 ++ 的为新加的

        char *ModeType(mode)
            int mode;
        {
            //....
            //....
        ++  case PERSONALREAD:
        ++      return "览个人文章";
            //....
        }

    f) 修改 modes.h , 在里面加上一行:
        #define PERSONALREAD 2003

    g) 修改 bbs.c

g.0 在前面加上下列函数说明:

/* add by hace */
extern void h_del_post(char *path,char *fname);
extern char * h_split(const char *s,char *buf);
extern void h_title_change(char *path,const char *filename,
            const char *newtitle);
extern void h_post_link(char *,char *,char *,char *);
int h_delete_range(char *,int,int);
extern int h_link_board(char *board);

/* end */

g.1 修改函数 int post_article(postboard, mailid)

        int post_article(postboard, mailid)
            char *postboard, *mailid;
        {
            //....  //省掉了N行

            if (!junkboard()) {
               set_safe_record();
               currentuser.numposts++;
               substitute_record(PASSFILE, &currentuser,
                    sizeof(currentuser), usernum);
            }
        ++  /* add by hace */

        ++  if(h_link_board(postboard)==1)
        ++  h_post_link(currentuser.userid,postfile.title,filepath,fname);

        ++  /* end */
            return FULLUPDATE;
        }

g.2 修改函数 int edit_title(ent, fileinfo, direct)

        int edit_title(ent, fileinfo, direct)
            int ent;
            struct fileheader *fileinfo;
            char *direct;
        {
            //....      //省掉了N行

            /* add by hace */

            ++  if(h_link_board(currboard)==1){
            ++      sprintf(genbuf,"%s/%c/%s",PerPostPath,
            ++          toupper(fileinfo->owner[0]),fileinfo->owner);
            ++      h_title_change(genbuf,fileinfo->filename,buf);
            ++  }

            /* end */

                substitute_record(direct, fileinfo, sizeof(*fileinfo), ent);
                }
            return PARTUPDATE;
        }

g.3 修改函数 int UndeleteArticle(ent, fileinfo, direct)

        int UndeleteArticle(ent, fileinfo, direct)
            int ent;
            struct fileheader *fileinfo;
            char *direct;
        {
            //....      //省掉了N行

            clear();
            move(2, 0);
            prints("'%s' 已恢复到 %s 板 \n", UFile.title, UBoard);
            pressreturn();

        ++   /* add by hace */

        ++  if(h_link_board(UBoard)==1){
        ++      memset(buf,0,sizeof(buf));
        ++      sprintf(buf,"boards/%s/%s",UBoard,UFile.filename);
        ++      h_post_link(UFile.owner,UFile.title,buf,UFile.filename);
        ++  }

        ++  /* end */

            return FULLUPDATE;
        }

g.4 修改函数 int del_post(int ent, struct fileheader *fileinfo,
                    char *direct)

        int del_post(int ent, struct fileheader *fileinfo, char *direct)
        {
            //.....         //省掉了N行

                    }
                }

        ++  /* add by hace */

        ++  if(h_link_board(currboard)==1){
        ++      char path[512];
        ++      memset(path,0,sizeof(path));
        ++      sprintf(path,"%s/%c/%s",PerPostPath,
        ++          toupper(fileinfo->owner[0]),fileinfo->owner);
        ++      h_del_post(path,fileinfo->filename);
        ++  }

        ++  /* end */

            return DIRCHANGED;
            }else if (SR_BMDELFLAG) {
                    return -1;
            }
            move(t_lines - 1, 0);
            prints("删除失败...");
            clrtoeol();
            egetch();
            return PARTUPDATE;
        }

g.5 增加函数 h_delete_range()

/*
 * h_delete_range() 由 record.c 中的
 * delete_range 增加下面 前面标有`++'的代码而得到
 */

int h_delete_range(char *filename, int id1, int id2)
{
    struct fileheader fhdr;
    char tmpfile[STRLEN], deleted[STRLEN];
    int fdr, fdw, fd, count;
    char h_path[128];

    tmpfilename(filename, tmpfile, deleted);
    if ((fd = open(".dellock", O_RDWR | O_CREAT | O_APPEND, 0644)) == -1)
        return -1;
    flock(fd, LOCK_EX);

    if ((fdr = open(filename, O_RDONLY, 0)) == -1) {
        flock(fd, LOCK_UN);
        close(fd);
        return -1;
    }
    if ((fdw = open(tmpfile, O_WRONLY | O_CREAT | O_EXCL, 0644)) == -1) {
        close(fdr);
        flock(fd, LOCK_UN);
        close(fd);
        return -1;
    }
    count = 1;
    while (read(fdr, &fhdr, sizeof(fhdr)) == sizeof(fhdr)) {
        if (count < id1 || count > id2 || fhdr.accessed[0] &
                (FILE_MARKED | FILE_DIGEST)) {
            if ((safewrite(fdw, (char *) &fhdr, sizeof(fhdr)) == -1)) {
                close(fdw);
                unlink(tmpfile);
                close(fdr);
                flock(fd, LOCK_UN);
                close(fd);
                return -1;
            }
        } else {
            char *t;
            char buf[STRLEN], fullpath[STRLEN];

            strcpy(buf, filename);
            if ((t = strrchr(buf, '/')) != NULL)
                *t = '\0';
            sprintf(fullpath, "%s/%s", buf, fhdr.filename);
#ifdef BACKUP_RANGE_DELETE
/*
     if (strcmp(currboard, "deleted")&&strcmp(currboard,"junk")){
        cancelpost(currboard, currentuser.userid,&fhdr,
           !strcmp(fhdr.owner, currentuser.userid));
         }
*/
/* added by wer to backup the posts deleted with 'D'*/
/* Expand the non-backup range by quickmouse */
            if (!NotBackupBoard()) {
                cancelpost(currboard, currentuser.userid,
                        &fhdr, !strcmp(fhdr.owner, currentuser.userid));
            }
#endif
            unlink(fullpath);

        ++  /* add by hace  */

        ++  h_split(fullpath,buf);
        ++  if(h_link_board(buf)==1){

        ++      sprintf(h_path,"%s/%c/%s",PerPostPath,
        ++              toupper(fhdr.owner[0]),fhdr.owner);
        ++      h_del_post(h_path,fhdr.filename);

        ++  }

        ++  /* end */

        }
        count++;
    }
    close(fdw);
    close(fdr);
    if (rename(filename, deleted) == -1) {
        flock(fd, LOCK_UN);
        close(fd);
        return -1;
    }
    if (rename(tmpfile, filename) == -1) {
        flock(fd, LOCK_UN);
        close(fd);
        return -1;
    }
    flock(fd, LOCK_UN);
    close(fd);
    return 0;
}


    h) 修改 record.c , 把 delete_range() 函数注释掉.

    i) 修改 announce.c ,

i.0
    在前面增加下面的函数说明:
    char * h_split(const char *s,char *buf);
    int h_link_boards(char *board);

i.1 增加下面的函数:

i.1.1 h_split()
/* h_split()
 * 本函数用于获取路径中的板面字符串.
 * 若 *s="/home/bbs/boards/sysop/M.1049611297.A"
 * 则返回 *buf="sysop"
 */

char * h_split(const char *s,char *buf)
{
    int start,end;
    int len=strlen(s);
    start=end=0;
    for(;len>=0;)
        if(s[--len]=='/'){
            end=len;
            break;
        }
    for(;len>=0;)
        if(s[--len]=='/'){
            start=len+1;
            break;
        }
    for(len=0;len<end-start;len++)
        buf[len]=s[start+len];
    buf[len]='\0';
    return buf;
 }
}
/* end h_split() */

i.1.2 h_del_post()
/*
 * 当删除一篇文章时(用d,D,b)
 * 本调用本函数在个人文章里删除掉对应的链接
 * 和修改 .Names
 * 输入的 path="/home/bbs/PersonalPost/?/userid"
 * ? 为 A 到 Z
 * fname 为文件名,如 fname="M.1049546104.A"
 */

void h_del_post(char *path,char *fname)
{
    MENU me;
    int i=0;
    char fpath[128];
    me.path = path;
    me.level = -2003;
    a_loadnames(&me);
    for(i=0;i<me.num;i++){
        if(!strcmp(me.item[i]->fname,fname))break;
    }
    if(i>=me.num)return;
    sprintf(fpath,"%s/%s",path,fname);
    unlink(fpath);
    (me.num)--;
    me.now=i;
    for(i=me.now;i<me.num;i++){
        strcpy(me.item[i]->title,me.item[i+1]->title);
        strcpy(me.item[i]->fname,me.item[i+1]->fname);
    }
    a_savenames(&me);
}
/* end h_del_post() */

i.1.3 h_title_change()
/*
 * 当发表的文章被修改标题后
 * 会调本函数去修改相应的.Names中的标题
 */

void h_title_change(char *path,const char *filename,const char *newtitle)
{
    MENU me;
    int i;
    me.path=path;
    me.level=-2003;
    a_loadnames(&me);
    for(i=0;i<me.num;i++){
        if(!strcmp(me.item[i]->fname,filename)){
            strcpy(me.item[i]->title,newtitle);
            break;
        }
    }
    a_savenames(&me);
}
/* end h_title_change() */

i.1.4 h_link_board()
/*
 * 本函数检查发表文章所在的板块 board 是否
 * 需要记录到个人文章区里去,需要的话返回 1
 */
int h_link_board(char * board)
{
    char *n_lnboard[]={     //所定义的为不需要被记录到`个人文章区'里的
        "bbslists",         //注意,修改了n_lnboard[]后要修改后面的 len
        "BBS_help",
        "board",
        "cnAnnounce",
        "cnLists",
        "cnTest",
        "cnWeather",
        "deleted",
        "syssecurity",
        "junk",
        "newcomers",
        "notepad",
        "Penalization",
        "test",
        "vote",
        "Water",
    };
    int i,len=16;
    for(i=0;i<len;i++)
        if(!strcmp(board,n_lnboard[i]))return -1;
    return 1;
}
/* end h_link_board() */

i.1.5 h_post_link()
/*
 * 当发表一篇后,如果需要记录到`个人文章区'里的话
 * 就调用此函数, whopost 为文章发表者, title 为文章标题
 * filepath 为文件路径,如 boards/sysop/M.1049611297.A
 * fname 为文件名,如 M.1049611297.A
 */

void h_post_link(char *whopost,char *title,char *filepath,char *fname)
{
    char path[128],oldpath[128],newpath[128];
    FILE *fp;
    sprintf(oldpath,"%s/%s",BBSHOME,filepath);
    sprintf(newpath,"%s/%c/%s/%s",PerPostPath,toupper(whopost[0]),
            whopost,fname);
    sprintf(path,"%s/%c/%s/.Names",PerPostPath,toupper(whopost[0]),whopost);
    fp=fopen(path,"r");
    if(fp==NULL){
        memset(path,0,sizeof(path));
        sprintf(path,"%s/%c",PerPostPath,toupper(whopost[0]));
        mkdir(path,0755);
        sprintf(path,"%s/%s",path,whopost);
        mkdir(path,0755);
        sprintf(path,"%s/.Names",path);
        fp=fopen(path,"w");
        fprintf(fp,"#\n");
        fprintf(fp,"# Title= %s  ●  [%s] 的最近作品 \n",BBSNAME,whopost);
        fprintf(fp,"#\n");
        fprintf(fp,"Name=%s\n",title);
        fprintf(fp,"Path=~/%s\n",fname);
        fprintf(fp,"Numb=1\n#\n");
        fclose(fp);
    }else{
        MENU me;
        int i;
        memset(path,0,sizeof(path));
        sprintf(path,"%s/%c/%s",PerPostPath,toupper(whopost[0]),whopost);
        me.path=path;
        me.level=-2003;
        a_loadnames(&me);
        me.item[me.num]=(ITEM *)malloc(sizeof(ITEM));
        for(i=me.num;i>0;i--){
            strcpy(me.item[i]->title,me.item[i-1]->title);
            strcpy(me.item[i]->fname,me.item[i-1]->fname);
        }
        strcpy(me.item[0]->title,title);
        strcpy(me.item[0]->fname,fname);
        me.item[0]->host=NULL;
        me.item[0]->port=0;
        (me.num)++;
        a_savenames(&me);
        fclose(fp);
    }
    symlink(oldpath,newpath);
}

/* end h_post_link() */

--

    /
   /__  __   __  __
  /  / /  ) /   /__)
 /  /  \_/\ \__ \__

※ 修改:·hace 於 04月07日18:28:51 修改本文·[FROM: 深海]
※ 来源:·半边海BBS hace.dhs.org·[FROM: 深海]
--
※ 转载:·半边海BBS hace.dhs.org·[FROM: hace]


[回到开始] [上一篇][下一篇]

荔园在线首页 友情链接:深圳大学 深大招生 荔园晨风BBS S-Term软件 网络书店