From 0ed254d54fce0ad7aae1db700c6608fa7afe598a Mon Sep 17 00:00:00 2001 From: "Rob Swindell (on ChromeOS)" <rob@synchro.net> Date: Sun, 26 Mar 2023 19:04:01 -0700 Subject: [PATCH] A lot more progress on server configuration. Mail server configuration up next. --- src/sbbs3/scfg/scfgsrvr.c | 380 +++++++++++++++++++++++++++++++++++--- 1 file changed, 351 insertions(+), 29 deletions(-) diff --git a/src/sbbs3/scfg/scfgsrvr.c b/src/sbbs3/scfg/scfgsrvr.c index a5c81c4978..81a4fd0152 100644 --- a/src/sbbs3/scfg/scfgsrvr.c +++ b/src/sbbs3/scfg/scfgsrvr.c @@ -111,23 +111,17 @@ static void global_cfg(void) "`Global Server Settings:`\n" "\n" ; - switch(uifc.list(WIN_ACT|WIN_CHE|WIN_RHT|WIN_SAV, 0, 0, 0, &cur, &bar + switch(uifc.list(WIN_ACT|WIN_RHT|WIN_SAV|WIN_ESC, 0, 0, 0, &cur, &bar ,"Global Server Setttings",opt)) { case 0: - i = startup.log_level; - i = uifc.list(WIN_MID|WIN_SAV, 0, 0, 0, &i, 0, "Log Level", iniLogLevelStringList()); - if(i >= 0) - startup.log_level = i; + uifc.list(WIN_MID|WIN_SAV, 0, 0, 0, &startup.log_level, 0, "Log Level", iniLogLevelStringList()); break; case 1: - i = startup.tls_error_level; - i = uifc.list(WIN_MID|WIN_SAV, 0, 0, 0, &i, 0, "TLS Error Log Level", iniLogLevelStringList()); - if(i >= 0) - startup.tls_error_level = i; + uifc.list(WIN_MID|WIN_SAV, 0, 0, 0, &startup.tls_error_level, 0, "TLS Error Log Level", iniLogLevelStringList()); break; case 2: strListCombine(startup.interfaces, str, sizeof(str), ", "); - if(uifc.input(WIN_MID|WIN_SAV, 0, 0, "Network Interfaces", str, sizeof(str)-1, K_EDIT) >= 0) { + if(uifc.input(WIN_MID|WIN_SAV, 0, 0, "Inbound Network Interfaces", str, sizeof(str)-1, K_EDIT) >= 0) { strListFree(&startup.interfaces); strListSplitCopy(&startup.interfaces, str, ", "); uifc.changes = true; @@ -135,7 +129,7 @@ static void global_cfg(void) break; case 3: IPv4AddressToStr(startup.outgoing4.s_addr, str, sizeof(str)); - if(uifc.input(WIN_MID|WIN_SAV, 0, 0, "Outbound Network Interface", str, sizeof(str)-1, K_EDIT) > 0) + if(uifc.input(WIN_MID|WIN_SAV, 0, 0, "Outbound Network Interface (IPv4)", str, sizeof(str)-1, K_EDIT) > 0) startup.outgoing4.s_addr = parseIPv4Address(str); break; case 4: @@ -251,6 +245,7 @@ static void global_cfg(void) static void termsrvr_cfg(void) { static int cur, bar; + char str[256]; char tmp[256]; BOOL enabled = FALSE; bbs_startup_t startup = {0}; @@ -286,16 +281,22 @@ static void termsrvr_cfg(void) sprintf(opt[i++], "%-30s%u", "Last Node", startup.last_node); sprintf(opt[i++], "%-30s%s", "DOS Program Support", startup.options & BBS_OPT_NO_DOS ? "No" : "Yes"); sprintf(opt[i++], "%-30s%s", "SSH Support", startup.options & BBS_OPT_ALLOW_SSH ? "Yes" : "No"); - sprintf(opt[i++], "%-30s%s", "SSH Interfaces", startup.options & BBS_OPT_ALLOW_SSH ? strListCombine(startup.ssh_interfaces, tmp, sizeof(tmp), ", ") : "N/A"); + sprintf(opt[i++], "%-30s%s", "SSH Interfaces" + ,startup.options & BBS_OPT_ALLOW_SSH ? strListCombine(startup.ssh_interfaces, tmp, sizeof(tmp), ", ") : "N/A"); sprintf(opt[i++], "%-30s%u", "SSH Port", startup.ssh_port); - sprintf(opt[i++], "%-30s%s", "SSH Connect Timeout", startup.options & BBS_OPT_ALLOW_SSH ? vduration(startup.ssh_connect_timeout) : "N/A"); + sprintf(opt[i++], "%-30s%s", "SSH Connect Timeout" + ,startup.options & BBS_OPT_ALLOW_SSH ? vduration(startup.ssh_connect_timeout) : "N/A"); sprintf(opt[i++], "%-30s%s", "Telnet Support", startup.options & BBS_OPT_NO_TELNET ? "No" : "Yes"); - sprintf(opt[i++], "%-30s%s", "Telnet Interfaces", startup.options & BBS_OPT_NO_TELNET ? "N/A" : strListCombine(startup.telnet_interfaces, tmp, sizeof(tmp), ", ")); + sprintf(opt[i++], "%-30s%s", "Telnet Interfaces" + ,startup.options & BBS_OPT_NO_TELNET ? "N/A" : strListCombine(startup.telnet_interfaces, tmp, sizeof(tmp), ", ")); sprintf(opt[i++], "%-30s%u", "Telnet Port", startup.telnet_port); - sprintf(opt[i++], "%-30s%s", "Telnet Command Debug", startup.options & BBS_OPT_NO_TELNET ? "N/A" : startup.options & BBS_OPT_DEBUG_TELNET ? "Yes" : "No"); - sprintf(opt[i++], "%-30s%s", "Telnet Send Go-Aheads", startup.options & BBS_OPT_NO_TELNET ? "N/A" : startup.options & BBS_OPT_NO_TELNET_GA ? "No" : "Yes"); + sprintf(opt[i++], "%-30s%s", "Telnet Command Debug" + ,startup.options & BBS_OPT_NO_TELNET ? "N/A" : startup.options & BBS_OPT_DEBUG_TELNET ? "Yes" : "No"); + sprintf(opt[i++], "%-30s%s", "Telnet Send Go-Aheads" + ,startup.options & BBS_OPT_NO_TELNET ? "N/A" : startup.options & BBS_OPT_NO_TELNET_GA ? "No" : "Yes"); sprintf(opt[i++], "%-30s%s", "RLogin Support", startup.options & BBS_OPT_ALLOW_RLOGIN ? "Yes" : "No"); - sprintf(opt[i++], "%-30s%s", "RLogin Interfaces", startup.options & BBS_OPT_ALLOW_RLOGIN ? strListCombine(startup.rlogin_interfaces, tmp, sizeof(tmp), ", ") : "N/A"); + sprintf(opt[i++], "%-30s%s", "RLogin Interfaces" + ,startup.options & BBS_OPT_ALLOW_RLOGIN ? strListCombine(startup.rlogin_interfaces, tmp, sizeof(tmp), ", ") : "N/A"); sprintf(opt[i++], "%-30s%u", "RLogin Port", startup.rlogin_port); sprintf(opt[i++], "%-30s%u", "40 Column PETSCII Port", startup.pet40_port); sprintf(opt[i++], "%-30s%u", "80 Column PETSCII Port", startup.pet80_port); @@ -305,7 +306,8 @@ static void termsrvr_cfg(void) sprintf(opt[i++], "%-30s%s", "Max User Inactivity", vduration(startup.max_session_inactivity)); sprintf(opt[i++], "%-30s%u ms", "Output Buffer Drain Timeout", startup.outbuf_drain_timeout); sprintf(opt[i++], "%-30s%s", "Execute Timed Events", startup.options & BBS_OPT_NO_EVENTS ? "No" : "Yes"); - sprintf(opt[i++], "%-30s%s", "Execute QWK-relatd Events", startup.options & BBS_OPT_NO_EVENTS ? "N/A" : startup.options & BBS_OPT_NO_QWK_EVENTS ? "No" : "Yes"); + sprintf(opt[i++], "%-30s%s", "Execute QWK-relatd Events" + ,startup.options & BBS_OPT_NO_EVENTS ? "N/A" : startup.options & BBS_OPT_NO_QWK_EVENTS ? "No" : "Yes"); sprintf(opt[i++], "%-30s%s", "Lookup Client Hostname", startup.options & BBS_OPT_NO_HOST_LOOKUP ? "No" : "Yes"); if(!enabled) i = 1; @@ -315,21 +317,131 @@ static void termsrvr_cfg(void) "`Terminal Server Configuration:`\n" "\n" ; - switch(uifc.list(WIN_ACT|WIN_CHE|WIN_RHT|WIN_SAV, 0, 0, 0, &cur, &bar + switch(uifc.list(WIN_ACT|WIN_ESC|WIN_RHT|WIN_SAV, 0, 0, 0, &cur, &bar ,"Terminal Server",opt)) { case 0: enabled = !enabled; uifc.changes = true; break; case 1: - startup.options ^= BBS_OPT_NO_TELNET; + uifc.list(WIN_MID|WIN_SAV, 0, 0, 0, &startup.log_level, 0, "Log Level", iniLogLevelStringList()); break; case 2: - startup.options ^= BBS_OPT_ALLOW_SSH; + SAFEPRINTF(str, "%u", startup.first_node); + if(uifc.input(WIN_MID|WIN_SAV, 0, 0, "First Node Available For Terminal Logins", str, 3, K_NUMBER|K_EDIT) > 0) + startup.first_node = atoi(str); break; case 3: + SAFEPRINTF(str, "%u", startup.last_node); + if(uifc.input(WIN_MID|WIN_SAV, 0, 0, "Last Node Available For Terminal Logins", str, 3, K_NUMBER|K_EDIT) > 0) + startup.last_node = atoi(str); + break; + case 4: + startup.options ^= BBS_OPT_NO_DOS; + break; + case 5: + startup.options ^= BBS_OPT_ALLOW_SSH; + break; + case 6: + strListCombine(startup.ssh_interfaces, str, sizeof(str), ", "); + if(uifc.input(WIN_MID|WIN_SAV, 0, 0, "SSH Network Interfaces", str, sizeof(str)-1, K_EDIT) >= 0) { + strListFree(&startup.ssh_interfaces); + strListSplitCopy(&startup.ssh_interfaces, str, ", "); + uifc.changes = true; + } + break; + case 7: + SAFEPRINTF(str, "%u", startup.ssh_port); + if(uifc.input(WIN_MID|WIN_SAV, 0, 0, "SSH TCP Port", str, 5, K_NUMBER|K_EDIT) > 0) + startup.ssh_port = atoi(str); + break; + case 8: + SAFECOPY(str, duration(startup.ssh_connect_timeout, false)); + if(uifc.input(WIN_MID|WIN_SAV, 0, 0, "SSH Connect Timeout", str, 6, K_EDIT) > 0) + startup.ssh_connect_timeout = parse_duration(str); + break; + case 9: + startup.options ^= BBS_OPT_NO_TELNET; + break; + case 10: + strListCombine(startup.telnet_interfaces, str, sizeof(str), ", "); + if(uifc.input(WIN_MID|WIN_SAV, 0, 0, "Telnet Network Interfaces", str, sizeof(str)-1, K_EDIT) >= 0) { + strListFree(&startup.telnet_interfaces); + strListSplitCopy(&startup.telnet_interfaces, str, ", "); + uifc.changes = true; + } + break; + case 11: + SAFEPRINTF(str, "%u", startup.telnet_port); + if(uifc.input(WIN_MID|WIN_SAV, 0, 0, "Telnet TCP Port", str, 5, K_NUMBER|K_EDIT) > 0) + startup.telnet_port = atoi(str); + break; + case 12: + startup.options ^= BBS_OPT_DEBUG_TELNET; + break; + case 13: + startup.options ^= BBS_OPT_NO_TELNET_GA; + break; + case 14: startup.options ^= BBS_OPT_ALLOW_RLOGIN; break; + case 15: + strListCombine(startup.rlogin_interfaces, str, sizeof(str), ", "); + if(uifc.input(WIN_MID|WIN_SAV, 0, 0, "RLogin Network Interfaces", str, sizeof(str)-1, K_EDIT) >= 0) { + strListFree(&startup.rlogin_interfaces); + strListSplitCopy(&startup.rlogin_interfaces, str, ", "); + uifc.changes = true; + } + break; + case 16: + SAFEPRINTF(str, "%u", startup.rlogin_port); + if(uifc.input(WIN_MID|WIN_SAV, 0, 0, "RLogin TCP Port", str, 5, K_NUMBER|K_EDIT) > 0) + startup.rlogin_port = atoi(str); + break; + case 17: + SAFEPRINTF(str, "%u", startup.pet40_port); + if(uifc.input(WIN_MID|WIN_SAV, 0, 0, "40 Column CBM/PETSCII TCP Port", str, 5, K_NUMBER|K_EDIT) > 0) + startup.pet40_port = atoi(str); + break; + case 18: + SAFEPRINTF(str, "%u", startup.pet80_port); + if(uifc.input(WIN_MID|WIN_SAV, 0, 0, "80 Column CBM/PETSCII TCP Port", str, 5, K_NUMBER|K_EDIT) > 0) + startup.pet80_port = atoi(str); + break; + case 19: + SAFECOPY(str, maximum(startup.max_concurrent_connections)); + if(uifc.input(WIN_MID|WIN_SAV, 0, 0, "Maximum Concurrent (Unauthenticated) Connections", str, 10, K_EDIT) > 0) + startup.max_concurrent_connections = atoi(str); + break; + case 20: + SAFECOPY(str, duration(startup.max_login_inactivity, false)); + if(uifc.input(WIN_MID|WIN_SAV, 0, 0, "Maximum Socket Inactivity at Login", str, 10, K_EDIT) > 0) + startup.max_login_inactivity = parse_duration(str); + break; + case 21: + SAFECOPY(str, duration(startup.max_newuser_inactivity, false)); + if(uifc.input(WIN_MID|WIN_SAV, 0, 0, "Maximum Socket Inactivity at New User Registration", str, 10, K_EDIT) > 0) + startup.max_newuser_inactivity = parse_duration(str); + break; + case 22: + SAFECOPY(str, duration(startup.max_session_inactivity, false)); + if(uifc.input(WIN_MID|WIN_SAV, 0, 0, "Maximum Socket Inactivity during User Session", str, 10, K_EDIT) > 0) + startup.max_session_inactivity = parse_duration(str); + break; + case 23: + SAFEPRINTF(str, "%u", startup.outbuf_drain_timeout); + if(uifc.input(WIN_MID|WIN_SAV, 0, 0, "Output Buffer Draing Timeout (milliseconds)", str, 5, K_NUMBER|K_EDIT) > 0) + startup.outbuf_drain_timeout = atoi(str); + break; + case 24: + startup.options ^= BBS_OPT_NO_EVENTS; + break; + case 25: + startup.options ^= BBS_OPT_NO_QWK_EVENTS; + break; + case 26: + startup.options ^= BBS_OPT_NO_HOST_LOOKUP; + break; default: if(memcmp(&saved_startup, &startup, sizeof(startup)) != 0) uifc.changes = true; @@ -376,6 +488,7 @@ static void websrvr_cfg(void) { static int cur, bar; char tmp[256]; + char str[256]; BOOL enabled = FALSE; web_startup_t startup = {0}; @@ -409,7 +522,8 @@ static void websrvr_cfg(void) sprintf(opt[i++], "%-30s%s", "HTTP Interfaces", strListCombine(startup.interfaces, tmp, sizeof(tmp), ", ")); sprintf(opt[i++], "%-30s%u", "HTTP Port", startup.port); sprintf(opt[i++], "%-30s%s", "HTTPS Support", startup.options & WEB_OPT_ALLOW_TLS ? "Yes" : "No"); - sprintf(opt[i++], "%-30s%s", "HTTPS Interfaces", startup.options & WEB_OPT_ALLOW_TLS ? strListCombine(startup.tls_interfaces, tmp, sizeof(tmp), ", ") : "N/A"); + sprintf(opt[i++], "%-30s%s", "HTTPS Interfaces" + ,startup.options & WEB_OPT_ALLOW_TLS ? strListCombine(startup.tls_interfaces, tmp, sizeof(tmp), ", ") : "N/A"); sprintf(opt[i++], "%-30s%u", "HTTPS Port", startup.tls_port); sprintf(opt[i++], "%-30s%s", "SSJS File Extension", startup.ssjs_ext); sprintf(opt[i++], "%-30s%s", "Index Filenames", strListCombine(startup.index_file_name, tmp, sizeof(tmp), ", ")); @@ -417,7 +531,10 @@ static void websrvr_cfg(void) sprintf(opt[i++], "%-30s%s", "Error Sub-directory", startup.error_dir); sprintf(opt[i++], "%-30s%s", "Strict Transport Security", startup.options & WEB_OPT_HSTS_SAFE ? "Yes" : "No"); sprintf(opt[i++], "%-30s%s", "Virtual Host Support", startup.options & WEB_OPT_VIRTUAL_HOSTS ? "Yes" : "No"); - sprintf(opt[i++], "%-30s%s", "Access Logging", startup.options & WEB_OPT_HTTP_LOGGING ? startup.logfile_base : strDisabled); + SAFECOPY(str, startup.logfile_base); + if(*str == '\0') + SAFEPRINTF(str, "[%slogs/http-*]", cfg.logs_dir); + sprintf(opt[i++], "%-30s%s", "Access Logging", startup.options & WEB_OPT_HTTP_LOGGING ? str : strDisabled); sprintf(opt[i++], "%-30s%s", "Max Clients", maximum(startup.max_clients)); sprintf(opt[i++], "%-30s%s", "Max Inactivity", vduration(startup.max_inactivity)); sprintf(opt[i++], "%-30s%s", "Filebase Index Script", startup.file_index_script); @@ -442,15 +559,138 @@ static void websrvr_cfg(void) "`Web Server Configuration:`\n" "\n" ; - switch(uifc.list(WIN_ACT|WIN_CHE|WIN_RHT|WIN_SAV, 0, 0, 0, &cur, &bar + switch(uifc.list(WIN_ACT|WIN_ESC|WIN_RHT|WIN_SAV, 0, 0, 0, &cur, &bar ,"Web Server",opt)) { case 0: enabled = !enabled; uifc.changes = true; break; + case 1: + uifc.list(WIN_MID|WIN_SAV, 0, 0, 0, &startup.log_level, 0, "Log Level", iniLogLevelStringList()); + break; case 2: + strListCombine(startup.interfaces, str, sizeof(str), ", "); + if(uifc.input(WIN_MID|WIN_SAV, 0, 0, "Network Interfaces", str, sizeof(str)-1, K_EDIT) >= 0) { + strListFree(&startup.interfaces); + strListSplitCopy(&startup.interfaces, str, ", "); + uifc.changes = true; + } + break; + case 3: + SAFEPRINTF(str, "%u", startup.port); + if(uifc.input(WIN_MID|WIN_SAV, 0, 0, "TCP Port", str, 5, K_NUMBER|K_EDIT) > 0) + startup.port = atoi(str); + break; + case 4: startup.options ^= WEB_OPT_ALLOW_TLS; break; + case 5: + strListCombine(startup.tls_interfaces, str, sizeof(str), ", "); + if(uifc.input(WIN_MID|WIN_SAV, 0, 0, "HTTP/TLS Network Interfaces", str, sizeof(str)-1, K_EDIT) >= 0) { + strListFree(&startup.tls_interfaces); + strListSplitCopy(&startup.tls_interfaces, str, ", "); + uifc.changes = true; + } + break; + case 6: + SAFEPRINTF(str, "%u", startup.tls_port); + if(uifc.input(WIN_MID|WIN_SAV, 0, 0, "HTTP/TLS (HTTPS) TCP Port", str, 5, K_NUMBER|K_EDIT) > 0) + startup.tls_port = atoi(str); + break; + case 7: + uifc.input(WIN_MID|WIN_SAV, 0, 0, "Server-side JavaScript File Extension" + , startup.ssjs_ext, sizeof(startup.ssjs_ext) -1, K_EDIT); + break; + case 8: + strListCombine(startup.index_file_name, str, sizeof(str), ", "); + if(uifc.input(WIN_MID|WIN_SAV, 0, 0, "Index Filenames", str, sizeof(str)-1, K_EDIT) >= 0) { + strListFree(&startup.index_file_name); + strListSplitCopy(&startup.index_file_name, str, ", "); + uifc.changes = true; + } + break; + case 9: + uifc.input(WIN_MID|WIN_SAV, 0, 0, "Content Root Directory" + ,startup.root_dir, sizeof(startup.root_dir)-1, K_EDIT); + break; + case 10: + uifc.input(WIN_MID|WIN_SAV, 0, 0, "Error Sub-directory" + ,startup.error_dir, sizeof(startup.error_dir)-1, K_EDIT); + break; + case 11: + startup.options ^= WEB_OPT_HSTS_SAFE; + break; + case 12: + startup.options ^= WEB_OPT_VIRTUAL_HOSTS; + break; + case 13: + i = startup.options & WEB_OPT_HTTP_LOGGING ? 0 : 1; + i = uifc.list(WIN_SAV|WIN_MID, 0, 0, 0, &i, 0, "Log (to disk) HTTP Requests", uifcYesNoOpts); + if(i == 0) { + startup.options |= WEB_OPT_HTTP_LOGGING; + uifc.input(WIN_MID|WIN_SAV, 0, 0, "Base path/filename (blank = default)" + ,startup.logfile_base, sizeof(startup.logfile_base)-1, K_EDIT); + } else if(i == 1) + startup.options &= ~WEB_OPT_HTTP_LOGGING; + break; + case 14: + SAFECOPY(str, maximum(startup.max_clients)); + if(uifc.input(WIN_MID|WIN_SAV, 0, 0, "Maximum Client Count (0=unlimited)", str, 10, K_EDIT) > 0) + startup.max_clients = atoi(str); + break; + case 15: + SAFECOPY(str, duration(startup.max_inactivity, false)); + if(uifc.input(WIN_MID|WIN_SAV, 0, 0, "Maximum Client Inactivity", str, 10, K_EDIT) > 0) + startup.max_inactivity = parse_duration(str); + break; + case 16: + uifc.input(WIN_MID|WIN_SAV, 0, 0, "Filebase Index Script" + ,startup.file_index_script, sizeof(startup.file_index_script)-1, K_EDIT); + break; + case 17: + uifc.input(WIN_MID|WIN_SAV, 0, 0, "Filebase Virtual Path Prefix" + ,startup.file_vpath_prefix, sizeof(startup.file_vpath_prefix)-1, K_EDIT); + break; + case 18: + startup.file_vpath_for_vhosts = !startup.file_vpath_for_vhosts; + break; + case 19: + uifc.input(WIN_MID|WIN_SAV, 0, 0, "Authentication Methods" + ,startup.default_auth_list, sizeof(startup.default_auth_list)-1, K_EDIT); + break; + case 20: + SAFEPRINTF(str, "%u", startup.outbuf_drain_timeout); + if(uifc.input(WIN_MID|WIN_SAV, 0, 0, "Output Buffer Drain Timeout (milliseconds)" + ,str, 5, K_NUMBER|K_EDIT) > 0) + startup.outbuf_drain_timeout = atoi(str); + break; + case 21: + startup.options ^= BBS_OPT_NO_HOST_LOOKUP; + break; + case 22: + startup.options ^= WEB_OPT_NO_CGI; + break; + case 23: + uifc.input(WIN_MID|WIN_SAV, 0, 0, "CGI Directory" + ,startup.cgi_dir, sizeof(startup.cgi_dir)-1, K_EDIT); + break; + case 24: + strListCombine(startup.cgi_ext, str, sizeof(str), ", "); + if(uifc.input(WIN_MID|WIN_SAV, 0, 0, "CGI File Extensions", str, sizeof(str)-1, K_EDIT) >= 0) { + strListFree(&startup.cgi_ext); + strListSplitCopy(&startup.cgi_ext, str, ", "); + uifc.changes = true; + } + break; + case 25: + uifc.input(WIN_MID|WIN_SAV, 0, 0, "Default CGI MIME Content-Type" + ,startup.default_cgi_content, sizeof(startup.default_cgi_content)-1, K_EDIT); + break; + case 26: + duration_to_str(startup.max_cgi_inactivity, str, sizeof(str)); + if(uifc.input(WIN_MID|WIN_SAV, 0, 0, "Maximum CGI Inactivity", str, 10, K_EDIT) > 0) + startup.max_cgi_inactivity = parse_duration(str); + break; default: if(memcmp(&saved_startup, &startup, sizeof(startup)) != 0) uifc.changes = true; @@ -497,6 +737,7 @@ static void ftpsrvr_cfg(void) { static int cur, bar; char tmp[256]; + char str[256]; BOOL enabled = FALSE; ftp_startup_t startup = {0}; @@ -529,7 +770,8 @@ static void ftpsrvr_cfg(void) sprintf(opt[i++], "%-30s%s", "Log Level", iniLogLevelStringList()[startup.log_level]); sprintf(opt[i++], "%-30s%s", "Network Interfaces", strListCombine(startup.interfaces, tmp, sizeof(tmp), ", ")); sprintf(opt[i++], "%-30s%u, Data: %u", "Control Port", startup.port, startup.port - 1); - sprintf(opt[i++], "%-30s%s", "Passive Interface (IPv4)", startup.options & FTP_OPT_LOOKUP_PASV_IP ? "<automatic>" : IPv4AddressToStr(startup.pasv_ip_addr.s_addr, tmp, sizeof(tmp))); + sprintf(opt[i++], "%-30s%s", "Passive Interface (IPv4)" + ,startup.options & FTP_OPT_LOOKUP_PASV_IP ? "<automatic>" : IPv4AddressToStr(startup.pasv_ip_addr.s_addr, tmp, sizeof(tmp))); sprintf(opt[i++], "%-30s%u - %u", "Passive Port Range", startup.pasv_port_low, startup.pasv_port_high); sprintf(opt[i++], "%-30s%s", "Auto-generate Index File", startup.options & FTP_OPT_INDEX_FILE ? startup.index_file_name : strDisabled); sprintf(opt[i++], "%-30s%s", "QWK Message Packet Transfers", startup.options & FTP_OPT_ALLOW_QWK ? "Yes" : "No"); @@ -548,12 +790,92 @@ static void ftpsrvr_cfg(void) "`FTP Server Configuration:`\n" "\n" ; - switch(uifc.list(WIN_ACT|WIN_CHE|WIN_RHT|WIN_SAV, 0, 0, 0, &cur, &bar + switch(uifc.list(WIN_ACT|WIN_ESC|WIN_RHT|WIN_SAV, 0, 0, 0, &cur, &bar ,"FTP Server",opt)) { case 0: enabled = !enabled; uifc.changes = true; break; + case 1: + uifc.list(WIN_MID|WIN_SAV, 0, 0, 0, &startup.log_level, 0, "Log Level", iniLogLevelStringList()); + break; + case 2: + strListCombine(startup.interfaces, str, sizeof(str), ", "); + if(uifc.input(WIN_MID|WIN_SAV, 0, 0, "Network Interfaces", str, sizeof(str)-1, K_EDIT) >= 0) { + strListFree(&startup.interfaces); + strListSplitCopy(&startup.interfaces, str, ", "); + uifc.changes = true; + } + break; + case 3: + SAFEPRINTF(str, "%u", startup.port); + if(uifc.input(WIN_MID|WIN_SAV, 0, 0, "Control TCP Port", str, 5, K_NUMBER|K_EDIT) > 0) + startup.port = atoi(str); + break; + case 4: + i = startup.options & FTP_OPT_LOOKUP_PASV_IP ? 0 : 1; + i = uifc.list(WIN_MID|WIN_SAV, 0, 0, 0, &i, 0, "Automatically Detect Public IP Address", uifcYesNoOpts); + if(i == 0) + startup.options |= FTP_OPT_LOOKUP_PASV_IP; + else if(i == 1) { + startup.options &= ~FTP_OPT_LOOKUP_PASV_IP; + IPv4AddressToStr(startup.pasv_ip_addr.s_addr, str, sizeof(str)); + if(uifc.input(WIN_MID|WIN_SAV, 0, 0, "IPv4 Address for Passive Connections", str, sizeof(str)-1, K_EDIT) > 0) + startup.pasv_ip_addr.s_addr = parseIPv4Address(str); + } + break; + case 5: + SAFEPRINTF(str, "%u", startup.pasv_port_low); + if(uifc.input(WIN_MID|WIN_SAV, 0, 0, "Lowest Passive TCP Port", str, 5, K_NUMBER|K_EDIT) > 0) + startup.pasv_port_low = atoi(str); + else + break; + SAFEPRINTF(str, "%u", startup.pasv_port_high); + if(uifc.input(WIN_MID|WIN_SAV, 0, 0, "Highest Passive TCP Port", str, 5, K_NUMBER|K_EDIT) > 0) + startup.pasv_port_high = atoi(str); + break; + case 6: + i = startup.options & FTP_OPT_INDEX_FILE ? 0 : 1; + i = uifc.list(WIN_SAV|WIN_MID, 0, 0, 0, &i, 0, "Autogenerate Index Files", uifcYesNoOpts); + if(i == 0) { + startup.options |= FTP_OPT_INDEX_FILE; + uifc.input(WIN_MID|WIN_SAV, 0, 0, "Index Filename" + ,startup.index_file_name, sizeof(startup.index_file_name)-1, K_EDIT); + } else if(i == 1) + startup.options &= ~FTP_OPT_INDEX_FILE; + break; + case 7: + startup.options ^= FTP_OPT_ALLOW_QWK; + break; + case 8: + SAFECOPY(str, duration(startup.qwk_timeout, false)); + if(uifc.input(WIN_MID|WIN_SAV, 0, 0, "QWK Message Packet Creation Timeout", str, 10, K_EDIT) > 0) + startup.qwk_timeout = parse_duration(str); + break; + case 9: + SAFECOPY(str, maximum(startup.max_clients)); + if(uifc.input(WIN_MID|WIN_SAV, 0, 0, "Maximum Client Count (0=unlimited)", str, 10, K_EDIT) > 0) + startup.max_clients = atoi(str); + break; + case 10: + SAFECOPY(str, duration(startup.max_inactivity, false)); + if(uifc.input(WIN_MID|WIN_SAV, 0, 0, "Maximum Client Inactivity", str, 10, K_EDIT) > 0) + startup.max_inactivity = parse_duration(str); + break; + case 11: + SAFECOPY(str, maximum(startup.max_concurrent_connections)); + if(uifc.input(WIN_MID|WIN_SAV, 0, 0, "Maximum Concurrent (Unauthenticated) Connections", str, 10, K_EDIT) > 0) + startup.max_concurrent_connections = atoi(str); + break; + case 12: + startup.options ^= FTP_OPT_NO_LOCAL_FSYS; + break; + case 13: + startup.options ^= FTP_OPT_ALLOW_BOUNCE; + break; + case 14: + startup.options ^= BBS_OPT_NO_HOST_LOOKUP; + break; default: if(memcmp(&saved_startup, &startup, sizeof(startup)) != 0) uifc.changes = true; @@ -696,7 +1018,7 @@ static void mailsrvr_cfg(void) "`Mail Server Configuration:`\n" "\n" ; - switch(uifc.list(WIN_ACT|WIN_CHE|WIN_RHT|WIN_SAV, 0, 0, 0, &cur, &bar + switch(uifc.list(WIN_ACT|WIN_ESC|WIN_RHT|WIN_SAV, 0, 0, 0, &cur, &bar ,"Mail Server",opt)) { case 0: enabled = !enabled; @@ -789,7 +1111,7 @@ static void services_cfg(void) "`Services Server Configuration:`\n" "\n" ; - switch(uifc.list(WIN_ACT|WIN_CHE|WIN_RHT|WIN_SAV, 0, 0, 0, &cur, &bar + switch(uifc.list(WIN_ACT|WIN_ESC|WIN_RHT|WIN_SAV, 0, 0, 0, &cur, &bar ,"Services Server",opt)) { case 0: enabled = !enabled; @@ -886,7 +1208,7 @@ void server_cfg(void) "the `ctrl/sbbs.ini` file and `https://wiki.synchro.net/config:sbbs.ini`\n" "for reference.\n" ; - i = uifc.list(WIN_ORG|WIN_ACT|WIN_CHE,0,0,0,&srvr_dflt,0, "Server Configuration",opt); + i = uifc.list(WIN_ORG|WIN_ACT,0,0,0,&srvr_dflt,0, "Server Configuration",opt); switch(i) { case 0: global_cfg(); -- GitLab