diff options
author | piaip <piaip@63ad8ddf-47c3-0310-b6dd-a9e9d9715204> | 2007-12-02 12:02:48 +0800 |
---|---|---|
committer | piaip <piaip@63ad8ddf-47c3-0310-b6dd-a9e9d9715204> | 2007-12-02 12:02:48 +0800 |
commit | 23d973bd097f2ec285b0d4b1a08dd13f48d5dec1 (patch) | |
tree | 93bfc9f9517217df832ae14349a06b5d65d8b67e | |
parent | 6dbbad9a294b007ec184b689a601ed8077f4d50b (diff) | |
download | pttbbs-23d973bd097f2ec285b0d4b1a08dd13f48d5dec1.tar pttbbs-23d973bd097f2ec285b0d4b1a08dd13f48d5dec1.tar.gz pttbbs-23d973bd097f2ec285b0d4b1a08dd13f48d5dec1.tar.bz2 pttbbs-23d973bd097f2ec285b0d4b1a08dd13f48d5dec1.tar.lz pttbbs-23d973bd097f2ec285b0d4b1a08dd13f48d5dec1.tar.xz pttbbs-23d973bd097f2ec285b0d4b1a08dd13f48d5dec1.tar.zst pttbbs-23d973bd097f2ec285b0d4b1a08dd13f48d5dec1.zip |
*** IMPORTANT CHANGE ***
BRC v3, supporting local modification
THINK TWICE BEFORE YOU APPLY TO YOUR SYSTEM.
BRC v3 will double size of BRC v2.
BRC v3 can allow notifying changes of comment (recommend) system
BRC v3 may cause more syscall activities than v2
git-svn-id: http://opensvn.csie.org/pttbbs/trunk/pttbbs@3608 63ad8ddf-47c3-0310-b6dd-a9e9d9715204
-rw-r--r-- | docs/brc.txt | 19 | ||||
-rw-r--r-- | include/pttstruct.h | 4 | ||||
-rw-r--r-- | mbbsd/bbs.c | 127 | ||||
-rw-r--r-- | mbbsd/board.c | 8 | ||||
-rw-r--r-- | mbbsd/brc.c | 225 | ||||
-rw-r--r-- | sample/pttbbs.conf | 3 |
6 files changed, 213 insertions, 173 deletions
diff --git a/docs/brc.txt b/docs/brc.txt index 315a1fbc..d64f7918 100644 --- a/docs/brc.txt +++ b/docs/brc.txt @@ -1,6 +1,7 @@ - BRC documentation by scw 08/05/2003 + BRC (v2) documentation by scw 08/05/2003 06/12/2007 revised by kcwu + 12/02/2007 v3 by piaip 源起: 這篇文章主要是介紹 brc_* 的函式,這組函式是 pttbbs 用來紀錄文章已讀/未讀 @@ -43,8 +44,22 @@ BRC 是什麼?如何運作? 個人看的板太多,讓 .brc2 大小超過 BRC_MAXSIZE 有些板的紀錄就會不見( 24576 bytes 最少可以存 73 個板的資料,這還是用全部板 brc_num 都是 80 計算的)。但這 三個小缺點影響應該不大吧? + +v3 說明 + + Dec 2007 開始 ptt brc 引入 v3 格式,與前板不相容。所謂的 v3 是由於 BBS + 「推文」系統被濫用而產生的需求。推文的形式是在原文後附加新的一行文,但舊 + BRC 系統無法分辨此類更動;若想讓人分辨是否有新推文各家作法不一,常見的是比 + 照 edit_post 把檔案改名。這種方式除了效率不彰外,還有並非每個人都想看新推文 + 的問題。 + 考量許久後,從 BRC 下手還是正解。 在每個 BRC 記錄上多新增一個 modified + time 即可。 此方法可同時適用於分離檔案與原文附加的推文系統。代價是 BRC 大小 + 加倍成長,不過這似乎不是什麼大問題。 + 由於 v2 v3 實際差異並不大,這裡的說明保留以 v2 為主。 麻煩自己查 svn + 就知道 v3 改了哪邊了。 + -BRC 實作 +BRC v2 實作 interface: (in proto.h) diff --git a/include/pttstruct.h b/include/pttstruct.h index ee0512fc..dfc6dc2f 100644 --- a/include/pttstruct.h +++ b/include/pttstruct.h @@ -253,8 +253,8 @@ typedef struct boardheader_t { #define FNLEN 28 /* Length of filename */ typedef struct fileheader_t { - char filename[FNLEN]; /* M.1120582370.A.1EA [19+1] */ - int textlen; /* main text length in post */ + char filename[FNLEN]; /* M.1120582370.A.1EA [19+1], create time */ + time4_t modified; /* last modified time */ char pad; /* padding, not used */ char recommend; /* important level */ char owner[IDLEN + 2]; /* uid[.] */ diff --git a/mbbsd/bbs.c b/mbbsd/bbs.c index 86fc5d79..80a7bec2 100644 --- a/mbbsd/bbs.c +++ b/mbbsd/bbs.c @@ -317,10 +317,23 @@ readtitle(void) static void readdoent(int num, fileheader_t * ent) { - int type; + int type = ' '; char *mark, *title, color, special = 0, isonline = 0, recom[8]; - type = brc_unread(currbid, ent->filename) ? '+' : ' '; + + // type = brc_unread(currbid, ent->filename) ? '+' : ' '; + switch (brc_unread(currbid, ent->filename, ent->modified)) + { + case 1: // unread + type = '+'; + break; + case 2: // unread (modified) + type = '~'; + break; + default: + break; + } + if ((currmode & MODE_BOARD) && (ent->filemode & FILE_DIGEST)) type = (type == ' ') ? '*' : '#'; else if (currmode & MODE_BOARD || HasUserPerm(PERM_LOGINOK)) { @@ -921,15 +934,7 @@ do_general(int isbid) else if(!isbid) { /* general article */ -#ifdef USE_TEXTLEN - struct stat st; - - if (stat(fpath, &st) != -1) - { - /* put original file (text) length. */ - postfile.textlen = st.st_size; - } -#endif + postfile.modified = dasht(fpath); postfile.multi.money = aborted; } @@ -978,7 +983,7 @@ do_general(int isbid) #endif outgo_post(&postfile, currboard, cuser.userid, cuser.nickname); } - brc_addlist(postfile.filename); + brc_addlist(postfile.filename, postfile.modified); if( !bp->level || (currbrdattr & BRD_POSTMASK)) { @@ -1261,7 +1266,6 @@ edit_post(int ent, fileheader_t * fhdr, const char *direct) char genbuf[200]; fileheader_t postfile; boardheader_t *bp = getbcache(currbid); - struct stat oldstat, newstat; int isSysop = 0, recordTouched = 0; assert(0<=currbid-1 && currbid-1<MAX_BOARD); @@ -1291,60 +1295,19 @@ edit_post(int ent, fileheader_t * fhdr, const char *direct) setdirpath(genbuf, direct, fhdr->filename); local_article = fhdr->filemode & FILE_LOCAL; -#ifdef USE_TEXTLEN - if(fhdr->textlen > 0) - { - /* TODO SYSOP may need some function to edit entire file. */ - CopyN(genbuf, fpath, fhdr->textlen); - } - else -#endif - { - Copy(genbuf, fpath); - } - + Copy(genbuf, fpath); strlcpy(save_title, fhdr->title, sizeof(save_title)); do { - stat(genbuf, &oldstat); + time4_t oldmt, newmt; + oldmt = dasht(genbuf); if (vedit(fpath, 0, NULL) == -1) break; - stat(genbuf, &newstat); - - /* check textlen */ - if(fhdr->textlen > 0) - { - int gotnewstat = -1; - -#ifdef USE_TEXTLEN - /* TODO should we reload textlen info? - * multiple editing will make textlen invalid. */ - if(fhdr->textlen != newstat.st_size) - { -#ifdef DEBUG - vmsg("textlen != st_size, append tail."); -#endif - gotnewstat = stat(fpath, &newstat); - - /* copy from old content. */ - AppendTail(genbuf, fpath, fhdr->textlen); - } else { - gotnewstat = stat(fpath, &newstat); - } -#endif - - /* now update the record. */ - if(gotnewstat != -1) - fhdr->textlen = newstat.st_size; - else - fhdr->textlen = 0; - - recordTouched = 1; + newmt = dasht(genbuf); - } else /* old flavor, no textlen info */ - if (oldstat.st_mtime != newstat.st_mtime) + if (oldmt != newmt) { if (tolower(getans( "檔案已被別人修改過,要覆蓋\掉它嗎 [Y/n]?")) == 'n') @@ -1370,11 +1333,10 @@ edit_post(int ent, fileheader_t * fhdr, const char *direct) { int c = 0; struct tm *ptime; - time4_t xt = (time4_t)newstat.st_mtime; fprintf(fp, MSG_SEPERATOR "\n"); fprintf(fp, "以下為被別人修改過的最新內容: "); - ptime = localtime4(&xt); + ptime = localtime4(&newmt); fprintf(fp, " (%02d/%02d %02d:%02d)\n", ptime->tm_mon + 1, ptime->tm_mday, @@ -1391,6 +1353,14 @@ edit_post(int ent, fileheader_t * fhdr, const char *direct) Rename(fpath, genbuf); + // this is almost always true... + // whatever. + { + time4_t oldm = fhdr->modified; + fhdr->modified = dasht(genbuf); + recordTouched = (oldm == fhdr->modified) ? 1 : 0; + } + if(strcmp(save_title, fhdr->title)){ // Ptt: here is the black hole problem // (try getindex) @@ -1661,7 +1631,7 @@ read_post(int ent, fileheader_t * fhdr, const char *direct) else STATINC(STAT_READPOST_OLD); } - brc_addlist(fhdr->filename); + brc_addlist(fhdr->filename, fhdr->modified); strlcpy(currtitle, subject(fhdr->title), sizeof(currtitle)); switch(more_result) @@ -2094,24 +2064,37 @@ do_add_recommend(const char *direct, fileheader_t *fhdr, /* This is a solution to avoid most racing (still some), but cost four * system calls. */ + if(type == 0 && fhdr->recommend < 100 ) update = 1; else if(type == 1 && fhdr->recommend > -100) update = -1; + + // since we want to do 'modification'... + fhdr->modified = dasht(path); - if( update ){ + if( /* update */ 1){ int fd; + //Ptt: update only necessary if( (fd = open(direct, O_RDWR)) < 0 ) return -1; - if( lseek(fd, (sizeof(fileheader_t) * (ent - 1) + - (char *)&fhdr->recommend - (char *)fhdr), - SEEK_SET) >= 0 ){ + + if (lseek(fd, (sizeof(fileheader_t) * (ent-1) + + (char*)&fhdr->modified - (char*)fhdr), SEEK_SET) >= 0) + { + write(fd, &fhdr->modified, sizeof(fhdr->modified)); + } + + if( update && + lseek(fd, (sizeof(fileheader_t) * (ent - 1) + + (char *)&fhdr->recommend - (char *)fhdr), + SEEK_SET) >= 0 ){ // 如果 lseek 失敗就不會 write - read(fd, &fhdr->recommend, sizeof(char)); + read(fd, &fhdr->recommend, sizeof(fhdr->recommend)); fhdr->recommend += update; lseek(fd, -1, SEEK_CUR); - write(fd, &fhdr->recommend, sizeof(char)); + write(fd, &fhdr->recommend, sizeof(fhdr->recommend)); } close(fd); } @@ -2419,7 +2402,12 @@ recommend(int ent, fileheader_t * fhdr, const char *direct) // owner recommend type = 2; move(b_lines-1, 0); clrtoeol(); +#ifndef OLDRECOMMEND + outs("作者本人, 使用 → 加註方式\n"); +#else outs("作者本人首推, 使用 → 加註方式\n"); +#endif + } #ifndef DEBUG else if (!(currmode & MODE_BOARD) && @@ -3662,7 +3650,8 @@ const onekey_t read_comms[] = { { 1, push_bottom }, // Ctrl('Z') 26 { 0, NULL }, { 0, NULL }, { 0, NULL }, { 0, NULL }, { 0, NULL }, { 0, NULL }, { 0, NULL }, { 0, NULL }, { 0, NULL }, { 0, NULL }, - { 0, NULL }, { 0, NULL }, { 0, NULL }, { 0, NULL }, { 0, NULL }, + { 1, recommend }, // '%' (m3itoc style) + { 0, NULL }, { 0, NULL }, { 0, NULL }, { 0, NULL }, { 0, NULL }, { 0, NULL }, { 0, NULL }, { 0, NULL }, { 0, NULL }, { 0, NULL }, { 0, NULL }, { 0, NULL }, { 0, NULL }, { 0, NULL }, { 0, NULL }, { 0, NULL }, { 0, NULL }, { 0, NULL }, { 0, NULL }, diff --git a/mbbsd/board.c b/mbbsd/board.c index 7338b85a..85103397 100644 --- a/mbbsd/board.c +++ b/mbbsd/board.c @@ -200,7 +200,7 @@ check_newpost(boardstat_t * ptr) if (ftime > now + 10) ftime = B_LASTPOSTTIME(ptr) = now - 1; - if ( brc_unread_time(ptr->bid, ftime) ) + if ( brc_unread_time(ptr->bid, ftime, 0) ) ptr->myattr |= NBRD_UNREAD; return 1; @@ -243,6 +243,7 @@ addnewbrdstat(int n, int state) { boardstat_t *ptr; + // if(n == -32769) return 0; // ptt 2 local modification XXX who wrote this? and why? 請自首! assert(0<=n && n<MAX_BOARD); assert(0<=brdnum && brdnum<nbrdsize); ptr = &nbrd[brdnum++]; @@ -353,6 +354,7 @@ load_boards(char *key) state |= NBRD_TAG; if (is_set_attr(&fav->favh[i], FAVH_ADM_TAG)) state |= NBRD_TAG; + // 有些人 某些 bid < 0 Orzz // ptt2 local modification if (fav_getid(&fav->favh[i]) < 1) continue; addnewbrdstat(fav_getid(&fav->favh[i]) - 1, NBRD_FAV | state); @@ -497,7 +499,7 @@ unread_position(char *dirfile, boardstat_t * ptr) while (num > 0) { lseek(fd, (off_t) (num * sizeof(fh)), SEEK_SET); if (read(fd, fname, FNLEN) <= 0 || - !brc_unread(ptr->bid, fname)) + !brc_unread(ptr->bid, fname, 0)) break; num -= step; if (step < 32) @@ -508,7 +510,7 @@ unread_position(char *dirfile, boardstat_t * ptr) while (num < total) { lseek(fd, (off_t) (num * sizeof(fh)), SEEK_SET); if (read(fd, fname, FNLEN) <= 0 || - brc_unread(ptr->bid, fname)) + brc_unread(ptr->bid, fname, 0)) break; num++; } diff --git a/mbbsd/brc.c b/mbbsd/brc.c index 6e069449..da18c2a0 100644 --- a/mbbsd/brc.c +++ b/mbbsd/brc.c @@ -3,11 +3,13 @@ /** * 關於本檔案的細節,請見 docs/brc.txt。 + * v3: add last modified time for comment system. double max size. + * original time_t as 'create'. */ #ifndef BRC_MAXNUM #define BRC_STRLEN 15 /* Length of board name, for old brc */ -#define BRC_MAXSIZE 24576 /* Effective size of brc rc file, 8192 * 3 */ +#define BRC_MAXSIZE 49152 /* Effective size of brc rc file, 8192 * 3 * 2 */ #define BRC_MAXNUM 80 /* Upper bound of brc_num, size of brc_list */ #endif @@ -21,10 +23,15 @@ please rewrite brc.c typedef unsigned short brcbid_t; typedef unsigned short brcnbrd_t; +typedef struct { + time4_t create; + time4_t modified; +} brc_rec; + /* old brc rc file form: * board_name 15 bytes * brc_num 1 byte, binary integer - * brc_list brc_num * sizeof(int) bytes, brc_num binary integer(s) */ + * brc_list brc_num * sizeof(brc_rec) bytes */ static char brc_initialized = 0; static time4_t brc_expire_time; @@ -40,10 +47,10 @@ static int brc_alloc; // read records for currbid static int brc_currbid; static int brc_num; -static time4_t brc_list[BRC_MAXNUM]; +static brc_rec brc_list[BRC_MAXNUM]; -static char * const fn_oldboardrc = ".boardrc"; -static char * const fn_brc = ".brc2"; +static char * const fn_brc2= ".brc2"; +static char * const fn_brc = ".brc3"; /** * find read records of bid in given buffer region @@ -74,7 +81,7 @@ brc_findrecord_in(char *begin, char *endp, brcbid_t bid, brcnbrd_t *num) tbid = *(brcbid_t*)tmpp; tmpp += sizeof(brcbid_t); *num = *(brcnbrd_t*)tmpp; - tmpp += sizeof(brcnbrd_t) + *num * sizeof(time4_t); /* end of record */ + tmpp += sizeof(brcnbrd_t) + *num * sizeof(brc_rec); /* end of record */ if ( tmpp > endp ){ /* dangling, ignore the trailing data */ @@ -90,7 +97,7 @@ brc_findrecord_in(char *begin, char *endp, brcbid_t bid, brcnbrd_t *num) return 0; } -static time4_t * +static brc_rec * brc_find_record(int bid, int *num) { char *p; @@ -98,17 +105,17 @@ brc_find_record(int bid, int *num) p = brc_findrecord_in(brc_buf, brc_buf + brc_size, bid, &tnum); *num = tnum; if (p) - return (time4_t*)(p + sizeof(brcbid_t) + sizeof(brcnbrd_t)); + return (brc_rec*)(p + sizeof(brcbid_t) + sizeof(brcnbrd_t)); *num = 0; return 0; } static char * brc_putrecord(char *ptr, char *endp, brcbid_t bid, - brcnbrd_t num, const time4_t *list) + brcnbrd_t num, const brc_rec *list) { char * tmp; - if (num > 0 && list[0] > brc_expire_time && + if (num > 0 && list[0].create > brc_expire_time && ptr + sizeof(brcbid_t) + sizeof(brcnbrd_t) < endp) { if (num > BRC_MAXNUM) num = BRC_MAXNUM; @@ -119,9 +126,9 @@ brc_putrecord(char *ptr, char *endp, brcbid_t bid, ptr += sizeof(brcbid_t); *(brcnbrd_t*)ptr = num; /* write in brc_num */ ptr += sizeof(brcnbrd_t); - tmp = ptr + num * sizeof(time4_t); + tmp = ptr + num * sizeof(brc_rec); if (tmp <= endp) - memcpy(ptr, list, num * sizeof(time4_t)); /* write in brc_list */ + memcpy(ptr, list, num * sizeof(brc_rec)); /* write in brc_list */ ptr = tmp; } return ptr; @@ -178,7 +185,7 @@ brc_get_buf(int size){ } static inline void -brc_insert_record(brcbid_t bid, brcnbrd_t num, const time4_t* list) +brc_insert_record(brcbid_t bid, brcnbrd_t num, const brc_rec* list) { char *ptr; int new_size, end_size; @@ -186,7 +193,7 @@ brc_insert_record(brcbid_t bid, brcnbrd_t num, const time4_t* list) ptr = brc_findrecord_in(brc_buf, brc_buf + brc_size, bid, &tnum); - while (num > 0 && list[num - 1] < brc_expire_time) + while (num > 0 && list[num - 1].create < brc_expire_time) num--; /* don't write the times before brc_expire_time */ if (!ptr) { @@ -195,7 +202,7 @@ brc_insert_record(brcbid_t bid, brcnbrd_t num, const time4_t* list) /* put on the beginning */ if (num){ new_size = sizeof(brcbid_t) + sizeof(brcnbrd_t) - + num * sizeof(time4_t); + + num * sizeof(brc_rec); brc_size += new_size; if (brc_size > brc_alloc && !brc_enlarge_buf()) brc_size = BRC_MAXSIZE; @@ -206,13 +213,13 @@ brc_insert_record(brcbid_t bid, brcnbrd_t num, const time4_t* list) } else { /* ptr points to the old current brc list. * tmpp is the end of it (exclusive). */ - int len = sizeof(brcbid_t) + sizeof(brcnbrd_t) + tnum * sizeof(time4_t); + int len = sizeof(brcbid_t) + sizeof(brcnbrd_t) + tnum * sizeof(brc_rec); char *tmpp = ptr + len; end_size = brc_buf + brc_size - tmpp; if (num) { int sindex = ptr - brc_buf; new_size = (sizeof(brcbid_t) + sizeof(brcnbrd_t) - + num * sizeof(time4_t)); + + num * sizeof(brc_rec)); brc_size += new_size - len; if (brc_size > brc_alloc) { if (brc_enlarge_buf()) { @@ -246,72 +253,78 @@ brc_update(){ } } -/* return 1 if successfully read from old .boardrc file. - * otherwise, return 0. */ -inline static void -read_old_brc(int fd) +static void +read_brc2(void) { - char brdname[BRC_STRLEN + 1]; - char *ptr; - brcnbrd_t num; - brcbid_t bid; - brcbid_t read_brd[512]; - int nRead = 0, i; - - ptr = brc_buf; - brc_size = 0; - while (read(fd, brdname, BRC_STRLEN + 1) == BRC_STRLEN + 1) { - num = brdname[BRC_STRLEN]; - brdname[BRC_STRLEN] = 0; - bid = getbnum(brdname); - - for (i = 0; i < nRead; ++i) - if (read_brd[i] == bid) - break; - if (i != nRead){ - lseek(fd, num * sizeof(int), SEEK_CUR); - continue; - } - read_brd[nRead >= 512 ? nRead = 0 : nRead++] = bid; + char brcfile[STRLEN]; + int fd; + size_t sz2 = 0, sz3 = 0; + char *cvt = NULL, *cvthead = NULL; - *(brcbid_t*)ptr = bid; - ptr += sizeof(brcbid_t); - *(brcnbrd_t*)ptr = num; - ptr += sizeof(brcnbrd_t); - if (read(fd, ptr, sizeof(int) * num) != sizeof(int) * num) + brcbid_t bid; + brcnbrd_t num; + time4_t create; + brc_rec rec; + + setuserfile(brcfile, fn_brc2); + + if ((fd = open(brcfile, O_RDONLY)) == -1) + return; + + sz2 = dashs(brcfile); + sz3 = sz2 * 2; // max double size + + cvthead = cvt = malloc (sz3); + // now calculate real sz3 + + while (read(fd, &bid, sizeof(bid)) > 0) + { + if (read(fd, &num, sizeof(num)) < 1) break; - brc_size += sizeof(brcbid_t) + sizeof(brcnbrd_t) - + sizeof(time4_t) * num; - ptr += sizeof(time4_t) * num; + *(brcbid_t*)cvt = bid; cvt += sizeof(brcbid_t); + *(brcnbrd_t*)cvt = num;cvt += sizeof(brcnbrd_t); + for (; num > 0; num--) + { + read(fd, &create, sizeof(create)); + rec.create = create; + rec.modified = create; + *(brc_rec*)cvt = rec; cvt += sizeof(brc_rec); + } } + close(fd); + + // now cvthead is ready for v3. + brc_get_buf(sz3); + brc_size = sz3; + memcpy(brc_buf, cvthead, sz3); + + free(cvthead); } inline static void read_brc_buf(void) { - if (brc_buf == NULL) { - char brcfile[STRLEN]; - int fd; - struct stat brcstat; - - setuserfile(brcfile, fn_brc); - if ((fd = open(brcfile, O_RDONLY)) != -1) { - fstat(fd, &brcstat); - brc_get_buf(brcstat.st_size); - brc_size = read(fd, brc_buf, brc_alloc); - close(fd); - } else { - setuserfile(brcfile, fn_oldboardrc); - if ((fd = open(brcfile, O_RDONLY)) != -1) { - fstat(fd, &brcstat); - brc_get_buf(brcstat.st_size); - read_old_brc(fd); - close(fd); - } else - brc_size = 0; - } + char brcfile[STRLEN]; + int fd; + struct stat brcstat; + + if (brc_buf != NULL) + return; + + brc_size = 0; + setuserfile(brcfile, fn_brc); + + if ((fd = open(brcfile, O_RDONLY)) == -1) + { + read_brc2(); + return; } + + fstat(fd, &brcstat); + brc_get_buf(brcstat.st_size); + brc_size = read(fd, brc_buf, brc_alloc); + close(fd); } /* release allocated memory @@ -379,7 +392,7 @@ brc_initialize(){ * @return number of read record, 0 if no records */ static int -brc_read_record(int bid, int *num, time4_t *list){ +brc_read_record(int bid, int *num, brc_rec *list){ char *ptr; brcnbrd_t tnum; ptr = brc_findrecord_in(brc_buf, brc_buf + brc_size, bid, &tnum); @@ -387,10 +400,10 @@ brc_read_record(int bid, int *num, time4_t *list){ if ( ptr ){ assert(0 <= *num && *num <= BRC_MAXNUM); memcpy(list, ptr + sizeof(brcbid_t) + sizeof(brcnbrd_t), - *num * sizeof(time4_t)); + *num * sizeof(brc_rec)); return *num; } - list[0] = *num = 1; + list[0].create = *num = 1; return 0; } @@ -421,10 +434,14 @@ brc_initial_board(const char *boardname) static void brc_trunc(int bid, time4_t ftime){ - brc_insert_record(bid, 1, &ftime); + brc_rec r; + + r.create = ftime; + r.modified = ftime; + brc_insert_record(bid, 1, &r); if ( bid == brc_currbid ){ brc_num = 1; - brc_list[0] = ftime; + brc_list[0] = r; brc_changed = 0; } } @@ -440,50 +457,61 @@ brc_toggle_all_read(int bid, int is_all_read) } void -brc_addlist(const char *fname) +brc_addlist(const char *fname, time4_t modified) { int n, i; - time4_t ftime; + brc_rec frec; assert(currbid == brc_currbid); if (!cuser.userlevel) return; brc_initialize(); - ftime = atoi(&fname[2]); - if (ftime <= brc_expire_time /* too old, don't do any thing */ + frec.create = atoi(&fname[2]); + frec.modified = modified; + + if (frec.create <= brc_expire_time /* too old, don't do any thing */ /* || fname[0] != 'M' || fname[1] != '.' */ ) { return; } if (brc_num <= 0) { /* uninitialized */ - brc_list[0] = ftime; + brc_list[0] = frec; brc_num = 1; brc_changed = 1; return; } - if ((brc_num == 1) && (ftime < brc_list[0])) /* most when after 'v' */ + if ((brc_num == 1) && (frec.create < brc_list[0].create)) /* most when after 'v' */ return; for (n = 0; n < brc_num; n++) { /* using linear search */ - if (ftime == brc_list[n]) { + if (frec.create == brc_list[n].create) { + if (brc_list[n].modified < modified) + { + brc_list[n].modified = modified; + brc_changed = 1; + } return; - } else if (ftime > brc_list[n]) { + } else if (frec.create > brc_list[n].create) { if (brc_num < BRC_MAXNUM) brc_num++; - /* insert ftime into brc_list */ + /* insert frec into brc_list */ for (i = brc_num - 1; --i >= n; brc_list[i + 1] = brc_list[i]); - brc_list[n] = ftime; + brc_list[n] = frec; brc_changed = 1; return; } } } +// return: +// 0 - read +// 1 - unread (by create) +// 2 - unread (by modified) int -brc_unread_time(int bid, time4_t ftime) +brc_unread_time(int bid, time4_t ftime, time4_t modified) { int i; int bnum; - const time4_t *blist; + const brc_rec *blist; brc_initialize(); if (ftime <= brc_expire_time) /* too old */ @@ -498,21 +526,30 @@ brc_unread_time(int bid, time4_t ftime) if (bnum <= 0) return 1; + for (i = 0; i < bnum; i++) { /* using linear search */ - if (ftime > blist[i]) + if (ftime > blist[i].create) return 1; - else if (ftime == blist[i]) - return 0; + else if (ftime == blist[i].create) + { + time4_t brcm = blist[i].modified; + if (modified == 0 || brcm == 0) + return 0; + // bad case... seems like that someone is making -1. + if (modified == (time4_t)-1 || brcm == (time4_t)-1) + return 0; + return modified > brcm ? 2 : 0; + } } return 0; } int -brc_unread(int bid, const char *fname) +brc_unread(int bid, const char *fname, time4_t modified) { int ftime; ftime = atoi(&fname[2]); /* this will get the time of the file created */ - return brc_unread_time(bid, ftime); + return brc_unread_time(bid, ftime, modified); } diff --git a/sample/pttbbs.conf b/sample/pttbbs.conf index 6541dbd1..e0e3db06 100644 --- a/sample/pttbbs.conf +++ b/sample/pttbbs.conf @@ -142,9 +142,6 @@ /* "不"使用新式的 pmore (piaip's more) 代替舊式 bug 抓不完的 more */ //#define USE_TRADITIONAL_MORE -/* 使用 textlen 欄位來確定文章實際長度,避免蓋掉推文等。 */ -// #define USE_TEXTLEN - /* 使用 rfork()取代 fork() . 目前只在 FreeBSD上有效 */ //#define USE_RFORK |