summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/proto.h6
-rw-r--r--include/pttstruct.h5
-rw-r--r--mbbsd/edit.c2
-rw-r--r--mbbsd/io.c8
-rw-r--r--mbbsd/register.c12
-rw-r--r--mbbsd/user.c123
6 files changed, 135 insertions, 21 deletions
diff --git a/include/proto.h b/include/proto.h
index 4b969e08..2c9b060e 100644
--- a/include/proto.h
+++ b/include/proto.h
@@ -305,6 +305,7 @@ void set_converting_type(int which);
/* io */
int getdata(int line, int col, const char *prompt, char *buf, int len, int echo);
int igetch(void);
+int wait_input(float f, int flDoRefresh);
int getdata_str(int line, int col, const char *prompt, char *buf, int len, int echo, const char *defaultstr);
int getdata_buf(int line, int col, const char *prompt, char *buf, int len, int echo);
void add_io(int fd, int timeout);
@@ -708,6 +709,11 @@ int u_cloak(void);
int u_register(void);
int u_list(void);
+#if defined(DBCSAWARE_GETDATA) || defined(DBCSAWARE_EDIT)
+# define DBCSAWARE
+int u_detectDBCSAwareEvilClient();
+#endif
+
/* vote */
void b_suckinfile(FILE *fp, char *fname);
int b_results(void);
diff --git a/include/pttstruct.h b/include/pttstruct.h
index cb2049fd..d7dc1a00 100644
--- a/include/pttstruct.h
+++ b/include/pttstruct.h
@@ -115,10 +115,13 @@ typedef struct userec_t {
#define FRIEND_FLAG 0x10 /* true if show friends only */
#define BRDSORT_FLAG 0x20 /* true if the boards sorted alphabetical */
#define MOVIE_FLAG 0x40 /* true if show movie */
+
/* useless flag */
//#define COLOR_FLAG 0x80 /* true if the color mode open */
//#define MIND_FLAG 0x100 /* true if mind search mode open <-Heat*/
-#define RAWDBCS_FLAG 0x200 /* true if rawmode instead of DBCS-aware */
+
+#define DBCSAWARE_FLAG 0x200 /* true if DBCS-aware enabled. */
+/* please keep this even if you don't have DBCSAWARE features turned on */
/* these are flags in userec_t.uflag2 */
#define WATER_MASK 000003 /* water mask */
diff --git a/mbbsd/edit.c b/mbbsd/edit.c
index 539985c4..124d7d71 100644
--- a/mbbsd/edit.c
+++ b/mbbsd/edit.c
@@ -2477,7 +2477,7 @@ vedit(char *fpath, int saveheader, int *islocal)
currutmp->destuid = currstat;
#ifdef DBCSAWARE_EDIT
- mbcs_mode = !(cuser.uflag & RAWDBCS_FLAG);
+ mbcs_mode = (cuser.uflag & DBCSAWARE_FLAG) ? 1 : 0;
#endif
enter_edit_buffer();
diff --git a/mbbsd/io.c b/mbbsd/io.c
index 23ee3b47..c30e7aec 100644
--- a/mbbsd/io.c
+++ b/mbbsd/io.c
@@ -568,7 +568,7 @@ strip_nonebig5(unsigned char *str, int maxlen)
#ifdef DBCSAWARE_GETDATA
-#define ISDBCSAWARE() (!(cuser.uflag & RAWDBCS_FLAG))
+#define ISDBCSAWARE() (cuser.uflag & DBCSAWARE_FLAG)
int getDBCSstatus(unsigned char *s, int pos)
{
@@ -755,6 +755,12 @@ oldgetdata(int line, int col, const char *prompt, char *buf, int len, int echo)
break;
default:
if (isprint2(ch) && clen < len && x + clen < scr_cols) {
+#ifdef DBCSAWARE_GETDATA
+ /* to prevent single byte input */
+ if(ISDBCSAWARE() &&
+ clen >= len-1 && ch >= 0x80)
+ break;
+#endif
for (i = clen + 1; i > currchar; i--)
buf[i] = buf[i - 1];
buf[currchar] = ch;
diff --git a/mbbsd/register.c b/mbbsd/register.c
index d29466e0..b0d948d7 100644
--- a/mbbsd/register.c
+++ b/mbbsd/register.c
@@ -237,7 +237,7 @@ new_register(void)
vmsg("您嘗試錯誤的輸入太多,請下次再來吧");
exit(1);
}
- move(18, 0);
+ move(18, 0); clrtoeol();
outs(ANSI_COLOR(1;33) "為避免被偷看,您的密碼並不會顯示在畫面上,直接輸入完後按 Enter 鍵即可。" ANSI_RESET);
if ((getdata(19, 0, "請設定密碼:", passbuf,
sizeof(passbuf), NOECHO) < 3) ||
@@ -262,6 +262,14 @@ new_register(void)
newuser.firstlogin = newuser.lastlogin = now;
newuser.money = 0;
newuser.pager = 1;
+
+#ifdef DBCSAWARE
+ if(u_detectDBCSAwareEvilClient())
+ newuser.uflag &= ~DBCSAWARE_FLAG;
+ else
+ newuser.uflag |= DBCSAWARE_FLAG;
+#endif
+
allocid = getnewuserid();
if (allocid > MAX_USERS || allocid <= 0) {
fprintf(stderr, "本站人口已達飽和!\n");
@@ -330,3 +338,5 @@ check_register(void)
#endif
}
}
+/* vim:sw=4
+ */
diff --git a/mbbsd/user.c b/mbbsd/user.c
index 26c22abd..263fba09 100644
--- a/mbbsd/user.c
+++ b/mbbsd/user.c
@@ -278,37 +278,37 @@ void Customize(void)
memcpy(mindbuf, &currutmp->mind, 4);
mindbuf[4] = 0;
while( !done ){
- char maxc = 'A';
+ char maxc = 'a';
move(2, 0);
outs("您目前的個人化設定: ");
move(4, 0);
- prints("%-30s%10s\n", "A. 水球模式",
+ prints("%-40s%10s\n", "a. 水球模式",
wm[(cuser.uflag2 & WATER_MASK)]);
- prints("%-30s%10s\n", "B. 接受站外信", REJECT_OUTTAMAIL ? "否" : "是");
- prints("%-30s%10s\n", "C. 新板自動進我的最愛",
+ prints("%-40s%10s\n", "b. 接受站外信", REJECT_OUTTAMAIL ? "否" : "是");
+ prints("%-40s%10s\n", "c. 新板自動進我的最愛",
((cuser.uflag2 & FAVNEW_FLAG) ? "是" : "否"));
- prints("%-30s%10s\n", "D. 目前的心情", mindbuf);
- prints("%-30s%10s\n", "E. 高亮度顯示我的最愛",
+ prints("%-40s%10s\n", "d. 目前的心情", mindbuf);
+ prints("%-40s%10s\n", "e. 高亮度顯示我的最愛",
(!(cuser.uflag2 & FAVNOHILIGHT) ? "是" : "否"));
- prints("%-30s%10s\n", "F. 動態看板",
+ prints("%-40s%10s\n", "f. 動態看板",
((cuser.uflag & MOVIE_FLAG) ? "是" : "否"));
- maxc = 'F';
+ maxc = 'f';
#ifdef PLAY_ANGEL
if( HAS_PERM(PERM_ANGEL) ){
- prints("%-30s%10s\n", "G. 開放小主人詢問",
+ prints("%-40s%10s\n", "g. 開放小主人詢問",
(REJECT_QUESTION ? "否" : "是"));
- prints("%-30s%10s\n", "H. 接受的小主人性別", am[ANGEL_STATUS()]);
+ prints("%-40s%10s\n", "h. 接受的小主人性別", am[ANGEL_STATUS()]);
maxc = 'H';
}
#endif
-#if defined(DBCSAWARE_GETDATA) || defined(DBCSAWARE_EDIT)
- prints("%-30s%10s\n", "I. 自動偵測全型中文",
- (!(cuser.uflag & RAWDBCS_FLAG) ? "是" : "否"));
- maxc = 'I';
+#ifdef DBCSAWARE
+ prints("%-40s%10s\n", "i. 自動偵測雙位元字集(如全型中文)",
+ ((cuser.uflag & DBCSAWARE_FLAG) ? "是" : "否"));
+ maxc = 'i';
#endif
- key = getkey("請按 [A-%c] 切換設定,按 [Return] 結束:", maxc);
+ key = getkey("請按 [a-%c] 切換設定,按 [Return] 結束:", maxc);
switch (tolower(key)) {
case 'a':{
@@ -359,9 +359,16 @@ void Customize(void)
}
#endif
-#if defined(DBCSAWARE_GETDATA) || defined(DBCSAWARE_EDIT)
+#ifdef DBCSAWARE
case 'i':
- cuser.uflag ^= RAWDBCS_FLAG;
+ if(key == 'I') // one more try
+ {
+ if(u_detectDBCSAwareEvilClient())
+ cuser.uflag &= ~DBCSAWARE_FLAG;
+ else
+ cuser.uflag |= DBCSAWARE_FLAG;
+ } else
+ cuser.uflag ^= DBCSAWARE_FLAG;
break;
#endif
@@ -1660,3 +1667,85 @@ u_list(void)
return 0;
}
+#ifdef DBCSAWARE
+
+/* detect if user is using an evil client that sends double
+ * keys for DBCS data.
+ * True if client is evil.
+ */
+
+int u_detectDBCSAwareEvilClient()
+{
+ int ret = 0;
+
+ clear();
+ move(1, 0);
+ outs(ANSI_RESET
+ "* 本站支援自動偵測中文字的移動與編輯,但有些連線程式(如xxMan)自己會\n"
+ " 偷偷處理、多送按鍵,於是便會造成" ANSI_COLOR(1;37)
+ "一次移動兩個中文字的現象。" ANSI_RESET "\n\n"
+ "* 讓連線程式處理移動容易造成許\多顯示及移動上的問題,所以我們建議您\n"
+ " 關閉該程式上的此項設定(通常叫「偵測(全型或雙位元組)中文」),\n"
+ " 讓 BBS 系統可以正確的控制你的畫面。\n\n"
+ "* 為了幫助您正確的設定,我們現在會自動偵測您的連線程式的設定。\n"
+ " 請在設定好連線程式成您偏好的模式後按" ANSI_COLOR(1;33)
+ "一下" ANSI_RESET "您鍵盤上的" ANSI_COLOR(1;33)
+ "←" ANSI_RESET "\n" ANSI_COLOR(1;36)
+ " (另外左右方向鍵或寫 BS/Backspace 的倒退鍵與 Del 刪除鍵均可)\n"
+ ANSI_RESET);
+
+ /* clear buffer */
+ while(num_in_buf() > 0)
+ igetch();
+
+ while (1)
+ {
+ int ch = 0;
+
+ move(12, 0);
+ outs("這是偵測區,您的游標會出現在"
+ ANSI_COLOR(7) "這裡" ANSI_RESET);
+ move(12, 15*2);
+ ch = igetch();
+ if(ch != KEY_LEFT && ch != KEY_RIGHT &&
+ ch != Ctrl('H') && ch != '\177')
+ {
+ move(14, 0);
+ outs("請按一下上面指定的鍵! 你按到別的鍵了!");
+ } else {
+ move(16, 0);
+ /* Actually you may also use num_in_buf here. those clients
+ * usually sends doubled keys together in one packet.
+ * However when I was writing this, a bug (existed for more than 3
+ * years) of num_in_buf forced me to write new wait_input.
+ * Anyway it is fixed now.
+ */
+ if(wait_input(0.1, 1))
+ // if(igetch() == ch)
+ // if (num_in_buf() > 0)
+ {
+ /* evil dbcs aware client */
+ outs("很遺憾,您的連線程式還是會自己亂動。"
+ "若日後因此造成您瀏覽上的問題本站恕不處理。\n\n"
+ "已設定為「讓您的連線程式處理游標移動」。\n");
+ ret = 1;
+ } else {
+ /* good non-dbcs aware client */
+ outs("您的連線程式似乎不會亂送按鍵。\n\n"
+ "已設定為「讓 BBS 伺服器直接處理游標移動」。\n");
+ ret = 0;
+ }
+ outs( "\n若想改變設定請至 個人設定區 → 個人化設定 → \n"
+ " 調整「自動偵測雙位元字集(如全型中文)」之設定");
+ while(num_in_buf())
+ igetch();
+ break;
+ }
+ }
+ pressanykey();
+ return ret;
+}
+#endif
+
+/* vim:sw=4
+ */