附件,引用文章以及Bbs Resource Locator
bbs中不像http沒有鏈接的功能。
我們一般在版面上說:參考本版3321文
但是如果一個大站,發文很快,版主清得又勤,前面的3321文過几個小時可能
已經變成3105文。去找時已經找不到。
如果是几天前的文章,那這個3321文就不知哪去找了。
于是一些特別善心的人們會這樣來表示,參考 “02/04/02 lkchu 很好的一篇文章”
一些bbs會加入查找某段日期文章的功能,也比較好地應對這個問題。
我們這里在嘗試的是一種通用性的表示文章引用的方法。
起意是在和hightman研究在一篇文章中上載多個二進制附件時聊出來的。
一篇文章上載了相關的附件,附件是肯定另存一個地方會比較好。
因而就引入了在一篇文章中如何描述附件的位置的問題。
先談談本站“笑書亭”中使用的步驟:
1. ctrl-p發表文章
2. 寫著寫著需要一個附圖來說明,就按ctrl-x,這里借用了windtop的popupmenu
□□□□□□□□□□□□□□□□□□
□【存檔選項】 □
□┤[L]ocal 存為站內檔 ├□□
□ (S)ave 存檔 □□
□ (A)bort 放棄 □□
□ (T)itle 改標題 □□
□ (E)dit 繼續編輯 □□
□ (R)ead 讀取暫存檔 □□
□ (W)rite 寫入暫存檔 □□
□ (P)aste 插入引用鏈接 □□
□ (U)pload 上載附件 □□
□□□□□□□□□□□□□□□□□□□
3. 選擇Upload上載附件,底行提示:
請問選擇上載途徑. 1) HTTP 2) Zmodem. 0) 退出 [0]
4. 選2,再按Y,支持Zmodem的telnet client就會彈出對話框選擇文件
5. 上載結束,提示輸入文件描述,直接回車就記下文件名作為描述:
正在保存文件: 樣品.jpg (9894 bytes)
輸入描述:
6. 文章中插入一串字符:
"樣品.jpg":xfile:@0VDUEE9
顯示的這一串字符中,實際還包括頭尾的兩個不可見分隔碼,實際是
\004"樣品.jpg":xfile:@0VDUEE9\004
^^^^這個\004在vim中看是^D,cat的話是小黑塊,用戶從bbs界面無法輸入
7. 文章發表后,more中顯示:
"樣品.jpg":xfile:@0VDUEE9
8. 在more時按ctrl-d,用popupmenu列出本文內的所有鏈接:
□□□□□□□□□□□□□□□□□□
□【附件列表】 □
□┤[0] - 取消 ├□□
□ (1) - 樣品.jpg □□
□□□□□□□□□□□□□□□□□□□
9. 選擇文件按回車,支持ZModem的telnet client即開始下載。
----------------------------------------------------------------
上面這個 \004"樣品.jpg":xfile:@0VDUEE9\004
就是我們想說的BBS Resource Locator,用于定位在一個bbs站的資源。
這里提到的資源是指:版面文章,精華區文章,附件,以及投票結果,十大統計等。
目的是用于一串人類可以理解,又可以存在于文章中的字串來確切地
定位在一個bbs中的位址。
在閱讀文章時按ctrl-d用popupmenu的方式列出文章中的這種定位串,
供用戶選擇。
----------------------------------------------------------------
再談引用文章:
為了在文章中引用其它文章,也可以使用這種定位串。
在本站“笑書亭”中使用方法如下:
1. 上下左右找到你想引用文章
2. 按大寫M 生成文章的BRL引用串,存在內存中,底行顯示:
◆ 收錄剪貼板中: brl="Re: [問題] 匿名板的文章評分":A0VDRKKP
3. 發表文章時,ctrl-x,選取Paste
□□□□□□□□□□□□□□□□□□
□【存檔選項】 □
$"樣品.jpg":xfile:@0 □ [S]ave 存檔 □□
□ (A)bort 放棄 □□
□ (T)itle 改標題 □□
-- □ (E)dit 繼續編輯 □□
*[1;31m#*[33m Origin □ (R)ead 讀取暫存檔 □□ 66.net *[m
*[1;31m#*[35m Author □ (W)rite 寫入暫存檔 □□
□┤(P)aste 插入引用鏈接 ├□□
□ (U)pload 上載附件 □□
□□□□□□□□□□□□□□□□□□□
4. 文章中會插入一行:
"Re: [問題] 匿名板的文章評分":A0VDRKKP$TW-itoc
^同樣地,頭尾兩端包還包含\004這個不可見字符 ^
5. 閱讀文章時,顯示:
"樣品.jpg":xfile:@0VDUEE9
"Re: [問題] 匿名板的文章評分":A0VDRKKP$TW-itoc
6. 按ctrl-d,彈popupmenu列出所有鏈接:
□□□□□□□□□□□□□□□□□□
□【附件列表】 □
□┤[0] - 取消 ├□□
□ (1) - 樣品.jpg □□
□ (2) - Re: [問題] 匿名板的文 □□
□□□□□□□□□□□□□□□□□□□
7. 選擇閱讀或下載
8. 閱讀的文章讀完后會返回原來XO所在位置
--------------------------------------------------------------------
BRL = BRLDESC:(RTYPE)?:BRLPATH
BRLDESC = "[~"]*"
RTYPE = ("post", "gem", "xfile", "unkown")
BRLPATH = FILENAME($BOARD)?
FILENAME = ('A'..'Z', '0'..'9')+
BOARD = ('A'..'Z', '0'..'9')+
/*-------------------------------------------------------*/
/* BRL 在本站的資源定位 */
/* 0x4 "Description":A0UF95DL 0x4 最簡寫,默認本版版面文章 */
/* 0x4 "Description":post:A0UF95DL 0x4 本版文章 */
/* 0x4 "Description":A0UF95DL$sysop 0x4 sysop版上文章 */
/* 0x4 "Description":A0UF95DL$sysop 0x4 sysop版上文章 */
/* 0x4 "Description":post:A0UF95DL$sysop 0x4 sysop版上文章 */
/* 0x4 "Description":gem:A0UF95DL 0x4 本版精華區 */
/* 0x4 "Description":gem:A0UF95DL$sysop 0x4 sysop版精華區 */
/* 0x4 "Description":xfile:A0UF95DL 0x4 本版附件 */
/* 0x4 "Description":vote:A0UF95DL 0x4 本版投票結果 */
/* */
--------------------------------------------------------
限于篇幅,這里僅貼出解析代碼,完整的代碼等整理好
之后打包放出來,或者你知道笑書亭在哪的話,找我來要。
#define BRL_ESCCHAR 4
typedef struct {
int rtype;
char rtypestr[10];
char brdid[24];
char brldesc[64];
char brlpath[64];
} BRL;
enum
{
RT_POST=0, RT_GEM, RT_XFILE, RT_VOTE, RT_UNKNOWN=99
};
/*-------------------------------------------------------
Search brl in a char*;
return the first pos occur a complete BRL in str;
return null if not found.
if found, the desc and path are stored in brl;
-------------------------------------------------------*/
char *brl_find(unsigned char *str, BRL *brl, unsigned char **end)
{
int bstate, i;
unsigned char *ptr, *qtr, *t;
unsigned char whitespace[]=" ";
char brdidchars[] = "@0123456789_.-";
/*
暫時不用,什么都有可能
char brlchars[]="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
*/
#define BRLERROR 8
#define BRLFOUND 9
*brl->brldesc = NULL;
*brl->brlpath = NULL;
*brl->rtypestr = NULL;
*brl->brdid = NULL;
ptr = strchr(str, BRL_ESCCHAR);
if (ptr == NULL) return NULL;
ptr++;
qtr=ptr;
bstate = 0;
while ((*qtr != NULL)&&(*qtr!='\r')&&(*qtr!='\n')&&(*qtr!='\t')
&&(bstate != BRLERROR)&&(bstate!=BRLFOUND)) {
switch (bstate)
{
case 0 :
if (*qtr == '"') {
*brl->brldesc = '\0';
bstate = 1;
}
else if (strchr(whitespace, *qtr)) {
}
else bstate = BRLERROR;
break;
case 1 : /* description */
if (*qtr == '"'){
bstate = 2;
}
else if (*qtr >= 0x20) {
strncat(brl->brldesc, qtr, 1);
}
else bstate = BRLERROR;
break;
case 2 : /* brltype */
if (*qtr == ':') {
if ((*(qtr+1) != NULL) && (t = strchr(qtr+1, ':'))) {
strncpy(brl->rtypestr, qtr+1, t-qtr-1);
brl->rtypestr[t-qtr-1] = '\0';
qtr = t; /* 后面會 qtr++ */
}
bstate = 3;
*brl->brlpath = '\0';
}
else if (strchr(whitespace, *qtr)) {
}
else bstate = BRLERROR;
break;
case 3 : /* brlpath */
if (*qtr == BRL_ESCCHAR) {
bstate = BRLFOUND;
}
else if (*qtr == '$') {
bstate = 4;
}
else if (isalpha(*qtr) || strchr(brdidchars, *qtr)) {
strncat(brl->brlpath, qtr, 1);
}
else if (strchr(whitespace, *qtr)) {
}
else bstate = BRLERROR;
break;
case 4 : /* 版名 */
if (*qtr == BRL_ESCCHAR) {
bstate = BRLFOUND;
}
else if (isalpha(*qtr) || strchr(brdidchars, *qtr)) {
strncat(brl->brdid, qtr, 1);
}
else if (strchr(whitespace, *qtr)) {
}
else bstate = BRLERROR;
break;
case BRLERROR:
break;
case BRLFOUND:
break;
} /* switch (bstate)*/
qtr++;
}
if (bstate != BRLFOUND) {
return NULL;
}
*end = qtr; /* 指向 BRL_ESCCHAR 后面那個char */
if (strlen(brl->rtypestr) == 0) {
brl->rtype = RT_POST;
}
else {
str_lower(brl->rtypestr, brl->rtypestr);
i = 0;
while ((DEF_RTYPE[i]) && (!strstr(brl->rtypestr,DEF_RTYPE[i])))
i++;
if (!DEF_RTYPE[i]) brl->rtype = RT_UNKNOWN;
else brl->rtype = i;
}
return ptr;
}
--
# Origin # 笑書亭 bbs.dot66.net
# Author # 218.108.188.200
Maple 近期熱門文章
PTT數位生活區 即時熱門文章