From 972816d0be5b788f61e9ec2e6ac432a55f0e9dc2 Mon Sep 17 00:00:00 2001 From: Pichu Chen Date: Fri, 29 Jan 2021 23:48:12 +0800 Subject: [PATCH 01/43] NOKILLWATERBALL: fix typo on comment --- sample/pttbbs.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sample/pttbbs.conf b/sample/pttbbs.conf index 4911b46a9..8980f1514 100644 --- a/sample/pttbbs.conf +++ b/sample/pttbbs.conf @@ -200,7 +200,7 @@ //#define SAFE_ARTICLE_DELETE /* 若定義, 則在傳送水球的時候, 不會直接 kill 該程序. 理論上可以減少大 - 量的系統負和 */ + 量的系統負荷 */ //#define NOKILLWATERBALL /* 若定義, 則在系統超過負荷的時候, 新接的連線會留住 OVERLOADBLOCKFDS From 09cf0bdca8edb701f5532b90e9a41211b1ac708b Mon Sep 17 00:00:00 2001 From: Chuan-Heng Hsiao Date: Wed, 3 Feb 2021 10:17:31 -0500 Subject: [PATCH 02/43] Provided offset, we should use SEEK_SET in PttLock Found some functions use PttLock after lseek but some use PttLock without lseek. Provided offset, we should use SEEK_SET in PttLock. The following lines use PttLock F_WRLCK: https://github.com/ptt/pttbbs/blob/master/common/sys/record.c#L84 (after lseek) https://github.com/ptt/pttbbs/blob/master/common/sys/record.c#L133 (after lseek) https://github.com/ptt/pttbbs/blob/master/common/sys/record.c#L195 (no lseek) https://github.com/ptt/pttbbs/blob/master/common/sys/record.c#L261 (no lseek) The following lines use PttLock F_UNLCK: https://github.com/ptt/pttbbs/blob/master/common/sys/record.c#L86 (after lseek) https://github.com/ptt/pttbbs/blob/master/common/sys/record.c#L149 (after lseek) https://github.com/ptt/pttbbs/blob/master/common/sys/record.c#L223 (after lseek) https://github.com/ptt/pttbbs/blob/master/common/sys/record.c#L275 (after lseek) https://github.com/ptt/pttbbs/issues/100 --- common/sys/lock.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/common/sys/lock.c b/common/sys/lock.c index 4b28bab1d..a8a6a04fc 100644 --- a/common/sys/lock.c +++ b/common/sys/lock.c @@ -7,13 +7,13 @@ * @param mode F_WRLCK, F_UNLCK */ void -PttLock(int fd, int start, int size, int mode) +PttLock(int fd, int offset, int size, int mode) { static struct flock lock_it; int ret; - lock_it.l_whence = SEEK_CUR;/* from current point */ - lock_it.l_start = start; /* -"- */ + lock_it.l_whence = SEEK_SET;/* provided offset, we should use SEEK_SET */ + lock_it.l_start = offset; /* -"- */ lock_it.l_len = size; /* length of data */ lock_it.l_type = mode; /* set exclusive/write lock */ lock_it.l_pid = 0; /* pid not actually interesting */ From 9acd539f25b0beca7bd2cdb8230995268a1ff449 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Wed, 28 Jul 2021 20:26:04 +0800 Subject: [PATCH 03/43] util/bbsrf: Check load before executing mbbsd It makes sense to check the CPU load in bbsrf, the lightweight shim for SSH connections, before executing the heavy mbbsd, which might end up exiting right away due to high CPU load. This alleviates CPU load during high bursts of connections. --- util/bbsrf.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/util/bbsrf.c b/util/bbsrf.c index 1589aee2a..1933ded45 100644 --- a/util/bbsrf.c +++ b/util/bbsrf.c @@ -49,6 +49,17 @@ static int showbanfile(const char *filename) return fp ? 0 : -1; } +static int checkload() +{ + if (cpuload(NULL) <= MAX_CPULOAD) + return 0; + + fputs("系統過載, 請稍後再來\n", stdout); + sleep(10); + + return 1; +} + int main(int argc, const char **argv) { int uid; @@ -77,6 +88,10 @@ int main(int argc, const char **argv) return 1; } + if (checkload()) { + return 1; + } + get_remote_ip(sizeof(remote_ip), remote_ip); if (is_utf8) From 103bce7b485f74d0bd06badf259e152da92980f8 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Sun, 28 Nov 2021 23:34:20 +0800 Subject: [PATCH 04/43] fromd: Allow both GeoIP2 and GeoIP database usage When GeoIP2 support was introduced, the Makefile was mistakenly written to enable one or the other, when in fact the code supports enabling both with GeoIP2 as the preferred database. Fix the Makefile so that both solutions are enabled. --- daemon/fromd/Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/daemon/fromd/Makefile b/daemon/fromd/Makefile index 4544d73d0..f69466841 100644 --- a/daemon/fromd/Makefile +++ b/daemon/fromd/Makefile @@ -15,7 +15,8 @@ FROMD_LDFLAGS = -levent .if ${ENABLE_MAXMIND_DB} == "y" CFLAGS += -DFROMD_USE_MAXMIND_DB FROMD_LDFLAGS += -lmaxminddb -.elif ${ENABLE_GEOIP_DB} == "y" +.endif +.if ${ENABLE_GEOIP_DB} == "y" CFLAGS += -DFROMD_USE_GEOIP_DB FROMD_LDFLAGS += -lGeoIP .endif From 92145d5316e007c6fce81234e3b146960b950b22 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Wed, 9 Mar 2022 23:38:04 +0800 Subject: [PATCH 05/43] mbbsd: Fix incorrect wording for "punishment" --- mbbsd/user.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mbbsd/user.c b/mbbsd/user.c index 363e936d1..5430450a4 100644 --- a/mbbsd/user.c +++ b/mbbsd/user.c @@ -420,8 +420,8 @@ violate_law(userec_t * u, int unum) passwd_sync_update(unum, u); if (*ans == '1' || *ans == '2') delete_allpost(u->userid); - post_violatelaw(u->userid, cuser.userid, reason, "罰單處份"); - mail_violatelaw(u->userid, "站務警察", reason, "罰單處份"); + post_violatelaw(u->userid, cuser.userid, reason, "罰單處分"); + mail_violatelaw(u->userid, "站務警察", reason, "罰單處分"); } pressanykey(); } From be31aa073749fc775d4539a4d7e4ffc587a61238 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Sun, 3 Apr 2022 15:30:43 +0800 Subject: [PATCH 06/43] mbbsd: register_sms: Fix misleading default for user agreement The user agreement requires an explicit "yes" (agree) from the user. However the prompt is misleading in that 'Y" is capitalized, implying that it is the default. This leads to users just pressing enter, and returning to the menu. Change 'Y" to lower case to signal that an explicit 'y' is required. --- mbbsd/register_sms.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mbbsd/register_sms.cc b/mbbsd/register_sms.cc index f30a7fe43..a4be0c6ff 100644 --- a/mbbsd/register_sms.cc +++ b/mbbsd/register_sms.cc @@ -348,7 +348,7 @@ void SmsValidation::Run() { vmsg("系統錯誤,請至 " BN_BUGREPORT " 看板回報"); return; } - if (vans("請問您接受使用條款嗎? (Y/n) ") != 'y') { + if (vans("請問您接受使用條款嗎? (y/N) ") != 'y') { vmsg("操作取消"); return; } From eeb56c15284fafcdda8b9ae594ec5f1c1c6c9b23 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Sun, 3 Apr 2022 15:33:17 +0800 Subject: [PATCH 07/43] util: Include 'var.h' for external symbols instead of declaring locally Some global variables were declared locally without an extern qualifier. This leads to link errors with newer toolchains. Instead, drop the declarations and include "var.h" which provides all the proper declarations. --- util/reaper.c | 3 ++- util/uhash_loader.c | 3 +-- util/writemoney.c | 4 +--- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/util/reaper.c b/util/reaper.c index dad0948a4..1477eeaae 100644 --- a/util/reaper.c +++ b/util/reaper.c @@ -1,7 +1,8 @@ #define _UTIL_C_ + #include "bbs.h" +#include "var.h" -time4_t now; #undef MAX_GUEST_LIFE #undef MAX_LIFE diff --git a/util/uhash_loader.c b/util/uhash_loader.c index cc7fdd3a8..c3d359f92 100644 --- a/util/uhash_loader.c +++ b/util/uhash_loader.c @@ -1,13 +1,12 @@ /* standalone uhash loader -- jochang */ #include "bbs.h" #include "fnv_hash.h" +#include "var.h" void userec_add_to_uhash(int n, userec_t *id, int onfly); void fill_uhash(int onfly); void load_uhash(void); -SHM_t *SHM; - int main() { setgid(BBSGID); diff --git a/util/writemoney.c b/util/writemoney.c index 55335c81b..e6bdf77e4 100644 --- a/util/writemoney.c +++ b/util/writemoney.c @@ -1,9 +1,7 @@ /* SHM 銝剔 money 券典神 .PASSWDS */ #define _UTIL_C_ #include "bbs.h" - -time4_t now; -extern SHM_t *SHM; +#include "var.h" int main() { From c02217e667a472edb6d2bf5c70c2657cf9d7d23d Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Sun, 15 May 2022 02:56:42 +0800 Subject: [PATCH 08/43] mbbsd: Allow admins to change users' contact email Recently some users either forgot their password or had their accounts stolen, but their contact emails were either not up-to-date, or had been changed by the hackers. To facilitate in account recovery, allow admins to change users' contact email so that they can then recovery their accounts via email. --- mbbsd/user.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 57 insertions(+), 2 deletions(-) diff --git a/mbbsd/user.c b/mbbsd/user.c index 5430450a4..ad6374a5c 100644 --- a/mbbsd/user.c +++ b/mbbsd/user.c @@ -673,7 +673,11 @@ uinfo_query(const char *orig_uid, int adminmode, int unum) } ans = vans(adminmode ? +#ifdef USEREC_EMAIL_IS_CONTACT + "(1)改資料(2)密碼(3)權限(4)砍帳(5)改ID(6)寵物(7)審判(8)退文(M)信箱(V)認證 " : +#else "(1)改資料(2)密碼(3)權限(4)砍帳(5)改ID(6)寵物(7)審判(8)退文(V)認證 [0]結束 " : +#endif #ifdef USEREC_EMAIL_IS_CONTACT "請選擇 (1)修改資料 (2)設定密碼 (M)聯絡信箱 (V)認證資料 [0]結束 "); #else @@ -709,9 +713,60 @@ uinfo_query(const char *orig_uid, int adminmode, int unum) switch (ans) { #ifdef USEREC_EMAIL_IS_CONTACT case 'm': - if (!adminmode) + if (!adminmode) { change_contact_email(); - return; + return; + } else { + char email[EMAILSZ]; + + move(y+1, 0); + outs("請注意在此修改聯絡信箱將跳過黑白名單檢查。"); + + if (!getdata_str(y++, 0, "請修改聯絡信箱: ", email, sizeof(email), + DOECHO, x.email)) + return; + + // Nothing changed. + if (!strcmp(email, x.email)) { + vmsg("E-Mail 與原本相同。"); + fail++; + break; + } + + char reason[30]; + while (!getdata(y++, 0, "請輸入理由以示負責:", + reason, sizeof(reason), DOECHO)); + + if (vans(msg_sure_ny) != 'y') { + fail++; + break; + } + + pre_confirmed = 1; + + // Log change for security reasons. + char title[TTLEN], buf[STRLEN + EMAILSZ*2 + sizeof(reason)]; + snprintf(title, sizeof(title), "%s 的聯絡信箱變更通知 (by %s)", + orig_uid, cuser.userid); + snprintf(buf, sizeof(buf), "站長 %s 修改 %s 的聯絡信箱 %s -> %s\n理由:%s\n", + cuser.userid, orig_uid, x.email, email, reason); + post_msg(BN_SECURITY, title, buf, "[系統安全局]"); + + // Notify user + strlcpy(title, "聯絡信箱變更通知", sizeof(title)); + snprintf(buf, sizeof(buf), "您的聯絡信箱已變更為 %s\n", email); + mail_log2id_text(orig_uid, title, buf, cuser.userid, 1); + + // Log to user log. + char logfn[PATHLEN]; + sethomefile(logfn, x.userid, FN_USERSECURITY); + log_filef(logfn, LOG_CREAT, "%s %s (ContactEmail) %s -> %s\n", + Cdatelite(&now), "[Admin]", x.email, email); + + strlcpy(x.email, email, sizeof(x.email)); + } + + break; #endif case '1': From ef662bd18ea1cad1c64f70ee8cdab4d8c0d30fd5 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Sun, 15 May 2022 03:01:16 +0800 Subject: [PATCH 09/43] util/permreport: Also report PERM_POLICE holders PERM_POLICE has some power for managing boards. Report current permission holders in the permission report so that they are known. --- util/permreport.c | 1 + 1 file changed, 1 insertion(+) diff --git a/util/permreport.c b/util/permreport.c index 0d34897d9..85f6d0e3b 100644 --- a/util/permreport.c +++ b/util/permreport.c @@ -32,6 +32,7 @@ int main(void) { PERMCHECK(PERM_POLICE_MAN), PERMCHECK(PERM_SYSSUPERSUBOP), PERMCHECK(PERM_ACCTREG), + PERMCHECK(PERM_POLICE), #if 0 PERMCHECK(PERM_SYSSUBOP), PERMCHECK(PERM_ACTION), From bc72011b1b46922ef9d3b70f8c0050a3d4c66280 Mon Sep 17 00:00:00 2001 From: "Wei-Cheng Yeh (IID)" Date: Sun, 3 Jul 2022 01:02:42 +0800 Subject: [PATCH 10/43] bbslua: fix bbs.getstr(n, 8) causing assertion failure When `bbs.getstr(n, echo)` is executed, the echo flag passes through the following functions: bl_getstr() -> getdata_str() -> getdata2vgetflag() However, getdata2vgetflag() asserts that echo != GCARRY (8), which did not hold when `bbs.getstr(n, 8)` was executed, thus causing program termination. GCARRY is now filtered out for avoiding the assertion failure. --- mbbsd/bbslua.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mbbsd/bbslua.c b/mbbsd/bbslua.c index 782660fd7..222edc729 100644 --- a/mbbsd/bbslua.c +++ b/mbbsd/bbslua.c @@ -411,6 +411,8 @@ bl_getstr(lua_State* L) if (n > 2) pmsg = lua_tostring(L, 3); + echo &= ~GCARRY; // avoid assertion failure + if (len < 2) len = 2; if (len >= (int)sizeof(buf)) From 667ce9a8969d84b4c97989e84fe3092ebbb04b9e Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Sat, 9 Jul 2022 00:54:13 +0800 Subject: [PATCH 11/43] Drop support for dietlibc dietlibc support has not been tested for a very long time. Drop support for it. If someone is interested, they can revert this commit and try to get things working again. --- common/diet/Makefile | 11 - common/diet/alloc.c | 255 ---------------- common/diet/random.c | 711 ------------------------------------------- common/diet/time.c | 20 -- include/bbs.h | 4 - include/cmdiet.h | 17 -- mbbsd/Makefile | 13 - 7 files changed, 1031 deletions(-) delete mode 100644 common/diet/Makefile delete mode 100644 common/diet/alloc.c delete mode 100644 common/diet/random.c delete mode 100644 common/diet/time.c delete mode 100644 include/cmdiet.h diff --git a/common/diet/Makefile b/common/diet/Makefile deleted file mode 100644 index 72c02fbe1..000000000 --- a/common/diet/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -# $Id$ - -SRCROOT:= ../.. -.include "$(SRCROOT)/pttbbs.mk" - -SRCS:= alloc.c random.c time.c -LIB:= cmdiet - -install: - -.include diff --git a/common/diet/alloc.c b/common/diet/alloc.c deleted file mode 100644 index d57104339..000000000 --- a/common/diet/alloc.c +++ /dev/null @@ -1,255 +0,0 @@ -#ifdef __dietlibc__ -/* - * malloc/free by O.Dreesen - * - * first TRY: - * lists w/magics - * and now the second TRY - * let the kernel map all the stuff (if there is something to do) - */ - -#include -#include -#include - -#include -#include -#include -#include -#include - -#include /* for PAGE_SIZE */ - - -/* -- HELPER CODE --------------------------------------------------------- */ - -#ifndef MAP_FAILED -#define MAP_FAILED ((void*)-1) -#endif - -#ifndef NULL -#define NULL ((void*)0) -#endif - -typedef struct { - void* next; - size_t size; -} __alloc_t; - -#define BLOCK_START(b) (((void*)(b))-sizeof(__alloc_t)) -#define BLOCK_RET(b) (((void*)(b))+sizeof(__alloc_t)) - -#define MEM_BLOCK_SIZE PAGE_SIZE -#define PAGE_ALIGN(s) (((s)+MEM_BLOCK_SIZE-1)&(unsigned long)(~(MEM_BLOCK_SIZE-1))) - -/* a simple mmap :) */ -#if defined(__i386__) -#define REGPARM(x) __attribute__((regparm(x))) -#else -#define REGPARM(x) -#endif - -static void REGPARM(1) *do_mmap(size_t size) { - return mmap(0, size, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE, -1, (size_t)0); -} - -/* -- SMALL MEM ----------------------------------------------------------- */ - -static __alloc_t* __small_mem[8]; - -static int smallalloc[8]; -static int smallalloc_max[8]; - -#define __SMALL_NR(i) (MEM_BLOCK_SIZE/(i)) - -#define __MIN_SMALL_SIZE __SMALL_NR(256) /* 16 / 32 */ -#define __MAX_SMALL_SIZE __SMALL_NR(2) /* 2048 / 4096 */ - -#define GET_SIZE(s) (__MIN_SMALL_SIZE<>__ind_shift(); - while(size) { size>>=1; ++idx; } -// } - return idx; -} - -/* small mem */ -static void __small_free(void*_ptr,size_t _size) REGPARM(2); - -static void REGPARM(2) __small_free(void*_ptr,size_t _size) { - __alloc_t* ptr=BLOCK_START(_ptr); - size_t size=_size; - size_t idx=get_index(size); - - memset(ptr,0,size); /* allways zero out small mem */ - - ptr->next=__small_mem[idx]; - __small_mem[idx]=ptr; - - smallalloc[idx]--; - - if (MEM_BLOCK_SIZE == PAGE_SIZE && - smallalloc[idx] == 0 && - smallalloc_max[idx] < __SMALL_NR(size)) { - __alloc_t* p = __small_mem[idx]; - __alloc_t* ph = p - (size_t)p%PAGE_SIZE; - munmap(ph, MEM_BLOCK_SIZE); - __small_mem[idx] = 0; - } -} - -static void* REGPARM(1) __small_malloc(size_t _size) { - __alloc_t *ptr; - size_t size=_size; - size_t idx; - - idx=get_index(size); - ptr=__small_mem[idx]; - - if (ptr==0) { /* no free blocks ? */ - register int i,nr; - ptr=do_mmap(MEM_BLOCK_SIZE); - if (ptr==MAP_FAILED) return MAP_FAILED; - - __small_mem[idx]=ptr; - - nr=__SMALL_NR(size)-1; - for (i=0;inext=(((void*)ptr)+size); - ptr=ptr->next; - } - ptr->next=0; - - ptr=__small_mem[idx]; - } - - /* get a free block */ - __small_mem[idx]=ptr->next; - ptr->next=0; - - smallalloc[idx]++; - if(smallalloc[idx] > smallalloc_max[idx]) - smallalloc_max[idx] = smallalloc[idx]; - - return ptr; -} - -/* -- PUBLIC FUNCTIONS ---------------------------------------------------- */ - -static void _alloc_libc_free(void *ptr) { - register size_t size; - if (ptr) { - size=((__alloc_t*)BLOCK_START(ptr))->size; - if (size) { - if (size<=__MAX_SMALL_SIZE) - __small_free(ptr,size); - else - munmap(BLOCK_START(ptr),size); - } - } -} -void __libc_free(void *ptr) __attribute__((alias("_alloc_libc_free"))); -void free(void *ptr) __attribute__((weak,alias("_alloc_libc_free"))); -void if_freenameindex(void* ptr) __attribute__((alias("free"))); - -#ifdef WANT_MALLOC_ZERO -static __alloc_t zeromem[2]; -#endif - -static void* _alloc_libc_malloc(size_t size) { - __alloc_t* ptr; - size_t need; -#ifdef WANT_MALLOC_ZERO - if (!size) return BLOCK_RET(zeromem); -#else - if (!size) goto err_out; -#endif - size+=sizeof(__alloc_t); - if (sizesize=need; - return BLOCK_RET(ptr); -err_out: - (*__errno_location())=ENOMEM; - return 0; -} -void* __libc_malloc(size_t size) __attribute__((alias("_alloc_libc_malloc"))); -void* malloc(size_t size) __attribute__((weak,alias("_alloc_libc_malloc"))); - -void* __libc_calloc(size_t nmemb, size_t _size); -void* __libc_calloc(size_t nmemb, size_t _size) { - register size_t size=_size*nmemb; - if (nmemb && size/nmemb!=_size) { - (*__errno_location())=ENOMEM; - return 0; - } - return malloc(size); -} -void* calloc(size_t nmemb, size_t _size) __attribute__((weak,alias("__libc_calloc"))); - -void* __libc_realloc(void* ptr, size_t _size); -void* __libc_realloc(void* ptr, size_t _size) { - register size_t size=_size; - if (ptr) { - if (size) { - __alloc_t* tmp=BLOCK_START(ptr); - size+=sizeof(__alloc_t); - if (sizesize!=size) { - if ((tmp->size<=__MAX_SMALL_SIZE)) { - void *new=_alloc_libc_malloc(_size); - if (new) { - register __alloc_t* foo=BLOCK_START(new); - size=foo->size; - if (size>tmp->size) size=tmp->size; - if (size) memcpy(new,ptr,size-sizeof(__alloc_t)); - _alloc_libc_free(ptr); - } - ptr=new; - } - else { - register __alloc_t* foo; - size=PAGE_ALIGN(size); - foo=mremap(tmp,tmp->size,size,MREMAP_MAYMOVE); - if (foo==MAP_FAILED) { -retzero: - (*__errno_location())=ENOMEM; - ptr=0; - } - else { - foo->size=size; - ptr=BLOCK_RET(foo); - } - } - } - } - else { /* size==0 */ - _alloc_libc_free(ptr); - ptr = NULL; - } - } - else { /* ptr==0 */ - if (size) { - ptr=_alloc_libc_malloc(size); - } - } - return ptr; -} -void* realloc(void* ptr, size_t size) __attribute__((weak,alias("__libc_realloc"))); -#endif diff --git a/common/diet/random.c b/common/diet/random.c deleted file mode 100644 index dd369c41c..000000000 --- a/common/diet/random.c +++ /dev/null @@ -1,711 +0,0 @@ -#ifdef __dietlibc__ -/* - Copyright (C) 1995 Free Software Foundation - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307 USA. */ - -/* - Copyright (C) 1983 Regents of the University of California. - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - 4. Neither the name of the University nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - SUCH DAMAGE.*/ - -/* - * This is derived from the Berkeley source: - * @(#)random.c 5.5 (Berkeley) 7/6/88 - * It was reworked for the GNU C Library by Roland McGrath. - * Rewritten to be reentrant by Ulrich Drepper, 1995 - */ - -#include -#include -#include -#include -struct random_data - { - int32_t *fptr; /* Front pointer. */ - int32_t *rptr; /* Rear pointer. */ - int32_t *state; /* Array of state values. */ - int rand_type; /* Type of random number generator. */ - int rand_deg; /* Degree of random number generator. */ - int rand_sep; /* Distance between front and rear. */ - int32_t *end_ptr; /* Pointer behind state table. */ - }; -int __random_r (struct random_data *buf, int32_t *result); - - - -/* An improved random number generation package. In addition to the standard - rand()/srand() like interface, this package also has a special state info - interface. The initstate() routine is called with a seed, an array of - bytes, and a count of how many bytes are being passed in; this array is - then initialized to contain information for random number generation with - that much state information. Good sizes for the amount of state - information are 32, 64, 128, and 256 bytes. The state can be switched by - calling the setstate() function with the same array as was initialized - with initstate(). By default, the package runs with 128 bytes of state - information and generates far better random numbers than a linear - congruential generator. If the amount of state information is less than - 32 bytes, a simple linear congruential R.N.G. is used. Internally, the - state information is treated as an array of longs; the zeroth element of - the array is the type of R.N.G. being used (small integer); the remainder - of the array is the state information for the R.N.G. Thus, 32 bytes of - state information will give 7 longs worth of state information, which will - allow a degree seven polynomial. (Note: The zeroth word of state - information also has some other information stored in it; see setstate - for details). The random number generation technique is a linear feedback - shift register approach, employing trinomials (since there are fewer terms - to sum up that way). In this approach, the least significant bit of all - the numbers in the state table will act as a linear feedback shift register, - and will have period 2^deg - 1 (where deg is the degree of the polynomial - being used, assuming that the polynomial is irreducible and primitive). - The higher order bits will have longer periods, since their values are - also influenced by pseudo-random carries out of the lower bits. The - total period of the generator is approximately deg*(2**deg - 1); thus - doubling the amount of state information has a vast influence on the - period of the generator. Note: The deg*(2**deg - 1) is an approximation - only good for large deg, when the period of the shift register is the - dominant factor. With deg equal to seven, the period is actually much - longer than the 7*(2**7 - 1) predicted by this formula. */ - - - -/* For each of the currently supported random number generators, we have a - break value on the amount of state information (you need at least this many - bytes of state info to support this random number generator), a degree for - the polynomial (actually a trinomial) that the R.N.G. is based on, and - separation between the two lower order coefficients of the trinomial. */ - -/* Linear congruential. */ -#define TYPE_0 0 -#define BREAK_0 8 -#define DEG_0 0 -#define SEP_0 0 - -/* x**7 + x**3 + 1. */ -#define TYPE_1 1 -#define BREAK_1 32 -#define DEG_1 7 -#define SEP_1 3 - -/* x**15 + x + 1. */ -#define TYPE_2 2 -#define BREAK_2 64 -#define DEG_2 15 -#define SEP_2 1 - -/* x**31 + x**3 + 1. */ -#define TYPE_3 3 -#define BREAK_3 128 -#define DEG_3 31 -#define SEP_3 3 - -/* x**63 + x + 1. */ -#define TYPE_4 4 -#define BREAK_4 256 -#define DEG_4 63 -#define SEP_4 1 - - -/* Array versions of the above information to make code run faster. - Relies on fact that TYPE_i == i. */ - -#define MAX_TYPES 5 /* Max number of types above. */ - -struct random_poly_info -{ - int seps[MAX_TYPES]; - int degrees[MAX_TYPES]; -}; - -static const struct random_poly_info random_poly_info = -{ - { SEP_0, SEP_1, SEP_2, SEP_3, SEP_4 }, - { DEG_0, DEG_1, DEG_2, DEG_3, DEG_4 } -}; - - - - -/* Initialize the random number generator based on the given seed. If the - type is the trivial no-state-information type, just remember the seed. - Otherwise, initializes state[] based on the given "seed" via a linear - congruential generator. Then, the pointers are set to known locations - that are exactly rand_sep places apart. Lastly, it cycles the state - information a given number of times to get rid of any initial dependencies - introduced by the L.C.R.N.G. Note that the initialization of randtbl[] - for default usage relies on values produced by this routine. */ -int -__srandom_r (seed, buf) - unsigned int seed; - struct random_data *buf; -{ - int type; - int32_t *state; - long int i; - long int word; - int32_t *dst; - int kc; - - if (buf == NULL) - goto fail; - type = buf->rand_type; - if ((unsigned int) type >= MAX_TYPES) - goto fail; - - state = buf->state; - /* We must make sure the seed is not 0. Take arbitrarily 1 in this case. */ - if (seed == 0) - seed = 1; - state[0] = seed; - if (type == TYPE_0) - goto done; - - dst = state; - word = seed; - kc = buf->rand_deg; - for (i = 1; i < kc; ++i) - { - /* This does: - state[i] = (16807 * state[i - 1]) % 2147483647; - but avoids overflowing 31 bits. */ - long int hi = word / 127773; - long int lo = word % 127773; - word = 16807 * lo - 2836 * hi; - if (word < 0) - word += 2147483647; - *++dst = word; - } - - buf->fptr = &state[buf->rand_sep]; - buf->rptr = &state[0]; - kc *= 10; - while (--kc >= 0) - { - int32_t discard; - (void) __random_r (buf, &discard); - } - - done: - return 0; - - fail: - return -1; -} - - -/* Initialize the state information in the given array of N bytes for - future random number generation. Based on the number of bytes we - are given, and the break values for the different R.N.G.'s, we choose - the best (largest) one we can and set things up for it. srandom is - then called to initialize the state information. Note that on return - from srandom, we set state[-1] to be the type multiplexed with the current - value of the rear pointer; this is so successive calls to initstate won't - lose this information and will be able to restart with setstate. - Note: The first thing we do is save the current state, if any, just like - setstate so that it doesn't matter when initstate is called. - Returns a pointer to the old state. */ -int -__initstate_r (seed, arg_state, n, buf) - unsigned int seed; - char *arg_state; - size_t n; - struct random_data *buf; -{ - int type; - int degree; - int separation; - int32_t *state; - - if (buf == NULL) - goto fail; - - if (n >= BREAK_3) - type = n < BREAK_4 ? TYPE_3 : TYPE_4; - else if (n < BREAK_1) - { - if (n < BREAK_0) - { - __set_errno (EINVAL); - goto fail; - } - type = TYPE_0; - } - else - type = n < BREAK_2 ? TYPE_1 : TYPE_2; - - degree = random_poly_info.degrees[type]; - separation = random_poly_info.seps[type]; - - buf->rand_type = type; - buf->rand_sep = separation; - buf->rand_deg = degree; - state = &((int32_t *) arg_state)[1]; /* First location. */ - /* Must set END_PTR before srandom. */ - buf->end_ptr = &state[degree]; - - buf->state = state; - - __srandom_r (seed, buf); - - state[-1] = TYPE_0; - if (type != TYPE_0) - state[-1] = (buf->rptr - state) * MAX_TYPES + type; - - return 0; - - fail: - __set_errno (EINVAL); - return -1; -} - - -/* Restore the state from the given state array. - Note: It is important that we also remember the locations of the pointers - in the current state information, and restore the locations of the pointers - from the old state information. This is done by multiplexing the pointer - location into the zeroth word of the state information. Note that due - to the order in which things are done, it is OK to call setstate with the - same state as the current state - Returns a pointer to the old state information. */ -int -__setstate_r (arg_state, buf) - char *arg_state; - struct random_data *buf; -{ - int32_t *new_state = 1 + (int32_t *) arg_state; - int type; - int old_type; - int32_t *old_state; - int degree; - int separation; - - if (arg_state == NULL || buf == NULL) - goto fail; - - old_type = buf->rand_type; - old_state = buf->state; - if (old_type == TYPE_0) - old_state[-1] = TYPE_0; - else - old_state[-1] = (MAX_TYPES * (buf->rptr - old_state)) + old_type; - - type = new_state[-1] % MAX_TYPES; - if (type < TYPE_0 || type > TYPE_4) - goto fail; - - buf->rand_deg = degree = random_poly_info.degrees[type]; - buf->rand_sep = separation = random_poly_info.seps[type]; - buf->rand_type = type; - - if (type != TYPE_0) - { - int rear = new_state[-1] / MAX_TYPES; - buf->rptr = &new_state[rear]; - buf->fptr = &new_state[(rear + separation) % degree]; - } - buf->state = new_state; - /* Set end_ptr too. */ - buf->end_ptr = &new_state[degree]; - - return 0; - - fail: - __set_errno (EINVAL); - return -1; -} - - -/* If we are using the trivial TYPE_0 R.N.G., just do the old linear - congruential bit. Otherwise, we do our fancy trinomial stuff, which is the - same in all the other cases due to all the global variables that have been - set up. The basic operation is to add the number at the rear pointer into - the one at the front pointer. Then both pointers are advanced to the next - location cyclically in the table. The value returned is the sum generated, - reduced to 31 bits by throwing away the "least random" low bit. - Note: The code takes advantage of the fact that both the front and - rear pointers can't wrap on the same call by not testing the rear - pointer if the front one has wrapped. Returns a 31-bit random number. */ - -int -__random_r (buf, result) - struct random_data *buf; - int32_t *result; -{ - int32_t *state; - - if (buf == NULL || result == NULL) - goto fail; - - state = buf->state; - - if (buf->rand_type == TYPE_0) - { - int32_t val = state[0]; - val = ((state[0] * 1103515245) + 12345) & 0x7fffffff; - state[0] = val; - *result = val; - } - else - { - int32_t *fptr = buf->fptr; - int32_t *rptr = buf->rptr; - int32_t *end_ptr = buf->end_ptr; - int32_t val; - - val = *fptr += *rptr; - /* Chucking least random bit. */ - *result = (val >> 1) & 0x7fffffff; - ++fptr; - if (fptr >= end_ptr) - { - fptr = state; - ++rptr; - } - else - { - ++rptr; - if (rptr >= end_ptr) - rptr = state; - } - buf->fptr = fptr; - buf->rptr = rptr; - } - return 0; - - fail: - __set_errno (EINVAL); - return -1; -} - -/* Copyright (C) 1995 Free Software Foundation - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307 USA. */ - -/* - * This is derived from the Berkeley source: - * @(#)random.c 5.5 (Berkeley) 7/6/88 - * It was reworked for the GNU C Library by Roland McGrath. - * Rewritten to use reentrant functions by Ulrich Drepper, 1995. - */ - -/* - Copyright (C) 1983 Regents of the University of California. - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - 4. Neither the name of the University nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - SUCH DAMAGE.*/ - -#include -#include -#include - - -/* An improved random number generation package. In addition to the standard - rand()/srand() like interface, this package also has a special state info - interface. The initstate() routine is called with a seed, an array of - bytes, and a count of how many bytes are being passed in; this array is - then initialized to contain information for random number generation with - that much state information. Good sizes for the amount of state - information are 32, 64, 128, and 256 bytes. The state can be switched by - calling the setstate() function with the same array as was initialized - with initstate(). By default, the package runs with 128 bytes of state - information and generates far better random numbers than a linear - congruential generator. If the amount of state information is less than - 32 bytes, a simple linear congruential R.N.G. is used. Internally, the - state information is treated as an array of longs; the zeroth element of - the array is the type of R.N.G. being used (small integer); the remainder - of the array is the state information for the R.N.G. Thus, 32 bytes of - state information will give 7 longs worth of state information, which will - allow a degree seven polynomial. (Note: The zeroth word of state - information also has some other information stored in it; see setstate - for details). The random number generation technique is a linear feedback - shift register approach, employing trinomials (since there are fewer terms - to sum up that way). In this approach, the least significant bit of all - the numbers in the state table will act as a linear feedback shift register, - and will have period 2^deg - 1 (where deg is the degree of the polynomial - being used, assuming that the polynomial is irreducible and primitive). - The higher order bits will have longer periods, since their values are - also influenced by pseudo-random carries out of the lower bits. The - total period of the generator is approximately deg*(2**deg - 1); thus - doubling the amount of state information has a vast influence on the - period of the generator. Note: The deg*(2**deg - 1) is an approximation - only good for large deg, when the period of the shift register is the - dominant factor. With deg equal to seven, the period is actually much - longer than the 7*(2**7 - 1) predicted by this formula. */ - - - -/* For each of the currently supported random number generators, we have a - break value on the amount of state information (you need at least this many - bytes of state info to support this random number generator), a degree for - the polynomial (actually a trinomial) that the R.N.G. is based on, and - separation between the two lower order coefficients of the trinomial. */ - -/* Linear congruential. */ -#define TYPE_0 0 -#define BREAK_0 8 -#define DEG_0 0 -#define SEP_0 0 - -/* x**7 + x**3 + 1. */ -#define TYPE_1 1 -#define BREAK_1 32 -#define DEG_1 7 -#define SEP_1 3 - -/* x**15 + x + 1. */ -#define TYPE_2 2 -#define BREAK_2 64 -#define DEG_2 15 -#define SEP_2 1 - -/* x**31 + x**3 + 1. */ -#define TYPE_3 3 -#define BREAK_3 128 -#define DEG_3 31 -#define SEP_3 3 - -/* x**63 + x + 1. */ -#define TYPE_4 4 -#define BREAK_4 256 -#define DEG_4 63 -#define SEP_4 1 - - -/* Array versions of the above information to make code run faster. - Relies on fact that TYPE_i == i. */ - -#define MAX_TYPES 5 /* Max number of types above. */ - - -/* Initially, everything is set up as if from: - initstate(1, randtbl, 128); - Note that this initialization takes advantage of the fact that srandom - advances the front and rear pointers 10*rand_deg times, and hence the - rear pointer which starts at 0 will also end up at zero; thus the zeroth - element of the state information, which contains info about the current - position of the rear pointer is just - (MAX_TYPES * (rptr - state)) + TYPE_3 == TYPE_3. */ - -static int32_t randtbl[DEG_3 + 1] = - { - TYPE_3, - - -1726662223, 379960547, 1735697613, 1040273694, 1313901226, - 1627687941, -179304937, -2073333483, 1780058412, -1989503057, - -615974602, 344556628, 939512070, -1249116260, 1507946756, - -812545463, 154635395, 1388815473, -1926676823, 525320961, - -1009028674, 968117788, -123449607, 1284210865, 435012392, - -2017506339, -911064859, -370259173, 1132637927, 1398500161, - -205601318, - }; - - -static struct random_data unsafe_state = - { -/* FPTR and RPTR are two pointers into the state info, a front and a rear - pointer. These two pointers are always rand_sep places aparts, as they - cycle through the state information. (Yes, this does mean we could get - away with just one pointer, but the code for random is more efficient - this way). The pointers are left positioned as they would be from the call: - initstate(1, randtbl, 128); - (The position of the rear pointer, rptr, is really 0 (as explained above - in the initialization of randtbl) because the state table pointer is set - to point to randtbl[1] (as explained below).) */ - - .fptr = &randtbl[SEP_3 + 1], - .rptr = &randtbl[1], - -/* The following things are the pointer to the state information table, - the type of the current generator, the degree of the current polynomial - being used, and the separation between the two pointers. - Note that for efficiency of random, we remember the first location of - the state information, not the zeroth. Hence it is valid to access - state[-1], which is used to store the type of the R.N.G. - Also, we remember the last location, since this is more efficient than - indexing every time to find the address of the last element to see if - the front and rear pointers have wrapped. */ - - .state = &randtbl[1], - - .rand_type = TYPE_3, - .rand_deg = DEG_3, - .rand_sep = SEP_3, - - .end_ptr = &randtbl[sizeof (randtbl) / sizeof (randtbl[0])] -}; - -/* POSIX.1c requires that there is mutual exclusion for the `rand' and - `srand' functions to prevent concurrent calls from modifying common - data. */ - -/* Initialize the random number generator based on the given seed. If the - type is the trivial no-state-information type, just remember the seed. - Otherwise, initializes state[] based on the given "seed" via a linear - congruential generator. Then, the pointers are set to known locations - that are exactly rand_sep places apart. Lastly, it cycles the state - information a given number of times to get rid of any initial dependencies - introduced by the L.C.R.N.G. Note that the initialization of randtbl[] - for default usage relies on values produced by this routine. */ -void -__srandom (x) - unsigned int x; -{ - (void) __srandom_r (x, &unsafe_state); -} - - -/* Initialize the state information in the given array of N bytes for - future random number generation. Based on the number of bytes we - are given, and the break values for the different R.N.G.'s, we choose - the best (largest) one we can and set things up for it. srandom is - then called to initialize the state information. Note that on return - from srandom, we set state[-1] to be the type multiplexed with the current - value of the rear pointer; this is so successive calls to initstate won't - lose this information and will be able to restart with setstate. - Note: The first thing we do is save the current state, if any, just like - setstate so that it doesn't matter when initstate is called. - Returns a pointer to the old state. */ -char * -__initstate (seed, arg_state, n) - unsigned int seed; - char *arg_state; - size_t n; -{ - int32_t *ostate; - - - ostate = &unsafe_state.state[-1]; - - __initstate_r (seed, arg_state, n, &unsafe_state); - - - return (char *) ostate; -} - - -/* Restore the state from the given state array. - Note: It is important that we also remember the locations of the pointers - in the current state information, and restore the locations of the pointers - from the old state information. This is done by multiplexing the pointer - location into the zeroth word of the state information. Note that due - to the order in which things are done, it is OK to call setstate with the - same state as the current state - Returns a pointer to the old state information. */ -char * -__setstate (arg_state) - char *arg_state; -{ - int32_t *ostate; - - - ostate = &unsafe_state.state[-1]; - - if (__setstate_r (arg_state, &unsafe_state) < 0) - ostate = NULL; - - - return (char *) ostate; -} - - -/* If we are using the trivial TYPE_0 R.N.G., just do the old linear - congruential bit. Otherwise, we do our fancy trinomial stuff, which is the - same in all the other cases due to all the global variables that have been - set up. The basic operation is to add the number at the rear pointer into - the one at the front pointer. Then both pointers are advanced to the next - location cyclically in the table. The value returned is the sum generated, - reduced to 31 bits by throwing away the "least random" low bit. - Note: The code takes advantage of the fact that both the front and - rear pointers can't wrap on the same call by not testing the rear - pointer if the front one has wrapped. Returns a 31-bit random number. */ - -long int -__random (void) -{ - int32_t retval; - - - (void) __random_r (&unsafe_state, &retval); - - - return retval; -} - -long int glibc_random(void) { return __random(); } -void glibc_srandom(unsigned int seed) { __srandom(seed); } -char *glibc_initstate(unsigned int seed, char *state, size_t n) { return __initstate(seed,state,n); } -char *glibc_setstate(char *state) { return __setstate(state); } -#endif diff --git a/common/diet/time.c b/common/diet/time.c deleted file mode 100644 index 11f963c31..000000000 --- a/common/diet/time.c +++ /dev/null @@ -1,20 +0,0 @@ -#ifdef __dietlibc__ -#include -#warning "hardcoded time zone as GMT+8!" -extern void __maplocaltime(void); -extern time_t __tzfile_map(time_t t, int *isdst, int forward); -extern time_t timegm(struct tm *const t); - -time_t mktime(register struct tm* const t) { - time_t x=timegm(t); - x-=8*3600; - return x; -} - -struct tm* localtime_r(const time_t* t, struct tm* r) { - time_t tmp; - tmp=*t; - tmp+=8*3600; - return gmtime_r(&tmp,r); -} -#endif diff --git a/include/bbs.h b/include/bbs.h index 7892f646a..8514feb42 100644 --- a/include/bbs.h +++ b/include/bbs.h @@ -38,10 +38,6 @@ extern "C" { #include "cmsys.h" #include "cmbbs.h" -#ifdef __dietlibc__ -#include "cmdiet.h" -#endif - #include "ansi.h" #include "vtkbd.h" #include "vtuikit.h" diff --git a/include/cmdiet.h b/include/cmdiet.h deleted file mode 100644 index 3e56a1fe9..000000000 --- a/include/cmdiet.h +++ /dev/null @@ -1,17 +0,0 @@ -/* $Id$ */ - -#ifndef CMDIET_H -#define CMDIET_H - -#ifdef __dietlibc__ -#define random glibc_random -#define srandom glibc_srandom -#define initstate glibc_initstate -#define setstate glibc_setstate -long int random(void); -void srandom(unsigned int seed); -char *initstate(unsigned int seed, char *state, size_t n); -char *setstate(char *state); -#endif - -#endif diff --git a/mbbsd/Makefile b/mbbsd/Makefile index 70d8a9fc4..ae98b9756 100644 --- a/mbbsd/Makefile +++ b/mbbsd/Makefile @@ -24,16 +24,6 @@ OBJS:= admin.o assess.o edit.o xyz.o var.o vote.o voteboard.o comments.o \ $(UIOBJS) $(PAGEROBJS) $(PLUGOBJS) \ $(CHESSOBJS) $(GAMEOBJS) -####################################################################### -# special library (DIET) configuration -####################################################################### - -.if defined(DIET) -LDFLAGS+= -L$(SRCROOT)/common/diet -LDLIBS+= -ldiet -DIETCC:= diet -Os -.endif - # reduce .bss align overhead .if !defined(DEBUG) && $(OSTYPE)!="Darwin" LDFLAGS+=-Wl,--sort-common @@ -119,9 +109,6 @@ testsz: $(SRCROOT)/pttbbs.conf $(SRCROOT)/include/*.h testsz.c @./testsz @printf "\033[0;1;32mData size configuration OK\033[m\n" -mbbsd.o: mbbsd.c $(SRCROOT)/include/var.h - $(DIETCC) $(CC) $(CFLAGS) -c $< - ctags: ctags *.c $(SRCROOT)/include/*.h $(SRCROOT)/common/sys/*.c $(SRCROOT)/common/bbs/*.c From e9a13292e3545adb7614a8f8915ccd117e923971 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Sat, 9 Jul 2022 12:40:47 +0800 Subject: [PATCH 12/43] mbbsd: Reimplement AccountRecovery::NotifyUser() in C This avoids pulling in C++ just to reuse a single function. --- include/proto.h | 1 + mbbsd/mail.c | 17 +++++++++++++++++ mbbsd/recover.cc | 12 +----------- 3 files changed, 19 insertions(+), 11 deletions(-) diff --git a/include/proto.h b/include/proto.h index 2a56c5d94..afd5f0e6e 100644 --- a/include/proto.h +++ b/include/proto.h @@ -389,6 +389,7 @@ int m_read(void); int doforward(const char *direct, const fileheader_t *fh, int mode); int mail_reply(int ent, fileheader_t *fhdr, const char *direct); int bsmtp(const char *fpath, const char *title, const char *rcpt, const char *from); +int notify_password_change(const char *userid, const char *email); void hold_mail(const char *fpath, const char *receiver, const char *title); void m_init(void); int chkmailbox(void); diff --git a/mbbsd/mail.c b/mbbsd/mail.c index 94bfb56e7..b8ef61e72 100644 --- a/mbbsd/mail.c +++ b/mbbsd/mail.c @@ -2575,3 +2575,20 @@ bsmtp(const char *fpath, const char *title, const char *rcpt, const char *from) return chrono; } #endif /* USE_BSMTP */ + +/* + * Simple wrapper to send password changed notification letter to + * designated email address. + */ +int notify_password_change(const char *userid, const char *email) +{ + char subject[128]; + int ret; + + snprintf(subject, sizeof(subject), " %s - %s (%s) - 密碼已更變", + BBSNAME, userid, fromhost); + + ret = bsmtp("etc/passwdchanged", subject, email, "non-exist"); + + return ret > 0 ? 0 : -1; +} diff --git a/mbbsd/recover.cc b/mbbsd/recover.cc index 086bc9dd5..1cef98a4e 100644 --- a/mbbsd/recover.cc +++ b/mbbsd/recover.cc @@ -157,16 +157,6 @@ void AccountRecovery::LogToSecurity(const UserHandle &user, post_msg(BN_SECURITY, title.c_str(), msg.c_str(), "[系統安全局]"); } -// static -void AccountRecovery::NotifyUser(const std::string &userid, - const std::string &email) { - std::string subject; - subject.append(" " BBSNAME " - "); - subject.append(userid); - subject.append(", 您的密碼已更變"); - bsmtp("etc/passwdchanged", subject.c_str(), email.c_str(), "non-exist"); -} - // static std::string AccountRecovery::GenCode(size_t len) { std::string s(len, '\0'); @@ -316,7 +306,7 @@ void AccountRecovery::ResetPasswd() { LogToSecurity(user_.value(), email_); for (const auto &email : all_emails_) { - NotifyUser(user_->userid, email); + notify_password_change(user_->userid.c_str(), email.c_str()); } // Log to user security. From 1073120a7d11ca721f80504994ac932c20536338 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Sat, 9 Jul 2022 12:47:55 +0800 Subject: [PATCH 13/43] mbbsd: Send email notification to user when password is changed An email notification will be sent to the user's email address on file. This is not sent if there is no email on file. Neither is it sent if an admin changed the password, to avoid confusing users. --- mbbsd/user.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/mbbsd/user.c b/mbbsd/user.c index ad6374a5c..e0ad71020 100644 --- a/mbbsd/user.c +++ b/mbbsd/user.c @@ -1107,6 +1107,12 @@ uinfo_query(const char *orig_uid, int adminmode, int unum) log_filef(logfn, LOG_CREAT, "%s %s (Passwd)\n", Cdatelite(&now), adminmode ? "[Admin]" : fromhost); } + + // Send notification email if user has email set. + // Only do so if not Admin to avoid confusing user. + if (user_has_email(&cuser) && !adminmode) + notify_password_change(cuser.userid, cuser.email); + break; case '3': From 26b55a036bef4025c3009cf66eff5e1c0d3124b1 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Tue, 12 Jul 2022 00:16:03 +0800 Subject: [PATCH 14/43] mbbsd: Check register email address harder The register email address checking is really bad. It only checks for one and only one '@'. The codebase already has is_valid_email(), which does a better check. Use that instead. --- mbbsd/register.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mbbsd/register.c b/mbbsd/register.c index d5cf462b3..7e8336b78 100644 --- a/mbbsd/register.c +++ b/mbbsd/register.c @@ -992,8 +992,8 @@ normalize_email(char *email) { char *c = strchr(email, '@'); - // reject no '@' or multiple '@' - if (c == NULL || c != strrchr(email, '@')) + // reject no '@' or invalid email address + if (!c || !is_valid_email(email)) return false; // domain tolower From 3fe93cceade2d195066de2d925659bef267dcc2c Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Tue, 12 Jul 2022 00:25:36 +0800 Subject: [PATCH 15/43] mbbsd: Drop user_has_email() user_has_email() calls normalize_email() on a copy of the user's email address, which then does str_lower() on that copy. This is unnecessary, since we only want to check the validaty of the email address. Replace all invocations with a direct call to is_valid_email() and drop user_has_email(). --- include/proto.h | 1 - mbbsd/register.c | 8 -------- mbbsd/user.c | 4 ++-- 3 files changed, 2 insertions(+), 11 deletions(-) diff --git a/include/proto.h b/include/proto.h index afd5f0e6e..207802a82 100644 --- a/include/proto.h +++ b/include/proto.h @@ -577,7 +577,6 @@ int regform_estimate_queuesize(); void ensure_user_agreement_version(); void new_register(void); void check_register(void); -bool user_has_email(const userec_t *u); bool check_email_allow_reject_lists( char *email, const char **errmsg, const char **notice_file); void register_mail_complete_and_exit(); diff --git a/mbbsd/register.c b/mbbsd/register.c index 7e8336b78..e150281bf 100644 --- a/mbbsd/register.c +++ b/mbbsd/register.c @@ -1002,14 +1002,6 @@ normalize_email(char *email) return true; } -bool -user_has_email(const userec_t *u) -{ - char email[sizeof(u->email)]; - strlcpy(email, u->email, sizeof(email)); - return normalize_email(email); -} - bool check_email_allow_reject_lists(char *email, const char **errmsg, const char **notice_file) { diff --git a/mbbsd/user.c b/mbbsd/user.c index e0ad71020..5e3f41210 100644 --- a/mbbsd/user.c +++ b/mbbsd/user.c @@ -1002,7 +1002,7 @@ uinfo_query(const char *orig_uid, int adminmode, int unum) if (!adminmode) { #ifdef USEREC_EMAIL_IS_CONTACT # ifdef REQUIRE_CONTACT_EMAIL_TO_CHANGE_PASSWORD - if (!user_has_email(&cuser)) { + if (is_valid_email(cuser.email)) { move(y, 0); outs("設定聯絡信箱後才能修改密碼唷!"); fail++; @@ -1110,7 +1110,7 @@ uinfo_query(const char *orig_uid, int adminmode, int unum) // Send notification email if user has email set. // Only do so if not Admin to avoid confusing user. - if (user_has_email(&cuser) && !adminmode) + if (is_valid_email(cuser.email) && !adminmode) notify_password_change(cuser.userid, cuser.email); break; From 149f8d67f0cc521e8bf572c918bc3544c4a0be6f Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Mon, 11 Jul 2022 23:58:04 +0800 Subject: [PATCH 16/43] mbbsd: Send email notification to user when contact email is changed An email notification will be sent to the user's old email address on file. This is not sent if there is no email on file. --- mbbsd/register.c | 16 ++++++++++++++++ sample/etc/Makefile | 1 + sample/etc/emailchanged | 23 +++++++++++++++++++++++ 3 files changed, 40 insertions(+) create mode 100644 sample/etc/emailchanged diff --git a/mbbsd/register.c b/mbbsd/register.c index e150281bf..fe3bf5b4f 100644 --- a/mbbsd/register.c +++ b/mbbsd/register.c @@ -1687,6 +1687,18 @@ u_register() #ifdef USEREC_EMAIL_IS_CONTACT +static int notify_email_change(const char *userid, const char *email) +{ + char subject[128]; + int ret; + + snprintf(subject, sizeof(subject), " %s - %s (%s) - 聯絡信箱已更變", + BBSNAME, userid, fromhost); + + ret = bsmtp("etc/emailchanged", subject, email, "non-exist"); + + return ret > 0 ? 0 : -1; +} void change_contact_email() { @@ -1705,6 +1717,10 @@ change_contact_email() log_filef(logfn, LOG_CREAT, "%s %s (ContactEmail) %s -> %s\n", Cdatelite(&now), fromhost, cuser.email, email); + // Send notification to old email address if it was valid + if (is_valid_email(cuser.email)) + notify_email_change(cuser.userid, cuser.email); + // Write. pwcuSetEmail(email); diff --git a/sample/etc/Makefile b/sample/etc/Makefile index faef18186..3c041e56c 100644 --- a/sample/etc/Makefile +++ b/sample/etc/Makefile @@ -8,6 +8,7 @@ FILES= Welcome Welcome_login \ feast sysop banip.conf \ ve.hlp board.help boardlist.help \ editable expire2.conf domain_name_query.cidr \ + passwdchanged emailchanged \ banemail whitemail whitemail.notice ziphome.exclude all: diff --git a/sample/etc/emailchanged b/sample/etc/emailchanged new file mode 100644 index 000000000..ef528a353 --- /dev/null +++ b/sample/etc/emailchanged @@ -0,0 +1,23 @@ +Message below is written in Chinese/Big5. +If you cannot read Chinese/Big5, skip to English section. +------------------------------------------------------------- +親愛的使用者您好: + + 您的聯絡信箱已經更變. + + 如此為您本人操作, 請忽略此封信. + + 如非您本人操作, 請立刻登入並修改您的密碼及聯絡信箱. + +------------------------------------------------------------- +Dear user, + + This mail is to confirm your contact email address + has been changed. + + If it was you, you may discard this email. + + If it was not you, please login immediately and + change your password and contact email. + +------------------------------------------------------------- From 3431a69b2ae31e6b6af2f215e952b1312b9b8be3 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Wed, 13 Jul 2022 23:38:39 +0800 Subject: [PATCH 17/43] sample/etc: Add passwdchanged and emailchanged passwdchanged and emailchanged are notification letters that are sent to users when their password or email was changed. --- sample/etc/editable | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sample/etc/editable b/sample/etc/editable index 51716e249..af288ed92 100644 --- a/sample/etc/editable +++ b/sample/etc/editable @@ -58,6 +58,8 @@ etc/regnotes/phone etc/regnotes/mobile 註冊細項說明[手機] etc/regnotes/birthday 註冊細項說明[生日] etc/regnotes/sex 註冊細項說明[性別] +etc/passwdchanged 密碼更動通知信 +etc/emailchanged 聯絡信箱更動通知信 # ---------------------------------------- # 按鍵說明系列 # ---------------------------------------- From cbc682d782e9cb3f54d04c1ee95e28b31f7a9eee Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Wed, 13 Jul 2022 21:25:48 +0800 Subject: [PATCH 18/43] mbbsd: Drop inline for static functions Let compile decide whether to inline or not. --- mbbsd/angel.c | 6 +++--- mbbsd/board.c | 4 ++-- mbbsd/brc.c | 6 +++--- mbbsd/ccw.c | 2 +- mbbsd/chess.c | 16 ++++++++-------- mbbsd/edit.c | 39 +++++++++++++++++++-------------------- mbbsd/fav.c | 38 +++++++++++++++++++------------------- mbbsd/friend.c | 4 ++-- mbbsd/io.c | 12 ++++++------ mbbsd/mbbsd.c | 10 +++++----- mbbsd/nios.c | 2 +- mbbsd/pmore.c | 2 +- mbbsd/talk.c | 2 +- mbbsd/vtuikit.c | 6 +++--- 14 files changed, 74 insertions(+), 75 deletions(-) diff --git a/mbbsd/angel.c b/mbbsd/angel.c index f364666c3..2368dff71 100644 --- a/mbbsd/angel.c +++ b/mbbsd/angel.c @@ -759,7 +759,7 @@ FindAngel(void){ } #ifdef BN_NEWBIE -static inline void +static void GotoNewHand(){ char old_board[IDLEN + 1] = ""; int canRead = 1; @@ -785,7 +785,7 @@ GotoNewHand(){ #endif -static inline void +static void NoAngelFound(const char* msg){ // don't worry about the screen - // it should have been backuped before entering here. @@ -807,7 +807,7 @@ NoAngelFound(const char* msg){ #endif } -static inline void +static void AngelNotOnline(){ char msg_fn[PATHLEN]; diff --git a/mbbsd/board.c b/mbbsd/board.c index c84b0d2f0..bbbf02883 100644 --- a/mbbsd/board.c +++ b/mbbsd/board.c @@ -153,7 +153,7 @@ save_brdbuf(void) fav_free(); } -static inline int +static int HasBoardPermNormally(boardheader_t *bptr) { register int level, brdattr; @@ -1320,7 +1320,7 @@ brdlist_foot(void) } -static inline const char * +static const char * make_class_color(char *name) { /* 0;34 is too dark */ diff --git a/mbbsd/brc.c b/mbbsd/brc.c index fa0afac72..c44dc2183 100644 --- a/mbbsd/brc.c +++ b/mbbsd/brc.c @@ -137,7 +137,7 @@ brc_putrecord(char *ptr, char *endp, brcbid_t bid, return ptr; } -static inline int +static int brc_enlarge_buf(void) { char *buffer; @@ -175,7 +175,7 @@ brc_enlarge_buf(void) #undef THE_FREE } -static inline void +static void brc_get_buf(int size){ if (!size) brc_alloc = BRC_BLOCKSIZE; @@ -187,7 +187,7 @@ brc_get_buf(int size){ assert(brc_buf); } -static inline void +static void brc_insert_record(brcbid_t bid, brcnbrd_t num, const brc_rec* list) { char *ptr; diff --git a/mbbsd/ccw.c b/mbbsd/ccw.c index bc9b334ab..6095300b0 100644 --- a/mbbsd/ccw.c +++ b/mbbsd/ccw.c @@ -98,7 +98,7 @@ typedef struct CCW_CTX { // CCW helpers #ifndef DEBUG -# define CCW_PROTO static inline +# define CCW_PROTO static #else # define CCW_PROTO #endif diff --git a/mbbsd/chess.c b/mbbsd/chess.c index dff841e55..a70a19234 100644 --- a/mbbsd/chess.c +++ b/mbbsd/chess.c @@ -225,7 +225,7 @@ ChessRedraw(const ChessInfo* info) ChessDrawLine(info, i); } -inline static int +static int ChessTimeCountDownCalc(ChessInfo* info, int who, int length) { info->lefttime[who] -= length; @@ -272,7 +272,7 @@ ChessStepMade(ChessInfo* info, int who) /* * Start of the network communication function. */ -inline static ChessStepType +static ChessStepType ChessRecvMove(ChessInfo* info, int sock, void *step) { if (read(sock, step, info->constants->step_entry_size) @@ -281,7 +281,7 @@ ChessRecvMove(ChessInfo* info, int sock, void *step) return *(ChessStepType*) step; } -inline static int +static int ChessSendMove(ChessInfo* info, int sock, const void *step) { if (write(sock, step, info->constants->step_entry_size) @@ -290,7 +290,7 @@ ChessSendMove(ChessInfo* info, int sock, const void *step) return 1; } -inline static int +static int ChessStepSendOpposite(ChessInfo* info, const void* step) { void (*orig_handler)(int); @@ -310,7 +310,7 @@ ChessStepSendOpposite(ChessInfo* info, const void* step) return result; } -inline static void +static void ChessStepBroadcast(ChessInfo* info, const void *step) { ChessBroadcastListNode *p = &(info->broadcast_list.head); @@ -350,7 +350,7 @@ ChessMessageSend(ChessInfo* info, ChessStepType type) return ChessStepSend(info, &type); } -static inline int +static int ChessCheckAlive(ChessInfo* info) { ChessStepType type = CHESS_STEP_NOP; @@ -373,7 +373,7 @@ ChessStepReceive(ChessInfo* info, void* step) return result; } -inline static void +static void ChessReplayUntil(ChessInfo* info, int n) { const void* step; @@ -1649,7 +1649,7 @@ ChessShowRequest(void) } } -inline static const char* +static const char* ChessTimeStr(int second) { static char buf[10]; diff --git a/mbbsd/edit.c b/mbbsd/edit.c index 9f82115d7..3f76d4ef8 100644 --- a/mbbsd/edit.c +++ b/mbbsd/edit.c @@ -54,7 +54,6 @@ #if 0 #define DEBUG -#define inline #endif /** @@ -182,7 +181,7 @@ static editor_internal_t *curr_buf = NULL; static const char * const fp_bak = "bak"; // forward declare -static inline int has_block_selection(void); +static int has_block_selection(void); static textline_t * alloc_line(short length); static void block_cancel(void); @@ -283,7 +282,7 @@ fix_cursor(char *str, int pos, int dir) #endif /* 記憶體管理與編輯處理 */ -static inline void +static void edit_buffer_constructor(editor_internal_t *buf) { /* all unspecified columns are 0 */ @@ -297,7 +296,7 @@ edit_buffer_constructor(editor_internal_t *buf) } -static inline void +static void enter_edit_buffer(void) { editor_internal_t *p = curr_buf; @@ -307,7 +306,7 @@ enter_edit_buffer(void) edit_buffer_constructor(curr_buf); } -static inline void +static void free_line(textline_t *p) { if (p == curr_buf->oldcurrline) @@ -318,7 +317,7 @@ free_line(textline_t *p) free(p); } -static inline void +static void edit_buffer_destructor(void) { textline_t *p, *pnext; @@ -335,7 +334,7 @@ edit_buffer_destructor(void) free(curr_buf->sitesig_string); } -static inline void +static void exit_edit_buffer(void) { editor_internal_t *p = curr_buf; @@ -406,7 +405,7 @@ n2ansi(short nx, textline_t * line) /* 螢幕處理:輔助訊息、顯示編輯內容 */ -static inline void +static void show_phone_mode_panel(void) { int i; @@ -515,7 +514,7 @@ edit_buffer_check_healthy(textline_t *line) #endif } -static inline int visible_window_height(void); +static int visible_window_height(void); static void edit_check_healthy() @@ -597,7 +596,7 @@ edit_check_healthy() /** * return the middle line of the window. */ -static inline int +static int middle_line(void) { return p_lines / 2 + 1; @@ -624,7 +623,7 @@ back_line(textline_t * pos, int num, bool changeln) return pos; } -static inline int +static int visible_window_height(void) { if (curr_buf->phone_mode) @@ -657,7 +656,7 @@ forward_line(textline_t * pos, int num, bool changeln) /** * move the cursor to the next line with ansimode fixed. */ -static inline void +static void cursor_to_next_line(void) { short pos; @@ -682,7 +681,7 @@ cursor_to_next_line(void) /** * opposite to cursor_to_next_line. */ -static inline void +static void cursor_to_prev_line(void) { short pos; @@ -704,7 +703,7 @@ cursor_to_prev_line(void) } } -static inline void +static void edit_window_adjust(void) { int offset = 0; @@ -731,7 +730,7 @@ edit_window_adjust(void) } } -static inline void +static void edit_window_adjust_middle(void) { if (curr_buf->currln < middle_line()) { @@ -2081,7 +2080,7 @@ write_file(const char *fpath, int saveheader, char mytitle[STRLEN], return 0; } -static inline int +static int has_block_selection(void) { return curr_buf->blockln >= 0; @@ -2104,7 +2103,7 @@ block_cancel(void) } } -static inline void +static void setup_block_begin_end(textline_t **begin, textline_t **end) { if (curr_buf->currln >= curr_buf->blockln) { @@ -2919,7 +2918,7 @@ detect_attr(const char *ps, size_t len) return attr; } -static inline void +static void display_textline_internal(textline_t *p, int i) { short tmp; @@ -3364,7 +3363,7 @@ insert_ansi_code(void) curr_buf->insert_mode = ch; } -static inline void +static void phone_mode_switch(void) { if (curr_buf->phone_mode) @@ -3403,7 +3402,7 @@ phone_char(char c) * When get the key for phone mode, handle it (e.g. edit_msg) and return the * key. Otherwise return 0. */ -static inline char +static char phone_mode_filter(char ch) { if (!curr_buf->phone_mode) diff --git a/mbbsd/fav.c b/mbbsd/fav.c index f79dfcea5..57bde8b8b 100644 --- a/mbbsd/fav.c +++ b/mbbsd/fav.c @@ -61,15 +61,15 @@ static void fav_free_branch(fav_t *fp); * cast_(board|line|folder) 一族用於將 base class 作轉型 * (不檢查實際 data type) */ -inline static fav_board_t *cast_board(fav_type_t *p){ +static fav_board_t *cast_board(fav_type_t *p){ return (fav_board_t *)p->fp; } -inline static fav_line_t *cast_line(fav_type_t *p){ +static fav_line_t *cast_line(fav_type_t *p){ return (fav_line_t *)p->fp; } -inline static fav_folder_t *cast_folder(fav_type_t *p){ +static fav_folder_t *cast_folder(fav_type_t *p){ return (fav_folder_t *)p->fp; } @@ -103,11 +103,11 @@ inline int get_item_type(fav_type_t *ft){ /** * 將一個指定的 dir pointer 存下來,之後可用 fav_get_tmp_fav 來存用 */ -inline static void fav_set_tmp_folder(fav_t *fp){ +static void fav_set_tmp_folder(fav_t *fp){ fav_tmp = fp; } -inline static fav_t *fav_get_tmp_fav(void){ +static fav_t *fav_get_tmp_fav(void){ return fav_tmp; } @@ -156,11 +156,11 @@ static void fav_increase(fav_t *fp, fav_type_t *ft) fp->DataTail++; } -inline static int get_folder_num(fav_t *fp) { +static int get_folder_num(fav_t *fp) { return fp->nFolders; } -inline static int get_line_num(fav_t *fp) { +static int get_line_num(fav_t *fp) { return fp->nLines; } @@ -228,7 +228,7 @@ static int get_type_size(int type) return 0; } -inline static void* fav_malloc(int size){ +static void* fav_malloc(int size){ void *p; assert(size>0); p = (void *)malloc(size); @@ -240,7 +240,7 @@ inline static void* fav_malloc(int size){ /** * 只複製 fav_type_t */ -inline static void +static void fav_item_copy(fav_type_t *target, const fav_type_t *source){ target->type = source->type; target->attr = source->attr; @@ -391,20 +391,20 @@ inline int fav_stack_full(void){ return fav_stack_num >= FAV_MAXDEPTH; } -inline static int fav_stack_push_fav(fav_t *fp){ +static int fav_stack_push_fav(fav_t *fp){ if (fav_stack_full()) return -1; fav_stack[fav_stack_num++] = fp; return 0; } -inline static int fav_stack_push(fav_type_t *ft){ +static int fav_stack_push(fav_type_t *ft){ // if (ft->type != FAVT_FOLDER) // return -1; return fav_stack_push_fav(get_fav_folder(ft)); } -inline static void fav_stack_pop(void){ +static void fav_stack_pop(void){ fav_stack[--fav_stack_num] = NULL; } @@ -629,7 +629,7 @@ int fav_save(void) /** * remove ft (設為 invalid,實際上會等到 save 時才清除) */ -static inline void fav_free_item(fav_type_t *ft) +static void fav_free_item(fav_type_t *ft) { set_attr(ft, 0xFFFF, FALSE); } @@ -770,7 +770,7 @@ int fav_getid(fav_type_t *ft) return -1; } -inline static int is_maxsize(void){ +static int is_maxsize(void){ return fav_number >= MAX_FAV; } @@ -872,7 +872,7 @@ void move_in_current_folder(int from, int to) /** * allocate 一個 folder entry */ -inline static fav_t *alloc_folder_item(void){ +static fav_t *alloc_folder_item(void){ fav_t *fp = (fav_t *)fav_malloc(sizeof(fav_t)); fp->nAllocs = FAV_PRE_ALLOC; fp->favh = (fav_type_t *)fav_malloc(sizeof(fav_type_t) * FAV_PRE_ALLOC); @@ -993,7 +993,7 @@ static int remove_tagged_item(fav_t *fp, fav_type_t *ft) return fav_remove(fp, ft); } -inline static int fav_remove_tagged_item(fav_t *fp){ +static int fav_remove_tagged_item(fav_t *fp){ fav_dosomething_tagged_item(fp, remove_tagged_item); return 0; } @@ -1031,7 +1031,7 @@ static int add_and_remove_tag(fav_t *fp, fav_type_t *ft) return 0; } -inline static int fav_add_tagged_item(fav_t *fp){ +static int fav_add_tagged_item(fav_t *fp){ if (fp == fav_get_tmp_fav()) return -1; fav_dosomething_tagged_item(fp, add_and_remove_tag); @@ -1075,13 +1075,13 @@ void fav_add_all_tagged_item(void) fav_dosomething_all_tagged_item(fav_add_tagged_item); } -inline static int remove_tag(fav_t *fp GCC_UNUSED, fav_type_t *ft) +static int remove_tag(fav_t *fp GCC_UNUSED, fav_type_t *ft) { set_attr(ft, FAVH_TAG, FALSE); return 0; } -inline static int remove_tags(fav_t *fp) +static int remove_tags(fav_t *fp) { fav_dosomething_tagged_item(fp, remove_tag); return 0; diff --git a/mbbsd/friend.c b/mbbsd/friend.c index 462347f9e..d1dc264cb 100644 --- a/mbbsd/friend.c +++ b/mbbsd/friend.c @@ -58,7 +58,7 @@ setfriendfile(char *fpath, int type) setbfile(fpath, currboard, friend_file[type]); } -inline static int +static int friend_count(const char *fname) { return file_count_line(fname); @@ -395,7 +395,7 @@ friend_editdesc(const char *uident, int type) fclose(nfp); } -static inline void friend_load_real(int tosort, int maxf, +static void friend_load_real(int tosort, int maxf, short *destn, int *destar, const char *fn) { char genbuf[PATHLEN]; diff --git a/mbbsd/io.c b/mbbsd/io.c index 5d72558ce..54bde4470 100644 --- a/mbbsd/io.c +++ b/mbbsd/io.c @@ -333,7 +333,7 @@ process_pager_keys(int ch) static int i_newfd = 0; static struct timeval i_to, *i_top = NULL; -static inline void +static void add_io(int fd, int timeout) { i_newfd = fd; @@ -346,13 +346,13 @@ add_io(int fd, int timeout) i_top = NULL; } -static inline int +static int num_in_buf(void) { return vbuf_size(pvin); } -static inline void +static void drop_input(void) { vbuf_clear(pvin); @@ -363,7 +363,7 @@ drop_input(void) * =0 if nothing read * <0 if need to read again */ -static inline ssize_t +static ssize_t read_vin() { // Note: buf should be larger than pvin buffer size. unsigned char buf[IBUFSIZE]; @@ -502,7 +502,7 @@ dogetch(void) // virtual terminal keyboard context static VtkbdCtx vtkbd_ctx; -static inline int +static int igetch(void) { register int ch; @@ -562,7 +562,7 @@ igetch(void) * if f < 0, wait forever. * Return 1 if anything available. */ -static inline int +static int wait_input(float f, int bIgnoreBuf) { int sel = 0; diff --git a/mbbsd/mbbsd.c b/mbbsd/mbbsd.c index 24eee1732..8023ad1a4 100644 --- a/mbbsd/mbbsd.c +++ b/mbbsd/mbbsd.c @@ -1036,7 +1036,7 @@ setup_utmp(int mode) nice(3); } -inline static void welcome_msg(void) +static void welcome_msg(void) { prints(ANSI_RESET " 歡迎您再度拜訪,上次您是從 " ANSI_COLOR(1;33) "%s" ANSI_COLOR(0;37) " 連往本站。" @@ -1044,7 +1044,7 @@ inline static void welcome_msg(void) pressanykey(); } -inline static void check_bad_login(void) +static void check_bad_login(void) { char genbuf[200]; setuserfile(genbuf, FN_BADLOGIN); @@ -1120,7 +1120,7 @@ check_bad_clients(void) { vmsg("謝謝您的合作。如果您想提供更多資訊歡迎至" BN_BUGREPORT "報告"); } -inline static void append_log_recent_login() +static void append_log_recent_login() { char buf[STRLEN], logfn[PATHLEN]; int szlogfn = 0, szlogentry = 0; @@ -1140,7 +1140,7 @@ inline static void append_log_recent_login() log_file(logfn, LOG_CREAT, buf); } -inline static void check_mailbox_quota(void) +static void check_mailbox_quota(void) { if (!HasUserPerm(PERM_READMAIL)) return; @@ -1157,7 +1157,7 @@ static void init_guest_info(void) } #if FOREIGN_REG_DAY > 0 -inline static void foreign_warning(void){ +static void foreign_warning(void){ if ((HasUserFlag(UF_FOREIGN)) && !(HasUserFlag(UF_LIVERIGHT))){ if (login_start_time - cuser.firstlogin > (FOREIGN_REG_DAY - 5) * 24 * 3600){ mail_muser(cuser, "[出入境管理局]", "etc/foreign_expired_warn"); diff --git a/mbbsd/nios.c b/mbbsd/nios.c index 3deb52ef3..7ccefdb31 100644 --- a/mbbsd/nios.c +++ b/mbbsd/nios.c @@ -44,7 +44,7 @@ #endif #ifndef DEBUG -#define CIN_PROTO static inline +#define CIN_PROTO static #define VKEY_PROTO inline #else #define CIN_PROTO diff --git a/mbbsd/pmore.c b/mbbsd/pmore.c index 4f3a1ae06..87d8bd081 100644 --- a/mbbsd/pmore.c +++ b/mbbsd/pmore.c @@ -366,7 +366,7 @@ static int debug = 0; # define MFFPROTO #else # define MFPROTO static -# define MFFPROTO inline static +# define MFFPROTO static #endif /* DBCS users tend to write unsigned char. let's make compiler happy */ diff --git a/mbbsd/talk.c b/mbbsd/talk.c index cecdb1b20..0dc6ac830 100644 --- a/mbbsd/talk.c +++ b/mbbsd/talk.c @@ -2151,7 +2151,7 @@ call_in(const userinfo_t * uentp, int fri_stat) return 0; } -inline static void +static void userlist(void) { pickup_t *currpickup; diff --git a/mbbsd/vtuikit.c b/mbbsd/vtuikit.c index 1efcaf812..ad6fa6a1a 100644 --- a/mbbsd/vtuikit.c +++ b/mbbsd/vtuikit.c @@ -64,7 +64,7 @@ nblank(int n) outnc(n, ' '); } -static inline void +static void fillns(int n, const char *s) { while (n > 0 && *s) @@ -73,7 +73,7 @@ fillns(int n, const char *s) outnc(n, ' '); } -static inline void +static void fillns_ansi(int n, const char *s) { int d = strat_ansi(n, s); @@ -1117,7 +1117,7 @@ InputHistoryNext(char *s, int sz) // vget*: mini editbox //////////////////////////////////////////////////////////////////////// -static inline int +static int _vgetcbhandler(VGET_FCALLBACK cbptr, int *pabort, int c, VGET_RUNTIME *prt, void *instance) { if (!cbptr) From 30d477394a676bacdb8d5b93f4bfabd8fdeb9900 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Wed, 13 Jul 2022 23:34:41 +0800 Subject: [PATCH 19/43] mbbsd: Drop unused inline functions getbid() and getparent() don't seem to be used. Remove them. --- mbbsd/board.c | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/mbbsd/board.c b/mbbsd/board.c index bbbf02883..6aca5973f 100644 --- a/mbbsd/board.c +++ b/mbbsd/board.c @@ -54,18 +54,6 @@ static time4_t last_save_fav_and_brc; #define IS_LISTING_FAV() (yank_flag == 0) #define IS_LISTING_BRD() (yank_flag == 1) -inline int getbid(const boardheader_t *fh) -{ - return (fh - bcache); -} -inline boardheader_t *getparent(const boardheader_t *fh) -{ - if(fh->parent>0) - return getbcache(fh->parent); - else - return NULL; -} - // 程式中有特別用途所以不得自行 post / 修改的看板 int is_readonly_board(const char *bname) From c9507738445ccbe7fd8e12c10f00df17932397ad Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Sat, 16 Jul 2022 21:54:15 +0800 Subject: [PATCH 20/43] mbbsd: Fix user have contact email not able to change password In commit "mbbsd: Drop user_has_email()", the test for valid email address was accidentally inverted, causing the check to fail when it should succeed. --- mbbsd/user.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mbbsd/user.c b/mbbsd/user.c index 5e3f41210..18dd6f740 100644 --- a/mbbsd/user.c +++ b/mbbsd/user.c @@ -1002,7 +1002,7 @@ uinfo_query(const char *orig_uid, int adminmode, int unum) if (!adminmode) { #ifdef USEREC_EMAIL_IS_CONTACT # ifdef REQUIRE_CONTACT_EMAIL_TO_CHANGE_PASSWORD - if (is_valid_email(cuser.email)) { + if (!is_valid_email(cuser.email)) { move(y, 0); outs("設定聯絡信箱後才能修改密碼唷!"); fail++; From 8a6bd7a2430949f19c77503398cbd8353c69b7ff Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Sat, 10 Sep 2022 01:36:36 +0800 Subject: [PATCH 21/43] util/expire: Guard against bogus board names Especially when scanning directories, there maybe bogus directories where the board directories reside. This causes either benign errors, or corruption of the board article limit due to the directory name being longer than the board name field, overwriting the trailing fields. Guard against this by checking for a valid board name. --- util/expire.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/util/expire.c b/util/expire.c index b53b0c326..a7a26bf35 100644 --- a/util/expire.c +++ b/util/expire.c @@ -182,18 +182,19 @@ life_t db, table[MAX_BOARD], *key; void toexpire(char *brdname) { - if( brdname[0] > ' ' && brdname[0] != '.' ){ - key = NULL; + if (!is_valid_brdname(brdname)) + return; - if( count ) - key = (life_t *)bsearch(brdname, table, count, - sizeof(life_t), (QCAST)strcasecmp); - if( key == NULL ) - key = &db; + key = NULL; - strcpy(key->bname, brdname); - expire(key); - } + if( count ) + key = (life_t *)bsearch(brdname, table, count, + sizeof(life_t), (QCAST)strcasecmp); + if( key == NULL ) + key = &db; + + strcpy(key->bname, brdname); + expire(key); } void visitdir(char c) From d88275931ce8e4de21529650be4d8c9ca06aa975 Mon Sep 17 00:00:00 2001 From: Robert Wang Date: Sat, 31 Dec 2022 16:09:19 -0800 Subject: [PATCH 22/43] boardd/mand: Hide evbuffer API calls --- daemon/boardd/board_service_impl.cpp | 6 ++---- daemon/boardd/evbuffer.cpp | 6 ++++++ daemon/boardd/evbuffer.hpp | 4 +++- daemon/mand/Makefile | 2 +- daemon/mand/man_service_impl.cpp | 6 ++---- 5 files changed, 14 insertions(+), 10 deletions(-) diff --git a/daemon/boardd/board_service_impl.cpp b/daemon/boardd/board_service_impl.cpp index 6cc13c9e7..ca1c48fee 100644 --- a/daemon/boardd/board_service_impl.cpp +++ b/daemon/boardd/board_service_impl.cpp @@ -208,13 +208,11 @@ Status DoSelect(const std::string &fn, const std::string &consistency_token, select_result_t result; Evbuffer buf; - RETURN_ON_FAIL(SelectStatus(select_article(buf.Get(), &result, &spec))); + RETURN_ON_FAIL(SelectStatus(select_article(buf.GetBuffer(), &result, &spec))); if (!buf.ConvertUTF8()) return Status(StatusCode::INTERNAL, "convert utf8 failed"); - content->mutable_content()->assign( - reinterpret_cast(evbuffer_pullup(buf.Get(), -1)), - evbuffer_get_length(buf.Get())); + content->mutable_content()->assign(buf.StringView()); content->set_consistency_token(result.cachekey); content->set_offset(result.sel_offset); content->set_length(result.sel_size); diff --git a/daemon/boardd/evbuffer.cpp b/daemon/boardd/evbuffer.cpp index d7a32d1ea..6e40b827e 100644 --- a/daemon/boardd/evbuffer.cpp +++ b/daemon/boardd/evbuffer.cpp @@ -1,4 +1,5 @@ #include "daemon/boardd/evbuffer.hpp" +#include extern "C" { #include } @@ -14,3 +15,8 @@ bool Evbuffer::ConvertUTF8() { buf_ = evbuffer_new(); return false; } + +std::string_view Evbuffer::StringView() { + size_t len = evbuffer_get_length(buf_); + return {reinterpret_cast(evbuffer_pullup(buf_, len)), len}; +} diff --git a/daemon/boardd/evbuffer.hpp b/daemon/boardd/evbuffer.hpp index 704ba5aef..ddcf30902 100644 --- a/daemon/boardd/evbuffer.hpp +++ b/daemon/boardd/evbuffer.hpp @@ -1,6 +1,7 @@ #ifndef _PTTBBS_DAEMON_BOARDD_EVBUFFER_HPP_ #define _PTTBBS_DAEMON_BOARDD_EVBUFFER_HPP_ #include "daemon/boardd/macros.hpp" +#include extern "C" { #include #include "daemon/boardd/boardd.h" @@ -11,8 +12,9 @@ class Evbuffer final { Evbuffer(); ~Evbuffer(); - evbuffer *Get() { return buf_; } + evbuffer *GetBuffer() { return buf_; } bool ConvertUTF8(); + std::string_view StringView(); private: DISABLE_COPY_AND_ASSIGN(Evbuffer); diff --git a/daemon/mand/Makefile b/daemon/mand/Makefile index 9ba85ba84..bdfc97e0f 100644 --- a/daemon/mand/Makefile +++ b/daemon/mand/Makefile @@ -35,7 +35,7 @@ UTILDIR= $(SRCROOT)/util UTILOBJ= $(UTILDIR)/util_var.o COMMONFLAGS= -I$(SRCROOT) -I../boardd -CXXFLAGS+= -std=c++11 $(COMMONFLAGS) +CXXFLAGS+= -std=c++17 $(COMMONFLAGS) CFLAGS+= $(LIBEVENT_CFLAGS) $(COMMONFLAGS) LDFLAGS+= diff --git a/daemon/mand/man_service_impl.cpp b/daemon/mand/man_service_impl.cpp index 8abd030a7..fb22970b7 100644 --- a/daemon/mand/man_service_impl.cpp +++ b/daemon/mand/man_service_impl.cpp @@ -106,14 +106,12 @@ Status ManServiceImpl::Article(ServerContext *context, select_result_t result; Evbuffer buf; - if (select_article(buf.Get(), &result, &spec) < 0) + if (select_article(buf.GetBuffer(), &result, &spec) < 0) return Status(StatusCode::INTERNAL, "select_article failed"); if (!buf.ConvertUTF8()) return Status(StatusCode::INTERNAL, "convert utf8 failed"); - rep->mutable_content()->assign( - reinterpret_cast(evbuffer_pullup(buf.Get(), -1)), - evbuffer_get_length(buf.Get())); + rep->mutable_content()->assign(buf.StringView()); rep->set_cache_key(result.cachekey); rep->set_file_size(result.size); rep->set_selected_offset(result.sel_offset); From 6adbb11db72c61d6e6bb9f464742fc68d540180b Mon Sep 17 00:00:00 2001 From: Robert Wang Date: Sat, 31 Dec 2022 16:20:54 -0800 Subject: [PATCH 23/43] boardd: Use auto to prevent errors when Status is not in scope --- daemon/boardd/macros.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/daemon/boardd/macros.hpp b/daemon/boardd/macros.hpp index acb7f9034..e0fe74f30 100644 --- a/daemon/boardd/macros.hpp +++ b/daemon/boardd/macros.hpp @@ -7,7 +7,7 @@ #define RETURN_ON_FAIL(Expr) \ do { \ - Status s = (Expr); \ + auto s = (Expr); \ if (!s.ok()) \ return s; \ } while (0) From 8a32ccc55070cb240586d0423e27ed8d60e7c3c6 Mon Sep 17 00:00:00 2001 From: Chuan-Heng Hsiao Date: Wed, 31 Aug 2022 07:58:34 -0400 Subject: [PATCH 24/43] mbbsd: Ensure setting up contact-email contact-email will be frequently used for important operations (resetting password / notifications) We would like to ensure that valid contact-email exists right after successful login. Return err in change_contact_email. The program continues retrying setup contact-email until success. The users can close the program if they want to give up retrying setup contact-email. --- include/proto.h | 2 +- mbbsd/register.c | 21 +++++++++++++++++++-- sample/etc/ensurevalidcontactemail | 5 +++++ 3 files changed, 25 insertions(+), 3 deletions(-) create mode 100644 sample/etc/ensurevalidcontactemail diff --git a/include/proto.h b/include/proto.h index 207802a82..7e93edbf4 100644 --- a/include/proto.h +++ b/include/proto.h @@ -580,7 +580,7 @@ void check_register(void); bool check_email_allow_reject_lists( char *email, const char **errmsg, const char **notice_file); void register_mail_complete_and_exit(); -void change_contact_email(); +int change_contact_email(); /* register_sms */ void u_sms_verification(); diff --git a/mbbsd/register.c b/mbbsd/register.c index fe3bf5b4f..b70cdff76 100644 --- a/mbbsd/register.c +++ b/mbbsd/register.c @@ -1158,6 +1158,16 @@ void check_register(void) { char fn[PATHLEN]; + int ret = 0; + + // 確認一定要有聯絡信箱 + if (!is_valid_email(cuser.email)) { + more("etc/ensurevalidcontactemail", NA); + pressanykey(); + + // additional parentheses around "ret =" to please compiler + while ((ret = change_contact_email())); + } // 已經通過的就不用了 if (HasUserPerm(PERM_LOGINOK) || HasUserPerm(PERM_SYSOP)) @@ -1699,7 +1709,12 @@ static int notify_email_change(const char *userid, const char *email) return ret > 0 ? 0 : -1; } -void + +// change_contact_email +// +// Return: +// int: 0: ok -1: err +int change_contact_email() { char email[EMAILSZ] = {}; @@ -1709,7 +1724,7 @@ change_contact_email() ein.email = email; ein.allow_untrusted = true; if (register_email_verification(&ein) != REGISTER_OK) - return; + return -1; // Log. char logfn[PATHLEN]; @@ -1725,6 +1740,8 @@ change_contact_email() pwcuSetEmail(email); vmsg("聯絡信箱更新完成。"); + + return 0; } #endif diff --git a/sample/etc/ensurevalidcontactemail b/sample/etc/ensurevalidcontactemail new file mode 100644 index 000000000..79a216314 --- /dev/null +++ b/sample/etc/ensurevalidcontactemail @@ -0,0 +1,5 @@ +您的聯絡信箱不是有效的信箱, +請重新設定您的聯絡信箱。 + +如果無法使用 app 設定, +請使用網頁版 https://term.ptt.cc From 6a712d57098452a895088c90494ee201e4e0357e Mon Sep 17 00:00:00 2001 From: Chuan-Heng Hsiao Date: Wed, 31 Aug 2022 07:58:34 -0400 Subject: [PATCH 25/43] mbbsd: force update contact email if last-login < FORCE_UPDATE_CONTACT_EMAIL_LASTLOGIN. Besides checking the validity of the contact-email as the previous commit, we would like to conduct one-time-check contact-email right after login. One-time-check contact-email is implemented by enforcing updating the contact-email if the user's last-login is less than FORCE_UPDATE_CONTACT_EMAIL_LASTLOGIN. Adding is_skip_check_same_email as the parameter of change_contact_email to fulfill the requirement. --- include/proto.h | 2 +- mbbsd/register.c | 46 +++++++++++++++++++++++++----- mbbsd/user.c | 2 +- sample/etc/forceupdatecontactemail | 5 ++++ sample/pttbbs.conf | 3 ++ 5 files changed, 49 insertions(+), 9 deletions(-) create mode 100644 sample/etc/forceupdatecontactemail diff --git a/include/proto.h b/include/proto.h index 7e93edbf4..cc3e01284 100644 --- a/include/proto.h +++ b/include/proto.h @@ -580,7 +580,7 @@ void check_register(void); bool check_email_allow_reject_lists( char *email, const char **errmsg, const char **notice_file); void register_mail_complete_and_exit(); -int change_contact_email(); +int change_contact_email(bool skip_same_email_check); /* register_sms */ void u_sms_verification(); diff --git a/mbbsd/register.c b/mbbsd/register.c index b70cdff76..cd4949884 100644 --- a/mbbsd/register.c +++ b/mbbsd/register.c @@ -572,8 +572,25 @@ query_yn(int y, const char *msg) // New Registration (Phase 1: Create Account) ///////////////////////////////////////////////////////////////////////////// +// register_email_verification +// +// given the email input, generate a random code and send to +// the email address to verify the validity of the email. +// +// Params: +// ein: email input information. +// +// skip_same_email_check: +// whether to skip checking the input email is the same as the original +// email. +// 0: not skip checking (to check whether they are the same.) +// 1: skip checking (not to check whether they are the same.) +// +// Return: +// 0 (REGISTER_OK): ok +// < 0: error code static int -register_email_verification(email_input_t *ein) +register_email_verification(email_input_t *ein, bool skip_same_email_check) { char *email = ein->email; clear(); @@ -643,7 +660,7 @@ register_email_verification(email_input_t *ein) } while (err != REGISTER_OK); // Nothing changed. - if (!strcmp(email, orig)) { + if (!skip_same_email_check && !strcmp(email, orig)) { vmsg("E-Mail 與原本相同。"); return REGISTER_ERR_CANCEL; } @@ -750,7 +767,7 @@ new_register(void) ein.warn_untrusted = true; # endif // ALLOW_REGISTER_WITH_ONLY_CONTACT_EMAIL - if (register_email_verification(&ein) == REGISTER_OK) { + if (register_email_verification(&ein, 0) == REGISTER_OK) { email_verified = ein.is_trusted; } else { exit(1); @@ -1166,7 +1183,15 @@ check_register(void) pressanykey(); // additional parentheses around "ret =" to please compiler - while ((ret = change_contact_email())); + while ((ret = change_contact_email(0))); +#ifdef FORCE_UPDATE_CONTACT_EMAIL_LASTLOGIN + } else if (last_login_time < FORCE_UPDATE_CONTACT_EMAIL_LASTLOGIN) { + more("etc/forceupdatecontactemail", NA); + pressanykey(); + + // additional parentheses around "ret =" to please compiler + while ((ret = change_contact_email(1))); +#endif //FORCE_UPDATE_CONTACT_EMAIL_LASTLOGIN } // 已經通過的就不用了 @@ -1449,7 +1474,7 @@ u_email_verification() email_input_t ein = {}; ein.email = email; - if (register_email_verification(&ein) != REGISTER_OK) + if (register_email_verification(&ein, 0) != REGISTER_OK) return; assert(ein.is_trusted); @@ -1712,10 +1737,17 @@ static int notify_email_change(const char *userid, const char *email) // change_contact_email // +// Params: +// skip_same_email_check: +// whether to skip checking the input email is the same as the original +// email. +// 0: not skip checking (to check whether they are the same.) +// 1: skip checking (not to check whether they are the same.) +// // Return: // int: 0: ok -1: err int -change_contact_email() +change_contact_email(bool skip_same_email_check) { char email[EMAILSZ] = {}; memcpy(email, cuser.email, sizeof(email)); @@ -1723,7 +1755,7 @@ change_contact_email() email_input_t ein = {}; ein.email = email; ein.allow_untrusted = true; - if (register_email_verification(&ein) != REGISTER_OK) + if (register_email_verification(&ein, skip_same_email_check) != REGISTER_OK) return -1; // Log. diff --git a/mbbsd/user.c b/mbbsd/user.c index 18dd6f740..4f2ec8b5f 100644 --- a/mbbsd/user.c +++ b/mbbsd/user.c @@ -714,7 +714,7 @@ uinfo_query(const char *orig_uid, int adminmode, int unum) #ifdef USEREC_EMAIL_IS_CONTACT case 'm': if (!adminmode) { - change_contact_email(); + change_contact_email(0); return; } else { char email[EMAILSZ]; diff --git a/sample/etc/forceupdatecontactemail b/sample/etc/forceupdatecontactemail new file mode 100644 index 000000000..500775dee --- /dev/null +++ b/sample/etc/forceupdatecontactemail @@ -0,0 +1,5 @@ +您上次上站在 2022-12-20 00:00:00 之前, +請重新設定您的聯絡信箱。 + +如果無法使用 app 設定, +請使用網頁版 https://term.ptt.cc diff --git a/sample/pttbbs.conf b/sample/pttbbs.conf index c78c1826b..f24149d8b 100644 --- a/sample/pttbbs.conf +++ b/sample/pttbbs.conf @@ -287,6 +287,9 @@ //#define REQUIRE_CONTACT_EMAIL_TO_CHANGE_PASSWORD +/* 如果使用者上次 login 在 FORCE_UPDATE_CONTACT_EMAIL_LASTLOGIN 之前, 則重新設定聯絡信箱 */ +//#define FORCE_UPDATE_CONTACT_EMAIL_LASTLOGIN 0 + /* 前進站畫面 */ #define INSCREEN \ "前進站畫面 (請至 pttbbs.conf 修改您的前進站畫面)" From a425d48221612c6b44b6e191292fb1ea321e0ef4 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Fri, 27 Jan 2023 22:59:45 +0800 Subject: [PATCH 26/43] mbbsd: Ask user to use a long term email for registration / contact Previously users would use emails from their universities, and those ended up being closed after they graduated. Then they weren't able to use their listed emails for account recovery. --- mbbsd/register.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/mbbsd/register.c b/mbbsd/register.c index cd4949884..ce2594095 100644 --- a/mbbsd/register.c +++ b/mbbsd/register.c @@ -610,6 +610,10 @@ register_email_verification(email_input_t *ein, bool skip_same_email_check) } outs("\n" "**********************************************************\n" + "* 請填寫您能夠長期持有的信箱,請勿填寫學校/公司的信箱, *\n" + "* 避免畢業或離職時信箱被收回。失去聯絡信箱, *\n" + "* 將可能造成您再也無法使用您的批踢踢帳號。 *\n" + "* *\n" "* 若過久未收到請到郵件垃圾桶檢查是否被當作垃圾信(SPAM)了,*\n" "* 另外若輸入後發生認證碼錯誤請先確認輸入是否為最後一封 *\n" "* 收到的認證信,若真的仍然不行請再重填一次 E-Mail. *\n" From 45846361e1a297415e51fd64f155cc9f746530a6 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Fri, 27 Jan 2023 23:29:18 +0800 Subject: [PATCH 27/43] mbbsd: refine email input notice --- mbbsd/register.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/mbbsd/register.c b/mbbsd/register.c index ce2594095..c6e85f810 100644 --- a/mbbsd/register.c +++ b/mbbsd/register.c @@ -609,15 +609,16 @@ register_email_verification(email_input_t *ein, bool skip_same_email_check) " 註: 本站不接受 yahoo, kimo等免費的 E-Mail\n"); } outs("\n" - "**********************************************************\n" - "* 請填寫您能夠長期持有的信箱,請勿填寫學校/公司的信箱, *\n" - "* 避免畢業或離職時信箱被收回。失去聯絡信箱, *\n" - "* 將可能造成您再也無法使用您的批踢踢帳號。 *\n" - "* *\n" - "* 若過久未收到請到郵件垃圾桶檢查是否被當作垃圾信(SPAM)了,*\n" - "* 另外若輸入後發生認證碼錯誤請先確認輸入是否為最後一封 *\n" - "* 收到的認證信,若真的仍然不行請再重填一次 E-Mail. *\n" - "**********************************************************\n"); + "**********************************************************************\n" + "* 請填寫您能夠長期持有的信箱,勿填寫學校或公司的信箱等暫時信箱, *\n" + "* 避免畢業或離職時信箱被收回。 *\n" + "* 信箱可在【忘記密碼】或【帳號被他人使用】時,用來重置您的帳號密碼。 *\n" + "* 變更【密碼】與【聯絡信箱】時,也將會需要透過聯絡信箱來驗證。 *\n" + "* *\n" + "* 若過久未收到請到郵件垃圾桶檢查是否被當作垃圾信(SPAM)了。 *\n" + "* 另外若輸入後發生認證碼錯誤請先確認輸入是否為最後一封。 *\n" + "* 收到的認證信,若真的仍然不行請再重填一次 E-Mail. *\n" + "**********************************************************************\n"); // Get a valid email from user. int err; From d93e10f3f27a017780859287eae1cb7a1e082862 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Sat, 28 Jan 2023 02:40:16 +0800 Subject: [PATCH 28/43] util/outmail: Add build date to sender signature From local changes. --- util/outmail.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util/outmail.c b/util/outmail.c index d8177da37..c86e22b1f 100644 --- a/util/outmail.c +++ b/util/outmail.c @@ -88,7 +88,7 @@ void doSendBody(int sock, FILE *fp, char *from, char *to, char *subject) { "From: %s <%s>\r\n" "To: %s\r\n" "Subject: %s\r\n" - "X-Sender: outmail of pttbbs\r\n" + "X-Sender: outmail of pttbbs " __DATE__ "\r\n" "Mime-Version: 1.0\r\n" "Content-Type: text/plain; charset=\"big5\"\r\n" "Content-Transfer-Encoding: 8bit\r\n" From b8bdb4bbf21982f0c62029f988c0ed6e6b77566b Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Sat, 28 Jan 2023 02:40:55 +0800 Subject: [PATCH 29/43] util/outmail: Reset SMTP session state before sending email From local changes. --- util/outmail.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/util/outmail.c b/util/outmail.c index c86e22b1f..03fdd9212 100644 --- a/util/outmail.c +++ b/util/outmail.c @@ -115,6 +115,9 @@ void doSendBody(int sock, FILE *fp, char *from, char *to, char *subject) { void doSendMail(int sock, FILE *fp, char *from, char *to, char *subject) { char buf[256]; + if (sendRequest(sock, "rset\n") || waitReply(sock) != 2) + return; + snprintf(buf, sizeof(buf), "mail from: %s\n", from); if(sendRequest(sock, buf) || waitReply(sock) != 2) return; From 4015902893079f5b91cbe5fdb7a76d24ad26f640 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Sat, 28 Jan 2023 02:45:52 +0800 Subject: [PATCH 30/43] util/outmail: Indicate send progress of the current queue The recent forced update of contact email caused a lot of emails to be sent, overwhelming the outmail program. Add an indicator for the progress of the current queue. --- util/outmail.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/util/outmail.c b/util/outmail.c index 03fdd9212..81fa0c347 100644 --- a/util/outmail.c +++ b/util/outmail.c @@ -136,7 +136,9 @@ void doSendMail(int sock, FILE *fp, char *from, char *to, char *subject) { } void sendMail() { - int fd, smtpsock; + int fd, smtpsock, counter = 0; + long int total_count; + struct stat st; MailQueue mq; if(access(NEWINDEX, R_OK | W_OK)) { @@ -154,14 +156,19 @@ void sendMail() { fd = open(NEWINDEX, O_RDONLY); flock(fd, LOCK_EX); + fstat(fd, &st); + total_count = st.st_size / sizeof(mq); + while(read(fd, &mq, sizeof(mq)) > 0) { FILE *fp; char buf[256]; + counter++; snprintf(buf, sizeof(buf), "%s%s", mq.sender, FROM); if((fp = fopen(mq.filepath, "r"))) { - setproctitle("outmail: sending %s", mq.filepath); - printf("mailto: %s, relay server: %s:%d\n", mq.rcpt, smtpname, smtpport); + setproctitle("outmail: sending %d/%ld %s", counter, total_count, mq.filepath); + printf("mailto: %s, %d of %ld, relay server: %s:%d\n", mq.rcpt, counter, total_count, + smtpname, smtpport); doSendMail(smtpsock, fp, buf, mq.rcpt, mq.subject); fclose(fp); unlink(mq.filepath); From 873570c3460aa8296a7ecd1bc12f87aeb13fd07c Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Sat, 28 Jan 2023 02:50:57 +0800 Subject: [PATCH 31/43] util/outmail: Add PID to in-progress spool name The recent forced update of contact email caused a lot of emails to be sent, overwhelming the outmail program. Add PID to in-progress spool name. This would allow us to manually spawn additional instances to handle new spools in a timely fashion. --- util/outmail.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/util/outmail.c b/util/outmail.c index 81fa0c347..cf4d2f884 100644 --- a/util/outmail.c +++ b/util/outmail.c @@ -2,7 +2,7 @@ #define SPOOL BBSHOME "/out" #define INDEX SPOOL "/.DIR" -#define NEWINDEX SPOOL "/.DIR.sending" +#define NEWINDEX_PATTERN SPOOL "/.DIR.sending.%d" #define FROM ".bbs@" MYHOSTNAME #define SMTPPORT 25 char *smtpname; @@ -138,11 +138,14 @@ void doSendMail(int sock, FILE *fp, char *from, char *to, char *subject) { void sendMail() { int fd, smtpsock, counter = 0; long int total_count; + char spool_path[PATHLEN]; struct stat st; MailQueue mq; - - if(access(NEWINDEX, R_OK | W_OK)) { - if(link(INDEX, NEWINDEX) || unlink(INDEX)) + + snprintf(spool_path, sizeof(spool_path), NEWINDEX_PATTERN, getpid()); + + if(access(spool_path, R_OK | W_OK)) { + if(link(INDEX, spool_path) || unlink(INDEX)) /* nothing to do */ return; } @@ -154,7 +157,7 @@ void sendMail() { return; } - fd = open(NEWINDEX, O_RDONLY); + fd = open(spool_path, O_RDONLY); flock(fd, LOCK_EX); fstat(fd, &st); total_count = st.st_size / sizeof(mq); @@ -178,7 +181,7 @@ void sendMail() { } flock(fd, LOCK_UN); close(fd); - unlink(NEWINDEX); + unlink(spool_path); disconnectMailServer(smtpsock); } From e6c63428f3234610c4a4a82f47632e0c18dd878d Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Sat, 28 Jan 2023 03:03:07 +0800 Subject: [PATCH 32/43] util/outmail: Add one-shot mode Add mode to process current spool and then exit. Useful for emergency times when the existing process(es) are still busy processing their spools, and we want to temporarily spawn more processes. --- util/outmail.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/util/outmail.c b/util/outmail.c index cf4d2f884..ba91036b3 100644 --- a/util/outmail.c +++ b/util/outmail.c @@ -1,3 +1,5 @@ +#include + #include "bbs.h" #define SPOOL BBSHOME "/out" @@ -8,6 +10,7 @@ char *smtpname; int smtpport; char disclaimer[1024]; +bool one_shot; int waitReply(int sock) { char buf[256]; @@ -240,12 +243,16 @@ int main(int argc, char **argv, char **envp) { case 's': parseserver(optarg, &smtpname, &smtpport); break; + case 'o': + one_shot = true; + break; case 'q': listQueue(); return 0; default: - printf("usage:\toutmail [-qh] -s host[:port]\n" + printf("usage:\toutmail [-qoh] -s host[:port]\n" "\t-q\tlistqueue\n" + "\t-o\texit when current spool is fully processed (One-shot)\n" "\t-h\thelp\n" "\t-s\tset default smtp server to host[:port]\n"); return 0; @@ -262,10 +269,11 @@ int main(int argc, char **argv, char **envp) { } qp_encode(disclaimer, sizeof(disclaimer), "[" BBSNAME "]對本信內容恕不負責", "big5"); - for(;;) { + do { sendMail(); setproctitle("outmail: sleeping"); sleep(60); /* send mail every minute */ - } + } while (!one_shot); + return 0; } From d44e550591c6441f5d5ba5096bf79ff825641992 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Sat, 28 Jan 2023 12:57:11 +0800 Subject: [PATCH 33/43] mbbsd/recover: Only say "registered email only" if contact mail is disabled The account recovery UI has a misleading message saying that "only accounts with registered emails can be recovered". In reality, the system allows using either registered emails or their listed contact email if the contact email setting is enabled. --- mbbsd/recover.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/mbbsd/recover.cc b/mbbsd/recover.cc index 1cef98a4e..f6169fbc5 100644 --- a/mbbsd/recover.cc +++ b/mbbsd/recover.cc @@ -171,8 +171,10 @@ void AccountRecovery::UserErrorExit() { } void AccountRecovery::InputUserEmail() { - mvprints(y_++, 0, "目前僅能取回使用 Email 註冊之帳號。"); - y_++; +#ifndef USEREC_EMAIL_IS_CONTACT + mvprints(y_, 0, "目前僅能取回使用 Email 註冊之帳號。"); +#endif + y_ += 2; // Input userid. char userid[IDLEN + 1] = {}; From 14a90b7bb44f5b1e0b349403428d84f2c0d8779e Mon Sep 17 00:00:00 2001 From: pan93412 Date: Sun, 29 Jan 2023 03:08:29 +0800 Subject: [PATCH 34/43] =?UTF-8?q?mbbsd,=20sample:=20=E2=80=9C=E6=9B=B4?= =?UTF-8?q?=E8=AE=8A=E2=80=9D=20to=20a=20more=20widely-used=20vocabulary?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- mbbsd/mail.c | 2 +- mbbsd/register.c | 2 +- mbbsd/verifydb_info.cc | 2 +- sample/etc/emailchanged | 2 +- sample/etc/passwdchanged | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/mbbsd/mail.c b/mbbsd/mail.c index b8ef61e72..40cb1a8e3 100644 --- a/mbbsd/mail.c +++ b/mbbsd/mail.c @@ -2585,7 +2585,7 @@ int notify_password_change(const char *userid, const char *email) char subject[128]; int ret; - snprintf(subject, sizeof(subject), " %s - %s (%s) - 密碼已更變", + snprintf(subject, sizeof(subject), " %s - %s (%s) - 密碼已變更", BBSNAME, userid, fromhost); ret = bsmtp("etc/passwdchanged", subject, email, "non-exist"); diff --git a/mbbsd/register.c b/mbbsd/register.c index c6e85f810..903b086cf 100644 --- a/mbbsd/register.c +++ b/mbbsd/register.c @@ -1732,7 +1732,7 @@ static int notify_email_change(const char *userid, const char *email) char subject[128]; int ret; - snprintf(subject, sizeof(subject), " %s - %s (%s) - 聯絡信箱已更變", + snprintf(subject, sizeof(subject), " %s - %s (%s) - 聯絡信箱已變更", BBSNAME, userid, fromhost); ret = bsmtp("etc/emailchanged", subject, email, "non-exist"); diff --git a/mbbsd/verifydb_info.cc b/mbbsd/verifydb_info.cc index 2bd5fbae8..a690581f9 100644 --- a/mbbsd/verifydb_info.cc +++ b/mbbsd/verifydb_info.cc @@ -131,7 +131,7 @@ void verify_entry_email_edit(const VerifyDb::Entry *entry, bool *dirty) { // clang-format off outs(ANSI_COLOR(1;33)); // clang-format on - outs(" 如需修改認證狀態, 請使用權限更變選項."); + outs(" 如需修改認證狀態, 請使用權限變更選項."); outs(ANSI_RESET); char confirm[2] = {}; diff --git a/sample/etc/emailchanged b/sample/etc/emailchanged index ef528a353..599d8e92e 100644 --- a/sample/etc/emailchanged +++ b/sample/etc/emailchanged @@ -3,7 +3,7 @@ If you cannot read Chinese/Big5, skip to English section. ------------------------------------------------------------- 親愛的使用者您好: - 您的聯絡信箱已經更變. + 您的聯絡信箱已經變更. 如此為您本人操作, 請忽略此封信. diff --git a/sample/etc/passwdchanged b/sample/etc/passwdchanged index c1fbe383d..16ee0680e 100644 --- a/sample/etc/passwdchanged +++ b/sample/etc/passwdchanged @@ -3,7 +3,7 @@ If you cannot read Chinese/Big5, skip to English section. ------------------------------------------------------------- 親愛的使用者您好: - 您的密碼已經更變. + 您的密碼已經變更. 如此為您本人操作, 請忽略此封信. From 1847f5b9d756dad5b44d308054a18ce4f93f65a9 Mon Sep 17 00:00:00 2001 From: "Wei-Cheng Yeh (IID)" Date: Mon, 30 Jan 2023 18:12:46 +0800 Subject: [PATCH 35/43] pfterm: fix broken scrolling when term height > ft.rows fterm_rawscroll() required that term height == ft.rows in order to work properly, but it is not the case when ft.rows is a clipped value of term height. fterm_rawscroll() now only assumes the term height to be <= 9999. Since the actual term height might not be available to pfterm, 9999 instead of a dedicated variable is used to keep existing code work. --- mbbsd/pfterm.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/mbbsd/pfterm.c b/mbbsd/pfterm.c index e6438a0c3..36b4ba172 100644 --- a/mbbsd/pfterm.c +++ b/mbbsd/pfterm.c @@ -2187,9 +2187,17 @@ fterm_rawscroll (int dy) // we are not going to preserve (rx,ry) // so don't use fterm_move*. if (dy > 0) - fterm_rawcmd2(ft.rows, 1, 1, 'H'); + { + // use a large row number in case terminal height > ft.rows + // The terminal height passed to resizeterm() can be unreliable + fterm_rawcmd2(9999, 1, 1, 'H'); + } else + { + fterm_rawcmd2(ft.rows + 1 - ady, 1, 1, 'H'); + fterm_raws(ESC_STR "[J"); fterm_rawcmd2(1, 1, 1, 'H'); + } for (; ady > 0; ady--) { From 04d5210588fb76e7398250bf5f1d966ec683871a Mon Sep 17 00:00:00 2001 From: r2 Date: Thu, 16 Feb 2023 00:01:30 +0800 Subject: [PATCH 36/43] mbbsd: only call change_contact_email when USEREC_EMAIL_IS_CONTACT is defined if we call `change_contact_email()` function when USEREC_EMAIL_IS_CONTACT is not defined in pttbbs.conf, it will cause undefined reference error when compile this source. --- mbbsd/register.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mbbsd/register.c b/mbbsd/register.c index 903b086cf..8d0ced6a9 100644 --- a/mbbsd/register.c +++ b/mbbsd/register.c @@ -1182,6 +1182,7 @@ check_register(void) char fn[PATHLEN]; int ret = 0; +#ifdef USEREC_EMAIL_IS_CONTACT // 確認一定要有聯絡信箱 if (!is_valid_email(cuser.email)) { more("etc/ensurevalidcontactemail", NA); @@ -1198,6 +1199,7 @@ check_register(void) while ((ret = change_contact_email(1))); #endif //FORCE_UPDATE_CONTACT_EMAIL_LASTLOGIN } +#endif //USEREC_EMAIL_IS_CONTACT // 已經通過的就不用了 if (HasUserPerm(PERM_LOGINOK) || HasUserPerm(PERM_SYSOP)) From d5ae5a72b88ac433147efe41d4e649f9dd585078 Mon Sep 17 00:00:00 2001 From: Chuan-Heng Hsiao Date: Sat, 22 Apr 2023 14:32:55 -0400 Subject: [PATCH 37/43] mbbsd: Fix timestamp on new entry in verifydb_change_userid --- mbbsd/verifydb.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mbbsd/verifydb.cc b/mbbsd/verifydb.cc index 33c48bd98..734a91a35 100644 --- a/mbbsd/verifydb.cc +++ b/mbbsd/verifydb.cc @@ -203,7 +203,7 @@ int verifydb_change_userid(const char *from_userid, const char *to_userid, // (by using an empty vkey). Also, make sure the insert is successful // before deleting. if (verifydb_set(to_userid, entry->generation(), entry->vmethod(), - entry->vkey()->c_str(), entry->timestamp() < 0) || + entry->vkey()->c_str(), entry->timestamp()) < 0 || verifydb_set(from_userid, entry->generation(), entry->vmethod(), "", 0) < 0) ok = false; From 36fba52521db9610f18886da68bbb083507645f2 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Tue, 16 May 2023 21:49:55 +0800 Subject: [PATCH 38/43] mbbsd/register: Use better RNG for regcode --- mbbsd/register.c | 33 ++++++++------------------------- 1 file changed, 8 insertions(+), 25 deletions(-) diff --git a/mbbsd/register.c b/mbbsd/register.c index 8d0ced6a9..d8d423bb3 100644 --- a/mbbsd/register.c +++ b/mbbsd/register.c @@ -250,29 +250,6 @@ check_and_expire_account(int uid, const userec_t * urec, int expireRange) return val; } -//////////////////////////////////////////////////////////////////////////// -// Regcode Support -//////////////////////////////////////////////////////////////////////////// - -#define REGCODE_INITIAL "v6" // always 2 characters -#define REGCODE_LEN (13) -#define REGCODE_SZ (REGCODE_LEN + 1) - -static void -makeregcode(char *buf) -{ - int i; - // prevent ambigious characters: oOlI - const char *alphabet = "qwertyuipasdfghjkzxcvbnmoQWERTYUPASDFGHJKLZXCVBNM"; - - /* generate a new regcode */ - buf[REGCODE_LEN] = 0; - buf[0] = REGCODE_INITIAL[0]; - buf[1] = REGCODE_INITIAL[1]; - for( i = 2 ; i < REGCODE_LEN ; ++i ) - buf[i] = alphabet[random() % strlen(alphabet)]; -} - //////////////////////////////////////////////////////////////////////////// // Justify Utilities //////////////////////////////////////////////////////////////////////////// @@ -670,10 +647,16 @@ register_email_verification(email_input_t *ein, bool skip_same_email_check) return REGISTER_ERR_CANCEL; } +#define REGCODE_INITIAL "v6" // always 2 characters +#define REGCODE_LEN (13) + // Send and check regcode. - char inregcode[REGCODE_SZ] = {0}, regcode[REGCODE_SZ]; + char inregcode[REGCODE_LEN + 1] = {0}; + char regcode[REGCODE_LEN + 1] = REGCODE_INITIAL; char buf[80]; - makeregcode(regcode); + + random_text_code(regcode + strlen(REGCODE_INITIAL), + REGCODE_LEN - strlen(REGCODE_INITIAL)); tries = 0; int num_sent = 0; From 2e5bff2e66be424b3c486add679b419f51f491cc Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Tue, 16 May 2023 22:02:07 +0800 Subject: [PATCH 39/43] mbbsd/chess: Fix array evaulate always true warning --- mbbsd/chess.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mbbsd/chess.c b/mbbsd/chess.c index a70a19234..96756567a 100644 --- a/mbbsd/chess.c +++ b/mbbsd/chess.c @@ -1724,7 +1724,7 @@ ChessDrawExtraInfo(const ChessInfo* info, int line, int space) prints(ANSI_COLOR(1;33) "%s" ANSI_RESET, info->myturn == info->turn ? "輪到你下棋了" : "等待對方下棋"); - } else if (line == CHESS_DRAWING_REAL_STEP_ROW && info->last_movestr) { + } else if (line == CHESS_DRAWING_REAL_STEP_ROW && info->last_movestr[0]) { outs(info->last_movestr); } else if (line == CHESS_DRAWING_REAL_TIME_ROW1) { if (info->lefthand[0]) From 8d7ed56c3cdad341fdf2a76f959e12b6c058b3cc Mon Sep 17 00:00:00 2001 From: fxfxxxfxx Date: Sun, 30 Apr 2023 16:25:12 +0800 Subject: [PATCH 40/43] mbbsd: fix assertion failure when calling a_menu from vedit2 When pressing Ctrl-G in `vedit2()`, `a_menu()` is called with lastbid == 0. If the user try to enter a hidden entry, `is_hidden_board_friend()` would fail the assertion `0<=bid-1 && bid-1filemode & FILE_HIDE) { - if (currstat == ANNOUNCE || + if (currstat == ANNOUNCE || currstat == EDITEXP || !is_hidden_board_friend(me->bid, currutmp->uid)) return 0; } From 0447b25c9d8b2d2d086b3c721e96ed9983c88ad5 Mon Sep 17 00:00:00 2001 From: "Wei-Cheng Yeh (IID)" Date: Wed, 31 May 2023 22:32:43 +0800 Subject: [PATCH 41/43] fix pfterm fterm_rawscroll() output incompatibility by passing full term size from term_resize() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some third-party apps assume that the cursor-moving escapes have in-bound coord, which had become untrue due to 1847f5b9d756dad5b44d308054a18ce4f93f65a9 (ptt/pttbbs#120). To address this, new resizeterm_within() is introduced to the API of pfterm to allow passing the full terminal size along with the display region size. This partially reverts the forward scrolling handling of 1847f5b9d756dad5b44d308054a18ce4f93f65a9 * mbbsd/pfterm.c: * struct FlatTerm * add members rows_full & cols_full for the full terminal size * add comments which explain rows & cols vs. rows_full & cols_full * fterm_rawscroll() * replace hardcoded 9999 with ft.rows_full * remove now-irrelevant comments * move term-resizing handling into new resizeterm_within(), where ft.rows_full & ft.cols_full are now updated * make resizeterm() call resizeterm_within() with the given display region size as the assumed full terminal size * docs/pfterm.txt: * bump document version to v1.2 * change the used-only-once terminology 閬蝒 "window" -> 恍 "screen" * fix typo: col -> cols for the description of resizeterm() * document resizeterm_within() * add a paragraph which explains resizeterm() vs. resizeterm_within() * include/proto.h: * add declaration of resizeterm_within() * mbbsd/screen.c: * add adaptor resizeterm_within() for consistency with pfterm API * mbbsd/term.c * term_resize() * save the display region size in new local h_crop & w_crop instead * rearrange codes to always call resizeterm_within() --- docs/pfterm.txt | 14 +++++++++++--- include/proto.h | 1 + mbbsd/pfterm.c | 18 ++++++++++++++---- mbbsd/screen.c | 10 ++++++++++ mbbsd/term.c | 15 +++++++-------- 5 files changed, 43 insertions(+), 15 deletions(-) diff --git a/docs/pfterm.txt b/docs/pfterm.txt index a97bd62c2..bb7432eb7 100644 --- a/docs/pfterm.txt +++ b/docs/pfterm.txt @@ -6,8 +6,9 @@ API Manual 函式說明手冊 - VERSION 1.1 - 最後更新: 2007/12/24 18:00 piaip + VERSION 1.2 + v1.1: 2007/12/24 18:00 piaip + 最後更新: 2023/06/01 01:55 IID ============================================================================= @@ -32,9 +33,16 @@ // initialization 初始化 void initscr (void); 初始系統 -int resizeterm (int rows, int cols); 調整視窗大小為(rows,col) +int resizeterm (int rows, int cols); 調整畫面大小為(rows,cols) +int resizeterm_within( 調整顯示範圍為終端機畫面的部分區域: + int rows, int cols, 顯示範圍大小為(rows,cols), + int rows_full, int cols_full); 實際終端機則為(rows_full,cols_full) int endwin (void); 結束系統 + resizeterm() 假設顯示範圍大小 (rows,cols) 即為實際終端機大小。 + 但當顯示範圍與實際終端機大小不符時,畫面捲動行為將會不正確; + 可用 resizeterm_within() 指定實際終端機大小 (rows_full,cols_full)。 + // cursor 游標 void getyx (int *y, int *x); 取得目前游標位置 void move (int y, int x); 移動游標 diff --git a/include/proto.h b/include/proto.h index cc3e01284..f9685f6b0 100644 --- a/include/proto.h +++ b/include/proto.h @@ -595,6 +595,7 @@ ChessInfo* reversi_replay(FILE* fp); /* screen/pfterm (ncurses-like) */ void initscr (void); int resizeterm (int rows, int cols); +int resizeterm_within(int rows, int cols, int rows_full, int cols_full); void getyx (int *py, int *px); void move (int y, int x); void clear (void); diff --git a/mbbsd/pfterm.c b/mbbsd/pfterm.c index 36b4ba172..09bc1f0a1 100644 --- a/mbbsd/pfterm.c +++ b/mbbsd/pfterm.c @@ -241,7 +241,8 @@ typedef struct ftchar *dmap; // dirty map ftchar *dcmap; // processed display map ftattr attr; - int rows, cols; + int rows, cols; // the (possibly cropped) display region size + int rows_full, cols_full; // the full terminal size int y, x; int sy,sx; // stored cursor int mi; // map index, mi = current map and (1-mi) = old map @@ -346,6 +347,7 @@ static FlatTerm ft; // initialization void initscr (void); int resizeterm (int rows, int cols); +int resizeterm_within(int rows, int cols, int rows_full, int cols_full); int endwin (void); // attributes @@ -497,9 +499,19 @@ endwin(void) int resizeterm(int rows, int cols) +{ + // assume that the full terminal size == the display region size + return resizeterm_within(rows, cols, rows, cols); +} + +int +resizeterm_within(int rows, int cols, int rows_full, int cols_full) { int dirty = 0, mi = 0, i = 0; + ft.rows_full = rows_full; + ft.cols_full = cols_full; + rows = ranged(rows, FTSZ_MIN_ROW, FTSZ_MAX_ROW); cols = ranged(cols, FTSZ_MIN_COL, FTSZ_MAX_COL); @@ -2188,9 +2200,7 @@ fterm_rawscroll (int dy) // so don't use fterm_move*. if (dy > 0) { - // use a large row number in case terminal height > ft.rows - // The terminal height passed to resizeterm() can be unreliable - fterm_rawcmd2(9999, 1, 1, 'H'); + fterm_rawcmd2(ft.rows_full, 1, 1, 'H'); } else { diff --git a/mbbsd/screen.c b/mbbsd/screen.c index ff32910ab..65461657d 100644 --- a/mbbsd/screen.c +++ b/mbbsd/screen.c @@ -78,6 +78,16 @@ initscr(void) } } +int +resizeterm_within(int rows, int cols, int rows_full GCC_UNUSED, int cols_full GCC_UNUSED) +{ + // FIXME: rows_full instead of b_lines should be used for forward scrolling + if (rows != t_lines || cols != t_columns) { + return resizeterm(rows, cols); + } + return 0; +} + int resizeterm(int w, int h) { diff --git a/mbbsd/term.c b/mbbsd/term.c index 735abcb96..05bd13689 100644 --- a/mbbsd/term.c +++ b/mbbsd/term.c @@ -52,18 +52,17 @@ void term_resize(int w, int h) /* make sure reasonable size */ - h = MAX(24, MIN(100, h)); - w = MAX(80, MIN(200, w)); + int h_crop = MAX(24, MIN(100, h)); + int w_crop = MAX(80, MIN(200, w)); - if (w != t_columns || h != t_lines) + // invoke terminal system resize + resizeterm_within(h_crop, w_crop, h, w); + if (w_crop != t_columns || h_crop != t_lines) { - // invoke terminal system resize - resizeterm(h, w); - - t_lines = h; - t_columns = w; dorefresh = 1; } + t_lines = h_crop; + t_columns = w_crop; b_lines = t_lines - 1; p_lines = t_lines - 4; From 28d8e44b4b74c138fa825373a5c2787751cb2155 Mon Sep 17 00:00:00 2001 From: holishing Date: Thu, 22 Apr 2021 15:55:14 +0800 Subject: [PATCH 42/43] common/Makefile: let it compatible with Current bmake rules mk rules used in Debian (<=10) is legacy BSD-like make rules, [1] But nowadays Debian bmake maintainer is deprecating this and use upstream's mk files by default [2] In upstream bmake project, `bsd.*.mk` rules even directly linked to `*.mk`. [3] To be compatible with both mk versions as possible, we may adjust little details. [1]: https://salsa.debian.org/debian/bmake/-/tree/7a98c0c35bd4276514fe477adb95a45d1f94f69f/debian/mk [2]: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=986281 [3]: line 182 of mk/install-mk in http://www.crufty.net/ftp/pub/sjg/mk-20210330.tar.gz --- common/Makefile | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/common/Makefile b/common/Makefile index bb5b3bdae..0855c0dfe 100644 --- a/common/Makefile +++ b/common/Makefile @@ -7,4 +7,9 @@ SUBDIR:= bbs osdep sys SUBDIR+= fbs .endif +all: + +install: all + @true + .include From c4f6a2910ecde07f62445c38ecc980f5442f4838 Mon Sep 17 00:00:00 2001 From: holishing Date: Thu, 22 Apr 2021 16:03:04 +0800 Subject: [PATCH 43/43] sample/etc/Makefile: install newly added config file for new BBS by default * Enable register methods for New BBS by default * Also install blank sms notes by default for furthur needs --- sample/etc/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/sample/etc/Makefile b/sample/etc/Makefile index 3c041e56c..e39181912 100644 --- a/sample/etc/Makefile +++ b/sample/etc/Makefile @@ -5,6 +5,7 @@ INSTALLTAG=$(TARGET).installed FILES= Welcome Welcome_login \ Logout goodbye bad_host today_boring \ register registered registermail registeredmail \ + reg.methods reg.sms.notes \ feast sysop banip.conf \ ve.hlp board.help boardlist.help \ editable expire2.conf domain_name_query.cidr \