diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index e204c879710a6752cf6ad6d36c90cde4779300ab..825d202e34bb1291ad7755e9a64f12f593782a82 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -19,8 +19,9 @@ build-sbbs: artifacts: name: sbbs paths: - - "src/sbbs3/*.release/*" - - "src/sbbs3/*/*.release/*" + - "src/sbbs3/*.exe.release/*" + - "src/sbbs3/*.lib.release/*" + - "src/sbbs3/*/*.exe.release/*" build-sexpots: stage: build @@ -34,7 +35,7 @@ build-sexpots: artifacts: name: sexpots paths: - - "src/sexpots/*.release/*" + - "src/sexpots/*.exe.release/*" build-syncterm: stage: build @@ -48,7 +49,7 @@ build-syncterm: artifacts: name: syncterm paths: - - "src/syncterm/*.release/*" + - "src/syncterm/*.exe.release/*" # run tests using the binary built before #test: diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000000000000000000000000000000000000..eb48e4785049cf76ab210f68af16f9d051aed637 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,19 @@ +## Contributing changes to the Synchronet Source Repository + +Merge requests are considered and accepted at [gitlab.synchro.net](https://gitlab.synchro.net). +Do not submit pull/merge requests in the Synchronet *mirror projects* on github.com or gitlab.com; they won't be considered. + +When submitting merge requests to existing files, unless you have prior agreement with the maintainers: +* Use the dominant coding style of the file(s) being modified +* Do not perform tab to space conversions (or vice-versa); incidental trimming of trailing whitespace is okay +* Do not include changes that are not relevant to the merge request description/message +* Keep merge requests to a single topical change (e.g. don't combine new features with bug fixes with typo-fixes and style changes) + +In general, if it's a large set of changes, your best bet of getting it accepted and merged into the repo would be to discuss the concept of the change with the developers in the [Synchronet Programming conference](http://web.synchro.net/?page=001-forum.ssjs&sub=syncprog) **first**. + +When modifying the C/C++ source files: +* Do not call functions from `ctype.h` (e.g. `isprint`, `isspace`, `isdigit`, etc.) - use the `gen_defs.h IS_*` macros instead. + +If you were interested in contributing money, not code, then paypal to rob at synchro dot net. + +Thank you for contributing! \ No newline at end of file diff --git a/ctrl/sbbs.ini b/ctrl/sbbs.ini index 0a717ce8c7ba306018b27ebcf7424c52b03ca0d7..2aef936d3a74828f941e4ed4c6a4f29a574359e9 100644 --- a/ctrl/sbbs.ini +++ b/ctrl/sbbs.ini @@ -172,6 +172,7 @@ Options = XTRN_MINIMIZED | ALLOW_RLOGIN | ALLOW_SSH InboundSound = OutboundSound = ConnectTimeout = 30 + MaxConcurrentConnections = 0 ; Supported options (separated with |): ; DEBUG_RX_HEADER - Log header fields of received mail messages ; DEBUG_RX_BODY - Leave body text of received mail messages in temp directory forever diff --git a/ctrl/sbbsecho.ini b/ctrl/sbbsecho.ini index 48629697fb2affbef9b3e45d7b2a2387de66fd17..4d3fd036b04187e128f3b4bcdb8ad18a1bf283a7 100644 --- a/ctrl/sbbsecho.ini +++ b/ctrl/sbbsecho.ini @@ -153,6 +153,14 @@ DefaultRecipient = Zones = 57 DNSSuffix = NodeList = +[domain:cnet] + Zones = 64 + DNSSuffix = + NodeList = +[domain:scinet] + Zones = 77 + DNSSuffix = + NodeList = [domain:retronet] Zones = 80 DNSSuffix = @@ -173,6 +181,10 @@ DefaultRecipient = Zones = 169 DNSSuffix = NodeList = +[domain:devnet] + Zones = 256 + DNSSuffix = + NodeList = [domain:pinet] Zones = 314 DNSSuffix = @@ -189,6 +201,10 @@ DefaultRecipient = Zones = 432 DNSSuffix = ftn.vkradio.com NodeList = +[domain:musicnet] + Zones = 440 + DNSSuffix = + NodeList = [domain:justanet] Zones = 510 DNSSuffix = @@ -229,6 +245,10 @@ DefaultRecipient = Zones = 900 DNSSuffix = NodeList = +[domain:tqwnet] + Zones = 1337 + DNSSuffix = + NodeLIst = [domain:quartz] Zones = 2547 DNSSuffix = diff --git a/ctrl/text.dat b/ctrl/text.dat index 897bc0224f8bd393c32018a365a4f6fadeaebe7c..a2b4bf512a306bcace791e5175a661b764b99472 100644 --- a/ctrl/text.dat +++ b/ctrl/text.dat @@ -583,7 +583,7 @@ "\1h\1bUser Settings for \1w%s #%d\1b:\r\n\r\n" 474 UserDefaultsHdr "\1n\1b[\1h\1wT\1n\1b] \1hTerminal Mode \1n\1b\1\\: \1c%s\r\n" 475 UserDefaultsTerminal "\1n\1b[\1h\1wE\1n\1b] \1hExternal Editor \1n\1b\1\\: \1c%s\r\n" 476 UserDefaultsXeditor -"\1n\1b[\1h\1wL\1n\1b] \1hScreen Length \1n\1b\1\\: \1c%s %s\r\n" 477 UserDefaultsRows +"\1n\1b[\1h\1wL\1n\1b] \1hTerminal Dimensions \1n\1b\1\\: \1c%s %s\r\n" 477 UserDefaultsRows "\1n\1b[\1h\1wX\1n\1b] \1hExpert Menu Mode \1n\1b: \1c%s\r\n" 478 UserDefaultsMenuMode "\1n\1b[\1h\1wP\1n\1b] \1hScreen Pause \1n\1b: \1c%s\r\n" 479 UserDefaultsPause "\1n\1b[\1h\1wH\1n\1b] \1hHot Keys \1n\1b: \1c%s\r\n" 480 UserDefaultsHotKey @@ -604,8 +604,8 @@ "\r\n\1n\1h\1bWhich or [\1wQ\1b]uit: \1c" 494 UserDefaultsWhich "On" 495 On "Off" 496 Off -"\r\n\1_\1b\1h[\1c@CHECKMARK@\1b] \1yHow many rows on your monitor "\ 497 HowManyRows - "[\1wAuto Detect\1y]: " +"\1_\1b\1h[\1c@CHECKMARK@\1b] \1yTerminal rows "\ 497 HowManyRows + "[\1wAuto\1y]: \1n" "\r\n\1_\1y\1hCurrent Password: \1w" 498 CurrentPassword "Forward personal e-mail to network mail address" 499 ForwardMailQ "\1_\1b\1h[\1c@CHECKMARK@\1b] \1yNetwork mail address\1\\ "\ 500 EnterNetMailAddress @@ -1021,4 +1021,6 @@ "\xda\xbf\xd9\xc0" 839 SpinningCursor6 "\xdc\xde\xdf\xdd" 840 SpinningCursor7 "\xdc\xdd\xdf\xde" 841 SpinningCursor8 -"\xfa\xf9\xfe\xf9" 842 SpinningCursor9 \ No newline at end of file +"\xfa\xf9\xfe\xf9" 842 SpinningCursor9 +"\1_\1b\1h[\1c@CHECKMARK@\1b] \1yTerminal columns "\ 843 HowManyColumns + "[\1wAuto\1y]: \1n" \ No newline at end of file diff --git a/exec/init-fidonet.ini b/exec/init-fidonet.ini index e3c33868ba902c1398a9fb6d6bd9ca7c47cde2fc..0591376899a7cad042950b37ba3d27a2aaaca894 100644 --- a/exec/init-fidonet.ini +++ b/exec/init-fidonet.ini @@ -10,6 +10,7 @@ ; name = Name of the network, usually the same as the 5D domain, <= 8 chars ; desc = Short description of the network ; info = URL to information about the network +; pack = URL to info pack file ; coord = Name of the zone/network coordinator ; email = Internet email address of the zone/network coordinator ; fido = FidoNet address of the zone/network coordinator (for NetMail) @@ -46,11 +47,24 @@ desc = Australasia [zone:4] name = FidoNet desc = Latin America (except Puerto Rico) - + +[zone:11] +name = WWIVnet +desc = WWIVnet +info = https://www.wwivbbs.org/docs/network/wwivnet.html +coord = Mark Hofmann +email = mark@weather-station.org +addr = 11:1/100 +host = bbs.weather-station.org +port = 24555 +echolist = https://raw.githubusercontent.com/wwivbbs/wwivnet/master/wwivnet/wwivnet.na +areatag_prefix = WWIV_ + [zone:21] name = fsxNet desc = Fun, Simple and eXperimental network info = http://fsxnet.nz/ +pack = https://github.com/fsxnet/infopack/archive/master.zip coord = Paul Hayton email = avon@bbs.nz addr = 21:1/100 @@ -76,32 +90,32 @@ areatitle_prefix = AmigaNet: [zone:40] name = CyberNet desc = Stock, Trading, Cybersecurity, OS, Technology, Hacking, Crypto -info = http://www.thebytexchange.com/cybernet/ +info = telnet://bbs.thebytexchange.com:23 coord = Chad Adams email = nugax@thebytexchange.com addr = 40:1/1@cybernet fido = 1:19/37 host = hub.cybernetbbs.net -echolist = http://thebytexchange.com/cybernet/cybernet.na areatag_prefix = CN_ [zone:44] name = DoRENET desc = BBS modifications, coding, ansi/asci etc info = https://www.dreamlandbbs.org/dorenet/ +pack = https://www.dreamlandbbs.org/wp-content/uploads/2020/04/dorenet.zip coord = Dream Master addr = 44:100/0 fido = 1:218/530 host = bbs.dreamlandbbs.org handles = true echolist = DORENET.NA -areatag_prefix = DN_ +areatag_prefix = DN_ areatag_exclude = netmail [zone:46] name = Agoranet desc = The Official Network of ACiD Productions -info = ftp://pharcyde.org/agoranet/AGN_INFO/agoranet.zip +pack = ftp://pharcyde.org/agoranet/AGN_INFO/agoranet.zip coord = Nicholas Boel email = accessd@pharcyde.org addr = 46:1/100 @@ -129,31 +143,71 @@ areatag_prefix = CNT_ name = SciNet desc = Active network for the BBS scene info = https://scinet-ftn.org/ +pack = https://scinet-ftn.org/sciinfo.zip coord = Frank Linhares email = scinet@diskshop.ca addr = 77:1/100 fido = 1:229/101 dns = scinet-ftn.org +host = bbs.diskshop.ca echolist = https://scinet-ftn.org/scinet.na -areatag_prefix = areatitle_prefix = SciNet: +[zone:256] +name = DevNet +desc = developer oriented network +info = http://www.digitaldistortionbbs.com, Also available as QWK. See pack. +pack = ftp://digitaldistortionbbs.com/bbs/INFOPAKS/DevNet.zip +coord = Tony Langdon +email = vk3jed@vkradio.com +addr = 256:8/100 +host = bridge.vkradio.com +echolist = devnet.na +areatag_prefix = DEV_ + [zone:432] name = VKRadio desc = hobbyist radio communication oriented network -info = https://vkradio.com/vkradio.zip +info = https://vkradio.com/vkradio.zip +pack = https://vkradio.com/vkradio.zip coord = Tony Langdon email = vk3jed@vkradio.com addr = 432:1/100 fido = 3:633/410 dns = ftn.vkradio.com +host = bridge.vkradio.com echolist = https://vkradio.com/vkradio.na areatag_prefix = VK_ +[zone:440] +name = MusicNet +desc = music oriented network +info = http://www.digitaldistortionbbs.com, Also available as QWK. See pack. +pack = ftp://digitaldistortionbbs.com/bbs/INFOPAKS/MusicNet.zip +coord = Tony Langdon +email = vk3jed@vkradio.com +addr = 440:1/100 +host = bridge.vkradio.com +echolist = musicnet.na +areatag_prefix = MUS_ + +[zone:316] +name = Whisper +desc = Family-Oriented Bulletin Board Message/File Network +info = http://www.cr1mson.org/whispernet.html +pack = http://www.cr1mson.org/uploads/1/4/5/3/14535704/whispnet.zip +coord = Jon Justvig +email = jonathanjustvig@gmail.com +addr = 316:36/1 +host = vintagebbsing.com +echolist = wenmbone.na +areatag_prefix = WHISP_ + [zone:618] -name = Micronet +name = Micronet desc = laid-back, friendly and comfortable mail info = https://minftn.net/ +pack = http://minftn.net/mininfo.zip coord = Sean Dennis email = zc@minftn.net fido = 1:18/200 @@ -162,3 +216,15 @@ addr = 618:618/2 host = phoenix.bnbbbs.net echolist = micronet.na areatag_prefix = MIN_ + +[zone:1337] +name = tqwNet +desc = A network for having fun and international friendships +info = https://www.erb.pw/ +pack = https://www.erb.pw/tqwinfo.zip +coord = MeaTLoTioN +email = ml@erb.pw +addr = 1337:3/100 +host = hub.ca.erb.pw +echolist = tqwnet.na +areatag_prefix = TQW_ diff --git a/exec/init-fidonet.js b/exec/init-fidonet.js index a204eccf23b3b442721db8b73be6b8b7b4e79a4a..8f93b89a19291c0e4438db71f680517e45ba540a 100644 --- a/exec/init-fidonet.js +++ b/exec/init-fidonet.js @@ -22,15 +22,16 @@ "use strict"; -const REVISION = "$Revision: 1.29 $".split(' ')[1]; +const REVISION = "$Revision: 1.30 $".split(' ')[1]; require('sbbsdefs.js', 'SUB_NAME'); +const temp_node = 9999; var netname; var netdns; var netzone = parseInt(argv[0], 10); if(!netzone) netname = argv[0]; var echolist_url = argv[1]; -// If you want your Othernet listed here, please provide information +// If you want your Othernet listed in init-fidonet.ini, please provide information // and an http[s] URL to your official EchoList var network; var fidoaddr = load({}, 'fidoaddr.js'); @@ -42,7 +43,7 @@ print("************************************************************************* var network_list = {}; var file = new File(js.exec_dir + "init-fidonet.ini"); -if (file.open("r")) { +if(file.open("r")) { var list = file.iniGetSections("zone:", "zone"); for(var i in list) network_list[list[i].substr(5)] = file.iniGetObject(list[i]); @@ -59,15 +60,15 @@ function aborted() function exclude_strings(list, patterns, flags) { patterns = [].concat(patterns); - if (flags === undefined) + if(flags === undefined) flags = 'i'; return list.reduce(function (a, c) { var matched = patterns.some(function (e) { - if (typeof e == 'string') + if(typeof e == 'string') e = new RegExp(e, flags); return c.match(e); - }); - if (!matched) + }); + if(!matched) a.push(c); return a; }, []); @@ -150,11 +151,13 @@ function send_app_netmail(destaddr) body_text += "\r\n"; body_text += "My system is " + system.name + " at " + system.inet_addr + ".\r\n"; body_text += "\r\n"; - body_text += "I am using Synchronet-" + system.platform + " v" + system.full_version + body_text += "I am using Synchronet-" + system.platform + " v" + system.full_version + " with SBBSecho and BinkIT.\r\n"; body_text += "\r\n"; body_text += "My requested AreaFix password is: '" + link.AreaFixPwd + "'\r\n"; body_text += "My requested BinkP Session password is: '" + link.SessionPwd + "'\r\n"; + if(link.TicFilePwd) + body_text += "My requested TIC Password is: '" + link.TicFilePwd + "'\r\n"; body_text += "\r\n"; body_text += "I will be using 'Type-2+' (FSC-39) packets with no password.\r\n"; body_text += "Uncompressed or PKZIP-archived EchoMail bundles will work fine.\r\n"; @@ -187,13 +190,13 @@ function lookup_network(info) if(result) return result; } - + var file = new File("sbbsecho.ini"); - if (!file.open("r")) { + if(!file.open("r")) { alert("Error " + file.error + " opening " + file.name); return false; } - + if(typeof info == "number") { // zone var dns; var domain_list = file.iniGetSections("domain:"); @@ -230,12 +233,52 @@ function lookup_network(info) return result; } -function get_linked_node(addr) +function get_domain(zone) +{ + var file = new File("sbbsecho.ini"); + if(!file.open("r")) { + alert("Error " + file.error + " opening " + file.name); + return false; + } + + var domain_list = file.iniGetSections("domain:"); + if(domain_list) { + var zonemap = {}; + for(var i = 0; i < domain_list.length && !result; i++) { + var section = domain_list[i]; + var netname = section.substr(7) + var zones = file.iniGetValue(section, "Zones"); + if(!zones) + continue; + if(typeof zones == 'number') { + if(zone == zones) { + return netname; + } + continue; + } + zones = zones.split(','); + for(var j = 0; j < zones.length; j++) { + if(zone == zones[j]) { + return netname; + } + } + } + file.close(); + return result; + } + return ""; +} + +function get_linked_node(addr, domain) { var file = new File("sbbsecho.ini"); - if (!file.open("r")) + if(!file.open("r")) return false; - var result = file.iniGetObject("node:" + addr); + var result = false; + if(domain) + result = file.iniGetObject("node:" + addr + "@" + domain); + if (!result) + result = file.iniGetObject("node:" + addr); file.close(); return result; } @@ -243,14 +286,14 @@ function get_linked_node(addr) function get_binkp_sysop() { var file = new File("sbbsecho.ini"); - if (!file.open("r")) + if(!file.open("r")) return false; var result = file.iniGetValue("Binkp", "Sysop"); file.close(); return result; } -function update_sbbsecho_ini(hub, link, echolist_fname, areamgr) +function update_sbbsecho_ini(hub, link, domain, echolist_fname, areamgr) { function makepath(path) { @@ -295,15 +338,36 @@ function update_sbbsecho_ini(hub, link, echolist_fname, areamgr) if(!binkp) binkp = {}; binkp.sysop = sysop; if(!file.iniSetObject("binkp", binkp)) { - return "Error" + file.error + " writign to " + file.name; + return "Error" + file.error + " writing to " + file.name; } + + var prefnode; var section = "node:" + fidoaddr.to_str(hub); - if(!file.iniGetObject(section) - || confirm("Overwrite hub [" + section + "] configuration in " + file.name)) { - if(!file.iniSetObject(section, link)) { - return "Error " + file.error + " writing to " + file.name; + + if(domain) { + if(file.iniGetObject(section)) { + if(confirm("Migrate " + section + " to " + section + "@" + domain)) { + if(!file.iniSetObject(section + "@" + domain, link)) { + return "Error " + file.error + " writing to " + file.name; + } else { + file.iniRemoveSection(section); + } + } + } else { + if(!file.iniGetObject(section) || confirm("Overwrite hub [" + section + "@" + domain + "] configuration in " + file.name)) { + if(!file.iniSetObject(section + "@" + domain, link)) { + return "Error " + file.error + " writing to " + file.name; + } + } + } + } else { + if(!file.iniGetObject(section) || confirm("Overwrite hub [" + section + "] configuration in " + file.name)) { + if(!file.iniSetObject(section, link)) { + return "Error " + file.error + " writing to " + file.name; + } } } + var section = "node:" + hub.zone + ":ALL"; if(confirm("Route all zone " + hub.zone + " netmail through your hub")) { if(!file.iniSetObject(section, @@ -343,7 +407,6 @@ else if(netname) { netzone = lookup_network(netname); network = network_list[netzone]; } - if(!netzone) { for(var zone in network_list) { var desc = ""; @@ -358,7 +421,8 @@ if(!netzone) { email = " <" + network_list[zone].email + ">"; if(network_list[zone].fido) email += " " + network_list[zone].fido; - print(" coordinator: " + (network_list[zone].coord || "") + email); + // removed because screen is scrolling so much with so many networks + //print(" coordinator: " + (network_list[zone].coord || "") + email); } } var which; @@ -377,10 +441,13 @@ if(network) else network = {}; + +var domain = get_domain(netzone); + if(netzone <= 6) netname = "FidoNet"; else { - while((!netname || netname.indexOf(' ') >= 0 || netname.length > 8 + while((!netname || netname.indexOf(' ') >= 0 || netname.length > 8 || !confirm("Network name is '" + netname + "'")) && !aborted()) { var str = prompt("Network name (no spaces or illegal filename chars) [" + netname + "]"); if(str) @@ -391,7 +458,12 @@ if(netname) { print("Network name: " + netname); print("Network zone: " + netzone); print("Network info: " + network.info); - print("Network coordinator: " + network.coord + if(domain) + print("Network domain: " + domain); + if (network.pack) { + print("Network pack: " + network.pack); + } + print("Network coordinator: " + network.coord + (network.email ? (" <" + network.email + ">") : "") + (network.fido ? (" " + network.fido) : "")); if(network.also) @@ -403,12 +475,12 @@ if(netname) { print("Reading Message Area configuration file: msgs.cnf"); var cnflib = load({}, "cnflib.js"); var msgs_cnf = cnflib.read("msgs.cnf"); -if (!msgs_cnf) { +if(!msgs_cnf) { alert("Failed to read msgs.cnf"); exit(1); } -var your = {zone: NaN, net: NaN, node: 9999, point: 0}; +var your = {zone: NaN, net: NaN, node: temp_node, point: 0}; for(var i = 0; i < system.fido_addr_list.length; i++) { var addr = fidoaddr.parse(system.fido_addr_list[i]); if(!addr || addr.zone != netzone) @@ -432,7 +504,7 @@ while(((isNaN(hub.zone) || hub.zone < 1) hub = fidoaddr.parse(prompt("Your hub's address (zone:net/node)")); } -var link = get_linked_node(fidoaddr.to_str(hub)); +var link = get_linked_node(fidoaddr.to_str(hub), domain); if(!link) link = {}; @@ -477,11 +549,11 @@ while(!confirm("Your node address is " + fidoaddr.to_str(your)) && !aborted()) { your.net = NaN; your.node = NaN; while((isNaN(your.zone) || your.zone < 1) && !aborted()) - your.zone = parseInt(prompt("Your zone number (e.g. 1 for FidoNet North America)")); + your.zone = parseInt(prompt("Your zone number (e.g. " + hub.zone + ")")); while((isNaN(your.net) || your.net < 1) && !aborted()) - your.net = parseInt(prompt("Your network number (i.e. normally the same as your hub)")); + your.net = parseInt(prompt("Your network number (e.g. " + hub.net + ")")); while((isNaN(your.node) || your.node < 1) && !aborted()) - your.node = parseInt(prompt("Your node number (e.g. 9999 for temporary node)")); + your.node = parseInt(prompt("Your node number (e.g. " + temp_node + " for temporary node)")); while((isNaN(your.point)) && !aborted()) your.point = parseInt(prompt("Your point number (i.e. 0 for a normal node)")); } @@ -500,13 +572,15 @@ while((!sysop || !confirm("Your name is '" + sysop + "'")) && !aborted()) /* Get/Confirm passwords */ while((!link.AreaFixPwd || !confirm("Your AreaFix Password is '" + link.AreaFixPwd + "'")) && !aborted()) link.AreaFixPwd = prompt("Your AreaFix (a.k.a. Area Manager) Password (case in-sensitive)"); -while((!link.SessionPwd || !confirm("Your BinkP Session Passowrd is '" + link.SessionPwd + "'")) && !aborted()) +while((!link.SessionPwd || !confirm("Your BinkP Session Password is '" + link.SessionPwd + "'")) && !aborted()) link.SessionPwd = prompt("Your BinkP Session Password (case sensitive)"); +while(((!link.TicFilePwd && (link.TicFilePwd !== "")) || !confirm("Your TIC File Password is '" + (link.TicFilePwd ? link.TicFilePwd : "(not set)") + "'")) && !aborted()) + link.TicFilePwd = prompt("Your TIC File Password (case sensitive) (optional)"); /***********************************************/ /* SEND NODE NUMBER REQUEST NETMAIL (Internet) */ /***********************************************/ -if(your.node === 9999 && network.email && network.email.indexOf('@') > 0 +if(your.node === temp_node && network.email && network.email.indexOf('@') > 0 && confirm("Send a node number application to " + network.email)) { var result = send_app_netmail(network.email); if(typeof result !== 'boolean') { @@ -517,7 +591,7 @@ if(your.node === 9999 && network.email && network.email.indexOf('@') > 0 exit(0); if(confirm("Come back when you have your permanently-assigned node address")) { if(confirm("Save changes to FidoNet configuration file: sbbsecho.ini")) { - var result = update_sbbsecho_ini(hub, link); + var result = update_sbbsecho_ini(hub, link, domain); if (result != true) { alert(result); exit(1); @@ -545,12 +619,12 @@ if(!msg_area.grp[netname] && confirm("Create " + netname + " message group in SCFG->Message Areas")) { print("Adding Message Group: " + netname); msgs_cnf.grp.push( { - "name": netname, - "description": netname, - "ars": "", - "code_prefix": network.areatag_prefix === undefined - ? (netname.toUpperCase() + "_") : network.areatag_prefix - }); + "name": netname, + "description": netname, + "ars": "", + "code_prefix": network.areatag_prefix === undefined + ? (netname.toUpperCase() + "_") : network.areatag_prefix + }); } if(confirm("Save Changes to Message Area configuration file: msgs.cnf")) { if(!cnflib.write("msgs.cnf", undefined, msgs_cnf)) { @@ -564,11 +638,12 @@ if(confirm("Save Changes to Message Area configuration file: msgs.cnf")) { /* DOWNLOAD ECHOLIST */ /*********************/ var echolist_fname = file_getname(network.echolist); -if(network.echolist +load("http.js"); +if(network.echolist && (network.echolist.indexOf("http://") == 0 || network.echolist.indexOf("https://") == 0) && confirm("Download " + netname + " EchoList: " + file_getname(network.echolist))) { var echolist_url = network.echolist; - load("http.js"); + while(!aborted()) { while((!echolist_url || !confirm("Download from: " + echolist_url)) && !aborted()) { echolist_url = prompt("Echolist URL"); @@ -589,8 +664,8 @@ if(network.echolist break; continue; } - if(http_request.response_code == 200) { - print("Downloaded " + echolist_url + " to " + file.name); + if(http_request.response_code == http_request.status.ok) { + print("Downloaded " + echolist_url + " to " + system.ctrl_dir + file.name); file.write(contents); file.close(); break; @@ -601,14 +676,65 @@ if(network.echolist if(!confirm("Try again")) break; } +} else if (network.pack + && (network.pack.indexOf("http://") == 0 || network.pack.indexOf("https://") == 0) + && confirm("Download " + netname + " Info Pack: " + network.pack)) { + while(!aborted()) { + var packdlfilename = file_getname(network.pack) + var file = new File(packdlfilename); + if(!file.open("w")) { + alert("Error " + file.error + " opening " + file.name); + exit(1); + } + var http_request = new HTTPRequest(); + try { + var contents = http_request.Get(network.pack); + } catch(e) { + alert(e); + file.close(); + file_remove(system.ctrl_dir + file.name); + if(!confirm("Try again")) + break; + continue; + } + if(http_request.response_code == http_request.status.ok) { + print("Downloaded " + network.pack + " to " + system.ctrl_dir + file.name); + file.write(contents); + file.close(); + + // try to extract + var prefix = ""; + if(system.platform == "Win32") + prefix = system.exec_dir; + if (system.exec(prefix + "unzip -CLjo " + file_getname(network.pack) + " " + echolist_fname) !== 0) { + print("Please extract " + network.echolist + " from " + file.name + " into " + system.ctrl_dir); + } + + break; + } + file.close(); + file_remove(file.name); + alert("Error " + http_request.response_code + " downloading " + network.pack); + if(!confirm("Try again")) + break; + } } while(echolist_fname && !file_getcase(echolist_fname) && !aborted()) { alert(system.ctrl_dir + echolist_fname + " does not exist"); - if(!confirm("Install " + netname + " EchoList: " + echolist_fname)) - break; - prompt("Download and extract " + echolist_fname + " now... Press enter to continue"); + if ((network.echolist.indexOf("http://") == -1) && (network.echolist.indexOf("https://") == -1) + && (network.pack)) { + if (!confirm("Please extract the " + echolist_fname + " file from the pack " + file_getname(network.pack) + " into " + system.ctrl_dir + ". Continue?")) { + break; + } + } else { + if (!confirm("Please place " + echolist_fname + " into " + system.ctrl_dir + ". Continue?")) { + break; + } + } + + prompt(echolist_fname + " not found. Please put file into ctrl dir and press Enter."); } -echolist_fname = file_getcase(echolist_fname) +echolist_fname = file_getcase(system.ctrl_dir + echolist_fname) if(echolist_fname && file_size(echolist_fname) > 0) { if(network.areatag_exclude) { print("Removing " + network.areatag_exclude + " from " + echolist_fname); @@ -618,7 +744,7 @@ if(echolist_fname && file_size(echolist_fname) > 0) { } if(network.areatitle_prefix) { print("Removing " + network.areatitle_prefix + " Title Prefixes from " + echolist_fname); - var result = remove_prefix_from_titles(echolist_fname, network.areatitle_prefix); + var result = remove_prefix_from_title(echolist_fname, network.areatitle_prefix); if(result !== true) alert(result); } @@ -628,11 +754,11 @@ if(echolist_fname && file_size(echolist_fname) > 0) { if(!network.handles) misc |= SUB_NAME; system.exec(system.exec_dir + "scfg" - + " -import=" + echolist_fname + + " -import=" + echolist_fname + " -g" + netname + " -faddr=" + fidoaddr.to_str(your) + " -misc=" + misc - ); + ); } } @@ -640,7 +766,7 @@ if(echolist_fname && file_size(echolist_fname) > 0) { /* UPDATE SBBSECHO.INI */ /***********************/ if(confirm("Save changes to FidoNet configuration file: sbbsecho.ini")) { - var result = update_sbbsecho_ini(hub, link, echolist_fname, network.areamgr); + var result = update_sbbsecho_ini(hub, link, domain, echolist_fname, network.areamgr); if (result != true) { alert(result); exit(1); @@ -665,7 +791,7 @@ if(!file_touch(system.ctrl_dir + "recycle")) /******************************************/ /* SEND NODE NUMBER REQUEST NETMAIL (FTN) */ /******************************************/ -if(your.node === 9999) { +if(your.node === temp_node) { if(confirm("Send a node number application to " + fidoaddr.to_str(hub))) { var result = send_app_netmail(fidoaddr.to_str(hub)); if(typeof result !== 'boolean') { @@ -682,13 +808,13 @@ if(your.node === 9999) { } if(aborted() || confirm("Come back when you have a permanently-assigned node address")) exit(0); - } + } } /************************/ /* SEND AREAFIX NETMAIL */ /************************/ -if(your.node !== 9999 +if(your.node !== temp_node && confirm("Send an AreaFix request to link EchoMail areas with " + fidoaddr.to_str(hub))) { var msgbase = new MsgBase("mail"); @@ -701,12 +827,12 @@ if(your.node !== 9999 lines[i] = lines[i].split(/\s+/)[0]; } if(!msgbase.save_msg({ - to: network.areamgr || "AreaFix", - to_net_addr: fidoaddr.to_str(hub), - from: sysop, - from_ext: 1, - subject: link.AreaFixPwd - }, /* body text: */ lines.join('\r\n'))) { + to: network.areamgr || "AreaFix", + to_net_addr: fidoaddr.to_str(hub), + from: sysop, + from_ext: 1, + subject: link.AreaFixPwd + }, /* body text: */ lines.join('\r\n'))) { alert("Error saving message: " + msgbase.last_error); exit(1); } @@ -753,7 +879,7 @@ add_gfile("binkstats.ini", "Detailed BinkP (mail/file transfer) statistics"); /***********************/ print(netname + " initial setup completely successfully."); print(); -if(your.node == 9999) { +if(your.node == temp_node) { print("You used a temporary node address (" + fidoaddr.to_str(your) + "). You will need to update your"); print("SCFG->Networks->FidoNet->Address once your permanent node address has been"); diff --git a/exec/init-tickit.ini b/exec/init-tickit.ini index 1e3c6313d6476612097eaaf4c8a97781d2d076e2..9540144c3099a8c2d5530ceccabd5db77199b3e2 100644 --- a/exec/init-tickit.ini +++ b/exec/init-tickit.ini @@ -151,6 +151,11 @@ domain=scsinet nlmatch=scinet.* forcereplace=true +[TQWNODE] +domain=tqwnet +nlmatch=tqwnet.* +forcereplace=true + [XOFCHUBSLST] forcereplace=true diff --git a/exec/init-tickit.js b/exec/init-tickit.js index 1b6be06ae58b40c266dbdd6a20c0e4540893c62a..7a17b6b9e7e05bd8025e45a5539d1243b072c4ed 100644 --- a/exec/init-tickit.js +++ b/exec/init-tickit.js @@ -3,13 +3,13 @@ Nigel Reed - nigel@nigelreed.net sysop@endofthelinebbs.com This short crappy bit of code will create a tickit.ini file for you. You won't have - edit it by hang any more and it's easy to add a new network or new file areas. + edit it by hand any more and it's easy to add a new network or new file areas. It will parse init-tickit.ini and automatically create /sbbs/ctrl/tickit.ini */ "use strict"; -var init_ini = js.exec_dir + "init-tickit.ini"; +var init_ini = js.exec_dir + "init-tickit.ini"; var tickit_ini = system.ctrl_dir + "tickit.ini"; var ini = []; diff --git a/exec/lbshell.js b/exec/lbshell.js index bc1411c87760c1cac56bf9d33e5b88029c8840da..ac6553264e0b173b30f65e289f88fd9e8b565980 100644 --- a/exec/lbshell.js +++ b/exec/lbshell.js @@ -715,15 +715,9 @@ while(bbs.online) { console.writeln("DOORSCAN ERROR: "+e); log("Error running "+xtrn_area.sec_list[curr_xtrnsec].prog_list[parseInt(x_prog)].code+" "+e); } - - if(xtrn_area.sec_list[curr_xtrnsec].prog_list[parseInt(x_prog)].settings & XTRN_PAUSE) { - console.pause(); - } } else { bbs.exec_xtrn(xtrn_area.sec_list[curr_xtrnsec].prog_list[parseInt(x_prog)].number); - if(xtrn_area.sec_list[curr_xtrnsec].prog_list[parseInt(x_prog)].settings & XTRN_PAUSE) - console.pause(); } start_mouse(); draw_main(true); diff --git a/exec/load/acmev2.js b/exec/load/acmev2.js index 00ed4272f41c61c46fe7b3a6e425575f12d81db5..2a7af2ab18233eedc9a5b7751c0b86f04ab859be 100644 --- a/exec/load/acmev2.js +++ b/exec/load/acmev2.js @@ -40,7 +40,7 @@ require("http.js", "HTTPRequest"); function ACMEv2(opts) { if (opts.key === undefined) - throw('Need "key"!'); + throw new Error('Need "key"!'); this.key = opts.key; this.key_id = opts.key_id; @@ -70,9 +70,9 @@ ACMEv2.prototype.get_terms_of_service = function() { var dir = this.get_directory(); if (dir.meta === undefined) - throw('No "meta" in directory!'); + throw new Error('No "meta" in directory!'); if (dir.meta.termsOfService === undefined) - throw('No "termsOfService" in directory metadata'); + throw new Error('No "termsOfService" in directory metadata'); return dir.meta.termsOfService; }; @@ -84,7 +84,7 @@ ACMEv2.prototype.get_directory = function() this.log_headers(); if (this.ua.response_code != 200) { log(LOG_DEBUG, ret); - throw("Error fetching directory"); + throw new Error("Error fetching directory"); } this.update_nonce(); this.directory = JSON.parse(ret); @@ -98,12 +98,12 @@ ACMEv2.prototype.create_new_account = function(opts) if (this.ua.response_code != 201 && this.ua.response_code != 200) { log(LOG_DEBUG, ret); - throw("newAccount returned "+this.ua.response_code+", not a 200 or 201 status!"); + throw new Error("newAccount returned "+this.ua.response_code+", not a 200 or 201 status!"); } if (this.ua.response_headers_parsed.Location === undefined) { log(LOG_DEBUG, this.ua.response_headers.join("\n")); - throw("No Location header in newAccount response."); + throw new Error("No Location header in newAccount response."); } this.key_id = this.ua.response_headers_parsed.Location[0]; return JSON.parse(ret); @@ -117,7 +117,7 @@ ACMEv2.prototype.update_account = function(opts) if (this.ua.response_code != 201 && this.ua.response_code != 200) { log(LOG_DEBUG, ret); - throw("update_account returned "+this.ua.response_code+", not a 200 or 201 status!"); + throw new Error("update_account returned "+this.ua.response_code+", not a 200 or 201 status!"); } return JSON.parse(ret); }; @@ -132,17 +132,17 @@ ACMEv2.prototype.create_new_order = function(opts) var ret; if (opts.identifiers === undefined) - throw("create_new_order() requires an identifier in opts"); + throw new Error("create_new_order() requires an identifier in opts"); ret = this.post('newOrder', opts); if (this.ua.response_code != 201) { log(LOG_DEBUG, ret); - throw("newOrder responded with "+this.ua.response_code+" not 201"); + throw new Error("newOrder responded with "+this.ua.response_code+" not 201"); } ret = JSON.parse(ret); if (this.ua.response_headers_parsed.Location === undefined) { log(LOG_DEBUG, this.ua.response_headers.join("\n")); - throw("No Location header in 201 response."); + throw new Error("No Location header in 201 response."); } ret.Location=this.ua.response_headers_parsed.Location[0]; @@ -156,7 +156,7 @@ ACMEv2.prototype.accept_challenge = function(challenge) var ret = this.post_url(challenge.url, opts); if (this.ua.response_code != 200) { log(LOG_DEBUG, ret); - throw("accept_challenge did not return 200"); + throw new Error("accept_challenge did not return 200"); } return JSON.parse(ret); }; @@ -187,18 +187,18 @@ ACMEv2.prototype.finalize_order = function(order, csr) var opts = {}; if (order === undefined) - throw("Missing order"); + throw new Error("Missing order"); if (csr === undefined) - throw("Missing csr"); + throw new Error("Missing csr"); if (typeof(csr) != 'object' || csr.export_cert === undefined) - throw("Invalid csr"); + throw new Error("Invalid csr"); opts.csr = this.base64url(csr.export_cert(CryptCert.FORMAT.CERTIFICATE)); log(LOG_DEBUG, "Finalizing order."); var ret = this.post_url(order.finalize, opts); if (this.ua.response_code != 200) { log(LOG_DEBUG, ret); - throw("finalize_order did not return 200"); + throw new Error("finalize_order did not return 200"); } return JSON.parse(ret); @@ -208,13 +208,13 @@ ACMEv2.prototype.poll_order = function(order) { var loc = order.Location; if (loc === undefined) - throw("No order location!"); + throw new Error("No order location!"); log(LOG_DEBUG, "Polling oder."); var ret = this.ua.Get(loc); this.log_headers(); if (this.ua.response_code != 200) { log(LOG_DEBUG, ret); - throw("order poll did not return 200"); + throw new Error("order poll did not return 200"); } this.update_nonce(); @@ -245,7 +245,7 @@ ACMEv2.prototype.get_jwk = function(key) var ret = {}; if (key === undefined) - throw("change_key() requires a new key."); + throw new Error("change_key() requires a new key."); /* Create the inner object signed with old key */ switch(key.algo) { case CryptContext.ALGO.RSA: @@ -271,13 +271,13 @@ ACMEv2.prototype.get_jwk = function(key) ret.shalen = 512; break; default: - throw("Unhandled ECC curve size "+key.keysize); + throw new Error("Unhandled ECC curve size "+key.keysize); } ret.jwk.x = key.public_key.x; ret.jwk.y = key.public_key.y; break; default: - throw("Unknown algorithm in new key"); + throw new Error("Unknown algorithm in new key"); } return ret; }; @@ -290,7 +290,7 @@ ACMEv2.prototype.change_key = function(new_key) var jwk; if (new_key === undefined) - throw("change_key() requires a new key."); + throw new Error("change_key() requires a new key."); /* Create the inner object signed with old key */ jwk = this.get_jwk(new_key); inner.protected.alg = jwk.alg; @@ -304,7 +304,7 @@ ACMEv2.prototype.change_key = function(new_key) ret = this.post('keyChange', inner); if (this.ua.response_code != 200) { log(LOG_DEBUG, ret); - throw("keyChange did not return 200"); + throw new Error("keyChange did not return 200"); } this.key = new_key; return JSON.parse(ret); @@ -357,7 +357,7 @@ ACMEv2.prototype.revoke = function(cert, reason) ret = this.post('revokeCert', opts); if (this.ua.response_code != 200) { log(LOG_DEBUG, ret); - throw("revokeCert did not return 200"); + throw new Error("revokeCert did not return 200"); } return; }; @@ -392,13 +392,13 @@ ACMEv2.prototype.create_pkcs7 = function(cert) ACMEv2.prototype.get_cert = function(order) { if (order.certificate === undefined) - throw("Order has no certificate!"); + throw new Error("Order has no certificate!"); log(LOG_DEBUG, "Getting certificate."); var cert = this.ua.Get(order.certificate); this.log_headers(); if (this.ua.response_code != 200) { log(LOG_DEBUG, cert); - throw("get_cert request did not return 200"); + throw new Error("get_cert request did not return 200"); } this.update_nonce(); @@ -417,7 +417,7 @@ ACMEv2.prototype.post = function(link, data) post_method = 'post_full_jwt'; url = this.get_directory()[link]; if (url === undefined) - throw('Unknown link name: "'+link+'"'); + throw new Error('Unknown link name: "'+link+'"'); log(LOG_DEBUG, "Calling "+link+"."); return this.post_url(url, data, post_method); }; @@ -444,7 +444,7 @@ ACMEv2.prototype.get_authorization = function(url) this.log_headers(); if (this.ua.response_code != 200) { log(LOG_DEBUG, ret); - throw("get_authorization request did not return 200"); + throw new Error("get_authorization request did not return 200"); } this.update_nonce(); @@ -588,7 +588,7 @@ ACMEv2.prototype.post_url = function(url, data, post_method) protected.alg = jwk.alg; protected.kid = this.key_id; if (protected.kid === undefined) - throw("No key_id available!"); + throw new Error("No key_id available!"); break; case 'post_full_jwt': protected.nonce = this.get_nonce(); diff --git a/exec/load/binkp.js b/exec/load/binkp.js index 979b78d8597dfd32901e9041d2cca21d6acaca93..068f486989d1f8b816992da6bd72e7d1a4aba8f3 100644 --- a/exec/load/binkp.js +++ b/exec/load/binkp.js @@ -412,7 +412,7 @@ BinkP.prototype.connect = function(addr, password, auth_cb, port, inet_host, tls this.in_keys = undefined; this.out_keys = undefined; if (addr === undefined) - throw("No address specified!"); + throw new Error("No address specified!"); addr = FIDO.parse_addr(addr, this.default_zone, this.default_domain); if (!password) @@ -1041,7 +1041,7 @@ BinkP.prototype.recvFrame = function(timeout) ret = new this.Frame(); i = this.sock.recv(1, timeout); if (i === null) { - log(LOG_INFO, "Error in recv() of first byte of packet header"); + log(LOG_INFO, "Error in recv() of first byte of packet header, timeout = " + timeout); this.sock.close(); this.sock = undefined; return undefined; diff --git a/exec/load/fido.js b/exec/load/fido.js index 813f97ffc6a9f93d50ef7c4e5840e8ca638e5d76..0702b7fd64f6b9b11603e4e19709060739bd1f26 100644 --- a/exec/load/fido.js +++ b/exec/load/fido.js @@ -74,9 +74,9 @@ var FIDO = { set: function(val) { net = parseInt(val, 10); if (typeof net !== 'number') - throw('net is not a number!'); + throw new Error('net is not a number!'); if (net < 0 || net > 65535) - throw('net out of range'); + throw new Error('net out of range'); } }, "node": { @@ -85,7 +85,7 @@ var FIDO = { set: function(val) { node = parseInt(val, 10); if (typeof node !== 'number') - throw('node is not a number!'); + throw new Error('node is not a number!'); if (node < 0 || node > 65535) throw ('node out of range'); } @@ -103,9 +103,9 @@ var FIDO = { else zone = parseInt(val, 10); if (typeof zone !== 'number') - throw('zone is not a number!'); + throw new Error('zone is not a number!'); if (zone < -1 || zone > 65535) - throw('zone out of range'); + throw new Error('zone out of range'); } }, "point": { @@ -121,7 +121,7 @@ var FIDO = { else point = parseInt(val, 10); if (typeof point !== 'number') - throw('point is not a number!'); + throw new Error('point is not a number!'); if (point < 0 || point > 65535) throw ('point out of range'); } @@ -139,7 +139,7 @@ var FIDO = { else domain = val.toString().toLowerCase().substr(0, 8); if (typeof domain !== 'string') - throw('domain is not a string'); + throw new Error('domain is not a string'); } } }); @@ -153,7 +153,7 @@ var FIDO = { if(addr) m = addr.toString().match(/^(?:([0-9]+):)?([0-9]+)\/([0-9]+)(?:\.([0-9]+))?(?:@(.*))?$/); if (!m) - throw('invalid address '+addr); + throw new Error('invalid address '+addr); zone = m[1]; domain = m[5]; if (zone == undefined) @@ -174,14 +174,14 @@ var FIDO = { var ext; if (default_zone === undefined) - throw("Default zone unspecified"); + throw new Error("Default zone unspecified"); m = path.match(/(?:\.([0-9a-f]{3,4})[\/\\])?([0-9a-f]{4})([0-9a-f]{4})\.(...)(?:[\/\\]([0-9a-f]{8})\.(...))?$/i); if (m === null) - throw("Invalid flo file path"); + throw new Error("Invalid flo file path"); ext = m[4]; if (m[5] != null) { if (m[4].toUpperCase() !== 'PNT') - throw("Invalid flo file path"); + throw new Error("Invalid flo file path"); ext = m[6]; } switch(ext.toLowerCase()) { @@ -200,7 +200,7 @@ var FIDO = { case 'try': break; default: - throw("Invalid flo file path"); + throw new Error("Invalid flo file path"); } zone = m[1]; if (zone == null) @@ -230,12 +230,12 @@ var FIDO = { domain = ''; if (!f.open("r")) - throw("Unable to open '"+f.name+"'."); + throw new Error("Unable to open '"+f.name+"'."); // Validate first line... var line = f.readln(2048); if (line == undefined) - throw("Unable to read first line in '"+f.name+"'"); + throw new Error("Unable to read first line in '"+f.name+"'"); var m; if ((m=line.match(/^;A (.*) Nodelist for (.*) -- Day number ([0-9]+) : ([0-9]{5})$/)) !== null) { ret.domain = m[1]; @@ -502,7 +502,7 @@ Object.defineProperties(FIDO.Addr.prototype, { // TODO: Use default zone from system.fido_addr_list[0]? if (this.zone === undefined) - throw('zone is undefined'); + throw new Error('zone is undefined'); // TODO: These don't need to be loaded into different objects since we're doing 5D if (FIDO.FTNDomains.nodeListFN[this.domain] !== undefined && file_exists(FIDO.FTNDomains.nodeListFN[this.domain])) { @@ -530,7 +530,7 @@ Object.defineProperties(FIDO.Addr.prototype, { get: function() { // TODO: Use default zone from system.fido_addr_list[0]? if (this.zone === undefined) - throw('zone is undefined'); + throw new Error('zone is undefined'); // TODO: These don't need to be loaded into different objects since we're doing 5D if (FIDO.FTNDomains.nodeListFN[this.domain] !== undefined && file_exists(FIDO.FTNDomains.nodeListFN[this.domain])) { @@ -643,7 +643,7 @@ FIDO.Packet.prototype.setBin = function(offset, len, val) { var str = ''; if (typeof(val) !== 'number') - throw('Invalid setBin value type'); + throw new Error('Invalid setBin value type'); for (i=0; i<len; i++) { str += ascii(val & 0xff); val >>= 8; diff --git a/exec/load/fido_syscfg.js b/exec/load/fido_syscfg.js index 3214b8109e0a0c11b52aae3dd7ebf7d1203c1949..1cdbd251cb8851c24fe066a37ba52a9ce8ec0518 100644 --- a/exec/load/fido_syscfg.js +++ b/exec/load/fido_syscfg.js @@ -40,7 +40,7 @@ function SBBSEchoCfg () ecfg = new File(file_cfgname(system.ctrl_dir, 'sbbsecho.ini')); if (!ecfg.open("r")) - throw("Unable to open '"+ecfg.name+"'"); + throw new Error("Unable to open '"+ecfg.name+"'"); this.inbound = backslash(ecfg.iniGetValue(null, "Inbound", "../fido/nonsecure")); if (this.inbound !== null) diff --git a/exec/load/fidocfg.js b/exec/load/fidocfg.js index 84d7c6508ac07b0acadbf7351d73f29923087791..706b1c2dc1fa95662ffefdbd3ba2e2d918a618a0 100644 --- a/exec/load/fidocfg.js +++ b/exec/load/fidocfg.js @@ -66,7 +66,7 @@ function TickITCfg() { } if (!tcfg.open("r")) - throw("Unable to open '"+tcfg.name+"'"); + throw new Error("Unable to open '"+tcfg.name+"'"); this.gcfg = tcfg.iniGetObject(); lcprops(this.gcfg); if (this.gcfg.handler !== undefined) { diff --git a/exec/load/frame.js b/exec/load/frame.js index 515407c650a65d303ed860662789de3afce132b1..b221323a250ec37824e6f6ee65b0f271c382dc87 100644 --- a/exec/load/frame.js +++ b/exec/load/frame.js @@ -189,14 +189,14 @@ Frame.prototype.__defineSetter__("child", function(frame) { if(frame instanceof Frame) this.__relations__.child.push(frame); else - throw("child not an instance of Frame()"); + throw new Error("child not an instance of Frame()"); }); Frame.prototype.__defineGetter__("attr", function() { return this.__properties__.attr; }); Frame.prototype.__defineSetter__("attr", function(attr) { if(attr !== undefined && isNaN(attr)) - throw("invalid attribute: " + attr); + throw new Error("invalid attribute: " + attr); this.__properties__.attr = attr; }); Frame.prototype.__defineGetter__("x", function() { @@ -208,7 +208,7 @@ Frame.prototype.__defineSetter__("x", function(x) { if(x == undefined) return; if(!this.__checkX__(x)) - throw("invalid x coordinate: " + x); + throw new Error("invalid x coordinate: " + x); this.__properties__.x = Number(x); }); Frame.prototype.__defineGetter__("y", function() { @@ -220,7 +220,7 @@ Frame.prototype.__defineSetter__("y", function(y) { if(y == undefined) return; if(!this.__checkY__(y)) - throw("invalid y coordinate: " + y); + throw new Error("invalid y coordinate: " + y); this.__properties__.y = Number(y); }); Frame.prototype.__defineGetter__("width", function() { @@ -232,7 +232,7 @@ Frame.prototype.__defineSetter__("width", function(width) { if(width == undefined) return; if(!this.__checkWidth__(this.x,Number(width))) - throw("invalid width: " + width); + throw new Error("invalid width: " + width); this.__properties__.width = Number(width); }); Frame.prototype.__defineGetter__("height", function() { @@ -244,7 +244,7 @@ Frame.prototype.__defineSetter__("height", function(height) { if(height == undefined) return; if(!this.__checkHeight__(this.y,Number(height))) - throw("invalid height: " + height); + throw new Error("invalid height: " + height); this.__properties__.height = Number(height); }); @@ -289,7 +289,7 @@ Frame.prototype.__defineSetter__("checkbounds", function(bool) { if(typeof bool == "boolean") this.__settings__.checkbounds=bool; else - throw("non-boolean checkbounds: " + bool); + throw new Error("non-boolean checkbounds: " + bool); }); Frame.prototype.__defineGetter__("transparent", function() { return this.__settings__.transparent; @@ -298,7 +298,7 @@ Frame.prototype.__defineSetter__("transparent", function(bool) { if(typeof bool == "boolean") this.__settings__.transparent=bool; else - throw("non-boolean transparent: " + bool); + throw new Error("non-boolean transparent: " + bool); }); Frame.prototype.__defineGetter__("lf_strict", function() { return this.__settings__.lf_strict; @@ -307,7 +307,7 @@ Frame.prototype.__defineSetter__("lf_strict", function(bool) { if(typeof bool == "boolean") this.__settings__.lf_strict=bool; else - throw("non-boolean lf_strict: " + bool); + throw new Error("non-boolean lf_strict: " + bool); }); Frame.prototype.__defineGetter__("scrollbars", function() { return this.__settings__.scrollbars; @@ -316,7 +316,7 @@ Frame.prototype.__defineSetter__("scrollbars", function(bool) { if(typeof bool == "boolean") this.__settings__.scrollbars=bool; else - throw("non-boolean scrollbars: " + bool); + throw new Error("non-boolean scrollbars: " + bool); }); Frame.prototype.__defineGetter__("v_scroll", function() { return this.__settings__.v_scroll; @@ -325,7 +325,7 @@ Frame.prototype.__defineSetter__("v_scroll", function(bool) { if(typeof bool == "boolean") this.__settings__.v_scroll=bool; else - throw("non-boolean v_scroll: " + bool); + throw new Error("non-boolean v_scroll: " + bool); }); Frame.prototype.__defineGetter__("word_wrap", function() { return this.__settings__.word_wrap; @@ -334,7 +334,7 @@ Frame.prototype.__defineSetter__("word_wrap", function(bool) { if(typeof bool == "boolean") this.__settings__.word_wrap=bool; else - throw("non-boolean word_wrap: " + bool); + throw new Error("non-boolean word_wrap: " + bool); }); Frame.prototype.__defineGetter__("h_scroll", function() { return this.__settings__.h_scroll; @@ -343,7 +343,7 @@ Frame.prototype.__defineSetter__("h_scroll", function(bool) { if(typeof bool == "boolean") this.__settings__.h_scroll=bool; else - throw("non-boolean h_scroll: " + bool); + throw new Error("non-boolean h_scroll: " + bool); }); Frame.prototype.__defineGetter__("is_open",function() { return this.__properties__.open; @@ -355,7 +355,7 @@ Frame.prototype.__defineSetter__("atcodes", function(bool) { if(typeof bool == "boolean") this.__settings__.atcodes=bool; else - throw("non-boolean atcode: " + bool); + throw new Error("non-boolean atcode: " + bool); }); /* public methods */ @@ -367,7 +367,7 @@ Frame.prototype.getData = function(x,y,use_offset) { py += this.__position__.offset.y; } // if(!this.__properties__.data[py] || !this.__properties__.data[py][px]) - // throw("Frame.getData() - invalid coordinates: " + px + "," + py); + // throw new Error("Frame.getData() - invalid coordinates: " + px + "," + py); if(!this.__properties__.data[py] || !this.__properties__.data[py][px]) return new Char(); return this.__properties__.data[py][px]; @@ -381,7 +381,7 @@ Frame.prototype.setData = function(x,y,ch,attr,use_offset) { } //I don't remember why I did this, but it was probably important at the time //if(!this.__properties__.data[py] || !this.__properties__.data[py][px]) - // throw("Frame.setData() - invalid coordinates: " + px + "," + py); + // throw new Error("Frame.setData() - invalid coordinates: " + px + "," + py); if(!this.__properties__.data[py]) this.__properties__.data[py] = []; if(!this.__properties__.data[py][px]) @@ -820,13 +820,13 @@ Frame.prototype.load = function(filename,width,height) { this.putmsg(lines.shift() + "\r\n"); break; default: - throw("unsupported filetype"); + throw new Error("unsupported filetype"); break; } } Frame.prototype.load_bin = function(contents, width, height, offset) { if(width == undefined || height == undefined) - throw("unknown graphic dimensions"); + throw new Error("unknown graphic dimensions"); if(offset == undefined) offset = 0; for(var y=0; y<height; y++) { for(var x=0; x<width; x++) { @@ -1516,7 +1516,7 @@ Display.prototype.__defineSetter__("x", function(x) { if(x == undefined) this.__properties__.x = 1; else if(isNaN(x)) - throw("invalid x coordinate: " + x); + throw new Error("invalid x coordinate: " + x); else this.__properties__.x = Number(x); }); @@ -1527,7 +1527,7 @@ Display.prototype.__defineSetter__("y", function(y) { if(y == undefined) this.__properties__.y = 1; else if(isNaN(y) || y < 1 || y > console.screen_rows) - throw("invalid y coordinate: " + y); + throw new Error("invalid y coordinate: " + y); else this.__properties__.y = Number(y); }); @@ -1538,7 +1538,7 @@ Display.prototype.__defineSetter__("width", function(width) { if(width == undefined) this.__properties__.width = console.screen_columns; else if(isNaN(width) || (this.x + Number(width) - 1) > (console.screen_columns)) - throw("invalid width: " + width); + throw new Error("invalid width: " + width); else this.__properties__.width = Number(width); }); @@ -1549,7 +1549,7 @@ Display.prototype.__defineSetter__("height", function(height) { if(height == undefined) this.__properties__.height = console.screen_rows; else if(isNaN(height) || (this.y + Number(height) - 1) > (console.screen_rows)) - throw("invalid height: " + height); + throw new Error("invalid height: " + height); else this.__properties__.height = Number(height); }); @@ -1763,7 +1763,7 @@ function Cursor(x,y,frame) { if(frame instanceof Frame) this.__properties__.frame = frame; else - throw("the frame is not a frame"); + throw new Error("the frame is not a frame"); this.x = x; this.y = y; @@ -1774,7 +1774,7 @@ Cursor.prototype.__defineGetter__("x", function() { }); Cursor.prototype.__defineSetter__("x", function(x) { if(isNaN(x)) - throw("invalid x coordinate: " + x); + throw new Error("invalid x coordinate: " + x); this.__properties__.x = x; }); Cursor.prototype.__defineGetter__("y", function() { @@ -1782,7 +1782,7 @@ Cursor.prototype.__defineGetter__("y", function() { }); Cursor.prototype.__defineSetter__("y", function(y) { if(isNaN(y)) - throw("invalid y coordinate: " + y); + throw new Error("invalid y coordinate: " + y); this.__properties__.y = y; }); @@ -1799,7 +1799,7 @@ function Offset(x,y,frame) { if(frame instanceof Frame) this.__properties__.frame = frame; else - throw("the frame is not a frame"); + throw new Error("the frame is not a frame"); this.x = x; this.y = y; @@ -1810,7 +1810,7 @@ Offset.prototype.__defineGetter__("x", function() { }); Offset.prototype.__defineSetter__("x", function(x) { if(x == undefined) - throw("invalid x offset: " + x); + throw new Error("invalid x offset: " + x); else if(x < 0) x = 0; this.__properties__.x = x; @@ -1820,7 +1820,7 @@ Offset.prototype.__defineGetter__("y", function() { }); Offset.prototype.__defineSetter__("y", function(y) { if(y == undefined) - throw("invalid y offset: " + y); + throw new Error("invalid y offset: " + y); else if(y < 0) y = 0; this.__properties__.y = y; diff --git a/exec/load/ftn_nodelist.js b/exec/load/ftn_nodelist.js index 05d7578e6166f75915000c618d8c74891f114cc5..c1fa6016e263bffba970f070281946a7efaad2ee 100644 --- a/exec/load/ftn_nodelist.js +++ b/exec/load/ftn_nodelist.js @@ -63,12 +63,12 @@ function NodeList(filename, warn) }); if (!f.open("r")) - throw("Unable to open '"+f.name+"'."); + throw new Error("Unable to open '"+f.name+"'."); // Validate first line... var line = f.readln(2048); if (line == undefined) - throw("Unable to read first line in '"+f.name+"'"); + throw new Error("Unable to read first line in '"+f.name+"'"); var m; if ((m=line.match(/^;A (.*) Nodelist for (.*) -- Day number ([0-9]+) : ([0-9]{5})$/)) !== null) { this.domain = m[1]; diff --git a/exec/load/ftp.js b/exec/load/ftp.js index f3fcbdcec91e35ae9acfead849194308dc11d43f..d8d70a165aaca304ee00ecc45047728ac1f15a7d 100644 --- a/exec/load/ftp.js +++ b/exec/load/ftp.js @@ -7,7 +7,7 @@ function FTP(host, user, pass, port, dport, bindhost, account) var ret; if (host === undefined) - throw("No hostname specified"); + throw new Error("No hostname specified"); this.revision = "JSFTP v" + "$Revision: 1.23 $".split(' ')[1]; @@ -40,19 +40,19 @@ function FTP(host, user, pass, port, dport, bindhost, account) } if (parseInt(response, 10) !== 220) { this.socket.close(); - throw("Invalid response from server: " + response); + throw new Error("Invalid response from server: " + response); } ret = parseInt(response = this.cmd("USER "+this.user, true), 10) if (ret === 331) ret = parseInt(response = this.cmd("PASS "+this.pass, true), 10); if (ret === 332) { if (this.account === undefined) - throw("Account required"); + throw new Error("Account required"); ret = parseInt(response = this.cmd("ACCT "+this.account, true), 10); } if (ret !== 230 && ret != 202) { this.socket.close(); - throw("Login failed: " + response); + throw new Error("Login failed: " + response); } this.ascii = false; this.passive = true; @@ -298,7 +298,7 @@ FTP.prototype.do_sendfile = function(src, data_socket) var f = new File(src); if (!f.open("rb")) { data_socket.close(); - throw("Error " + f.error + " opening file '" + f.name + "'"); + throw new Error("Error " + f.error + " opening file '" + f.name + "'"); } do { @@ -315,7 +315,7 @@ FTP.prototype.do_sendfile = function(src, data_socket) rstr = this.cmd(undefined, true); if (parseInt(rstr, 10) !== 226) { - throw("Data connection not closed: "+rstr); + throw new Error("Data connection not closed: "+rstr); } if (!error) log(LOG_DEBUG, "Sent "+total+" bytes."); @@ -333,7 +333,7 @@ FTP.prototype.cmd = function(cmd, needresp) var done = false; if (!this.socket.is_connected) - throw("Socket disconnected"); + throw new Error("Socket disconnected"); if (cmd !== undefined) { while (this.socket.data_waiting) { @@ -343,7 +343,7 @@ FTP.prototype.cmd = function(cmd, needresp) cmdline = cmd.replace(/\xff/g, "\xff\xff") + '\r\n'; log(LOG_DEBUG, "CMD: '"+cmd+"'"); if (this.socket.send(cmdline) != cmdline.length) - throw("Error " + this.socket.error + " sending command: '" + cmd + "'"); + throw new Error("Error " + this.socket.error + " sending command: '" + cmd + "'"); } if (needresp === true) { @@ -355,7 +355,7 @@ FTP.prototype.cmd = function(cmd, needresp) m = rd.match(/^([0-9]{3})([- ])/); if (rsp === undefined) { if (m === null) { - throw("Invalid response: "+rd); + throw new Error("Invalid response: "+rd); } rsp = m[1]; if (m[2] === ' ') @@ -373,9 +373,9 @@ FTP.prototype.cmd = function(cmd, needresp) } else { if(cmd) - throw("recvline timeout waiting for response to command: '" + cmd + "'"); + throw new Error("recvline timeout waiting for response to command: '" + cmd + "'"); else - throw("recvline timeout waiting for additional response"); + throw new Error("recvline timeout waiting for additional response"); } } while(this.socket.is_connected && !done); return ret; @@ -399,7 +399,7 @@ FTP.prototype.data_socket = function(cmd) else rstr = this.cmd("TYPE I", true); if (parseInt(rstr, 10) !== 200) - throw("Unable to create data socket: " + rstr); + throw new Error("Unable to create data socket: " + rstr); ip6 = this.socket.local_ip_address.indexOf(':') !== -1; if (this.passive) { @@ -407,20 +407,20 @@ FTP.prototype.data_socket = function(cmd) if (ip6) { rstr = this.cmd("EPSV", true); if (parseInt(rstr, 10) !== 229) - throw("EPSV Failed: " + rstr); + throw new Error("EPSV Failed: " + rstr); m = rstr.match(/\(\|\|\|([0-9]+)\|\)/); if (m === null) - throw("Unable to parse EPSV reply: " + rstr); + throw new Error("Unable to parse EPSV reply: " + rstr); rhost = this.host; rport = parseInt(m[1], 10); } else { rstr = this.cmd("PASV", true); if (parseInt(rstr, 10) !== 227) - throw("PASV Failed: " + rstr); + throw new Error("PASV Failed: " + rstr); m = rstr.match(/\(([0-9]+),([0-9]+),([0-9]+),([0-9]+),([0-9]+),([0-9]+)\)/); if (m === null) - throw("Unable to parse PASV reply: " + rstr); + throw new Error("Unable to parse PASV reply: " + rstr); rhost = m[1] + '.' + m[2] + '.' + m[3] + '.' + m[4]; rport = (parseInt(m[5], 10) << 8) | parseInt(m[6], 10); } @@ -443,11 +443,11 @@ FTP.prototype.data_socket = function(cmd) } } catch(e) { ds.close(); - throw(e); + throw new Error(e); } if (parseInt(rstr, 10) !== 200) { ds.close(); - throw("EPRT/PORT rejected: " + rstr); + throw new Error("EPRT/PORT rejected: " + rstr); } } @@ -461,14 +461,14 @@ FTP.prototype.data_socket = function(cmd) // Fall-through default: ds.close(); - throw(cmd+" failed: " + rstr); + throw new Error(cmd+" failed: " + rstr); } if (!this.passive) { selret = socket_select([ds], this.timeout); if (selret === null || selret.length === 0) { ds.close(); - throw("Timeout waiting for remote to connect"); + throw new Error("Timeout waiting for remote to connect"); } ts = ds.accept(); ds.close(); @@ -496,7 +496,7 @@ FTP.prototype.do_get = function(cmd, dest) f = new File(dest); if (!f.open("wb")) { data_socket.close(); - throw("Error " + f.error + " opening file '" + f.name + "'"); + throw new Error("Error " + f.error + " opening file '" + f.name + "'"); } } @@ -510,14 +510,14 @@ FTP.prototype.do_get = function(cmd, dest) f.write(rbuf); } else { - throw("recv timeout"); + throw new Error("recv timeout"); } } while(data_socket.is_connected && this.socket.is_connected); data_socket.close(); if (f !== undefined) f.close(); if (parseInt(this.cmd(undefined, true), 10) !== 226) - throw("Data connection not closed"); + throw new Error("Data connection not closed"); log(LOG_DEBUG, "Received "+total+" bytes."); if (dest === undefined) return ret; diff --git a/exec/load/graphic.js b/exec/load/graphic.js index f5b8acbbf059a1125992a88b7df4a55f59423ef5..4e895b122a67c686298cb8928fb0910249ea4ae1 100644 --- a/exec/load/graphic.js +++ b/exec/load/graphic.js @@ -690,7 +690,7 @@ Graphic.prototype.load = function(filename, offset) var l; if(!file_type) - throw("unsupported file type: " + filename); + throw new Error("unsupported file type: " + filename); switch(file_type.substr(1).toUpperCase()) { case "ANS": @@ -716,7 +716,7 @@ Graphic.prototype.load = function(filename, offset) this.putmsg(undefined,undefined,l,true); break; default: - throw("unsupported file type: " + filename); + throw new Error("unsupported file type: " + filename); } return(true); }; diff --git a/exec/load/http.js b/exec/load/http.js index 0af0a1970649dd6ff41b16157bd73e85cff812c9..40d5049bd86273712e4fc4a0dd3c910dcf31190c 100644 --- a/exec/load/http.js +++ b/exec/load/http.js @@ -114,39 +114,39 @@ HTTPRequest.prototype.SendRequest=function() { port = this.url.port?this.url.port:(this.url.scheme=='http'?80:443); if (js.global.ConnectedSocket != undefined) { if ((this.sock = new ConnectedSocket(this.url.host, port)) == null) - throw(format("Unable to connect to %s:%u", this.url.host, this.url.port)); + throw new Error(format("Unable to connect to %s:%u", this.url.host, this.url.port)); } else { if((this.sock=new Socket(SOCK_STREAM))==null) - throw("Unable to create socket"); + throw new Error("Unable to create socket"); if(!this.sock.connect(this.url.host, port)) { this.sock.close(); - throw(format("Unable to connect to %s:%u", this.url.host, this.url.port)); + throw new Error(format("Unable to connect to %s:%u", this.url.host, this.url.port)); } } if(this.url.scheme=='https') this.sock.ssl_session=true; if(!do_send(this.sock, this.request+"\r\n")) - throw("Unable to send request: " + this.request); + throw new Error("Unable to send request: " + this.request); for(i in this.request_headers) { if(!do_send(this.sock, this.request_headers[i]+"\r\n")) - throw("Unable to send headers"); + throw new Error("Unable to send headers"); } if(!do_send(this.sock, "\r\n")) - throw("Unable to terminate headers"); + throw new Error("Unable to terminate headers"); if(this.body != undefined) { if(!do_send(this.sock, this.body)) - throw("Unable to send body"); + throw new Error("Unable to send body"); } }; HTTPRequest.prototype.ReadStatus=function() { this.status_line=this.sock.recvline(4096); if(this.status_line==null) - throw("Unable to read status"); + throw new Error("Unable to read status"); var m = this.status_line.match(/^HTTP\/[0-9]+\.[0-9]+ ([0-9]{3})/); if (m === null) - throw("Unable to parse status line '"+this.status_line+"'"); + throw new Error("Unable to parse status line '"+this.status_line+"'"); this.response_code = parseInt(m[1], 10); }; @@ -159,7 +159,7 @@ HTTPRequest.prototype.ReadHeaders=function() { for(;;) { header=this.sock.recvline(4096, 120); if(header==null) - throw("Unable to receive headers"); + throw new Error("Unable to receive headers"); if(header=='') return; this.response_headers.push(header); diff --git a/exec/load/json-chat.js b/exec/load/json-chat.js index 1fcf59391988804e4dcf3064e1a77b41bc92014d..a71373ad7468ef559987a6010d2b2716861c7e20 100644 --- a/exec/load/json-chat.js +++ b/exec/load/json-chat.js @@ -38,7 +38,7 @@ function JSONChat(usernum,jsonclient,host,port) { if(!this.client) { if(!host || isNaN(port)) - throw("invalid client arguments"); + throw new Error("invalid client arguments"); this.client = new JSONClient(host,port); } if(!this.client.connect()) { @@ -48,7 +48,7 @@ function JSONChat(usernum,jsonclient,host,port) { if(this.nick) this.client.subscribe("chat","channels." + this.nick.name + ".messages"); else - throw("invalid user number"); + throw new Error("invalid user number"); for(var c in this.channels) this.join(c.name); return true; diff --git a/exec/load/mouse_getkey.js b/exec/load/mouse_getkey.js index 890cb093d28aba456884d88536ac27590e9f5144..6a368f8274291210c225ed67ae1206ee1cee9deb 100644 --- a/exec/load/mouse_getkey.js +++ b/exec/load/mouse_getkey.js @@ -18,7 +18,7 @@ function mouse_getkey(mode, timeout, enabled) var safe_mode = mode & ~(K_UPPER|K_UPRLWR|K_NUMBER|K_ALPHA|K_NOEXASC); if (safe_mode != mode) { - throw("Invalid mode "+mode+" for mouse_getkey()"); + throw new Error("Invalid mode "+mode+" for mouse_getkey()"); } function mouse_enable(enable) diff --git a/exec/load/recordfile.js b/exec/load/recordfile.js index b788647c199b02de9b5c2e79f7d12fd1d0753317..52195269144ddd4ac6c07b619989837dc9055591 100644 --- a/exec/load/recordfile.js +++ b/exec/load/recordfile.js @@ -116,7 +116,7 @@ RecordFileRecord.prototype.flushRead = function(keeplocked) } this.parent.file.close(); if (!this.parent.file.open('rb+', true, this.parent.RecordLength)) { - throw('Unable to re-open '+this.parent.file.name); + throw new Error('Unable to re-open '+this.parent.file.name); } if (locked) { this.lock(); diff --git a/exec/load/require.js b/exec/load/require.js index 53b486b99910871a96d04019a6d0e41ea0f983ea..bcfbc2e25fd1ee1a5183b209b2f2dc1438e5d891 100644 --- a/exec/load/require.js +++ b/exec/load/require.js @@ -3,7 +3,7 @@ if (eval('typeof('+argv[2]+') !== "undefined" ? true : false')) js.global.require_module_file = 'dummy.js'; load(js.global.require_module_file); if (eval('typeof('+argv[2]+') == "undefined"')) - throw("ERROR: load()ing "+argv[1]+" didn't define symbol \""+argv[2]+"\""); + throw new Error("ERROR: load()ing "+argv[1]+" didn't define symbol \""+argv[2]+"\""); if (argv[0] === 'undefined') { Object.defineProperties(this, { "argv": { diff --git a/exec/load/rss-atom.js b/exec/load/rss-atom.js index 78dd53e563e2a26437714bc7f5d75934d2736c50..8400bbad13e66648760e71d967ec1cc605a9b497 100644 --- a/exec/load/rss-atom.js +++ b/exec/load/rss-atom.js @@ -119,11 +119,15 @@ const Item = function (i) { this.title = i.title.length() ? i.title[0].toString() : ''; // uh ... this.date = i.pubDate.length() ? i.pubDate[0].toString() : (i.updated.length() ? i.updated[0].toString() : ''); this.author = i.author.length() ? i.author.toString() : ''; - this.body = i.description.length() ? i.description[0].toString() : (i.summary.length() ? i.summary[0].toString() : ''); + this.body = ''; this.content = i.encoded.length() ? i.encoded.toString() : ''; this.link = i.link.length() ? skipsp(truncsp(i.link[0].toString())) : ''; this.enclosures = []; + if (i.description.length()) this.body += i.description[0].toString(); + if (i.summary.length()) this.body += i.summary[0].toString(); + if (i.content.length()) this.body += i.content[0].toString(); + var enclosures = i.enclosure.length(); for (var n = 0; n < enclosures; n++) { this.enclosures.push({ @@ -155,6 +159,14 @@ const Channel = function (c) { } +function toLocal(x) { + for each(var e in x) { + e.setName(e.localName()); + toLocal(e); + } + return x; +} + const Feed = function (url, follow_redirects) { this.channels = []; @@ -176,8 +188,8 @@ const Feed = function (url, follow_redirects) { } httpRequest = undefined; } - var feed = new XML(doc.replace(/^<\?xml.*\?>/g, "")); - doc = undefined; + var feed = toLocal(new XML(doc.replace(/^<\?xml.*\?>/g, ""))); + doc = undefined; switch (feed.localName()) { case "rss": var channels = feed.channel.length(); diff --git a/exec/load/sbbsdefs.js b/exec/load/sbbsdefs.js index 82d078dd197df3705a295a5ecfabc16e867edcd1..c8f071d887c8185c144ebc13e93117b18822970d 100644 --- a/exec/load/sbbsdefs.js +++ b/exec/load/sbbsdefs.js @@ -198,6 +198,7 @@ var K_USEOFFSET =(1<<20); /* Use console.getstr_offset with getstr() */ var K_NOSPIN =(1<<21); /* Do not honor user's spinning cursor */ var K_ANSI_CPR =(1<<22); /* ANSI Cursor Position Report expected */ var K_TRIM =(1<<23); /* Trim white-space from both ends of str */ +var K_CTRLKEYS =(1<<24); /* No control-key handling/eating in inkey()*/ /********************************************/ /********************************************/ @@ -205,7 +206,7 @@ var K_TRIM =(1<<23); /* Trim white-space from both ends of str */ /********************************************/ var P_NONE =0; /* No special behavior */ var P_NOABORT =(1<<0); /* Disallows abortion of a message */ -var P_SAVEATR =(1<<1); /* Save the new current attributres after */ +var P_SAVEATR =(1<<1); /* Save the new current attributes after */ /* msg has printed */ var P_NOATCODES =(1<<2); /* Don't allow @ codes */ var P_OPENCLOSE =(1<<3); /* Open and close the file */ @@ -221,6 +222,8 @@ var P_WRAP =(1<<12); /* Wrap/split long-lines, ungracefully */ var P_UTF8 =(1<<13); /* Message is UTF-8 encoded */ var P_AUTO_UTF8 =(1<<14); /* Message may be UTF-8, auto-detect */ var P_NOXATTRS =(1<<15); /* No "Extra Attribute Codes" supported */ +var P_MARKUP =(1<<16); /* Support StyleCodes/Rich/StructuredText */ +var P_HIDEMARKS =(1<<17); /* Hide the mark-up tags */ /********************************************/ /********************************************/ diff --git a/exec/load/sprite.js b/exec/load/sprite.js index dc9a1f8d7c56508797da5232ed21b6614b3b8195..da160c1e87432ee8414a8792c65cd1140729a706 100644 --- a/exec/load/sprite.js +++ b/exec/load/sprite.js @@ -436,10 +436,10 @@ Sprite.Aerial = function(fileName, parentFrame, x, y, bearing, position) { if(!file_exists(fileName + ".ini")) fileName = js.exec_dir + "sprites/" + fileName; if(!file_exists(fileName + ".ini")) { - throw("Sprite file missing: " + fileName + ".ini"); + throw new Error("Sprite file missing: " + fileName + ".ini"); } if(!file_exists(fileName + ".bin")) { - throw("Sprite file missing: " + fileName + ".bin"); + throw new Error("Sprite file missing: " + fileName + ".bin"); } this.x = x; @@ -958,10 +958,10 @@ Sprite.Profile = function(fileName, parentFrame, x, y, bearing, position) { if(!file_exists(fileName + ".ini")) fileName = js.exec_dir + "sprites/" + fileName; if(!file_exists(fileName + ".ini")) { - throw("Sprite file missing: " + fileName + ".ini"); + throw new Error("Sprite file missing: " + fileName + ".ini"); } if(!file_exists(fileName + ".bin")) { - throw("Sprite file missing: " + fileName + ".bin"); + throw new Error("Sprite file missing: " + fileName + ".bin"); } this.x = x; diff --git a/exec/load/text.js b/exec/load/text.js index 0294ac23814cb84158dca9b7209e1f0c642d1407..247263d9ac2e5b1bf034aa7adb018b8b820bffed 100644 --- a/exec/load/text.js +++ b/exec/load/text.js @@ -849,7 +849,8 @@ var SpinningCursor6=839; var SpinningCursor7=840; var SpinningCursor8=841; var SpinningCursor9=842; +var HowManyColumns=843; -var TOTAL_TEXT=843; +var TOTAL_TEXT=844; this; diff --git a/exec/load/tree.js b/exec/load/tree.js index e3ffbcaecb76c6b76f2f2494d58c999b03cf945a..44ca5cf8882c8735bb8a7ea6aa301dfc9823eb66 100644 --- a/exec/load/tree.js +++ b/exec/load/tree.js @@ -204,7 +204,7 @@ Tree.prototype.__defineSetter__("frame",function(frame) { return true; } else { - throw("frame parameter must be a Frame() object"); + throw new Error("frame parameter must be a Frame() object"); } }); Tree.prototype.__defineGetter__("items",function() { @@ -216,7 +216,7 @@ Tree.prototype.__defineSetter__("items",function(items) { return true; } else { - throw("items parameter must be an array"); + throw new Error("items parameter must be an array"); } }); Tree.prototype.__defineGetter__("parent",function() { diff --git a/exec/xtrn_sec.js b/exec/xtrn_sec.js index 55d7f156b824d1f490cb08c58bf7b6d299628f84..f312d5e904e21e13c78e8f041bb96e021feff914 100644 --- a/exec/xtrn_sec.js +++ b/exec/xtrn_sec.js @@ -94,11 +94,6 @@ function exec_xtrn(prog) load('fonts.js', 'default'); if(options.eval_after_exec) eval(options.eval_after_exec); - - if(prog.settings&XTRN_PAUSE) - console.pause(); - else - console.line_counter=0; } function external_program_menu(xsec) @@ -130,13 +125,20 @@ function external_program_menu(xsec) if(options.clear_screen) console.clear(LIGHTGRAY); - var secnum = xtrn_area.sec_list[xsec].number+1 + var secnum = xtrn_area.sec_list[xsec].number+1; + var seccode = xtrn_area.sec_list[xsec].code; if(bbs.menu_exists("xtrn" + secnum + "_head")) { bbs.menu("xtrn" + secnum + "_head"); } + else if(bbs.menu_exists("xtrn" + seccode + "_head")) { + bbs.menu("xtrn" + seccode + "_head"); + } if(bbs.menu_exists("xtrn" + secnum)) { bbs.menu("xtrn" + secnum); } + else if(bbs.menu_exists("xtrn" + seccode)) { + bbs.menu("xtrn" + seccode); + } else { var multicolumn = options.multicolumn && prog_list.length > options.singlecolumn_height; if(options.sort) diff --git a/install/GNUmakefile b/install/GNUmakefile index c944b26b8d765d8d05cea06cdeba2db008dac03d..3b7980c035075744ae872ab7e14eb1422ab9e6c8 100644 --- a/install/GNUmakefile +++ b/install/GNUmakefile @@ -160,13 +160,13 @@ baja: run sbbs3 $(MAKE) -C $(SBBSDIR)/exec $(MKFLAGS) BAJAPATH=$(REPODIR)/src/sbbs3/$(CCPRE).$(machine).exe.$(BUILDPATH)/baja sbj: run - $(MAKE) -C $(REPODIR)/xtrn/sbj $(MKFLAGS) + $(MAKE) -C $(SBBSDIR)/xtrn/sbj $(MKFLAGS) dpoker: run - $(MAKE) -C $(REPODIR)/xtrn/dpoker $(MKFLAGS) SBBS_SRC=$(REPODIR)/src/sbbs3/ XPDEV=$(REPODIR)/src/xpdev/ + $(MAKE) -C $(SBBSDIR)/xtrn/dpoker $(MKFLAGS) SBBS_SRC=$(REPODIR)/src/sbbs3/ XPDEV=$(REPODIR)/src/xpdev/ tbd: run - $(MAKE) -C $(REPODIR)/xtrn/tbd $(MKFLAGS) SBBS_SRC=$(REPODIR)/src/sbbs3/ XPDEV=$(REPODIR)/src/xpdev/ + $(MAKE) -C $(SBBSDIR)/xtrn/tbd $(MKFLAGS) SBBS_SRC=$(REPODIR)/src/sbbs3/ XPDEV=$(REPODIR)/src/xpdev/ gtkuseredit: src ifdef USE_GLADE diff --git a/src/build/Common.gmake b/src/build/Common.gmake index fd6af34f9774aa0b22c5ceb1f99468826ba3b93e..71b5f0d0d82755900cde42d3fe7a61028dff8179 100644 --- a/src/build/Common.gmake +++ b/src/build/Common.gmake @@ -328,7 +328,7 @@ endif # PThread-specific flags ifeq ($(os),linux) # Linux - CFLAGS += -DPOSIX_C_SOURCE=200809L -D_DEFAULT_SOURCE -D_BSD_SOURCE -DSPEED_MACROS_ONLY -D_GNU_SOURCE + CFLAGS += -DPOSIX_C_SOURCE=200809L -D_DEFAULT_SOURCE -D_BSD_SOURCE -DSPEED_MACROS_ONLY -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 ifndef THREADS_ACTUALLY_WORK CFLAGS += -D_THREAD_SUID_BROKEN endif diff --git a/src/conio/ansi_cio.c b/src/conio/ansi_cio.c index 5f87ec5b9ba419daa587ec94a7c7f646f6680dc0..7d12107ce3b8aecfd3c0e2b97f972e026876738f 100644 --- a/src/conio/ansi_cio.c +++ b/src/conio/ansi_cio.c @@ -44,6 +44,16 @@ struct termios tio_default; /* Initial term settings */ #endif +#ifdef _WIN32 + #ifndef ENABLE_VIRTUAL_TERMINAL_INPUT + #define ENABLE_VIRTUAL_TERMINAL_INPUT 0x0200 + #endif + #ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING + #define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004 + #endif +#endif + + #include "ciolib.h" #include "ansi_cio.h" @@ -931,10 +941,12 @@ int ansi_initio_cb(void) { #ifdef _WIN32 if(isatty(fileno(stdin))) { - if(!SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), 0)) + if(!SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), ENABLE_VIRTUAL_TERMINAL_INPUT)) return(0); - if(!SetConsoleMode(GetStdHandle(STD_OUTPUT_HANDLE), 0)) + DWORD conmode = 0; + GetConsoleMode(GetStdHandle(STD_OUTPUT_HANDLE), &conmode); + if(!SetConsoleMode(GetStdHandle(STD_OUTPUT_HANDLE), conmode | ENABLE_VIRTUAL_TERMINAL_PROCESSING)) return(0); } setmode(fileno(stdout),_O_BINARY); diff --git a/src/sbbs3/addfiles.c b/src/sbbs3/addfiles.c index 5dabc3ba37fd3d33ad653c5e483a955d496e421c..d087ae9f6b3c068cd1d6e53f07b60475d0ac6659 100644 --- a/src/sbbs3/addfiles.c +++ b/src/sbbs3/addfiles.c @@ -91,7 +91,7 @@ void prep_desc(char *str) tmp[j++]=str[i]; else if(j && str[i]<=' ' && str[i] > 0&& tmp[j-1]==' ') continue; - else if(i && !isalnum((uchar)str[i]) && str[i]==str[i-1]) + else if(i && !IS_ALPHANUMERIC(str[i]) && str[i]==str[i-1]) continue; else if(str[i]>=' ' || str[i]<0) tmp[j++]=str[i]; @@ -248,7 +248,7 @@ bool get_file_diz(file_t* f, const char* filepath, char* ext) sprintf(tmpext,"%.256s",ext); prep_desc(tmpext); for(i=0;tmpext[i];i++) - if(isalpha((uchar)tmpext[i])) + if(IS_ALPHA(tmpext[i])) break; sprintf(f->desc,"%.*s",LEN_FDESC,tmpext+i); for(i=0;(f->desc[i]>=' ' || f->desc[i]<0) && i<LEN_FDESC;i++) @@ -411,7 +411,7 @@ void addlist(char *inpath, file_t f, uint dskip, uint sskip) else /* no space after filename? */ continue; #endif - if(!isalnum(*fname)) { // filename doesn't begin with an alpha-numeric char? + if(!IS_ALPHANUMERIC(*fname)) { // filename doesn't begin with an alpha-numeric char? continue; } SAFEPRINTF2(filepath,"%s%s",cur_altpath ? scfg.altpath[cur_altpath-1] @@ -756,7 +756,7 @@ int main(int argc, char **argv) mode|=AUTO_ADD; i=0; } else { - if(!isalnum((uchar)argv[1][0]) && argc==2) { + if(!IS_ALPHANUMERIC(argv[1][0]) && argc==2) { puts(usage); return(1); } @@ -862,7 +862,7 @@ int main(int argc, char **argv) return(1); } } - else if(isdigit((uchar)argv[j][0])) { + else if(IS_DIGIT(argv[j][0])) { if(desc_offset==0) desc_offset=atoi(argv[j]); else @@ -872,9 +872,9 @@ int main(int argc, char **argv) else if(argv[j][0]=='+') { /* filelist - FILES.BBS */ listgiven=1; if(argc > j+1 - && isdigit((uchar)argv[j+1][0])) { /* skip x characters before description */ + && IS_DIGIT(argv[j+1][0])) { /* skip x characters before description */ if(argc > j+2 - && isdigit((uchar)argv[j+2][0])) { /* skip x characters before size */ + && IS_DIGIT(argv[j+2][0])) { /* skip x characters before size */ addlist(argv[j]+1,f,atoi(argv[j+1]),atoi(argv[j+2])); j+=2; } diff --git a/src/sbbs3/allusers.c b/src/sbbs3/allusers.c index 4d5ea513c7fdeaa837321149bf0ae6949b7dae62..ef8d3525f15357d3303a9ceac27d4f5848b220dd 100644 --- a/src/sbbs3/allusers.c +++ b/src/sbbs3/allusers.c @@ -182,22 +182,22 @@ int main(int argc, char **argv) case 'F': /* Set required flags */ j=3; set=1; - if(isdigit(argv[i][2])) + if(IS_DIGIT(argv[i][2])) set=argv[i][2]&0xf; else j=2; for(;argv[i][j];j++) - if(isalpha(argv[i][j])) + if(IS_ALPHA(argv[i][j])) reqflags[set-1]|=FLAG(toupper(argv[i][j])); break; case 'R': /* Set required restrictions */ for(j=2;argv[i][j];j++) - if(isalpha(argv[i][j])) + if(IS_ALPHA(argv[i][j])) reqrest|=FLAG(toupper(argv[i][j])); break; case 'E': /* Set required exemptions */ for(j=2;argv[i][j];j++) - if(isalpha(argv[i][j])) + if(IS_ALPHA(argv[i][j])) reqexempt|=FLAG(toupper(argv[i][j])); break; default: /* Unrecognized include */ @@ -210,7 +210,7 @@ int main(int argc, char **argv) case 'F': /* flags */ j=3; set=1; - if(isdigit(argv[i][2])) + if(IS_DIGIT(argv[i][2])) set=argv[i][2]&0xf; else j=2; @@ -221,7 +221,7 @@ int main(int argc, char **argv) sub=1; } for(;argv[i][j];j++) - if(isalpha(argv[i][j])) + if(IS_ALPHA(argv[i][j])) flags|=FLAG(toupper(argv[i][j])); SAFEPRINTF(str,"%suser.dat",dir); if(!fexistcase(str) || (file=sopen(str,O_RDWR|O_BINARY,SH_DENYNO))==-1) { @@ -285,7 +285,7 @@ int main(int argc, char **argv) sub=1; } for(;argv[i][j];j++) - if(isalpha(argv[i][j])) + if(IS_ALPHA(argv[i][j])) flags|=FLAG(toupper(argv[i][j])); SAFEPRINTF(str,"%suser.dat",dir); if(!fexistcase(str) || (file=sopen(str,O_RDWR|O_BINARY,SH_DENYNO))==-1) { diff --git a/src/sbbs3/ansiterm.cpp b/src/sbbs3/ansiterm.cpp index 7077b60af01568a484a39ebc17f69cadf7b28b43..d130acb177e9198cf99a35fc23ff5bfea2ea4f56 100644 --- a/src/sbbs3/ansiterm.cpp +++ b/src/sbbs3/ansiterm.cpp @@ -210,7 +210,8 @@ char* sbbs_t::ansi(int atr, int curatr, char* str) void sbbs_t::ansi_getlines() { - if(sys_status&SS_USERON && useron.misc&ANSI && !useron.rows /* Auto-detect rows */ + if(sys_status&SS_USERON && useron.misc&ANSI + && (useron.rows == TERM_ROWS_AUTO || useron.cols == TERM_COLS_AUTO) && online==ON_REMOTE) { /* Remote */ SYNC; putcom("\x1b[s\x1b[255B\x1b[255C\x1b[6n\x1b[u"); @@ -242,7 +243,7 @@ bool sbbs_t::ansi_getxy(int* x, int* y) rsp++; start=time(NULL); } - else if(isdigit(ch) && rsp==2) { + else if(IS_DIGIT(ch) && rsp==2) { if(y!=NULL) { (*y)*=10; (*y)+=(ch&0xf); @@ -253,7 +254,7 @@ bool sbbs_t::ansi_getxy(int* x, int* y) rsp++; start=time(NULL); } - else if(isdigit(ch) && rsp==3) { + else if(IS_DIGIT(ch) && rsp==3) { if(x!=NULL) { (*x)*=10; (*x)+=(ch&0xf); diff --git a/src/sbbs3/answer.cpp b/src/sbbs3/answer.cpp index 38f3471164cd9b2ef92d3df069b4d159a535e9a4..f09930cda9d89eadcb3550712393274c02f1e719 100644 --- a/src/sbbs3/answer.cpp +++ b/src/sbbs3/answer.cpp @@ -109,7 +109,6 @@ bool sbbs_t::answer() useron.number=matchuser(&cfg, rlogin_name, /* sysop_alias: */FALSE); if(useron.number) { getuserdat(&cfg,&useron); - useron.misc&=~TERM_FLAGS; SAFEPRINTF(path,"%srlogin.cfg",cfg.ctrl_dir); if(!findstr(client.addr,path)) { SAFECOPY(tmp, rlogin_pass); @@ -158,7 +157,7 @@ bool sbbs_t::answer() badlogin(useron.alias, tmp); bputs(text[InvalidLogon]); } - lprintf(LOG_WARNING,"!CLIENT IP NOT LISTED in %s", path); + lprintf(LOG_DEBUG,"!CLIENT IP (%s) NOT LISTED in %s", client.addr, path); useron.number=0; hangup(); } @@ -213,7 +212,6 @@ bool sbbs_t::answer() useron.number=matchuser(&cfg, rlogin_name, /* sysop_alias: */FALSE); if(useron.number) { getuserdat(&cfg,&useron); - useron.misc&=~TERM_FLAGS; for(i=0;i<3 && online;i++) { if(stricmp(tmp,useron.pass)) { if(cfg.sys_misc&SM_ECHO_PW) @@ -390,6 +388,7 @@ bool sbbs_t::answer() else SAFECOPY(terminal,"DUMB"); } + update_nodeterm(); /* AutoLogon via IP or Caller ID here */ if(!useron.number && !(sys_status&SS_RLOGIN) diff --git a/src/sbbs3/ars.c b/src/sbbs3/ars.c index 8eb049dfbcbb6047f178b02fec6d1d119368e509..d03edddd557f28ffbce19795e5e698cc238ca55f 100644 --- a/src/sbbs3/ars.c +++ b/src/sbbs3/ars.c @@ -102,7 +102,7 @@ uchar* arstr(ushort* count, const char* str, scfg_t* cfg, uchar* ar_buf) if(str[i]=='&') continue; - if(isalpha(str[i])) { + if(IS_ALPHA(str[i])) { p=np=str+i; SKIP_ALPHA(np); n=np-p; @@ -248,7 +248,7 @@ uchar* arstr(ushort* count, const char* str, scfg_t* cfg, uchar* ar_buf) continue; } - if(!arg_expected && isalpha(str[i])) { + if(!arg_expected && IS_ALPHA(str[i])) { n=i; if(!strnicmp(str+i,"AGE",3)) { artype=AR_AGE; @@ -550,7 +550,7 @@ uchar* arstr(ushort* count, const char* str, scfg_t* cfg, uchar* ar_buf) ar[j++]=AR_EQUAL; not=equal=0; - if(artype==AR_FLAG1 && isdigit(str[i])) { /* flag set specified */ + if(artype==AR_FLAG1 && IS_DIGIT(str[i])) { /* flag set specified */ switch(str[i]) { case '2': artype=AR_FLAG2; @@ -567,15 +567,15 @@ uchar* arstr(ushort* count, const char* str, scfg_t* cfg, uchar* ar_buf) arg_expected=FALSE; - if(artype==AR_SUB && !isdigit(str[i])) + if(artype==AR_SUB && !IS_DIGIT(str[i])) artype=AR_SUBCODE; - if(artype==AR_DIR && !isdigit(str[i])) + if(artype==AR_DIR && !IS_DIGIT(str[i])) artype=AR_DIRCODE; if(artype==AR_INVALID) artype=AR_LEVEL; ar[j++]=artype; - if(isdigit(str[i]) && !ar_string_arg(artype)) { + if(IS_DIGIT(str[i]) && !ar_string_arg(artype)) { if(artype==AR_TIME) { n=atoi(str+i)*60; p=strchr(str+i,':'); @@ -583,7 +583,7 @@ uchar* arstr(ushort* count, const char* str, scfg_t* cfg, uchar* ar_buf) n+=atoi(p+1); *((short *)(ar+j))=n; j+=2; - while(isdigit(str[i+1]) || str[i+1]==':') i++; + while(IS_DIGIT(str[i+1]) || str[i+1]==':') i++; continue; } n=atoi(str+i); @@ -635,7 +635,7 @@ uchar* arstr(ushort* count, const char* str, scfg_t* cfg, uchar* ar_buf) j--; break; } - while(isdigit(str[i+1])) i++; + while(IS_DIGIT(str[i+1])) i++; continue; } maxlen=128; @@ -681,7 +681,7 @@ uchar* arstr(ushort* count, const char* str, scfg_t* cfg, uchar* ar_buf) } else /* Unknown sub-board */ j--; - while(isalpha(str[i+1])) i++; + while(IS_ALPHA(str[i+1])) i++; break; case AR_DIR: for(n=0;n<(uint)cfg->total_dirs;n++) @@ -693,7 +693,7 @@ uchar* arstr(ushort* count, const char* str, scfg_t* cfg, uchar* ar_buf) } else /* Unknown directory */ j--; - while(isalpha(str[i+1])) i++; + while(IS_ALPHA(str[i+1])) i++; break; case AR_DAY: if(toupper(str[i])=='S' @@ -712,7 +712,7 @@ uchar* arstr(ushort* count, const char* str, scfg_t* cfg, uchar* ar_buf) else if(toupper(str[i])=='F') /* Friday */ ar[j++]=5; else ar[j++]=6; /* Saturday */ - while(isalpha(str[i+1])) i++; + while(IS_ALPHA(str[i+1])) i++; break; default: /* Badly formed ARS, digit expected */ j--; diff --git a/src/sbbs3/atcodes.cpp b/src/sbbs3/atcodes.cpp index b1ed9e9cb8cc4a9fbe9ed0eee27a5d6c801bb457..a51b5aa9c72b0e3abccbd6b774f11041e38aa678 100644 --- a/src/sbbs3/atcodes.cpp +++ b/src/sbbs3/atcodes.cpp @@ -52,7 +52,7 @@ static char* separate_thousands(const char* src, char *dest, size_t maxlen, char if(strlen(src) * 1.3 > maxlen) return (char*)src; const char* tail = src; - while(*tail && isdigit(*tail)) + while(*tail && IS_DIGIT(*tail)) tail++; if(tail == src) return (char*)src; @@ -174,13 +174,13 @@ int sbbs_t::show_atcode(const char *instr, JSObject* obj) if(p!=NULL) { char* lp = p; lp++; // skip the '|' or '-' - while(*lp == '>'|| isalpha((uchar)*lp)) + while(*lp == '>'|| IS_ALPHA(*lp)) lp++; if(*lp) width_specified = true; - while(*lp && !isdigit((uchar)*lp)) + while(*lp && !IS_DIGIT(*lp)) lp++; - if(*lp && isdigit((uchar)*lp)) { + if(*lp && IS_DIGIT(*lp)) { disp_len=atoi(lp); width_specified = true; } diff --git a/src/sbbs3/baja.c b/src/sbbs3/baja.c index b572083c842022d1409e77c45b3a8c84d572faa1..654a4dc0ff114c9fdd97b10a29f43595a2de5928 100644 --- a/src/sbbs3/baja.c +++ b/src/sbbs3/baja.c @@ -148,7 +148,7 @@ int32_t val(char *src, char *p) static int inside; int32_t l; - if(isdigit((uchar)*p) || *p=='-') /* Dec, Hex, or Oct */ + if(IS_DIGIT(*p) || *p=='-') /* Dec, Hex, or Oct */ l=strtol(p,&p,0); else if(*p=='\'') { /* Char */ p++; @@ -230,11 +230,11 @@ void writecstr(char *p) continue; } if(*p=='\\') { /* escape */ p++; - if(isdigit((uchar)*p)) { + if(IS_DIGIT(*p)) { sprintf(tmp,"%.3s",p); str[j]=atoi(tmp); /* decimal, NOT octal */ - if(isdigit((uchar)*(++p))) /* skip up to 3 digits */ - if(isdigit((uchar)*(++p))) + if(IS_DIGIT(*(++p))) /* skip up to 3 digits */ + if(IS_DIGIT(*(++p))) p++; j++; continue; } @@ -311,7 +311,7 @@ void newvar(char* src, char *in) char name[128]; int32_t i,l; - if(isdigit((uchar)*in)) { + if(IS_DIGIT(*in)) { printf("!SYNTAX ERROR (illegal variable name):\n"); printf(linestr,src,line,(char*)in); bail(1); @@ -377,7 +377,7 @@ int32_t isvar(char *arg) char name[128],*p; int32_t i,l; - if(!arg || !(*arg) || isdigit((uchar)*arg)) + if(!arg || !(*arg) || IS_DIGIT(*arg)) return(0); sprintf(name,"%.80s",arg); @@ -426,7 +426,7 @@ void expdefs(char *line) continue; } for(sp=p;*sp;sp++) - if(!isalnum((uchar)*sp) && *sp!='_') + if(!IS_ALPHANUMERIC(*sp) && *sp!='_') break; sav[0]=*sp; /* Save delimiter */ sav[1]=0; @@ -1185,7 +1185,7 @@ void compile(char *src) if(!stricmp(p,"COMPARE_INT_VAR") || (!stricmp(p,"COMPARE") - && (isdigit((uchar)*arg2) || atol(arg2) || *arg2=='\'' || *arg2=='.'))) { + && (IS_DIGIT(*arg2) || atol(arg2) || *arg2=='\'' || *arg2=='.'))) { if(!(*arg)) break; fputc(CS_VAR_INSTRUCTION,out); @@ -1290,7 +1290,7 @@ void compile(char *src) if(!stricmp(p,"ADD_INT_VAR") || (!stricmp(p,"ADD") - && (isdigit((uchar)*arg2) || atol(arg2) || *arg2=='\'' || *arg2=='.'))) { + && (IS_DIGIT(*arg2) || atol(arg2) || *arg2=='\'' || *arg2=='.'))) { if(!(*arg)) break; fputc(CS_VAR_INSTRUCTION,out); fputc(ADD_INT_VAR,out); @@ -1318,7 +1318,7 @@ void compile(char *src) if(!stricmp(p,"SUB_INT_VAR") || (!stricmp(p,"SUB") - && (isdigit((uchar)*arg2) || atol(arg2) || *arg2=='\'' || *arg2=='.'))) { + && (IS_DIGIT(*arg2) || atol(arg2) || *arg2=='\'' || *arg2=='.'))) { if(!(*arg)) break; fputc(CS_VAR_INSTRUCTION,out); fputc(SUB_INT_VAR,out); @@ -1346,7 +1346,7 @@ void compile(char *src) if(!stricmp(p,"MUL_INT_VAR") || (!stricmp(p,"MUL") - && (isdigit((uchar)*arg2) || atol(arg2) || *arg2=='\'' || *arg2=='.'))) { + && (IS_DIGIT(*arg2) || atol(arg2) || *arg2=='\'' || *arg2=='.'))) { if(!(*arg)) break; fputc(CS_VAR_INSTRUCTION,out); fputc(MUL_INT_VAR,out); @@ -1374,7 +1374,7 @@ void compile(char *src) if(!stricmp(p,"DIV_INT_VAR") || (!stricmp(p,"DIV") - && (isdigit((uchar)*arg2) || atol(arg2) || *arg2=='\'' || *arg2=='.'))) { + && (IS_DIGIT(*arg2) || atol(arg2) || *arg2=='\'' || *arg2=='.'))) { if(!(*arg)) break; fputc(CS_VAR_INSTRUCTION,out); fputc(DIV_INT_VAR,out); @@ -1402,7 +1402,7 @@ void compile(char *src) if(!stricmp(p,"MOD_INT_VAR") || (!stricmp(p,"MOD") - && (isdigit((uchar)*arg2) || atol(arg2) || *arg2=='\'' || *arg2=='.'))) { + && (IS_DIGIT(*arg2) || atol(arg2) || *arg2=='\'' || *arg2=='.'))) { if(!(*arg)) break; fputc(CS_VAR_INSTRUCTION,out); fputc(MOD_INT_VAR,out); @@ -1430,7 +1430,7 @@ void compile(char *src) if(!stricmp(p,"AND_INT_VAR") || (!stricmp(p,"AND") - && (isdigit((uchar)*arg2) || atol(arg2) || *arg2=='\'' || *arg2=='.'))) { + && (IS_DIGIT(*arg2) || atol(arg2) || *arg2=='\'' || *arg2=='.'))) { if(!(*arg)) break; fputc(CS_VAR_INSTRUCTION,out); fputc(AND_INT_VAR,out); @@ -1474,7 +1474,7 @@ void compile(char *src) if(!stricmp(p,"OR_INT_VAR") || (!stricmp(p,"OR") - && (isdigit((uchar)*arg2) || atol(arg2) || *arg2=='\'' || *arg2=='.'))) { + && (IS_DIGIT(*arg2) || atol(arg2) || *arg2=='\'' || *arg2=='.'))) { if(!(*arg)) break; fputc(CS_VAR_INSTRUCTION,out); fputc(OR_INT_VAR,out); @@ -1500,7 +1500,7 @@ void compile(char *src) if(!stricmp(p,"NOT_INT_VAR") || (!stricmp(p,"NOT") - && (isdigit((uchar)*arg2) || atol(arg2) || *arg2=='\'' || *arg2=='.'))) { + && (IS_DIGIT(*arg2) || atol(arg2) || *arg2=='\'' || *arg2=='.'))) { if(!(*arg)) break; fputc(CS_VAR_INSTRUCTION,out); fputc(NOT_INT_VAR,out); @@ -1526,7 +1526,7 @@ void compile(char *src) if(!stricmp(p,"XOR_INT_VAR") || (!stricmp(p,"XOR") - && (isdigit((uchar)*arg2) || atol(arg2) || *arg2=='\'' || *arg2=='.'))) { + && (IS_DIGIT(*arg2) || atol(arg2) || *arg2=='\'' || *arg2=='.'))) { if(!(*arg)) break; fputc(CS_VAR_INSTRUCTION,out); fputc(XOR_INT_VAR,out); @@ -1678,7 +1678,7 @@ void compile(char *src) if(!(*arg)) break; fputc(CS_FIO_FUNCTION,out); - if(!(*arg3) || isdigit((uchar)*arg3) || atoi(arg3)) + if(!(*arg3) || IS_DIGIT(*arg3) || atoi(arg3)) fputc(FIO_READ,out); else fputc(FIO_READ_VAR,out); @@ -1691,7 +1691,7 @@ void compile(char *src) if(p) *p=0; writecrc(src,arg2); /* Variable */ - if(isdigit((uchar)*arg3)) + if(IS_DIGIT(*arg3)) i=val(src,arg3); /* Length */ else i=0; @@ -1703,7 +1703,7 @@ void compile(char *src) if(!stricmp(p,"FWRITE")) { if(!(*arg)) break; fputc(CS_FIO_FUNCTION,out); - if(!(*arg3) || isdigit((uchar)*arg3) || atoi(arg3)) + if(!(*arg3) || IS_DIGIT(*arg3) || atoi(arg3)) fputc(FIO_WRITE,out); else fputc(FIO_WRITE_VAR,out); @@ -1716,7 +1716,7 @@ void compile(char *src) if(p) *p=0; writecrc(src,arg2); /* Variable */ - if(isdigit((uchar)*arg3)) + if(IS_DIGIT(*arg3)) i=val(src,arg3); /* Length */ else i=0; @@ -1769,7 +1769,7 @@ void compile(char *src) if(!stricmp(p,"FSET_POS") || !stricmp(p,"FSEEK")) { if(!(*arg)) break; fputc(CS_FIO_FUNCTION,out); - if(isdigit((uchar)*arg2) || atol(arg2)) + if(IS_DIGIT(*arg2) || atol(arg2)) fputc(FIO_SEEK,out); else fputc(FIO_SEEK_VAR,out); @@ -1781,7 +1781,7 @@ void compile(char *src) p=strchr(arg2,' '); if(p) *p=0; - if(atol(arg2) || isdigit((uchar)*arg2)) { + if(atol(arg2) || IS_DIGIT(*arg2)) { l=val(src,arg2); fwrite(&l,4,1,out); } else @@ -1800,7 +1800,7 @@ void compile(char *src) if(!stricmp(p,"FLOCK")) { if(!(*arg)) break; fputc(CS_FIO_FUNCTION,out); - if(isdigit((uchar)*arg2) || atol(arg2)) + if(IS_DIGIT(*arg2) || atol(arg2)) fputc(FIO_LOCK,out); else fputc(FIO_LOCK_VAR,out); @@ -1809,7 +1809,7 @@ void compile(char *src) break; *p=0; writecrc(src,arg); /* File handle */ - if(atol(arg2) || isdigit((uchar)*arg2)) { + if(atol(arg2) || IS_DIGIT(*arg2)) { l=val(src,arg2); if(!l) break; @@ -1820,7 +1820,7 @@ void compile(char *src) if(!stricmp(p,"FUNLOCK")) { if(!(*arg)) break; fputc(CS_FIO_FUNCTION,out); - if(isdigit((uchar)*arg2) || atol(arg2)) + if(IS_DIGIT(*arg2) || atol(arg2)) fputc(FIO_UNLOCK,out); else fputc(FIO_UNLOCK_VAR,out); @@ -1829,7 +1829,7 @@ void compile(char *src) break; *p=0; writecrc(src,arg); /* File handle */ - if(atol(arg2) || isdigit((uchar)*arg2)) { + if(atol(arg2) || IS_DIGIT(*arg2)) { l=val(src,arg2); if(!l) break; @@ -1840,7 +1840,7 @@ void compile(char *src) if(!stricmp(p,"FSET_LENGTH")) { if(!(*arg)) break; fputc(CS_FIO_FUNCTION,out); - if(isdigit((uchar)*arg2) || atol(arg2)) + if(IS_DIGIT(*arg2) || atol(arg2)) fputc(FIO_SET_LENGTH,out); else fputc(FIO_SET_LENGTH_VAR,out); @@ -1849,7 +1849,7 @@ void compile(char *src) break; *p=0; writecrc(src,arg); /* File handle */ - if(atol(arg2) || isdigit((uchar)*arg2)) { + if(atol(arg2) || IS_DIGIT(*arg2)) { l=val(src,arg2); fwrite(&l,4,1,out); } else @@ -2548,7 +2548,7 @@ void compile(char *src) if(!stricmp(p,"GETSTR")) { p=strchr(arg,' '); if(p) *p=0; - if((!(*arg) || isdigit((uchar)*arg) || !stricmp(arg,"STR")) && !(*arg3)) + if((!(*arg) || IS_DIGIT(*arg) || !stricmp(arg,"STR")) && !(*arg3)) fprintf(out,"%c%c",CS_GETSTR,atoi(arg) ? atoi(arg) : *arg2 ? atoi(arg2) : 128); else { @@ -2577,7 +2577,7 @@ void compile(char *src) if(!(*arg)) break; p=strchr(arg,' '); if(p) *p=0; - if(isdigit((uchar)*arg)) { + if(IS_DIGIT(*arg)) { i=val(src,arg); fprintf(out,"%c",CS_GETNUM); fwrite(&i,2,1,out); } @@ -2612,7 +2612,7 @@ void compile(char *src) if(!stricmp(p,"GETLINE")) { p=strchr(arg,' '); if(p) *p=0; - if(!(*arg) || isdigit((uchar)*arg)) + if(!(*arg) || IS_DIGIT(*arg)) fprintf(out,"%c%c",CS_GETLINE,*arg ? atoi(arg) :128); else { if((l=isvar(arg2))!=0) { @@ -2632,7 +2632,7 @@ void compile(char *src) if(!stricmp(p,"GETSTRUPR")) { p=strchr(arg,' '); if(p) *p=0; - if(!(*arg) || isdigit((uchar)*arg)) + if(!(*arg) || IS_DIGIT(*arg)) fprintf(out,"%c%c",CS_GETSTRUPR,*arg ? atoi(arg) :128); else { if((l=isvar(arg2))!=0) { @@ -2652,7 +2652,7 @@ void compile(char *src) if(!stricmp(p,"GETNAME")) { p=strchr(arg,' '); if(p) *p=0; - if(!(*arg) || isdigit((uchar)*arg)) + if(!(*arg) || IS_DIGIT(*arg)) fprintf(out,"%c%c",CS_GETNAME,*arg ? atoi(arg) :25); else { if((l=isvar(arg2))!=0) { @@ -2673,7 +2673,7 @@ void compile(char *src) if(!(*arg)) break; p=strchr(arg,' '); if(p) *p=0; - if(isdigit((uchar)*arg)) + if(IS_DIGIT(*arg)) fprintf(out,"%c%c",CS_SHIFT_STR,atoi(arg)); else { if((l=isvar(arg2))!=0) { diff --git a/src/sbbs3/build.bat b/src/sbbs3/build.bat index 160182e46a6dfa3af7cbdaa9a269cf863379e25b..dd8dde46a9146cbd2d10d81862ed4c63b0f3f7e0 100755 --- a/src/sbbs3/build.bat +++ b/src/sbbs3/build.bat @@ -2,5 +2,5 @@ setlocal rem *** Requires Microsoft Visual C++ 2019 *** call "%VS160COMNTOOLS%\VsMSBuildCmd.bat" -msbuild sbbs3.sln /p:Platform="Win32" %1 %2 %3 %4 %5 +msbuild sbbs3.sln /p:Platform="Win32" %* if errorlevel 1 echo. & echo !ERROR(s) occurred & exit /b 1 \ No newline at end of file diff --git a/src/sbbs3/chat.cpp b/src/sbbs3/chat.cpp index 1d68f5209226aa858c2fbfce1ac8bc275adffa17..321c907bd00b5c7822e40a09cd5a56d5ab15c67a 100644 --- a/src/sbbs3/chat.cpp +++ b/src/sbbs3/chat.cpp @@ -1571,7 +1571,7 @@ void sbbs_t::guruchat(char* line, char* gurubuf, int gurunum, char* last_answer) j=strlen(line); k=0; for(i=0;i<j;i++) { - if(line[i]<0 || !isalnum((uchar)line[i])) { + if(line[i]<0 || !IS_ALPHANUMERIC(line[i])) { if(!k) /* beginning non-alphanumeric */ continue; if(line[i]==line[i+1]) /* redundant non-alnum */ @@ -1584,7 +1584,7 @@ void sbbs_t::guruchat(char* line, char* gurubuf, int gurunum, char* last_answer) cstr[k]=0; while(k) { k--; - if(!isalnum((uchar)cstr[k])) + if(!IS_ALPHANUMERIC(cstr[k])) continue; break; } @@ -1786,8 +1786,8 @@ void sbbs_t::guruchat(char* line, char* gurubuf, int gurunum, char* last_answer) if(action!=NODE_MCHT) { for(i=0;i<k;i++) { if(i && mistakes && theanswer[i]!=theanswer[i-1] && - ((!isalnum((uchar)theanswer[i]) && !sbbs_random(100)) - || (isalnum((uchar)theanswer[i]) && !sbbs_random(30)))) { + ((!IS_ALPHANUMERIC(theanswer[i]) && !sbbs_random(100)) + || (IS_ALPHANUMERIC(theanswer[i]) && !sbbs_random(30)))) { c=j=((uint)sbbs_random(3)+1); /* 1 to 3 chars */ if(c<strcspn(theanswer+(i+1),"\0., ")) c=j=1; @@ -1909,7 +1909,7 @@ bool sbbs_t::guruexp(char **ptrptr, char *line) if((**ptrptr)==')') break; c=0; - while((**ptrptr) && isspace(**ptrptr)) + while((**ptrptr) && IS_WHITESPACE(**ptrptr)) (*ptrptr)++; while((**ptrptr)!='|' && (**ptrptr)!='&' && (**ptrptr)!=')' &&(**ptrptr)) { str[c++]=(**ptrptr); @@ -1948,13 +1948,13 @@ bool sbbs_t::guruexp(char **ptrptr, char *line) else { cp=strstr(line,str); if(cp && c) { - if(cp!=line || isalnum((uchar)*(cp+strlen(str)))) + if(cp!=line || IS_ALPHANUMERIC(*(cp+strlen(str)))) cp=0; } else { /* must be isolated word */ while(cp) - if((cp!=line && isalnum((uchar)*(cp-1))) - || isalnum((uchar)*(cp+strlen(str)))) + if((cp!=line && IS_ALPHANUMERIC(*(cp-1))) + || IS_ALPHANUMERIC(*(cp+strlen(str)))) cp=strstr(cp+strlen(str),str); else break; diff --git a/src/sbbs3/clean.bat b/src/sbbs3/clean.bat new file mode 100644 index 0000000000000000000000000000000000000000..9eb3574c9fcaf174f306859a78bc0b093520f449 --- /dev/null +++ b/src/sbbs3/clean.bat @@ -0,0 +1,4 @@ +@echo off +setlocal +call build.bat /t:Clean +call release.bat /t:Clean \ No newline at end of file diff --git a/src/sbbs3/con_out.cpp b/src/sbbs3/con_out.cpp index 1c2ed232e850608ca3a279e2f4d66d0bc1280434..fb1f43b15cb8cf06ac6bf77de93f0a1c6b13129e 100644 --- a/src/sbbs3/con_out.cpp +++ b/src/sbbs3/con_out.cpp @@ -178,7 +178,7 @@ size_t sbbs_t::bstrlen(const char *str, long mode) /* Perform PETSCII terminal output translation (from ASCII/CP437) */ unsigned char cp437_to_petscii(unsigned char ch) { - if(isalpha(ch)) + if(IS_ALPHA(ch)) return ch ^ 0x20; /* swap upper/lower case */ switch(ch) { case '\1': return '@'; @@ -260,7 +260,7 @@ int sbbs_t::petscii_to_ansibbs(unsigned char ch) { if((ch&0xe0) == 0xc0) /* "Codes $60-$7F are, actually, copies of codes $C0-$DF" */ ch = 0x60 | (ch&0x1f); - if(isalpha(ch)) + if(IS_ALPHA(ch)) return outchar(ch ^ 0x20); /* swap upper/lower case */ switch(ch) { case '\r': newline(); break; @@ -556,6 +556,32 @@ const char* sbbs_t::term_charset(long term) return "CP437"; } +/****************************************************************************/ +/* For node spying purposes */ +/****************************************************************************/ +bool sbbs_t::update_nodeterm(void) +{ + str_list_t ini = strListInit(); + iniSetInteger(&ini, ROOT_SECTION, "cols", cols, NULL); + iniSetInteger(&ini, ROOT_SECTION, "rows", rows, NULL); + iniSetString(&ini, ROOT_SECTION, "type", term_type(), NULL); + iniSetString(&ini, ROOT_SECTION, "chars", term_charset(), NULL); + iniSetHexInt(&ini, ROOT_SECTION, "flags", term_supports(), NULL); + iniSetHexInt(&ini, ROOT_SECTION, "mouse", mouse_mode, NULL); + iniSetHexInt(&ini, ROOT_SECTION, "console", console, NULL); + + char path[MAX_PATH + 1]; + SAFEPRINTF(path, "%sterminal.ini", cfg.node_dir); + FILE* fp = iniOpenFile(path, /* create: */TRUE); + bool result = false; + if(fp != NULL) { + result = iniWriteFile(fp, ini); + iniCloseFile(fp); + } + strListFree(&ini); + return result; +} + /****************************************************************************/ /* Outputs character */ /* Performs terminal translations (e.g. EXASCII-to-ASCII, FF->ESC[2J) */ @@ -1038,7 +1064,7 @@ void sbbs_t::ctrl_a(char x) cursor_right((uchar)x-0x7f); return; } - if(isdigit(x)) { /* background color */ + if(IS_DIGIT(x)) { /* background color */ atr &= (BG_BRIGHT|BLINK|0x0f); } switch(toupper(x)) { diff --git a/src/sbbs3/ctrl/MailCfgDlgUnit.cpp b/src/sbbs3/ctrl/MailCfgDlgUnit.cpp index 7b862b42ea88054820a8d6137c8882c1599bfa71..96b40c132259fb6b28dda9b0bc783f360ae7b0c3 100644 --- a/src/sbbs3/ctrl/MailCfgDlgUnit.cpp +++ b/src/sbbs3/ctrl/MailCfgDlgUnit.cpp @@ -95,10 +95,10 @@ void __fastcall TMailCfgDlg::FormShow(TObject *Sender) MaxMsgsWaitingEdit->Text="N/A"; else MaxMsgsWaitingEdit->Text=AnsiString(MainForm->mail_startup.max_msgs_waiting); - if(MainForm->mail_startup.lines_per_yield == 0) - LinesPerYieldEdit->Text="N/A"; + if(MainForm->mail_startup.max_concurrent_connections == 0) + MaxConConEdit->Text="N/A"; else - LinesPerYieldEdit->Text=AnsiString(MainForm->mail_startup.lines_per_yield); + MaxConConEdit->Text=AnsiString((int)MainForm->mail_startup.max_concurrent_connections); AutoStartCheckBox->Checked=MainForm->MailAutoStart; LogFileCheckBox->Checked=MainForm->MailLogFile; @@ -234,7 +234,7 @@ void __fastcall TMailCfgDlg::OKBtnClick(TObject *Sender) MainForm->mail_startup.max_msgs_waiting=MaxMsgsWaitingEdit->Text.ToIntDef(0); MainForm->mail_startup.max_delivery_attempts=DeliveryAttemptsEdit->Text.ToIntDef(MAIL_DEFAULT_MAX_DELIVERY_ATTEMPTS); MainForm->mail_startup.rescan_frequency=RescanFreqEdit->Text.ToIntDef(MAIL_DEFAULT_RESCAN_FREQUENCY); - MainForm->mail_startup.lines_per_yield=LinesPerYieldEdit->Text.ToIntDef(0); + MainForm->mail_startup.max_concurrent_connections=MaxConConEdit->Text.ToIntDef(0); SAFECOPY(MainForm->mail_startup.default_charset ,DefCharsetEdit->Text.c_str()); diff --git a/src/sbbs3/ctrl/MailCfgDlgUnit.dfm b/src/sbbs3/ctrl/MailCfgDlgUnit.dfm index c4533d5f35d5a95610a64f481648befabe93bee9..41200ee03aea661eba9300870d56dcc5ce561c64 100644 --- a/src/sbbs3/ctrl/MailCfgDlgUnit.dfm +++ b/src/sbbs3/ctrl/MailCfgDlgUnit.dfm @@ -1,6 +1,6 @@ object MailCfgDlg: TMailCfgDlg - Left = 1213 - Top = 393 + Left = 1274 + Top = 822 BorderStyle = bsDialog Caption = 'Mail Server Configuration' ClientHeight = 246 @@ -53,8 +53,8 @@ object MailCfgDlg: TMailCfgDlg Top = 3 Width = 278 Height = 199 - ActivePage = POP3TabSheet - TabIndex = 2 + ActivePage = GeneralTabSheet + TabIndex = 0 TabOrder = 3 object GeneralTabSheet: TTabSheet Caption = 'General' @@ -84,13 +84,13 @@ object MailCfgDlg: TMailCfgDlg AutoSize = False Caption = 'Max Inactivity' end - object LinesPerYieldLabel: TLabel + object MaxConConLabel: TLabel Left = 7 Top = 140 Width = 85 Height = 19 AutoSize = False - Caption = 'Lines Per Yield' + Caption = 'Max Con-Conn' end object MaxMsgsLabel: TLabel Left = 7 @@ -178,14 +178,12 @@ object MailCfgDlg: TMailCfgDlg ShowHint = True TabOrder = 10 end - object LinesPerYieldEdit: TEdit + object MaxConConEdit: TEdit Left = 92 Top = 140 Width = 39 Height = 21 - Hint = - 'Number of lines of message text sent/received between time-slice' + - ' yields' + Hint = 'Maximum Concurrent Connections from same IP (0=unlimited)' ParentShowHint = False ShowHint = True TabOrder = 6 diff --git a/src/sbbs3/ctrl/MailCfgDlgUnit.h b/src/sbbs3/ctrl/MailCfgDlgUnit.h index c6598a4cdade958402ed0a30c4bc81e53aacb29b..258490faee238dae494057ce0f7eb58620f551b7 100644 --- a/src/sbbs3/ctrl/MailCfgDlgUnit.h +++ b/src/sbbs3/ctrl/MailCfgDlgUnit.h @@ -112,8 +112,8 @@ __published: TEdit *BLHeaderEdit; TLabel *BLSubjectLabel; TLabel *BLHeaderLabel; - TEdit *LinesPerYieldEdit; - TLabel *LinesPerYieldLabel; + TEdit *MaxConConEdit; + TLabel *MaxConConLabel; TLabel *MaxRecipientsLabel; TEdit *MaxRecipientsEdit; TButton *DNSBLExemptionsButton; diff --git a/src/sbbs3/ctrl/TelnetCfgDlgUnit.cpp b/src/sbbs3/ctrl/TelnetCfgDlgUnit.cpp index ed2f1b368524f207722c3aab289368f1254a5f06..60e9ab7ff82f5896cd480ac2f6c23697e6c03ebc 100644 --- a/src/sbbs3/ctrl/TelnetCfgDlgUnit.cpp +++ b/src/sbbs3/ctrl/TelnetCfgDlgUnit.cpp @@ -83,7 +83,10 @@ void __fastcall TTelnetCfgDlg::FormShow(TObject *Sender) FirstNodeEdit->Text=AnsiString((int)MainForm->bbs_startup.first_node); LastNodeEdit->Text=AnsiString((int)MainForm->bbs_startup.last_node); - MaxConConEdit->Text=AnsiString((int)MainForm->bbs_startup.max_concurrent_connections); + if(MainForm->bbs_startup.max_concurrent_connections == 0) + MaxConConEdit->Text="N/A"; + else + MaxConConEdit->Text=AnsiString((int)MainForm->bbs_startup.max_concurrent_connections); AutoStartCheckBox->Checked=MainForm->SysAutoStart; AnswerSoundEdit->Text=AnsiString(MainForm->bbs_startup.answer_sound); HangupSoundEdit->Text=AnsiString(MainForm->bbs_startup.hangup_sound); diff --git a/src/sbbs3/dat_rec.c b/src/sbbs3/dat_rec.c index 0cec87f4adc5ee05577fc93a5767f606254234ba..b8ccaf78a08d6b4e7c57ba847c292eb703d9000e 100644 --- a/src/sbbs3/dat_rec.c +++ b/src/sbbs3/dat_rec.c @@ -41,7 +41,7 @@ /* Places into 'strout' CR or ETX terminated string starting at */ /* 'start' and ending at 'start'+'length' or terminator from 'strin' */ /****************************************************************************/ -void DLLCALL getrec(const char *strin,int start,int length,char *strout) +int DLLCALL getrec(const char *strin,int start,int length,char *strout) { int i=0,stop; @@ -52,6 +52,7 @@ void DLLCALL getrec(const char *strin,int start,int length,char *strout) strout[i++]=strin[start++]; } strout[i]=0; + return i; } /****************************************************************************/ diff --git a/src/sbbs3/dat_rec.h b/src/sbbs3/dat_rec.h index e60dd510291d8152f4de56b09f5808aeef8cc62a..b266c0bd049ba9e7bcf5c863b9303218d4b80a72 100644 --- a/src/sbbs3/dat_rec.h +++ b/src/sbbs3/dat_rec.h @@ -70,7 +70,7 @@ extern "C" { #endif -DLLEXPORT void DLLCALL getrec(const char *instr,int start,int length,char *outstr); /* Retrieve a record from a string */ +DLLEXPORT int DLLCALL getrec(const char *instr,int start,int length,char *outstr); /* Retrieve a record from a string */ DLLEXPORT void DLLCALL putrec(char *outstr,int start,int length,char *instr); /* Place a record into a string */ #ifdef __cplusplus diff --git a/src/sbbs3/date_str.c b/src/sbbs3/date_str.c index 310aff910194e4a4e1c8ce95c249824e6869505e..c2f2b4d38422e8678c18ce410ad51858017c8049 100644 --- a/src/sbbs3/date_str.c +++ b/src/sbbs3/date_str.c @@ -54,18 +54,18 @@ time32_t DLLCALL dstrtounix(scfg_t* cfg, const char *instr) if(!instr[0] || !strncmp(instr,"00/00/00",8)) return(0); - if(isdigit(instr[0]) && isdigit(instr[1]) - && isdigit(instr[3]) && isdigit(instr[4]) - && isdigit(instr[6]) && isdigit(instr[7])) + if(IS_DIGIT(instr[0]) && IS_DIGIT(instr[1]) + && IS_DIGIT(instr[3]) && IS_DIGIT(instr[4]) + && IS_DIGIT(instr[6]) && IS_DIGIT(instr[7])) p=instr; /* correctly formatted */ else { p=instr; /* incorrectly formatted */ - while(*p && isdigit(*p)) p++; + while(*p && IS_DIGIT(*p)) p++; if(*p==0) return(0); p++; day=p; - while(*p && isdigit(*p)) p++; + while(*p && IS_DIGIT(*p)) p++; if(*p==0) return(0); p++; diff --git a/src/sbbs3/download.cpp b/src/sbbs3/download.cpp index e953f8ebfb0c2e7a3cc36963628873b7e2ec651b..cabc7730049567086e01385d74fc21929518c4db 100644 --- a/src/sbbs3/download.cpp +++ b/src/sbbs3/download.cpp @@ -264,7 +264,8 @@ int sbbs_t::protocol(prot_t* prot, enum XFER_TYPE type /****************************************************************************/ void sbbs_t::autohangup() { - char a,c,k; + int a,c; + char k; char tmp[512]; if(online!=ON_REMOTE) diff --git a/src/sbbs3/exec.cpp b/src/sbbs3/exec.cpp index 770aabcc377cf1c0710fb81b071e96d7402a6c95..f864952c7177a32fe42d350b3c1402ee063478d6 100644 --- a/src/sbbs3/exec.cpp +++ b/src/sbbs3/exec.cpp @@ -696,13 +696,11 @@ long sbbs_t::js_execfile(const char *cmd, const char* startup_dir, JSObject* sco JS_ExecuteScript(js_cx, js_scope, js_script, &rval); sys_status &=~ SS_ABORT; - if(scope==NULL) { - JS_GetProperty(js_cx, js_scope, "exit_code", &rval); - if(rval!=JSVAL_VOID) - JS_ValueToInt32(js_cx,rval,&result); + JS_GetProperty(js_cx, js_scope, "exit_code", &rval); + if(rval!=JSVAL_VOID) + JS_ValueToInt32(js_cx,rval,&result); - js_EvalOnExit(js_cx, js_scope, &js_callback); - } + js_EvalOnExit(js_cx, js_scope, &js_callback); JS_ReportPendingException(js_cx); /* Added Dec-4-2005, rswindell */ @@ -1523,9 +1521,9 @@ int sbbs_t::exec(csi_t *csi) csi->logic=*csi->ip++; return(0); case CS_CMDKEY: - if( ((*csi->ip)==CS_DIGIT && isdigit(csi->cmd)) + if( ((*csi->ip)==CS_DIGIT && IS_DIGIT(csi->cmd)) || ((*csi->ip)==CS_EDIGIT && csi->cmd&0x80 - && isdigit(csi->cmd&0x7f))) { + && IS_DIGIT(csi->cmd&0x7f))) { csi->ip++; return(0); } @@ -1599,9 +1597,9 @@ int sbbs_t::exec(csi_t *csi) memmove(csi->str,csi->str+i,j+1); return(0); case CS_COMPARE_KEY: - if( ((*csi->ip)==CS_DIGIT && isdigit(csi->cmd)) + if( ((*csi->ip)==CS_DIGIT && IS_DIGIT(csi->cmd)) || ((*csi->ip)==CS_EDIGIT && csi->cmd&0x80 - && isdigit(csi->cmd&0x7f))) { + && IS_DIGIT(csi->cmd&0x7f))) { csi->ip++; csi->logic=LOGIC_TRUE; } @@ -1630,7 +1628,7 @@ int sbbs_t::exec(csi_t *csi) } switch(*(csi->ip++)) { case USER_STRING_ALIAS: - if(!isalpha(csi->str[0]) || trashcan(csi->str,"name")) + if(!IS_ALPHA(csi->str[0]) || trashcan(csi->str,"name")) break; i=matchuser(&cfg,csi->str,TRUE /*sysop_alias*/); if(i && i!=useron.number) diff --git a/src/sbbs3/execfile.cpp b/src/sbbs3/execfile.cpp index 061bd073f236442017f0b22499eabba0a32a22a6..a27f220ea66a2db584613c5ba9e1755d598fdab4 100644 --- a/src/sbbs3/execfile.cpp +++ b/src/sbbs3/execfile.cpp @@ -127,7 +127,7 @@ int sbbs_t::exec_file(csi_t *csi) if((ch&0xf)*10U<=usrdirs[curlib] && (ch&0xf) && usrlibs) { i=(ch&0xf)*10; ch=getkey(K_UPPER); - if(!isdigit(ch) && ch!=CR) { + if(!IS_DIGIT(ch) && ch!=CR) { ungetkey(ch); curdir[curlib]=(i/10)-1; return(0); @@ -142,7 +142,7 @@ int sbbs_t::exec_file(csi_t *csi) if(i*10<=usrdirs[curlib]) { /* 100+ dirs */ i*=10; ch=getkey(K_UPPER); - if(!isdigit(ch) && ch!=CR) { + if(!IS_DIGIT(ch) && ch!=CR) { ungetkey(ch); curdir[curlib]=(i/10)-1; return(0); @@ -179,7 +179,7 @@ int sbbs_t::exec_file(csi_t *csi) if((ch&0xf)*10U<=usrlibs && (ch&0xf)) { i=(ch&0xf)*10; ch=getkey(K_UPPER); - if(!isdigit(ch) && ch!=CR) { + if(!IS_DIGIT(ch) && ch!=CR) { ungetkey(ch); curlib=(i/10)-1; return(0); diff --git a/src/sbbs3/execmsg.cpp b/src/sbbs3/execmsg.cpp index e5952d8600d9210c825eeb721672a585d9278377..ce327dd3b912816637699c05ded2f851cf0c9f17 100644 --- a/src/sbbs3/execmsg.cpp +++ b/src/sbbs3/execmsg.cpp @@ -123,7 +123,7 @@ int sbbs_t::exec_msg(csi_t *csi) if(usrgrps && (ch&0xf)*10U<=usrsubs[curgrp] && (ch&0xf)) { i=(ch&0xf)*10; ch=getkey(K_UPPER); - if(!isdigit((uchar)ch) && ch!=CR) { + if(!IS_DIGIT(ch) && ch!=CR) { ungetkey(ch); cursub[curgrp]=(i/10)-1; return(0); @@ -138,7 +138,7 @@ int sbbs_t::exec_msg(csi_t *csi) if(i*10<=usrsubs[curgrp]) { /* 100+ subs */ i*=10; ch=getkey(K_UPPER); - if(!isdigit((uchar)ch) && ch!=CR) { + if(!IS_DIGIT(ch) && ch!=CR) { ungetkey(ch); cursub[curgrp]=(i/10)-1; return(0); @@ -175,7 +175,7 @@ int sbbs_t::exec_msg(csi_t *csi) if((ch&0xf)*10U<=usrgrps && (ch&0xf)) { i=(ch&0xf)*10; ch=getkey(K_UPPER); - if(!isdigit((uchar)ch) && ch!=CR) { + if(!IS_DIGIT(ch) && ch!=CR) { ungetkey(ch); curgrp=(i/10)-1; return(0); diff --git a/src/sbbs3/filedat.c b/src/sbbs3/filedat.c index 0940ec962e9ddcbb43916a066460e21458b7ee2b..a47c1cc5ac4f683e30346272043ebf93a0466c61 100644 --- a/src/sbbs3/filedat.c +++ b/src/sbbs3/filedat.c @@ -659,6 +659,7 @@ void DLLCALL putextdesc(scfg_t* cfg, uint dirnum, ulong datoffset, char *ext) char str[MAX_PATH+1],nulbuf[F_EXBSIZE]; int file; + strip_ansi(ext); strip_invalid_attr(ext); /* eliminate bogus ctrl-a codes */ memset(nulbuf,0,sizeof(nulbuf)); SAFEPRINTF2(str,"%s%s.exb",cfg->dir[dirnum]->data_dir,cfg->dir[dirnum]->code); diff --git a/src/sbbs3/ftpsrvr.c b/src/sbbs3/ftpsrvr.c index 9e9065a6787332b2e131db7e88798c6c8ffcbc9d..ba9d9b77362899efee793113af5a5716def3a117 100644 --- a/src/sbbs3/ftpsrvr.c +++ b/src/sbbs3/ftpsrvr.c @@ -1887,8 +1887,8 @@ static void receive_thread(void* arg) SAFECOPY(desc,ext); strip_exascii(desc, desc); /* strip extended ASCII chars */ prep_file_desc(desc, desc); /* strip control chars and dupe chars */ - for(i=0;desc[i];i++) /* find approprate first char */ - if(isalnum(desc[i])) + for(i=0;desc[i];i++) /* find appropriate first char */ + if(IS_ALPHANUMERIC(desc[i])) break; SAFECOPY(f.desc,desc+i); } @@ -5080,9 +5080,14 @@ static void ctrl_thread(void* arg) if(!fexistcase(qwkfile)) { lprintf(LOG_INFO,"%04d <%s> creating QWK packet...",sock,user.alias); sprintf(str,"%spack%04u.now",scfg.data_dir,user.number); - if(!ftouch(str)) - lprintf(LOG_ERR,"%04d <%s> !ERROR creating semaphore file: %s" - ,sock, user.alias, str); + if(!fmutex(str, startup->host_name, /* max_age: */60 * 60)) { + lprintf(LOG_WARNING, "%04d <%s> !ERROR %d creating mutex-semaphore file: %s" + ,sock, user.alias, errno, str); + sockprintf(sock,sess,"451 Packet creation already in progress (are you logged-in concurrently?)"); + filepos=0; + continue; + } + t=time(NULL); while(fexist(str) && !terminate_server) { if(!socket_check(sock,NULL,NULL,0)) diff --git a/src/sbbs3/getkey.cpp b/src/sbbs3/getkey.cpp index f4a0258ccadebaea4cfc092591c0efe10862aad4..b7c1a3e56ee3ef21adeb9b5c115cbbef29b773c0 100644 --- a/src/sbbs3/getkey.cpp +++ b/src/sbbs3/getkey.cpp @@ -91,9 +91,9 @@ char sbbs_t::getkey(long mode) return(0); now=time(NULL); if(ch) { - if(mode&K_NUMBER && isprint(ch) && !isdigit(ch)) + if(mode&K_NUMBER && IS_PRINTABLE(ch) && !IS_DIGIT(ch)) continue; - if(mode&K_ALPHA && isprint(ch) && !isalpha(ch)) + if(mode&K_ALPHA && IS_PRINTABLE(ch) && !IS_ALPHA(ch)) continue; if(mode&K_NOEXASC && ch&0x80) continue; @@ -365,7 +365,7 @@ long sbbs_t::getkeys(const char *keys, ulong max, long mode) lncntr=0; return(-1); } - if(ch && !n && ((keys == NULL && !isdigit(ch)) || (strchr(str,ch)))) { /* return character if in string */ + if(ch && !n && ((keys == NULL && !IS_DIGIT(ch)) || (strchr(str,ch)))) { /* return character if in string */ if(ch > ' ') { if(!(mode&K_NOECHO)) outchar(ch); @@ -411,7 +411,7 @@ long sbbs_t::getkeys(const char *keys, ulong max, long mode) i/=10; n--; } - else if(max && isdigit(ch) && (i*10)+(ch&0xf)<=max && (ch!='0' || n)) { + else if(max && IS_DIGIT(ch) && (i*10)+(ch&0xf)<=max && (ch!='0' || n)) { i*=10; n++; i+=ch&0xf; @@ -475,13 +475,14 @@ void sbbs_t::pause() /****************************************************************************/ void sbbs_t::ungetkey(char ch, bool insert) { + char dbg[2] = {}; #if 0 /* this way breaks ansi_getxy() */ RingBufWrite(&inbuf,(uchar*)&ch,sizeof(uchar)); #else if(keybuf_space()) { char* p = c_escape_char(ch); if(p == NULL) { - char dbg[2] = { ch, 0 }; + dbg[0] = ch; p = dbg; } lprintf(LOG_DEBUG, "%s key into keybuf: %02X (%s)", insert ? "insert" : "append", ch, p); diff --git a/src/sbbs3/getstr.cpp b/src/sbbs3/getstr.cpp index bee868bdac1ff61465c5f4be5a0456cd762bde52..92308498de39dea168df3553ccf20afb2142d456 100644 --- a/src/sbbs3/getstr.cpp +++ b/src/sbbs3/getstr.cpp @@ -99,7 +99,7 @@ size_t sbbs_t::getstr(char *strout, size_t maxlen, long mode, const str_list_t h if(mode&K_AUTODEL && str1[0] && !(mode&K_NOECHO)) { ch=getkey(mode|K_GETSTR); attr(atr); - if(isprint(ch) || ch==DEL) { + if(IS_PRINTABLE(ch) || ch==DEL) { for(i=0;i<l;i++) backspace(); i=l=0; @@ -689,7 +689,7 @@ long sbbs_t::getnum(ulong max, ulong dflt) i/=10; n--; } - else if(isdigit(ch) && (i*10UL)+(ch&0xf)<=max && (dflt || ch!='0' || n)) { + else if(IS_DIGIT(ch) && (i*10UL)+(ch&0xf)<=max && (dflt || ch!='0' || n)) { i*=10L; n++; i+=ch&0xf; diff --git a/src/sbbs3/inkey.cpp b/src/sbbs3/inkey.cpp index 082e6b19bf01889ca2a49e1d7715a0bd5b690995..089006e87ba26a6c535fde6a925e64a1398dfc19 100644 --- a/src/sbbs3/inkey.cpp +++ b/src/sbbs3/inkey.cpp @@ -74,7 +74,7 @@ int kbincom(sbbs_t* sbbs, unsigned long timeout) } if((ch&0xe0) == 0xc0) /* "Codes $60-$7F are, actually, copies of codes $C0-$DF" */ ch = 0x60 | (ch&0x1f); - if(isalpha((unsigned char)ch)) + if(IS_ALPHA(ch)) ch ^= 0x20; /* Swap upper/lower case */ } @@ -116,7 +116,7 @@ char sbbs_t::inkey(long mode, unsigned long timeout) this->timeout=time(NULL); /* Is this a control key */ - if(ch<' ') { + if(!(mode & K_CTRLKEYS) && ch < ' ') { if(cfg.ctrlkey_passthru&(1<<ch)) /* flagged as passthru? */ return(ch); /* do not handle here */ return(handle_ctrlkey(ch,mode)); @@ -416,7 +416,7 @@ char sbbs_t::handle_ctrlkey(char ch, long mode) return 0; } str[i++] = byte; - if(isalpha(byte)) + if(IS_ALPHA(byte)) break; } str[i] = 0; @@ -487,7 +487,7 @@ char sbbs_t::handle_ctrlkey(char ch, long mode) #endif return 0; } - if(ch!=';' && !isdigit((uchar)ch) && ch!='R') { /* other ANSI */ + if(ch!=';' && !IS_DIGIT(ch) && ch!='R') { /* other ANSI */ str[i]=0; switch(ch) { case 'A': @@ -533,15 +533,17 @@ char sbbs_t::handle_ctrlkey(char ch, long mode) return(ESC); } if(ch=='R') { /* cursor position report */ - if(mode&K_ANSI_CPR && i && !(useron.rows)) { /* auto-detect rows */ + if(mode&K_ANSI_CPR && i) { /* auto-detect rows */ int x,y; str[i]=0; if(sscanf(str,"%u;%u",&y,&x)==2) { lprintf(LOG_DEBUG,"received ANSI cursor position report: %ux%u" ,x, y); /* Sanity check the coordinates in the response: */ - if(x >= TERM_COLS_MIN && x <= TERM_COLS_MAX) cols=x; - if(y >= TERM_ROWS_MIN && y <= TERM_ROWS_MAX) rows=y; + if(useron.cols == TERM_COLS_AUTO && x >= TERM_COLS_MIN && x <= TERM_COLS_MAX) cols=x; + if(useron.rows == TERM_ROWS_AUTO && y >= TERM_ROWS_MIN && y <= TERM_ROWS_MAX) rows=y; + if(useron.cols == TERM_COLS_AUTO || useron.rows == TERM_ROWS_AUTO) + update_nodeterm(); } } return(0); diff --git a/src/sbbs3/js_bbs.cpp b/src/sbbs3/js_bbs.cpp index 0e1121e74bd12c466f4ce5a0e2f5088953c1d762..e21ddaf9b2da36364a9da629bae103f4bdc0f252 100644 --- a/src/sbbs3/js_bbs.cpp +++ b/src/sbbs3/js_bbs.cpp @@ -1662,7 +1662,7 @@ js_atcode(JSContext *cx, uintN argc, jsval *arglist) else if((p=strstr(instr,"-R"))!=NULL) padded_right=true; if(p!=NULL) { - if(*(p+2) && isdigit(*(p+2))) + if(*(p+2) && IS_DIGIT(*(p+2))) disp_len=atoi(p+2); *p=0; } diff --git a/src/sbbs3/js_console.cpp b/src/sbbs3/js_console.cpp index efc8894b05ec01489b3109533b3326cccbdcd1a0..972135757a7b430b09e76204a1355fa5e890ab64 100644 --- a/src/sbbs3/js_console.cpp +++ b/src/sbbs3/js_console.cpp @@ -2099,6 +2099,22 @@ js_term_supports(JSContext *cx, uintN argc, jsval *arglist) return(JS_TRUE); } +static JSBool +js_term_updated(JSContext *cx, uintN argc, jsval *arglist) +{ + sbbs_t* sbbs; + jsrefcount rc; + + if((sbbs=(sbbs_t*)js_GetClassPrivate(cx, JS_THIS_OBJECT(cx, arglist), &js_console_class))==NULL) + return JS_FALSE; + + rc=JS_SUSPENDREQUEST(cx); + JS_SET_RVAL(cx, arglist, BOOLEAN_TO_JSVAL(sbbs->update_nodeterm())); + JS_RESUMEREQUEST(cx, rc); + + return JS_TRUE; +} + static jsSyncMethodSpec js_console_functions[] = { {"inkey", js_inkey, 0, JSTYPE_STRING, JSDOCSTR("[mode=<tt>K_NONE</tt>] [,timeout=<tt>0</tt>]") ,JSDOCSTR("get a single key with optional <i>timeout</i> in milliseconds (defaults to 0, for no wait).<br>" @@ -2314,6 +2330,10 @@ static jsSyncMethodSpec js_console_functions[] = { "<i>terminal_flags</i> (numeric bit-field) if no <i>terminal_flags</i> were specified") ,314 }, + {"term_updated", js_term_updated, 1, JSTYPE_BOOLEAN, JSDOCSTR("") + ,JSDOCSTR("update the node's <tt>terminal.ini</tt> file to match the current terminal settings") + ,31802 + }, {"backspace", js_backspace, 0, JSTYPE_VOID, JSDOCSTR("[count=<tt>1</tt>]") ,JSDOCSTR("send a destructive backspace sequence") ,315 diff --git a/src/sbbs3/js_file.c b/src/sbbs3/js_file.c index b6d6ab25947f464b2b93f92c4ed7866568a648f2..646d48ef058a814f88f74bf196ebed9e8199777d 100644 --- a/src/sbbs3/js_file.c +++ b/src/sbbs3/js_file.c @@ -714,7 +714,7 @@ static jsval get_value(JSContext *cx, char* value) for(p=value;*p;p++) { if(*p=='.' && !f) f=TRUE; - else if(!isdigit((uchar)*p)) + else if(!IS_DIGIT(*p)) break; } if(*p==0) { diff --git a/src/sbbs3/js_global.c b/src/sbbs3/js_global.c index 2ee6631ea13c61c6dd3576b90a85baacf7256d45..9ee3956cce5062efc38592d7cb2b0e916cc9974e 100644 --- a/src/sbbs3/js_global.c +++ b/src/sbbs3/js_global.c @@ -1115,6 +1115,37 @@ js_strip_ctrl(JSContext *cx, uintN argc, jsval *arglist) return(JS_TRUE); } +static JSBool +js_strip_ansi(JSContext *cx, uintN argc, jsval *arglist) +{ + jsval *argv=JS_ARGV(cx, arglist); + char* buf = NULL; + JSString* js_str; + jsrefcount rc; + + JS_SET_RVAL(cx, arglist, JSVAL_VOID); + + if(argc==0 || JSVAL_IS_VOID(argv[0])) + return JS_TRUE; + + JSVALUE_TO_MSTRING(cx, argv[0], buf, NULL) + HANDLE_PENDING(cx, buf); + if(buf==NULL) + return JS_TRUE; + + rc=JS_SUSPENDREQUEST(cx); + strip_ansi(buf); + JS_RESUMEREQUEST(cx, rc); + + js_str = JS_NewStringCopyZ(cx, buf); + free(buf); + if(js_str==NULL) + return JS_FALSE; + + JS_SET_RVAL(cx, arglist, STRING_TO_JSVAL(js_str)); + return JS_TRUE; +} + static JSBool js_strip_exascii(JSContext *cx, uintN argc, jsval *arglist) { @@ -1855,7 +1886,7 @@ js_html_encode(JSContext *cx, uintN argc, jsval *arglist) ansi_seq[MAX_ANSI_SEQ]=0; for(lastparam=ansi_seq;*lastparam;lastparam++) { - if(isalpha(*lastparam)) + if(IS_ALPHA(*lastparam)) { *(++lastparam)=0; break; @@ -1865,16 +1896,16 @@ js_html_encode(JSContext *cx, uintN argc, jsval *arglist) param=ansi_seq; if(*param=='?') /* This is to fix ESC[?7 whatever that is */ param++; - if(isdigit(*param)) + if(IS_DIGIT(*param)) ansi_param[k++]=atoi(ansi_seq); - while(isspace(*param) || isdigit(*param)) + while(IS_WHITESPACE(*param) || IS_DIGIT(*param)) param++; lastparam=param; while((param=strchr(param,';'))!=NULL) { param++; ansi_param[k++]=atoi(param); - while(isspace(*param) || isdigit(*param)) + while(IS_WHITESPACE(*param) || IS_DIGIT(*param)) param++; lastparam=param; } @@ -4574,6 +4605,10 @@ static jsSyncMethodSpec js_global_functions[] = { ,JSDOCSTR("strip control characters from string, returns modified string") ,310 }, + {"strip_ansi", js_strip_ansi, 1, JSTYPE_STRING, JSDOCSTR("text") + ,JSDOCSTR("strip all ANSI terminal control sequences from string, returns modified string") + ,31802 + }, {"strip_exascii", js_strip_exascii, 1, JSTYPE_STRING, JSDOCSTR("text") ,JSDOCSTR("strip all extended-ASCII characters from string, returns modified string") ,310 diff --git a/src/sbbs3/js_server.c b/src/sbbs3/js_server.c index 55ddba7d5f023238b6d2ceffbac0155a64a79f9d..de81d138afac15b16f6b857780a24185077b7a86 100644 --- a/src/sbbs3/js_server.c +++ b/src/sbbs3/js_server.c @@ -150,7 +150,7 @@ static void remove_port_part(char *host) { char *p=strchr(host, 0)-1; - if (isdigit(*p)) { + if (IS_DIGIT(*p)) { /* * If the first and last : are not the same, and it doesn't * start with '[', there's no port part. @@ -164,7 +164,7 @@ static void remove_port_part(char *host) *p = 0; break; } - if (!isdigit(*p)) + if (!IS_DIGIT(*p)) break; } } diff --git a/src/sbbs3/js_socket.c b/src/sbbs3/js_socket.c index a987cf41f1b7a94efe419ca28c1085b3c95fff7d..e47b0335b5b491a0f263205d9e4d340122ab49bd 100644 --- a/src/sbbs3/js_socket.c +++ b/src/sbbs3/js_socket.c @@ -458,7 +458,7 @@ static ushort js_port(JSContext* cx, jsval val, int type) if(JSVAL_IS_STRING(val)) { str = JS_ValueToString(cx,val); JSSTRING_TO_ASTRING(cx, str, cp, 16, NULL); - if(isdigit(*cp)) + if(IS_DIGIT(*cp)) return((ushort)strtol(cp,NULL,0)); rc=JS_SUSPENDREQUEST(cx); serv = getservbyname(cp,type==SOCK_STREAM ? "tcp":"udp"); diff --git a/src/sbbs3/js_user.c b/src/sbbs3/js_user.c index 0eca3f60a95812c2f825ad30ff8c2f5688ff5269..f961a2b44e0ca449bed7d115ae7d19c3cff1be0f 100644 --- a/src/sbbs3/js_user.c +++ b/src/sbbs3/js_user.c @@ -102,7 +102,8 @@ enum { ,USER_PROP_FLAGS4 ,USER_PROP_EXEMPT ,USER_PROP_REST - ,USER_PROP_ROWS + ,USER_PROP_ROWS + ,USER_PROP_COLS ,USER_PROP_SEX ,USER_PROP_MISC ,USER_PROP_LEECH @@ -314,6 +315,9 @@ static JSBool js_user_get(JSContext *cx, JSObject *obj, jsid id, jsval *vp) case USER_PROP_ROWS: val=p->user->rows; break; + case USER_PROP_COLS: + val=p->user->cols; + break; case USER_PROP_SEX: sprintf(tmp,"%c",p->user->sex); s=tmp; @@ -538,6 +542,10 @@ static JSBool js_user_set(JSContext *cx, JSObject *obj, jsid id, JSBool strict, p->user->rows=atoi(str); putuserrec(scfg,p->user->number,U_ROWS,0,str); /* base 10 */ break; + case USER_PROP_COLS: + p->user->cols=atoi(str); + putuserrec(scfg,p->user->number,U_COLS,0,str); /* base 10 */ + break; case USER_PROP_SEX: p->user->sex=toupper(str[0]); putuserrec(scfg,p->user->number,U_SEX,0,strupr(str)); /* single char */ @@ -785,6 +793,7 @@ static jsSyncPropertySpec js_user_properties[] = { { "connection" ,USER_PROP_MODEM ,USER_PROP_FLAGS, 310}, { "modem" ,USER_PROP_MODEM ,USER_PROP_FLAGS, 310}, { "screen_rows" ,USER_PROP_ROWS ,USER_PROP_FLAGS, 310}, + { "screen_columns" ,USER_PROP_COLS ,USER_PROP_FLAGS, 31802}, { "gender" ,USER_PROP_SEX ,USER_PROP_FLAGS, 310}, { "cursub" ,USER_PROP_CURSUB ,USER_PROP_FLAGS, 310}, { "curdir" ,USER_PROP_CURDIR ,USER_PROP_FLAGS, 310}, @@ -829,8 +838,9 @@ static char* user_prop_desc[] = { ,"calculated age in years - <small>READ ONLY</small>" ,"connection type (protocol)" ,"AKA connection" - ,"terminal rows (lines)" - ,"gender type (e.g. M or F)" + ,"terminal rows (0 = auto-detect)" + ,"terminal columns (0 = auto-detect)" + ,"gender type (e.g. M or F or any single-character)" ,"current/last message sub-board (internal code)" ,"current/last file directory (internal code)" ,"current/last external program (internal code) run" diff --git a/src/sbbs3/jsexec.c b/src/sbbs3/jsexec.c index 636887a47f9b5caf65ef0b31246eca86e18093dc..cfe931314da8c44d638b72f64231739e3875c4e9 100644 --- a/src/sbbs3/jsexec.c +++ b/src/sbbs3/jsexec.c @@ -1111,7 +1111,7 @@ int parseLogLevel(const char* p) str_list_t logLevelStringList=iniLogLevelStringList(); int i; - if(isdigit(*p)) + if(IS_DIGIT(*p)) return strtol(p,NULL,0); /* Exact match */ diff --git a/src/sbbs3/load_cfg.c b/src/sbbs3/load_cfg.c index ee0ecb55f86c5b35c9528dff1c344e4e17a96b55..1c6ced9ba6200d84b9f8d6cd373c89dd6e6a8cc1 100644 --- a/src/sbbs3/load_cfg.c +++ b/src/sbbs3/load_cfg.c @@ -474,7 +474,7 @@ char* prep_code(char *str, const char* prefix) strcpy(str,tmp); if(j>LEN_CODE) { /* Extra chars? Strip symbolic chars */ for(i=j=0;str[i];i++) - if(isalnum(str[i])) + if(IS_ALPHANUMERIC(str[i])) tmp[j++]=str[i]; tmp[j]=0; strcpy(str,tmp); diff --git a/src/sbbs3/login.cpp b/src/sbbs3/login.cpp index d5ee19f77ef314db9d4c135d89b83b5a4868db17..7432b23b30cd2b59b555f41f62c5108429263e75 100644 --- a/src/sbbs3/login.cpp +++ b/src/sbbs3/login.cpp @@ -61,7 +61,7 @@ int sbbs_t::login(char *username, char *pw_prompt, const char* user_pw, const ch useron.number=0; username = parse_login(username); - if(!(cfg.node_misc&NM_NO_NUM) && isdigit((uchar)username[0])) { + if(!(cfg.node_misc&NM_NO_NUM) && IS_DIGIT(username[0])) { useron.number=atoi(username); getuserdat(&cfg,&useron); if(useron.number && useron.misc&(DELETED|INACTIVE)) @@ -71,7 +71,7 @@ int sbbs_t::login(char *username, char *pw_prompt, const char* user_pw, const ch if(!useron.number) { useron.number=matchuser(&cfg,username,FALSE); if(!useron.number && (uchar)username[0]<0x7f && username[1] - && isalpha(username[0]) && strchr(username,' ') && cfg.node_misc&NM_LOGON_R) + && IS_ALPHA(username[0]) && strchr(username,' ') && cfg.node_misc&NM_LOGON_R) useron.number=userdatdupe(0,U_NAME,LEN_NAME,username); if(useron.number) { getuserdat(&cfg,&useron); diff --git a/src/sbbs3/logon.cpp b/src/sbbs3/logon.cpp index 55754b7191a0aefa7159db5b1745e1f24822fc68..31b23906360f55c4ab4c406121f5203d078e33b2 100644 --- a/src/sbbs3/logon.cpp +++ b/src/sbbs3/logon.cpp @@ -79,7 +79,8 @@ bool sbbs_t::logon() if(useron.rest&FLAG('G')) { /* Guest account */ useron.misc=(cfg.new_misc&(~ASK_NSCAN)); - useron.rows=0; + useron.rows = TERM_ROWS_AUTO; + useron.cols = TERM_COLS_AUTO; useron.misc &= ~TERM_FLAGS; useron.misc|=autoterm; if(!(useron.misc&(ANSI|PETSCII)) && text[AnsiTerminalQ][0] && yesno(text[AnsiTerminalQ])) @@ -215,8 +216,11 @@ bool sbbs_t::logon() } bputs(text[LoggingOn]); - if(useron.rows) - rows=useron.rows; + if(useron.rows != TERM_ROWS_AUTO) + rows = useron.rows; + if(useron.cols != TERM_COLS_AUTO) + cols = useron.cols; + update_nodeterm(); if(tm.tm_mon + 1 == getbirthmonth(&cfg, useron.birth) && tm.tm_mday == getbirthday(&cfg, useron.birth) && !(useron.rest&FLAG('Q'))) { if(text[HappyBirthday][0]) { @@ -240,7 +244,7 @@ bool sbbs_t::logon() c=0; while(c < RAND_PASS_LEN) { /* Create random password */ str[c]=sbbs_random(43)+'0'; - if(isalnum(str[c])) + if(IS_ALPHANUMERIC(str[c])) c++; } str[c]=0; diff --git a/src/sbbs3/mailsrvr.c b/src/sbbs3/mailsrvr.c index 24fd1bd8bd2ad7195c7e6e4c28380c938c56a5c0..c4e01ca6de136938b8112848c77c94129821a467 100644 --- a/src/sbbs3/mailsrvr.c +++ b/src/sbbs3/mailsrvr.c @@ -1,6 +1,6 @@ /* Synchronet Mail (SMTP/POP3) server and sendmail threads */ -/* $Id: mailsrvr.c,v 1.734 2020/08/08 19:04:06 rswindell Exp $ */ +/* $Id: mailsrvr.c,v 1.735 2020/10/22 19:04:06 rswindell Exp $ */ // vi: tabstop=4 /**************************************************************************** @@ -40,7 +40,6 @@ #include <stdlib.h> /* ltoa in GNU C lib */ #include <stdarg.h> /* va_list */ #include <string.h> /* strrchr */ -#include <ctype.h> /* isdigit */ #include <fcntl.h> /* Open flags */ #include <errno.h> /* errno */ @@ -71,11 +70,11 @@ static const char* server_name="Synchronet Mail Server"; int dns_getmx(char* name, char* mx, char* mx2 ,DWORD intf, DWORD ip_addr, BOOL use_tcp, int timeout); -#define pop_err "-ERR" +#define pop_error "-ERR System Error: %s, try again later" +#define pop_auth_error "-ERR Authentication failure" #define ok_rsp "250 OK" #define auth_ok "235 User Authenticated" -#define sys_error "421 System error" -#define sys_unavail "421 System unavailable, try again later" +#define smtp_error "421 System Error: %s, try again later" #define insuf_stor "452 Insufficient system storage" #define badarg_rsp "501 Bad argument" #define badseq_rsp "503 Bad sequence of commands" @@ -84,6 +83,7 @@ int dns_getmx(char* name, char* mx, char* mx2 #define TIMEOUT_THREAD_WAIT 60 /* Seconds */ #define DNSBL_THROTTLE_VALUE 1000 /* Milliseconds */ +#define SMTP_MAX_BAD_CMDS 9 #define STATUS_WFC "Listening" @@ -105,11 +105,22 @@ static str_list_t recycle_semfiles; static str_list_t shutdown_semfiles; static int mailproc_count; static js_server_props_t js_server_props; +static link_list_t current_logins; +static link_list_t current_connections; +static bool savemsg_mutex_created = false; +static pthread_mutex_t savemsg_mutex; + +static const char* servprot_smtp = "SMTP"; +static const char* servprot_submission = "SMTP"; +static const char* servprot_submissions = "SMTPS"; +static const char* servprot_pop3 = "POP3"; +static const char* servprot_pop3s = "POP3S"; struct { volatile ulong sockets; volatile ulong errors; volatile ulong crit_errors; + volatile ulong connections_exceeded; volatile ulong connections_ignored; volatile ulong connections_refused; volatile ulong connections_served; @@ -207,7 +218,7 @@ static int lprintf(int level, const char *fmt, ...) return(0); #endif - return(startup->lputs(startup->cbdata,level,sbuf)); + return(startup->lputs(startup->cbdata, level, condense_whitespace(sbuf))); } #ifdef _WINSOCKAPI_ @@ -250,12 +261,15 @@ static void update_clients(void) static void client_on(SOCKET sock, client_t* client, BOOL update) { + if(!update) + listAddNodeData(¤t_connections, client->addr, strlen(client->addr)+1, sock, LAST_NODE); if(startup!=NULL && startup->client_on!=NULL) startup->client_on(startup->cbdata,TRUE,sock,client,update); } static void client_off(SOCKET sock) { + listRemoveTaggedNode(¤t_connections, sock, /* free_data */TRUE); if(startup!=NULL && startup->client_on!=NULL) startup->client_on(startup->cbdata,FALSE,sock,NULL,FALSE); } @@ -630,6 +644,23 @@ void originator_info(SOCKET socket, const char* protocol, CRYPT_SESSION sess, sm ); } +char* angle_bracket(char* buf, size_t max, const char* addr) +{ + if(*addr == '<') + safe_snprintf(buf, max, "%s", addr); + else + safe_snprintf(buf, max, "<%s>", addr); + return buf; +} + +int compare_addrs(const char* addr1, const char* addr2) +{ + char tmp1[256]; + char tmp2[256]; + + return strcmp(angle_bracket(tmp1, sizeof(tmp1), addr1), angle_bracket(tmp2, sizeof(tmp2), addr2)); +} + /* RFC822: The maximum total length of a text line including the <CRLF> is 1000 characters (but not counting the leading dot duplicated for transparency). @@ -645,6 +676,7 @@ static ulong sockmimetext(SOCKET socket, const char* prot, CRYPT_SESSION sess, s char fromaddr[256]=""; char fromhost[256]; char msgid[256]; + char tmp[256]; char date[64]; char* p; char* np; @@ -692,10 +724,7 @@ static ulong sockmimetext(SOCKET socket, const char* prot, CRYPT_SESSION sess, s SAFECOPY(fromaddr,(char*)msg->from_net.addr); else usermailaddr(&scfg,fromaddr,msg->from); - if(fromaddr[0]=='<') - s=sockprintf(socket,prot,sess,"From: %s %s",fromname,fromaddr); - else - s=sockprintf(socket,prot,sess,"From: %s <%s>",fromname,fromaddr); + s = sockprintf(socket,prot,sess,"From: %s %s", fromname, angle_bracket(tmp, sizeof(tmp), fromaddr)); } if(!s) return(0); @@ -916,7 +945,7 @@ static u_long resolve_ip(const char *inaddr) return((u_long)INADDR_NONE); for(p=addr;*p;p++) - if(*p!='.' && !isdigit((uchar)*p)) + if(*p!='.' && !IS_DIGIT(*p)) break; if(!(*p)) return(inet_addr(addr)); @@ -969,6 +998,7 @@ static void pop3_thread(void* arg) char buf[512]; char host_name[128]; char host_ip[INET6_ADDRSTRLEN]; + char server_ip[INET6_ADDRSTRLEN]; char username[128]; char password[128]; char challenge[256]; @@ -1001,6 +1031,7 @@ static void pop3_thread(void* arg) char *estr; int level; int stat; + union xp_sockaddr server_addr; SetThreadName("sbbs/pop3"); thread_up(TRUE /* setuid */); @@ -1019,22 +1050,32 @@ static void pop3_thread(void* arg) PlaySound(startup->pop3_sound, NULL, SND_ASYNC|SND_FILENAME); #endif + socklen_t addr_len = sizeof(server_addr); + if((i=getsockname(socket, &server_addr.addr, &addr_len))!=0) { + lprintf(LOG_CRIT,"%04d %s !ERROR %d (%d) getting address/port" + ,socket, client.protocol, i, ERROR_VALUE); + mail_close_socket(&socket, &session); + thread_down(); + return; + } + inet_addrtop(&pop3.client_addr, host_ip, sizeof(host_ip)); + inet_addrtop(&server_addr, server_ip, sizeof(server_ip)); if(startup->options&MAIL_OPT_DEBUG_POP3) - lprintf(LOG_INFO,"%04d %s connection accepted from: %s port %u" - ,socket, client.protocol, host_ip, inet_addrport(&pop3.client_addr)); + lprintf(LOG_INFO,"%04d %s [%s] connection accepted on %s port %u from port %u" + ,socket, client.protocol, host_ip, server_ip, inet_addrport(&server_addr), inet_addrport(&pop3.client_addr)); SAFECOPY(host_name, STR_NO_HOSTNAME); if(!(startup->options&MAIL_OPT_NO_HOST_LOOKUP)) { getnameinfo(&pop3.client_addr.addr, pop3.client_addr_len, host_name, sizeof(host_name), NULL, 0, NI_NAMEREQD); if(startup->options&MAIL_OPT_DEBUG_POP3) - lprintf(LOG_INFO,"%04d %s Hostname: %s [%s]", socket, client.protocol, host_name, host_ip); + lprintf(LOG_INFO,"%04d %s [%s] Hostname: %s", socket, client.protocol, host_ip, host_name); } if (pop3.tls_port) { if (get_ssl_cert(&scfg, &estr, &level) == -1) { if (estr) { - lprintf(level, "%04d %s !Failure getting certificate: %s", socket, client.protocol, estr); + lprintf(level, "%04d %s [%s] !Failure getting certificate: %s", socket, client.protocol, host_ip, estr); free_crypt_attrstr(estr); } mail_close_socket(&socket, &session); @@ -1094,11 +1135,11 @@ static void pop3_thread(void* arg) if(banned || trashcan(&scfg,host_ip,"ip")) { if(banned) { char ban_duration[128]; - lprintf(LOG_NOTICE, "%04d %s !TEMPORARY BAN of %s (%lu login attempts, last: %s) - remaining: %s" + lprintf(LOG_NOTICE, "%04d %s [%s] !TEMPORARY BAN (%lu login attempts, last: %s) - remaining: %s" ,socket, client.protocol, host_ip, attempted.count-attempted.dupes, attempted.user, seconds_to_str(banned, ban_duration)); } else - lprintf(LOG_NOTICE,"%04d %s !CLIENT IP ADDRESS BLOCKED: %s",socket, client.protocol, host_ip); + lprintf(LOG_NOTICE,"%04d %s [%s] !CLIENT IP ADDRESS BLOCKED",socket, client.protocol, host_ip); sockprintf(socket,client.protocol,session,"-ERR Access denied."); mail_close_socket(&socket, &session); thread_down(); @@ -1106,8 +1147,8 @@ static void pop3_thread(void* arg) } if(trashcan(&scfg,host_name,"host")) { - lprintf(LOG_NOTICE,"%04d %s !CLIENT HOSTNAME BLOCKED: %s" - ,socket, client.protocol, host_name); + lprintf(LOG_NOTICE,"%04d %s [%s] !CLIENT HOSTNAME BLOCKED: %s" + ,socket, client.protocol, host_ip, host_name); sockprintf(socket,client.protocol,session,"-ERR Access denied."); mail_close_socket(&socket, &session); thread_down(); @@ -1132,7 +1173,7 @@ static void pop3_thread(void* arg) if(startup->login_attempt.throttle && (login_attempts=loginAttempts(startup->login_attempt_list, &pop3.client_addr)) > 1) { - lprintf(LOG_DEBUG,"%04d %s Throttling suspicious connection from: %s (%lu login attempts)" + lprintf(LOG_DEBUG,"%04d %s [%s] Throttling suspicious connection (%lu login attempts)" ,socket, client.protocol, host_ip, login_attempts); mswait(login_attempts*startup->login_attempt.throttle); } @@ -1172,7 +1213,7 @@ static void pop3_thread(void* arg) else if (!stricmp(buf, "STLS")) { if (get_ssl_cert(&scfg, &estr, &level) == -1) { if (estr) { - lprintf(level, "%04d %s !TLS Failure getting certificate: %s", socket, client.protocol, estr); + lprintf(level, "%04d %s [%s] !TLS Failure getting certificate: %s", socket, client.protocol, host_ip, estr); free_crypt_attrstr(estr); } sockprintf(socket,client.protocol,session,"-ERR STLS command not supported"); @@ -1261,19 +1302,18 @@ static void pop3_thread(void* arg) else lprintf(LOG_NOTICE,"%04d %s [%s] !UNKNOWN USER: '%s'" ,socket, client.protocol, host_ip, username); - badlogin(socket, session, client.protocol, pop_err, username, password, host_name, &pop3.client_addr); + badlogin(socket, session, client.protocol, pop_auth_error, username, password, host_name, &pop3.client_addr); break; } if((i=getuserdat(&scfg, &user))!=0) { lprintf(LOG_ERR,"%04d %s [%s] !ERROR %d getting data on user (%s)" ,socket, client.protocol, host_ip, i, username); - badlogin(socket, session, client.protocol, pop_err, NULL, NULL, NULL, NULL); break; } if(user.misc&(DELETED|INACTIVE)) { lprintf(LOG_NOTICE,"%04d %s [%s] !DELETED or INACTIVE user #%u (%s)" ,socket, client.protocol, host_ip, user.number, username); - badlogin(socket, session, client.protocol, pop_err, NULL, NULL, NULL, NULL); + badlogin(socket, session, client.protocol, pop_auth_error, username, password, NULL, NULL); break; } if(apop) { @@ -1289,7 +1329,7 @@ static void pop3_thread(void* arg) lprintf(LOG_DEBUG,"%04d !POP3 calc digest: %s",socket,str); lprintf(LOG_DEBUG,"%04d !POP3 resp digest: %s",socket,response); #endif - badlogin(socket, session, client.protocol, pop_err, username, response, host_name, &pop3.client_addr); + badlogin(socket, session, client.protocol, pop_auth_error, username, response, host_name, &pop3.client_addr); break; } } else if(stricmp(password,user.pass)) { @@ -1299,12 +1339,14 @@ static void pop3_thread(void* arg) else lprintf(LOG_NOTICE,"%04d %s [%s] !FAILED Password attempt for user %s" ,socket, client.protocol, host_ip, username); - badlogin(socket, session, client.protocol, pop_err, username, password, host_name, &pop3.client_addr); + badlogin(socket, session, client.protocol, pop_auth_error, username, password, host_name, &pop3.client_addr); break; } - if(user.pass[0]) + if(user.pass[0]) { loginSuccess(startup->login_attempt_list, &pop3.client_addr); + listAddNodeData(¤t_logins, client.addr, strlen(client.addr) + 1, socket, LAST_NODE); + } putuserrec(&scfg,user.number,U_COMP,LEN_COMP,host_name); putuserrec(&scfg,user.number,U_IPADDR,LEN_IPADDR,host_ip); @@ -1315,8 +1357,8 @@ static void pop3_thread(void* arg) client_on(socket,&client,TRUE /* update */); activity=FALSE; - if(startup->options&MAIL_OPT_DEBUG_POP3) - lprintf(LOG_INFO,"%04d %s [%s] %s logged in %s", socket, client.protocol, host_ip, user.alias, apop ? "via APOP":""); + if(startup->options&MAIL_OPT_DEBUG_POP3) + lprintf(LOG_INFO,"%04d %s [%s] %s logged-in %s", socket, client.protocol, host_ip, user.alias, apop ? "via APOP":""); SAFEPRINTF2(str,"%s: %s", client.protocol, user.alias); status(str); @@ -1378,6 +1420,12 @@ static void pop3_thread(void* arg) sockprintf(socket,client.protocol,session,"+OK"); continue; } + if(!stricmp(buf, "CAPA")) { + // Capabilities + sockprintf(socket,client.protocol,session, "+OK Capability list follows"); + sockprintf(socket,client.protocol,session, "TOP\r\nUSER\r\nPIPELINING\r\nUIDL\r\nIMPLEMENTATION Synchronet POP3 Server %s-%s\r\n.", revision, PLATFORM_DESC); + continue; + } if(!stricmp(buf, "QUIT")) { sockprintf(socket,client.protocol,session,"+OK"); break; @@ -1429,7 +1477,7 @@ static void pop3_thread(void* arg) if(!strnicmp(buf, "LIST",4) || !strnicmp(buf,"UIDL",4)) { p=buf+4; SKIP_WHITESPACE(p); - if(isdigit((uchar)*p)) { + if(IS_DIGIT(*p)) { msgnum=strtoul(p, NULL, 10); if(msgnum<1 || msgnum>msgs) { lprintf(LOG_NOTICE,"%04d %s <%s> !INVALID message #%" PRIu32 @@ -1686,11 +1734,11 @@ static void pop3_thread(void* arg) if(activity) { if(user.number) - lprintf(LOG_INFO,"%04d %s <%s> logged out from port %u on %s [%s]" + lprintf(LOG_INFO,"%04d %s <%s> logged-out from port %u on %s [%s]" ,socket, client.protocol, user.alias, inet_addrport(&pop3.client_addr), host_name, host_ip); else - lprintf(LOG_INFO,"%04d %s client disconnected from port %u on %s [%s]" - ,socket, client.protocol, inet_addrport(&pop3.client_addr), host_name, host_ip); + lprintf(LOG_INFO,"%04d %s [%s] client disconnected from port %u on %s" + ,socket, client.protocol, host_ip, inet_addrport(&pop3.client_addr), host_name); } status(STATUS_WFC); @@ -1702,6 +1750,7 @@ static void pop3_thread(void* arg) smb_freemsgmem(&msg); smb_close(&smb); + listRemoveTaggedNode(¤t_logins, socket, /* free_data */TRUE); protected_uint32_adjust(&active_clients, -1); update_clients(); client_off(socket); @@ -1709,8 +1758,8 @@ static void pop3_thread(void* arg) { int32_t remain = thread_down(); if(startup->options&MAIL_OPT_DEBUG_POP3) - lprintf(LOG_DEBUG,"%04d %s session thread terminated (%u threads remain, %lu clients served)" - ,socket, client.protocol, remain, ++stats.pop3_served); + lprintf(LOG_DEBUG,"%04d %s [%s] session thread terminated (%u threads remain, %lu clients served)" + ,socket, client.protocol, host_ip, remain, ++stats.pop3_served); } /* Must be last */ @@ -1856,8 +1905,8 @@ static BOOL chk_email_addr(SOCKET socket, const char* prot, char* p, char* host_ if(!trashcan(&scfg,addr,"email")) return(TRUE); - lprintf(LOG_NOTICE,"%04d %s !BLOCKED %s e-mail address: %s" - ,socket, prot, source, addr); + lprintf(LOG_NOTICE,"%04d %s [%s] !BLOCKED %s e-mail address: %s" + ,socket, prot, host_ip, source, addr); SAFEPRINTF2(tmp,"Blocked %s e-mail address: %s", source, addr); spamlog(&scfg, (char*)prot, "REFUSED", tmp, host_name, host_ip, to, from); @@ -1883,30 +1932,24 @@ static BOOL email_addr_is_exempt(const char* addr) } static void exempt_email_addr(const char* comment - ,const char* fromname, const char* fromext, const char* fromaddr + ,const char* sender_info ,const char* toaddr) { char fname[MAX_PATH+1]; - char to[128]; + char to[256]; char tmp[128]; FILE* fp; - if(*toaddr == '<') - SAFECOPY(to, toaddr); - else - SAFEPRINTF(to,"<%s>",toaddr); + angle_bracket(to, sizeof(to), toaddr); if(!email_addr_is_exempt(to)) { SAFEPRINTF(fname,"%sdnsbl_exempt.cfg",scfg.ctrl_dir); if((fp=fopen(fname,"a"))==NULL) lprintf(LOG_ERR,"0000 !Error opening file: %s", fname); else { lprintf(LOG_INFO,"0000 %s: %s", comment, to); - fprintf(fp,"\n;%s from \"%s\"" - ,comment, fromname); - if(fromext!=NULL) - fprintf(fp,"%s",fromext); - fprintf(fp," %s on %s\n%s\n" - ,fromaddr, timestr(&scfg,time32(NULL),tmp), to); + fprintf(fp,"\n;%s from %s on %s\n%s\n" + ,comment, sender_info + ,timestr(&scfg,time32(NULL),tmp), to); fclose(fp); } } @@ -2384,7 +2427,7 @@ char* mimehdr_q_decode(char* buf) for(;*p != 0; p++) { if(*p == '=') { p++; - if(isxdigit(*p) && isxdigit(*(p + 1))) { + if(IS_HEXDIGIT(*p) && IS_HEXDIGIT(*(p + 1))) { uchar ch = HEX_CHAR_TO_INT(*p) << 4; p++; ch |= HEX_CHAR_TO_INT(*p); @@ -2611,7 +2654,7 @@ static int chk_received_hdr(SOCKET socket,const char* prot,const char *buf,IN_AD if(*p==0) break; p2=host_name; - for(;*p && !isspace((unsigned char)*p) && p2<host_name+126;p++) { + for(;*p && !IS_WHITESPACE(*p) && p2<host_name+126;p++) { *p2++=*p; } *p2=0; @@ -2645,8 +2688,8 @@ static int chk_received_hdr(SOCKET socket,const char* prot,const char *buf,IN_AD } if((dnsbl_result->s_addr=dns_blacklisted(socket,prot,&addr,host_name,dnsbl,dnsbl_ip))!=0) - lprintf(LOG_NOTICE,"%04d %s BLACKLISTED SERVER on %s: %s [%s] = %s" - ,socket, prot, dnsbl, host_name, ip, inet_ntoa(*dnsbl_result)); + lprintf(LOG_NOTICE,"%04d %s [%s] BLACKLISTED SERVER on %s: %s = %s" + ,socket, prot, ip, dnsbl, host_name, inet_ntoa(*dnsbl_result)); } while(0); free(fromstr); return(dnsbl_result->s_addr); @@ -2710,7 +2753,7 @@ static char* qp_decode(char* buf) p++; if(*p==0) /* soft link break */ break; - if(isxdigit(*p) && isxdigit(*(p+1))) { + if(IS_HEXDIGIT(*p) && IS_HEXDIGIT(*(p+1))) { char hex[3]; hex[0]=*p; hex[1]=*(p+1); @@ -2819,11 +2862,9 @@ static void smtp_thread(void* arg) char rcpt_name[128]; char rcpt_addr[128]; char sender[128]; - char sender_ext[128]; char sender_addr[128]; char hello_name[128]; char user_name[128]; - char user_pass[128]; char relay_list[MAX_PATH+1]; char domain_list[MAX_PATH+1]; char spam_bait[MAX_PATH+1]; @@ -2888,6 +2929,7 @@ static void smtp_thread(void* arg) user_t relay_user; node_t node; client_t client; + char client_id[128]; smtp_t smtp=*(smtp_t*)arg; union xp_sockaddr server_addr; IN_ADDR dnsbl_result; @@ -3012,7 +3054,7 @@ static void smtp_thread(void* arg) if((i=getsockname(socket, &server_addr.addr, &addr_len))!=0) { lprintf(LOG_CRIT,"%04d %s !ERROR %d (%d) getting address/port" ,socket, client.protocol, i, ERROR_VALUE); - sockprintf(socket,client.protocol,session,sys_error); + sockprintf(socket,client.protocol,session,smtp_error, "getsockname failure"); mail_close_socket(&socket, &session); thread_down(); return; @@ -3020,7 +3062,7 @@ static void smtp_thread(void* arg) if((mailproc_to_match=malloc(sizeof(BOOL)*mailproc_count))==NULL) { lprintf(LOG_CRIT,"%04d %s !ERROR allocating memory for mailproc_to_match", socket, client.protocol); - sockprintf(socket,client.protocol,session,sys_error); + sockprintf(socket,client.protocol,session,smtp_error, "malloc failure"); mail_close_socket(&socket, &session); thread_down(); return; @@ -3034,14 +3076,16 @@ static void smtp_thread(void* arg) memset(&relay_user,0,sizeof(relay_user)); inet_addrtop(&smtp.client_addr,host_ip,sizeof(host_ip)); + inet_addrtop(&server_addr,server_ip,sizeof(server_ip)); - lprintf(LOG_INFO,"%04d %s Connection accepted on port %u from: %s port %u" - ,socket, client.protocol, inet_addrport(&server_addr), host_ip, inet_addrport(&smtp.client_addr)); + lprintf(LOG_INFO,"%04d %s [%s] Connection accepted on %s port %u from port %u" + ,socket, client.protocol, host_ip, server_ip, inet_addrport(&server_addr), inet_addrport(&smtp.client_addr)); + SAFEPRINTF(client_id, "[%s]", host_ip); SAFECOPY(host_name, STR_NO_HOSTNAME); if(!(startup->options&MAIL_OPT_NO_HOST_LOOKUP)) { getnameinfo(&smtp.client_addr.addr, smtp.client_addr_len, host_name, sizeof(host_name), NULL, 0, NI_NAMEREQD); - lprintf(LOG_INFO,"%04d %s Hostname: %s [%s]", socket, client.protocol, host_name, host_ip); + lprintf(LOG_INFO,"%04d %s %s Hostname: %s", socket, client.protocol, client_id, host_name); } protected_uint32_adjust(&active_clients, 1); update_clients(); @@ -3052,8 +3096,6 @@ static void smtp_thread(void* arg) SAFEPRINTF(spam_block,"%sspamblock.cfg",scfg.ctrl_dir); SAFEPRINTF(spam_block_exemptions,"%sspamblock_exempt.cfg",scfg.ctrl_dir); - inet_addrtop(&server_addr,server_ip,sizeof(server_ip)); - if(strcmp(server_ip, host_ip)==0) { /* local connection */ dnsbl_result.s_addr=0; @@ -3061,8 +3103,8 @@ static void smtp_thread(void* arg) ulong banned = loginBanned(&scfg, startup->login_attempt_list, socket, host_name, startup->login_attempt, &attempted); if(banned) { char ban_duration[128]; - lprintf(LOG_NOTICE, "%04d !TEMPORARY BAN of %s (%lu login attempts, last: %s) - remaining: %s" - ,socket, host_ip, attempted.count-attempted.dupes, attempted.user, seconds_to_str(banned, ban_duration)); + lprintf(LOG_NOTICE, "%04d %s [%s] !TEMPORARY BAN (%lu login attempts, last: %s) - remaining: %s" + ,socket, client.protocol, host_ip, attempted.count-attempted.dupes, attempted.user, seconds_to_str(banned, ban_duration)); mail_close_socket(&socket, &session); thread_down(); protected_uint32_adjust(&active_clients, -1); @@ -3086,8 +3128,8 @@ static void smtp_thread(void* arg) } if(trashcan(&scfg,host_name,"host")) { - lprintf(LOG_NOTICE,"%04d %s !CLIENT HOSTNAME BLOCKED: %s (%lu total)" - ,socket, client.protocol, host_name, ++stats.sessions_refused); + lprintf(LOG_NOTICE,"%04d %s [%s] !CLIENT HOSTNAME BLOCKED: %s (%lu total)" + ,socket, client.protocol, host_ip, host_name, ++stats.sessions_refused); sockprintf(socket,client.protocol,session,"550 CLIENT HOSTNAME BLOCKED: %s", host_name); mail_close_socket(&socket, &session); thread_down(); @@ -3100,8 +3142,8 @@ static void smtp_thread(void* arg) /* SPAM Filters (mail-abuse.org) */ dnsbl_result.s_addr = dns_blacklisted(socket,client.protocol,&smtp.client_addr,host_name,dnsbl,dnsbl_ip); if(dnsbl_result.s_addr) { - lprintf(LOG_NOTICE,"%04d %s BLACKLISTED SERVER on %s: %s [%s] = %s" - ,socket, client.protocol, dnsbl, host_name, dnsbl_ip, inet_ntoa(dnsbl_result)); + lprintf(LOG_NOTICE,"%04d %s [%s] BLACKLISTED SERVER on %s: %s = %s" + ,socket, client.protocol, dnsbl_ip, dnsbl, host_name, inet_ntoa(dnsbl_result)); if(startup->options&MAIL_OPT_DNSBL_REFUSE) { SAFEPRINTF2(str,"Listed on %s as %s", dnsbl, inet_ntoa(dnsbl_result)); spamlog(&scfg, (char*)client.protocol, "SESSION REFUSED", str, host_name, dnsbl_ip, NULL, NULL); @@ -3122,9 +3164,9 @@ static void smtp_thread(void* arg) SAFEPRINTF(smb.file,"%smail",scfg.data_dir); if(smb_islocked(&smb)) { - lprintf(LOG_WARNING,"%04d %s !MAIL BASE LOCKED: %s" - ,socket, client.protocol, smb.last_error); - sockprintf(socket,client.protocol,session,sys_unavail); + lprintf(LOG_WARNING,"%04d %s [%s] !MAIL BASE LOCKED: %s" + ,socket, client.protocol, host_ip, smb.last_error); + sockprintf(socket,client.protocol,session, smtp_error, "mail base locked"); mail_close_socket(&socket, &session); thread_down(); protected_uint32_adjust(&active_clients, -1); @@ -3139,16 +3181,16 @@ static void smtp_thread(void* arg) srand((unsigned int)(time(NULL) ^ (time_t)GetCurrentThreadId())); /* seed random number generator */ rand(); /* throw-away first result */ SAFEPRINTF4(session_id,"%x%x%x%lx",getpid(),socket,rand(),(long)clock()); - lprintf(LOG_DEBUG,"%04d %s Session ID=%s", socket, client.protocol, session_id); + lprintf(LOG_DEBUG,"%04d %s [%s] Session ID=%s", socket, client.protocol, host_ip, session_id); SAFEPRINTF3(msgtxt_fname,"%sSBBS_%s.%s.msg", scfg.temp_dir, client.protocol, session_id); SAFEPRINTF3(newtxt_fname,"%sSBBS_%s.%s.new", scfg.temp_dir, client.protocol, session_id); SAFEPRINTF3(logtxt_fname,"%sSBBS_%s.%s.log", scfg.temp_dir, client.protocol, session_id); SAFEPRINTF3(rcptlst_fname,"%sSBBS_%s.%s.lst", scfg.temp_dir, client.protocol, session_id); rcptlst=fopen(rcptlst_fname,"w+"); if(rcptlst==NULL) { - lprintf(LOG_CRIT,"%04d %s !ERROR %d creating recipient list: %s" - ,socket, client.protocol, errno, rcptlst_fname); - sockprintf(socket,client.protocol,session,sys_error); + lprintf(LOG_CRIT,"%04d %s [%s] !ERROR %d creating recipient list: %s" + ,socket, client.protocol, host_ip, errno, rcptlst_fname); + sockprintf(socket,client.protocol,session,smtp_error, "fopen error"); mail_close_socket(&socket, &session); thread_down(); protected_uint32_adjust(&active_clients, -1); @@ -3203,23 +3245,23 @@ static void smtp_thread(void* arg) cmd=SMTP_CMD_NONE; if(msgtxt==NULL) { - lprintf(LOG_ERR,"%04d %s !NO MESSAGE TEXT FILE POINTER?", socket, client.protocol); + lprintf(LOG_ERR,"%04d %s %s !NO MESSAGE TEXT FILE POINTER?", socket, client.protocol, client_id); sockprintf(socket,client.protocol,session,"554 No message text"); continue; } if(ftell(msgtxt)<1) { - lprintf(LOG_ERR,"%04d %s !INVALID MESSAGE LENGTH: %ld (%lu lines)" - , socket, client.protocol, ftell(msgtxt), lines); + lprintf(LOG_ERR,"%04d %s %s !INVALID MESSAGE LENGTH: %ld (%lu lines)" + , socket, client.protocol, client_id, ftell(msgtxt), lines); sockprintf(socket,client.protocol,session,"554 No message text"); continue; } - lprintf(LOG_INFO,"%04d %s End of message (body: %lu lines, %lu bytes, header: %lu lines, %lu bytes)" - , socket, client.protocol, lines, ftell(msgtxt)-hdr_len, hdr_lines, hdr_len); + lprintf(LOG_INFO,"%04d %s %s End of message (body: %lu lines, %lu bytes, header: %lu lines, %lu bytes)" + , socket, client.protocol, client_id, lines, ftell(msgtxt)-hdr_len, hdr_lines, hdr_len); if(!socket_check(socket, NULL, NULL, 0)) { - lprintf(LOG_WARNING,"%04d %s !sender disconnected (premature evacuation)", socket, client.protocol); + lprintf(LOG_WARNING,"%04d %s %s !Sender disconnected (premature evacuation)", socket, client.protocol, client_id); continue; } @@ -3228,8 +3270,8 @@ static void smtp_thread(void* arg) /* Twit-listing (sender's name and e-mail addresses) here */ SAFEPRINTF(path,"%stwitlist.cfg",scfg.ctrl_dir); if(fexist(path) && (findstr(sender,path) || findstr(sender_addr,path))) { - lprintf(LOG_NOTICE,"%04d %s !FILTERING TWIT-LISTED SENDER: %s <%s> (%lu total)" - ,socket, client.protocol, sender, sender_addr, ++stats.msgs_refused); + lprintf(LOG_NOTICE,"%04d %s %s !FILTERING TWIT-LISTED SENDER: %s <%s> (%lu total)" + ,socket, client.protocol, client_id, sender, sender_addr, ++stats.msgs_refused); SAFEPRINTF2(tmp,"Twit-listed sender: %s <%s>", sender, sender_addr); spamlog(&scfg, (char*)client.protocol, "REFUSED", tmp, host_name, host_ip, rcpt_addr, reverse_path); sockprintf(socket,client.protocol,session, "554 Sender not allowed."); @@ -3271,17 +3313,17 @@ static void smtp_thread(void* arg) ,head,sender_addr,host_ip,host_name,tail); else safe_snprintf(str,sizeof(str),"%s%s%s",head,sender_addr,tail); - + if((telegram_buf=(char*)malloc(length+strlen(str)+1))==NULL) { - lprintf(LOG_CRIT,"%04d %s !ERROR allocating %lu bytes of memory for telegram from %s" - ,socket, client.protocol,length+strlen(str)+1,sender_addr); + lprintf(LOG_CRIT,"%04d %s %s !ERROR allocating %lu bytes of memory for telegram from %s" + ,socket, client.protocol, client_id, length+strlen(str)+1,sender_addr); sockprintf(socket,client.protocol,session, insuf_stor); continue; } strcpy(telegram_buf,str); /* can't use SAFECOPY here */ if(fread(telegram_buf+strlen(str),1,length,msgtxt)!=length) { - lprintf(LOG_ERR,"%04d %s !ERROR reading %lu bytes from telegram file" - ,socket, client.protocol,length); + lprintf(LOG_ERR,"%04d %s %s !ERROR reading %lu bytes from telegram file" + ,socket, client.protocol, client_id, length); sockprintf(socket,client.protocol,session, insuf_stor); free(telegram_buf); continue; @@ -3301,11 +3343,11 @@ static void smtp_thread(void* arg) SAFECOPY(rcpt_addr,iniReadString(rcptlst,section ,smb_hfieldtype(RECIPIENTNETADDR),rcpt_to,value)); if((i=putsmsg(&scfg,usernum,telegram_buf))==0) - lprintf(LOG_INFO,"%04d %s Created telegram (%ld/%lu bytes) from %s to %s <%s>" - ,socket, client.protocol, length, (ulong)strlen(telegram_buf), sender_addr, rcpt_to, rcpt_addr); + lprintf(LOG_INFO,"%04d %s %s Created telegram (%ld/%lu bytes) from %s to %s <%s>" + ,socket, client.protocol, client_id, length, (ulong)strlen(telegram_buf), sender_addr, rcpt_to, rcpt_addr); else - lprintf(LOG_ERR,"%04d %s !ERROR %d creating telegram from %s to %s <%s>" - ,socket, client.protocol, i, sender_addr, rcpt_to, rcpt_addr); + lprintf(LOG_ERR,"%04d %s %s !ERROR %d creating telegram from %s to %s <%s>" + ,socket, client.protocol, client_id, i, sender_addr, rcpt_to, rcpt_addr); } iniFreeStringList(sec_list); free(telegram_buf); @@ -3351,18 +3393,18 @@ static void smtp_thread(void* arg) ,host_name, host_ip, relay_user.number ,rcpt_addr ,sender, sender_addr, reverse_path, str); - lprintf(LOG_INFO,"%04d %s Executing external mail processor: %s" - ,socket, client.protocol, mp->name); + lprintf(LOG_INFO,"%04d %s %s Executing external mail processor: %s" + ,socket, client.protocol, client_id, mp->name); if(mp->native) { - lprintf(LOG_DEBUG,"%04d %s Executing external command: %s" - ,socket, client.protocol, str); + lprintf(LOG_DEBUG,"%04d %s %s Executing external command: %s" + ,socket, client.protocol, client_id, str); if((j=system(str))!=0) { - lprintf(LOG_NOTICE,"%04d %s system(%s) returned %d (errno: %d)" - ,socket, client.protocol, str, j, errno); + lprintf(LOG_NOTICE,"%04d %s %s system(%s) returned %d (errno: %d)" + ,socket, client.protocol, client_id, str, j, errno); if(mp->ignore_on_error) { - lprintf(LOG_WARNING,"%04d %s !IGNORED MAIL due to mail processor (%s) error: %d" - ,socket, client.protocol, mp->name, j); + lprintf(LOG_WARNING,"%04d %s %s !IGNORED MAIL due to mail processor (%s) error: %d" + ,socket, client.protocol, client_id, mp->name, j); msg_handled=TRUE; } } @@ -3393,8 +3435,8 @@ static void smtp_thread(void* arg) if(!fgets(str,sizeof(str),proc_out)) break; truncsp(str); - lprintf(LOG_DEBUG,"%04d %s External mail processor (%s) debug: %s" - ,socket, client.protocol, mp->name, str); + lprintf(LOG_DEBUG,"%04d %s %s External mail processor (%s) debug: %s" + ,socket, client.protocol, client_id, mp->name, str); } fclose(proc_out); } @@ -3407,15 +3449,15 @@ static void smtp_thread(void* arg) } if(flength(proc_err_fname)>0 && (proc_out=fopen(proc_err_fname,"r"))!=NULL) { - lprintf(LOG_WARNING,"%04d %s !External mail processor (%s) created: %s" - ,socket, client.protocol, mailproc->name, proc_err_fname); + lprintf(LOG_WARNING,"%04d %s %s !External mail processor (%s) created: %s" + ,socket, client.protocol, client_id, mailproc->name, proc_err_fname); while(!feof(proc_out)) { int n; if(!fgets(str,sizeof(str),proc_out)) break; truncsp(str); - lprintf(LOG_WARNING,"%04d %s !External mail processor (%s) error: %s" - ,socket, client.protocol, mailproc->name, str); + lprintf(LOG_WARNING,"%04d %s %s !External mail processor (%s) error: %s" + ,socket, client.protocol, client_id, mailproc->name, str); n=atoi(str); if(n>=100 && n<1000) sockprintf(socket,client.protocol,session,"%s", str); @@ -3428,8 +3470,8 @@ static void smtp_thread(void* arg) msg_handled=TRUE; } else if(!fexist(msgtxt_fname) || !fexist(rcptlst_fname)) { - lprintf(LOG_NOTICE,"%04d %s External mail processor (%s) removed %s file" - ,socket, client.protocol + lprintf(LOG_NOTICE,"%04d %s %s External mail processor (%s) removed %s file" + ,socket, client.protocol, client_id ,mailproc->name ,fexist(msgtxt_fname)==FALSE ? "message text" : "recipient list"); sockprintf(socket,client.protocol,session,ok_rsp); @@ -3444,23 +3486,23 @@ static void smtp_thread(void* arg) /* We must do this before continuing for handled msgs */ /* to prevent freopen(NULL) and orphaned temp files */ if((rcptlst=fopen(rcptlst_fname,fexist(rcptlst_fname) ? "r":"w+"))==NULL) { - lprintf(LOG_ERR,"%04d %s !ERROR %d re-opening recipient list: %s" - ,socket, client.protocol, errno, rcptlst_fname); + lprintf(LOG_ERR,"%04d %s %s !ERROR %d re-opening recipient list: %s" + ,socket, client.protocol, client_id, errno, rcptlst_fname); if(!msg_handled) - sockprintf(socket,client.protocol,session,sys_error); + sockprintf(socket,client.protocol,session,smtp_error, "fopen error"); continue; } if(!msg_handled && subnum==INVALID_SUB && iniReadSectionCount(rcptlst,NULL) < 1) { - lprintf(LOG_DEBUG,"%04d %s No recipients in recipient list file (message handled by external mail processor?)" - ,socket, client.protocol); + lprintf(LOG_DEBUG,"%04d %s %s No recipients in recipient list file (message handled by external mail processor?)" + ,socket, client.protocol, client_id); sockprintf(socket,client.protocol,session,ok_rsp); msg_handled=TRUE; } if(msg_handled) { if(mailproc!=NULL) - lprintf(LOG_NOTICE,"%04d %s Message handled by external mail processor (%s, %lu total)" - ,socket, client.protocol, mailproc->name, ++mailproc->handled); + lprintf(LOG_NOTICE,"%04d %s %s Message handled by external mail processor (%s, %lu total)" + ,socket, client.protocol, client_id, mailproc->name, ++mailproc->handled); continue; } @@ -3472,9 +3514,9 @@ static void smtp_thread(void* arg) remove(newtxt_fname); if((msgtxt=fopen(msgtxt_fname,"rb"))==NULL) { - lprintf(LOG_ERR,"%04d %s !ERROR %d re-opening message file: %s" - ,socket, client.protocol, errno, msgtxt_fname); - sockprintf(socket,client.protocol,session,sys_error); + lprintf(LOG_ERR,"%04d %s %s !ERROR %d re-opening message file: %s" + ,socket, client.protocol, client_id, errno, msgtxt_fname); + sockprintf(socket,client.protocol,session,smtp_error, "fopen error"); continue; } @@ -3501,8 +3543,8 @@ static void smtp_thread(void* arg) /* SPAM Filtering/Logging */ if(relay_user.number==0) { if(trashcan(&scfg,p,"subject")) { - lprintf(LOG_NOTICE,"%04d %s !BLOCKED SUBJECT (%s) from: %s (%lu total)" - ,socket, client.protocol, p, reverse_path, ++stats.msgs_refused); + lprintf(LOG_NOTICE,"%04d %s %s !BLOCKED SUBJECT (%s) from: %s (%lu total)" + ,socket, client.protocol, client_id, p, reverse_path, ++stats.msgs_refused); SAFEPRINTF2(tmp,"Blocked subject (%s) from: %s" ,p, reverse_path); spamlog(&scfg, (char*)client.protocol, "REFUSED" @@ -3516,8 +3558,8 @@ static void smtp_thread(void* arg) ,(int)sizeof(str)/2, startup->dnsbl_tag ,(int)sizeof(str)/2, p); p=str; - lprintf(LOG_NOTICE,"%04d %s TAGGED MAIL SUBJECT from blacklisted server with: %s" - ,socket, client.protocol, startup->dnsbl_tag); + lprintf(LOG_NOTICE,"%04d %s %s TAGGED MAIL SUBJECT from blacklisted server with: %s" + ,socket, client.protocol, client_id, startup->dnsbl_tag); msg.hdr.attr |= MSG_SPAM; } } @@ -3541,11 +3583,11 @@ static void smtp_thread(void* arg) } if((smb_error=parse_header_field((char*)buf, &msg, &hfield_type))!=SMB_SUCCESS) { if(smb_error==SMB_ERR_HDR_LEN) - lprintf(LOG_WARNING,"%04d %s !MESSAGE HEADER EXCEEDS %u BYTES" - ,socket, client.protocol, SMB_MAX_HDR_LEN); + lprintf(LOG_WARNING,"%04d %s %s !MESSAGE HEADER EXCEEDS %u BYTES" + ,socket, client.protocol, client_id, SMB_MAX_HDR_LEN); else - lprintf(LOG_ERR,"%04d %s !ERROR %d adding header field: %s" - ,socket, client.protocol, smb_error, buf); + lprintf(LOG_ERR,"%04d %s %s !ERROR %d adding header field: %s" + ,socket, client.protocol, client_id, smb_error, buf); break; } } @@ -3594,8 +3636,8 @@ static void smtp_thread(void* arg) ,startup->dnsbl_hdr, dnsbl_ip ,dnsbl, inet_ntoa(dnsbl_result)); smb_hfield_str(&msg, RFC822HEADER, str); - lprintf(LOG_NOTICE,"%04d %s TAGGED MAIL HEADER from blacklisted server with: %s" - ,socket, client.protocol, startup->dnsbl_hdr); + lprintf(LOG_NOTICE,"%04d %s %s TAGGED MAIL HEADER from blacklisted server with: %s" + ,socket, client.protocol, client_id, startup->dnsbl_hdr); } if(startup->dnsbl_hdr[0] || startup->dnsbl_tag[0]) { SAFEPRINTF2(str,"Listed on %s as %s", dnsbl, inet_ntoa(dnsbl_result)); @@ -3604,21 +3646,36 @@ static void smtp_thread(void* arg) } if(dnsbl_recvhdr) /* DNSBL-listed IP found in Received header? */ dnsbl_result.s_addr=0; /* Reset DNSBL look-up result between messages */ - + if((scfg.sys_misc&SM_DELREADM) || ((startup->options&MAIL_OPT_KILL_READ_SPAM) && (msg.hdr.attr&MSG_SPAM))) msg.hdr.attr |= MSG_KILLREAD; if(sender[0]==0) { - lprintf(LOG_WARNING,"%04d %s !MISSING mail header 'FROM' field (%lu total)" - ,socket, client.protocol, ++stats.msgs_refused); + lprintf(LOG_WARNING,"%04d %s %s !MISSING mail header 'FROM' field (%lu total)" + ,socket, client.protocol, client_id, ++stats.msgs_refused); sockprintf(socket,client.protocol,session, "554 Mail header missing 'FROM' field"); subnum=INVALID_SUB; continue; } + if(relay_user.number == 0 + && strchr(sender, '@') != NULL + && compare_addrs(sender, sender_addr) != 0) { + lprintf(LOG_WARNING,"%04d %s %s !FORGED mail header 'FROM' field (%lu total)" + ,socket, client.protocol, client_id, ++stats.msgs_refused); + sockprintf(socket,client.protocol,session, "554 Mail header contains mismatched 'FROM' field"); + subnum=INVALID_SUB; + continue; + } + char sender_info[512]; if(relay_user.number) { SAFEPRINTF(str,"%u",relay_user.number); smb_hfield_str(&msg, SENDEREXT, str); + SAFEPRINTF2(sender_info, "'%s' #%u", sender, relay_user.number); + } else if(compare_addrs(sender, sender_addr) == 0) { + angle_bracket(sender_info, sizeof(sender_info), sender_addr); + } else { + safe_snprintf(sender_info, sizeof(sender_info), "'%s' %s", sender, angle_bracket(tmp, sizeof(tmp), sender_addr)); } if(relay_user.number && subnum!=INVALID_SUB) { nettype=NET_NONE; @@ -3676,8 +3733,8 @@ static void smtp_thread(void* arg) length=filelength(fileno(msgtxt))-ftell(msgtxt); if(startup->max_msg_size && length>startup->max_msg_size) { - lprintf(LOG_WARNING,"%04d %s !Message size (%lu) exceeds maximum: %u bytes" - ,socket, client.protocol,length,startup->max_msg_size); + lprintf(LOG_WARNING,"%04d %s %s !Message size (%lu) from %s to <%s> exceeds maximum: %u bytes" + ,socket, client.protocol, client_id, length, sender_info, rcpt_addr, startup->max_msg_size); sockprintf(socket,client.protocol,session, "552 Message size (%lu) exceeds maximum: %u bytes" ,length,startup->max_msg_size); subnum=INVALID_SUB; @@ -3686,8 +3743,8 @@ static void smtp_thread(void* arg) } if((msgbuf=(char*)malloc(length+1))==NULL) { - lprintf(LOG_CRIT,"%04d %s !ERROR allocating %lu bytes of memory" - ,socket, client.protocol,length+1); + lprintf(LOG_CRIT,"%04d %s %s !ERROR allocating %lu bytes of memory" + ,socket, client.protocol, client_id, length+1); sockprintf(socket,client.protocol,session, insuf_stor); subnum=INVALID_SUB; continue; @@ -3703,8 +3760,8 @@ static void smtp_thread(void* arg) memset(&relay_user,0,sizeof(relay_user)); if(!can_user_post(&scfg,subnum,&relay_user,&client,&reason)) { - lprintf(LOG_WARNING,"%04d %s !%s (user #%u) cannot post on %s (reason: %u)" - ,socket, client.protocol, sender_addr, relay_user.number + lprintf(LOG_WARNING,"%04d %s %s !%s (user #%u) cannot post on %s (reason: %u)" + ,socket, client.protocol, client_id, sender_addr, relay_user.number ,scfg.sub[subnum]->sname, reason + 1); sockprintf(socket,client.protocol,session,"550 Insufficient access"); subnum=INVALID_SUB; @@ -3718,13 +3775,13 @@ static void smtp_thread(void* arg) smb.subnum=subnum; if((i=savemsg(&scfg, &smb, &msg, &client, server_host_name(), msgbuf, /* remsg: */NULL))!=SMB_SUCCESS) { - lprintf(LOG_WARNING,"%04d %s !ERROR %d (%s) posting message to %s (%s)" - ,socket, client.protocol, i, smb.last_error, scfg.sub[subnum]->sname, smb.file); + lprintf(LOG_WARNING,"%04d %s %s !ERROR %d (%s) %s posting message to %s (%s)" + ,socket, client.protocol, client_id, i, smb.last_error, sender_info, scfg.sub[subnum]->sname, smb.file); sockprintf(socket,client.protocol,session, "452 ERROR %d (%s) posting message" ,i,smb.last_error); } else { - lprintf(LOG_INFO,"%04d %s %s posted a message on %s (%s)" - ,socket, client.protocol, sender_addr, scfg.sub[subnum]->sname, smb.file); + lprintf(LOG_INFO,"%04d %s %s %s posted a message on %s (%s)" + ,socket, client.protocol, client_id, sender_info, scfg.sub[subnum]->sname, smb.file); sockprintf(socket,client.protocol,session,ok_rsp); if(relay_user.number != 0) user_posted_msg(&scfg, &relay_user, 1); @@ -3745,49 +3802,50 @@ static void smtp_thread(void* arg) if((dnsbl_recvhdr || dnsbl_result.s_addr) && startup->options&MAIL_OPT_DNSBL_SPAMHASH) is_spam=TRUE; - lprintf(LOG_DEBUG,"%04d %s Calculating message hashes (sources=%lx, msglen=%lu)" - ,socket, client.protocol, sources, (ulong)strlen(msgbuf)); + lprintf(LOG_DEBUG,"%04d %s %s Calculating message hashes (sources=%lx, msglen=%lu)" + ,socket, client.protocol, client_id, sources, (ulong)strlen(msgbuf)); if((hashes=smb_msghashes(&msg, (uchar*)msgbuf, sources)) != NULL) { hash_t found; for(i=0;hashes[i];i++) - lprintf(LOG_DEBUG,"%04d %s Message %s crc32=%x flags=%x length=%u" - ,socket, client.protocol, smb_hashsourcetype(hashes[i]->source) + lprintf(LOG_DEBUG,"%04d %s %s Message %s crc32=%x flags=%x length=%u" + ,socket, client.protocol, client_id, smb_hashsourcetype(hashes[i]->source) ,hashes[i]->crc32, hashes[i]->flags, hashes[i]->length); - lprintf(LOG_DEBUG, "%04d %s Searching SPAM database for a match", socket, client.protocol); + lprintf(LOG_DEBUG, "%04d %s %s Searching SPAM database for a match", socket, client.protocol, client_id); if((i=smb_findhash(&spam, hashes, &found, sources, /* Mark: */TRUE))==SMB_SUCCESS) { SAFEPRINTF3(str,"%s (%s) found in SPAM database (added on %s)" ,smb_hashsourcetype(found.source) ,smb_hashsource(&msg,found.source) ,timestr(&scfg,found.time,tmp) ); - lprintf(LOG_NOTICE,"%04d %s Message %s", socket, client.protocol, str); + lprintf(LOG_NOTICE,"%04d %s %s Message from %s %s", socket, client.protocol, client_id, sender_info, str); if(!is_spam) { spamlog(&scfg, (char*)client.protocol, "IGNORED" ,str, host_name, host_ip, rcpt_addr, reverse_path); is_spam=TRUE; } } else { - lprintf(LOG_DEBUG, "%04d %s Done searching SPAM database", socket, client.protocol); + lprintf(LOG_DEBUG, "%04d %s %s Done searching SPAM database", socket, client.protocol, client_id); if(i!=SMB_ERR_NOT_FOUND) - lprintf(LOG_ERR,"%04d %s !ERROR %d (%s) opening SPAM database" - ,socket, client.protocol, i, spam.last_error); + lprintf(LOG_ERR,"%04d %s %s !ERROR %d (%s) opening SPAM database" + ,socket, client.protocol, client_id, i, spam.last_error); } - + if(is_spam) { size_t n,total=0; for(n=0;hashes[n]!=NULL;n++) if(!(hashes[n]->flags&SMB_HASH_MARKED)) { - lprintf(LOG_INFO,"%04d %s Adding message %s (%s) to SPAM database" - ,socket, client.protocol + lprintf(LOG_INFO,"%04d %s %s Adding message %s (%s) from %s to SPAM database" + ,socket, client.protocol, client_id ,smb_hashsourcetype(hashes[n]->source) ,smb_hashsource(&msg,hashes[n]->source) + ,sender_info ); total++; } if(total) { - lprintf(LOG_DEBUG,"%04d %s Adding %lu message hashes to SPAM database", socket, client.protocol, (ulong)total); + lprintf(LOG_DEBUG,"%04d %s %s Adding %lu message hashes to SPAM database", socket, client.protocol, client_id, (ulong)total); smb_addhashes(&spam, hashes, /* skip_marked: */TRUE); } if(i!=SMB_SUCCESS && !spam_bait_result && (dnsbl_recvhdr || dnsbl_result.s_addr)) @@ -3797,17 +3855,17 @@ static void smtp_thread(void* arg) smb_freehashes(hashes); } else - lprintf(LOG_ERR,"%04d %s smb_msghashes returned NULL", socket, client.protocol); + lprintf(LOG_ERR,"%04d %s %s !smb_msghashes returned NULL", socket, client.protocol, client_id); if(is_spam || ((startup->options&MAIL_OPT_DNSBL_IGNORE) && (dnsbl_recvhdr || dnsbl_result.s_addr))) { free(msgbuf); if(is_spam) - lprintf(LOG_NOTICE,"%04d %s !IGNORED SPAM MESSAGE (%lu total)" - ,socket, client.protocol, ++stats.msgs_ignored); + lprintf(LOG_NOTICE,"%04d %s %s !IGNORED SPAM MESSAGE from %s to <%s> (%lu total)" + ,socket, client.protocol, client_id, sender_info, rcpt_addr, ++stats.msgs_ignored); else { SAFEPRINTF2(str,"Listed on %s as %s", dnsbl, inet_ntoa(dnsbl_result)); - lprintf(LOG_NOTICE,"%04d %s !IGNORED MAIL from server: %s (%lu total)" - ,socket, client.protocol, str, ++stats.msgs_ignored); + lprintf(LOG_NOTICE,"%04d %s %s !IGNORED MAIL from %s to <%s> from server: %s (%lu total)" + ,socket, client.protocol, client_id, sender_info, rcpt_addr, str, ++stats.msgs_ignored); spamlog(&scfg, (char*)client.protocol, "IGNORED" ,str, host_name, dnsbl_ip, rcpt_addr, reverse_path); } @@ -3818,8 +3876,14 @@ static void smtp_thread(void* arg) } } - lprintf(LOG_DEBUG,"%04d %s Saving message to: '%s'", socket, client.protocol, rcpt_name); - + char rcpt_info[512]; + if(compare_addrs(rcpt_name, rcpt_addr) == 0) + angle_bracket(rcpt_info, sizeof(rcpt_info), rcpt_addr); + else + safe_snprintf(rcpt_info, sizeof(rcpt_info), "'%s' %s", rcpt_name, angle_bracket(tmp, sizeof(tmp), rcpt_addr)); + lprintf(LOG_DEBUG,"%04d %s %s Saving message data from %s to %s" + ,socket, client.protocol, client_id, sender_info, rcpt_info); + pthread_mutex_lock(&savemsg_mutex); /* E-mail */ smb.subnum=INVALID_SUB; /* creates message data, but no header or index records (since msg.to==NULL) */ @@ -3830,20 +3894,22 @@ static void smtp_thread(void* arg) free(msgbuf); if(i!=SMB_SUCCESS) { smb_close(&smb); - lprintf(LOG_CRIT,"%04d %s !ERROR %d (%s) saving message" - ,socket, client.protocol,i,smb.last_error); + pthread_mutex_unlock(&savemsg_mutex); + lprintf(LOG_CRIT,"%04d %s %s !ERROR %d (%s) saving message from %s to %s" + ,socket, client.protocol, client_id, i, smb.last_error, sender_info, rcpt_info); sockprintf(socket,client.protocol,session, "452 ERROR %d (%s) saving message" ,i,smb.last_error); continue; } - lprintf(LOG_DEBUG,"%04d %s Saved message data to: '%s'", socket, client.protocol, rcpt_name); + lprintf(LOG_DEBUG,"%04d %s %s Saved message data from %s to %s" + ,socket, client.protocol, client_id, sender_info, rcpt_info); sec_list=iniReadSectionList(rcptlst,NULL); /* Each section is a recipient */ for(rcpt_count=0; sec_list!=NULL && sec_list[rcpt_count]!=NULL && (startup->max_recipients==0 || rcpt_count<startup->max_recipients); rcpt_count++) { - + section=sec_list[rcpt_count]; SAFECOPY(rcpt_to,iniReadString(rcptlst,section ,smb_hfieldtype(RECIPIENT),"unknown",value)); @@ -3853,16 +3919,20 @@ static void smtp_thread(void* arg) SAFEPRINTF(str,"#%u",usernum); SAFECOPY(rcpt_addr,iniReadString(rcptlst,section ,smb_hfieldtype(RECIPIENTNETADDR),str,value)); SAFECOPY(forward_path, iniReadString(rcptlst, section, smb_hfieldtype(SMTPFORWARDPATH), "", value)); + if(compare_addrs(rcpt_to, rcpt_addr) == 0) + angle_bracket(rcpt_info, sizeof(rcpt_info), rcpt_addr); + else + safe_snprintf(rcpt_info, sizeof(rcpt_info), "'%s' %s", rcpt_to, angle_bracket(tmp, sizeof(tmp), rcpt_addr)); if(nettype==NET_NONE /* Local destination */ && usernum==0) { - lprintf(LOG_ERR,"%04d %s !can't deliver mail to user #0" - ,socket, client.protocol); + lprintf(LOG_ERR,"%04d %s %s !Can't deliver mail from %s to user #0" + ,socket, client.protocol, client_id, sender_info); break; } if((i=smb_copymsgmem(&smb,&newmsg,&msg))!=SMB_SUCCESS) { - lprintf(LOG_ERR,"%04d %s !ERROR %d (%s) copying message" - ,socket, client.protocol, i, smb.last_error); + lprintf(LOG_ERR,"%04d %s %s !ERROR %d (%s) copying message from %s" + ,socket, client.protocol, client_id, i, smb.last_error, sender_info); break; } @@ -3921,18 +3991,17 @@ static void smtp_thread(void* arg) smb_hfield(&newmsg, RECIPIENTAGENT, sizeof(agent), &agent); add_msg_ids(&scfg, &smb, &newmsg, /* remsg: */NULL); + lprintf(LOG_DEBUG,"%04d %s %s Adding message header from %s to %s" + ,socket, client.protocol, client_id, sender_info, rcpt_info); i=smb_addmsghdr(&smb,&newmsg,smb_storage_mode(&scfg, &smb)); smb_freemsgmem(&newmsg); if(i!=SMB_SUCCESS) { - lprintf(LOG_ERR,"%04d %s !ERROR %d (%s) adding message header" - ,socket, client.protocol, i, smb.last_error); + lprintf(LOG_ERR,"%04d %s %s !ERROR %d (%s) adding message header from %s to %s" + ,socket, client.protocol, client_id, i, smb.last_error, sender_info, rcpt_info); break; } - sender_ext[0]=0; - if(msg.from_ext!=NULL) - SAFEPRINTF(sender_ext," #%s",msg.from_ext); - lprintf(LOG_INFO,"%04d %s Created message #%u from %s%s [%s] to %s [%s]" - ,socket, client.protocol, newmsg.hdr.number, sender, sender_ext, smb_netaddrstr(&msg.from_net,tmp), rcpt_name, rcpt_addr); + lprintf(LOG_INFO,"%04d %s %s Added message header #%u from %s to %s" + ,socket, client.protocol, client_id, newmsg.hdr.number, sender_info, rcpt_info); if(relay_user.number!=0) user_sent_email(&scfg, &relay_user, 1, usernum==1); @@ -3987,6 +4056,7 @@ static void smtp_thread(void* arg) smb_close_da(&smb); #endif smb_close(&smb); + pthread_mutex_unlock(&savemsg_mutex); continue; } if(buf[0]==0 && state==SMTP_STATE_DATA_HEADER) { @@ -4027,14 +4097,14 @@ static void smtp_thread(void* arg) !(lines%startup->lines_per_yield)) YIELD(); if((lines%100) == 0 && (msgtxt != NULL)) - lprintf(LOG_DEBUG,"%04d %s received %lu lines (%lu bytes) of body text" - ,socket, client.protocol, lines, ftell(msgtxt)-hdr_len); + lprintf(LOG_DEBUG,"%04d %s %s received %lu lines (%lu bytes) of body text" + ,socket, client.protocol, client_id, lines, ftell(msgtxt)-hdr_len); continue; } /* RFC822 Header parsing */ strip_char(buf, buf, '\r'); /* There should be no bare carriage returns in header fields */ if(startup->options&MAIL_OPT_DEBUG_RX_HEADER) - lprintf(LOG_DEBUG,"%04d %s %s",socket, client.protocol, buf); + lprintf(LOG_DEBUG,"%04d %s %s %s",socket, client.protocol, client_id, buf); { char field[32]; @@ -4046,7 +4116,7 @@ static void smtp_thread(void* arg) ,sender_addr, sizeof(sender_addr)-1); } else if(stricmp(field,"CONTENT-TRANSFER-ENCODING")==0) { - lprintf(LOG_INFO,"%04d %s %s = %s", socket, client.protocol, field, p); + lprintf(LOG_INFO,"%04d %s %s %s = %s", socket, client.protocol, client_id, field, p); if(stricmp(p,"base64")==0) content_encoding=ENCODING_BASE64; else if(stricmp(p,"quoted-printable")==0) @@ -4068,7 +4138,7 @@ static void smtp_thread(void* arg) continue; } strip_ctrl(buf, buf); - lprintf(LOG_DEBUG,"%04d %s RX: %s", socket, client.protocol, buf); + lprintf(LOG_DEBUG,"%04d %s %s RX: %s", socket, client.protocol, client_id, buf); if(!strnicmp(buf,"HELO",4)) { p=buf+4; SKIP_WHITESPACE(p); @@ -4103,33 +4173,35 @@ static void smtp_thread(void* arg) subnum=INVALID_SUB; continue; } - ZERO_VAR(user_pass); if((auth_login=(stricmp(buf,"AUTH LOGIN")==0))==TRUE || strnicmp(buf,"AUTH PLAIN",10)==0) { + char user_pass[128] = ""; + ZERO_VAR(relay_user); + listRemoveTaggedNode(¤t_logins, socket, /* free_data */TRUE); if(auth_login) { sockprintf(socket,client.protocol,session,"334 VXNlcm5hbWU6"); /* Base64-encoded "Username:" */ if((rd=sockreadline(socket, client.protocol, session, buf, sizeof(buf)))<1) { - lprintf(LOG_WARNING,"%04d %s !missing AUTH LOGIN username argument", socket, client.protocol); + lprintf(LOG_WARNING,"%04d %s %s !Missing AUTH LOGIN username argument", socket, client.protocol, client_id); badlogin(socket, session, client.protocol, badarg_rsp, NULL, NULL, host_name, &smtp.client_addr); continue; } if(startup->options&MAIL_OPT_DEBUG_RX_RSP) - lprintf(LOG_DEBUG,"%04d RX: %s",socket,buf); - if(b64_decode(user_name,sizeof(user_name),buf,rd)<1) { - lprintf(LOG_WARNING,"%04d %s !bad AUTH LOGIN username argument", socket, client.protocol); + lprintf(LOG_DEBUG,"%04d %s %s RX: %s", socket, client.protocol, client_id, buf); + if(b64_decode(user_name,sizeof(user_name),buf,rd)<1 || str_has_ctrl(user_name)) { + lprintf(LOG_WARNING,"%04d %s %s !Bad AUTH LOGIN username argument", socket, client.protocol, client_id); badlogin(socket, session, client.protocol, badarg_rsp, NULL, NULL, host_name, &smtp.client_addr); continue; } sockprintf(socket,client.protocol,session,"334 UGFzc3dvcmQ6"); /* Base64-encoded "Password:" */ if((rd=sockreadline(socket, client.protocol, session, buf, sizeof(buf)))<1) { - lprintf(LOG_WARNING,"%04d %s !missing AUTH LOGIN password argument", socket, client.protocol); + lprintf(LOG_WARNING,"%04d %s %s !Missing AUTH LOGIN password argument", socket, client.protocol, client_id); badlogin(socket, session, client.protocol, badarg_rsp, user_name, NULL, host_name, &smtp.client_addr); continue; } if(startup->options&MAIL_OPT_DEBUG_RX_RSP) - lprintf(LOG_DEBUG,"%04d RX: %s",socket,buf); - if(b64_decode(user_pass,sizeof(user_pass),buf,rd)<1) { - lprintf(LOG_WARNING,"%04d %s !bad AUTH LOGIN password argument", socket, client.protocol); + lprintf(LOG_DEBUG,"%04d %s %s RX: %s", socket, client.protocol, client_id, buf); + if(b64_decode(user_pass,sizeof(user_pass),buf,rd)<1 || str_has_ctrl(user_pass)) { + lprintf(LOG_WARNING,"%04d %s %s !Bad AUTH LOGIN password argument", socket, client.protocol, client_id); badlogin(socket, session, client.protocol, badarg_rsp, user_name, NULL, host_name, &smtp.client_addr); continue; } @@ -4137,13 +4209,13 @@ static void smtp_thread(void* arg) p=buf+10; SKIP_WHITESPACE(p); if(*p==0) { - lprintf(LOG_WARNING,"%04d %s !missing AUTH PLAIN argument", socket, client.protocol); + lprintf(LOG_WARNING,"%04d %s %s !Missing AUTH PLAIN argument", socket, client.protocol, client_id); badlogin(socket, session, client.protocol, badarg_rsp, NULL, NULL, host_name, &smtp.client_addr); continue; } ZERO_VAR(tmp); - if(b64_decode(tmp,sizeof(tmp),p,strlen(p))<1) { - lprintf(LOG_WARNING,"%04d %s !bad AUTH PLAIN argument", socket, client.protocol); + if(b64_decode(tmp,sizeof(tmp),p,strlen(p))<1 || str_has_ctrl(tmp)) { + lprintf(LOG_WARNING,"%04d %s %s !Bad AUTH PLAIN argument", socket, client.protocol, client_id); badlogin(socket, session, client.protocol, badarg_rsp, NULL, NULL, host_name, &smtp.client_addr); continue; } @@ -4151,7 +4223,7 @@ static void smtp_thread(void* arg) while(*p) p++; /* skip username */ p++; /* skip NULL */ if(*p==0) { - lprintf(LOG_WARNING,"%04d %s !missing AUTH PLAIN user-id argument", socket, client.protocol); + lprintf(LOG_WARNING,"%04d %s %s !Missing AUTH PLAIN user-id argument", socket, client.protocol, client_id); badlogin(socket, session, client.protocol, badarg_rsp, NULL, NULL, host_name, &smtp.client_addr); continue; } @@ -4159,7 +4231,7 @@ static void smtp_thread(void* arg) while(*p) p++; /* skip user-id */ p++; /* skip NULL */ if(*p==0) { - lprintf(LOG_WARNING,"%04d %s !missing AUTH PLAIN password argument", socket, client.protocol); + lprintf(LOG_WARNING,"%04d %s %s !Missing AUTH PLAIN password argument", socket, client.protocol, client_id); badlogin(socket, session, client.protocol, badarg_rsp, user_name, NULL, host_name, &smtp.client_addr); continue; } @@ -4168,51 +4240,57 @@ static void smtp_thread(void* arg) if((relay_user.number=matchuser(&scfg,user_name,FALSE))==0) { if(scfg.sys_misc&SM_ECHO_PW) - lprintf(LOG_WARNING,"%04d %s !UNKNOWN USER: '%s' (password: %s)" - ,socket, client.protocol, user_name, user_pass); + lprintf(LOG_WARNING,"%04d %s %s !UNKNOWN USER: '%s' (password: %s)" + ,socket, client.protocol, client_id, user_name, user_pass); else - lprintf(LOG_WARNING,"%04d %s !UNKNOWN USER: '%s'" - ,socket, client.protocol, user_name); + lprintf(LOG_WARNING,"%04d %s %s !UNKNOWN USER: '%s'" + ,socket, client.protocol, client_id, user_name); badlogin(socket, session, client.protocol, badauth_rsp, user_name, user_pass, host_name, &smtp.client_addr); break; } if((i=getuserdat(&scfg, &relay_user))!=0) { - lprintf(LOG_ERR,"%04d %s !ERROR %d getting data on user (%s)" - ,socket, client.protocol, i, user_name); + lprintf(LOG_ERR,"%04d %s %s !ERROR %d getting data on user (%s)" + ,socket, client.protocol, client_id, i, user_name); badlogin(socket, session, client.protocol, badauth_rsp, NULL, NULL, NULL, NULL); break; } if(relay_user.misc&(DELETED|INACTIVE)) { - lprintf(LOG_WARNING,"%04d %s !DELETED or INACTIVE user #%u (%s)" - ,socket, client.protocol, relay_user.number, user_name); + lprintf(LOG_WARNING,"%04d %s %s !DELETED or INACTIVE user #%u (%s)" + ,socket, client.protocol, client_id, relay_user.number, user_name); badlogin(socket, session, client.protocol, badauth_rsp, NULL, NULL, NULL, NULL); break; } if(stricmp(user_pass,relay_user.pass)) { if(scfg.sys_misc&SM_ECHO_PW) - lprintf(LOG_WARNING,"%04d %s !FAILED Password attempt for user %s: '%s' expected '%s'" - ,socket, client.protocol, user_name, user_pass, relay_user.pass); + lprintf(LOG_WARNING,"%04d %s %s !FAILED Password attempt for user %s: '%s' expected '%s'" + ,socket, client.protocol, client_id, user_name, user_pass, relay_user.pass); else - lprintf(LOG_WARNING,"%04d %s !FAILED Password attempt for user %s" - ,socket, client.protocol, user_name); + lprintf(LOG_WARNING,"%04d %s %s !FAILED Password attempt for user %s" + ,socket, client.protocol, client_id, user_name); badlogin(socket, session, client.protocol, badauth_rsp, user_name, user_pass, host_name, &smtp.client_addr); break; } - if(relay_user.pass[0]) + if(relay_user.pass[0]) { loginSuccess(startup->login_attempt_list, &smtp.client_addr); + listAddNodeData(¤t_logins, client.addr, strlen(client.addr) + 1, socket, LAST_NODE); + } /* Update client display */ client.user=relay_user.alias; client.usernum = relay_user.number; client_on(socket,&client,TRUE /* update */); - lprintf(LOG_INFO,"%04d %s %s authenticated using %s authentication" - ,socket,client.protocol,relay_user.alias,auth_login ? "LOGIN" : "PLAIN"); + lprintf(LOG_INFO,"%04d %s %s %s logged-in using %s authentication" + ,socket,client.protocol, client_id, relay_user.alias, auth_login ? "LOGIN" : "PLAIN"); + SAFEPRINTF(client_id, "<%s>", relay_user.alias); sockprintf(socket,client.protocol,session,auth_ok); continue; } if(!stricmp(buf,"AUTH CRAM-MD5")) { + ZERO_VAR(relay_user); + listRemoveTaggedNode(¤t_logins, socket, /* free_data */TRUE); + safe_snprintf(challenge,sizeof(challenge),"<%x%x%lx%lx@%s>" ,rand(),socket,(ulong)time(NULL),(ulong)clock(),server_host_name()); #if 0 @@ -4222,15 +4300,15 @@ static void smtp_thread(void* arg) b64_encode(str,sizeof(str),challenge,0); sockprintf(socket,client.protocol,session,"334 %s",str); if((rd=sockreadline(socket, client.protocol, session, buf, sizeof(buf)))<1) { - lprintf(LOG_WARNING,"%04d %s !missing AUTH CRAM-MD5 response", socket, client.protocol); + lprintf(LOG_WARNING,"%04d %s %s !Missing AUTH CRAM-MD5 response", socket, client.protocol, client_id); sockprintf(socket,client.protocol,session,badarg_rsp); continue; } if(startup->options&MAIL_OPT_DEBUG_RX_RSP) - lprintf(LOG_DEBUG,"%04d %s RX: %s",socket, client.protocol, buf); + lprintf(LOG_DEBUG,"%04d %s %s RX: %s",socket, client.protocol, client_id, buf); - if(b64_decode(response,sizeof(response),buf,rd)<1) { - lprintf(LOG_WARNING,"%04d %s !Bad AUTH CRAM-MD5 response", socket, client.protocol); + if(b64_decode(response,sizeof(response),buf,rd)<1 || str_has_ctrl(response)) { + lprintf(LOG_WARNING,"%04d %s %s !Bad AUTH CRAM-MD5 response", socket, client.protocol, client_id); sockprintf(socket,client.protocol,session,badarg_rsp); continue; } @@ -4244,20 +4322,20 @@ static void smtp_thread(void* arg) p=response; SAFECOPY(user_name,response); if((relay_user.number=matchuser(&scfg,user_name,FALSE))==0) { - lprintf(LOG_WARNING,"%04d %s !UNKNOWN USER: '%s'" - ,socket, client.protocol, user_name); + lprintf(LOG_WARNING,"%04d %s %s !UNKNOWN USER: '%s'" + ,socket, client.protocol, client_id, user_name); badlogin(socket, session, client.protocol, badauth_rsp, user_name, NULL, host_name, &smtp.client_addr); break; } if((i=getuserdat(&scfg, &relay_user))!=0) { - lprintf(LOG_ERR,"%04d %s !ERROR %d getting data on user (%s)" - ,socket, client.protocol, i, user_name); + lprintf(LOG_ERR,"%04d %s %s !ERROR %d getting data on user (%s)" + ,socket, client.protocol, client_id, i, user_name); badlogin(socket, session, client.protocol, badauth_rsp, NULL, NULL, NULL, NULL); break; } if(relay_user.misc&(DELETED|INACTIVE)) { - lprintf(LOG_WARNING,"%04d %s !DELETED or INACTIVE user #%u (%s)" - ,socket, client.protocol, relay_user.number, user_name); + lprintf(LOG_WARNING,"%04d %s %s !DELETED or INACTIVE user #%u (%s)" + ,socket, client.protocol, client_id, relay_user.number, user_name); badlogin(socket, session, client.protocol, badauth_rsp, NULL, NULL, NULL, NULL); break; } @@ -4275,8 +4353,8 @@ static void smtp_thread(void* arg) MD5_calc(digest,md5_data,sizeof(secret)+sizeof(digest)); MD5_hex((BYTE*)str,digest); if(strcmp(p,str)) { - lprintf(LOG_WARNING,"%04d !SMTP %s FAILED CRAM-MD5 authentication" - ,socket,relay_user.alias); + lprintf(LOG_WARNING,"%04d SMTP %s !%s FAILED CRAM-MD5 authentication" + ,socket, client_id, relay_user.alias); #if 0 lprintf(LOG_DEBUG,"%04d !SMTP calc digest: %s" ,socket,str); @@ -4287,16 +4365,19 @@ static void smtp_thread(void* arg) break; } - if(relay_user.pass[0]) + if(relay_user.pass[0]) { loginSuccess(startup->login_attempt_list, &smtp.client_addr); + listAddNodeData(¤t_logins, client.addr, strlen(client.addr) + 1, socket, LAST_NODE); + } /* Update client display */ client.user=relay_user.alias; client.usernum = relay_user.number; client_on(socket,&client,TRUE /* update */); - lprintf(LOG_INFO,"%04d %s %s authenticated using CRAM-MD5 authentication" - ,socket, client.protocol,relay_user.alias); + lprintf(LOG_INFO,"%04d %s %s %s logged-in using CRAM-MD5 authentication" + ,socket, client.protocol, client_id, relay_user.alias); + SAFEPRINTF(client_id, "<%s>", relay_user.alias); sockprintf(socket,client.protocol,session,auth_ok); continue; } @@ -4315,7 +4396,7 @@ static void smtp_thread(void* arg) } if(state<SMTP_STATE_HELO) { /* RFC 821 4.1.1 "The first command in a session must be the HELO command." */ - lprintf(LOG_WARNING,"%04d %s !MISSING 'HELO' command (Received: '%s')",socket, client.protocol, buf); + lprintf(LOG_WARNING,"%04d %s %s !MISSING 'HELO' command (Received: '%s')",socket, client.protocol, client_id, buf); sockprintf(socket,client.protocol,session, badseq_rsp); continue; } @@ -4336,9 +4417,9 @@ static void smtp_thread(void* arg) /* reset recipient list */ if((rcptlst=freopen(rcptlst_fname,"w+",rcptlst))==NULL) { - lprintf(LOG_ERR,"%04d %s !ERROR %d re-opening %s" - ,socket, client.protocol, errno, rcptlst_fname); - sockprintf(socket,client.protocol,session,sys_error); + lprintf(LOG_ERR,"%04d %s %s !ERROR %d re-opening %s" + ,socket, client.protocol, client_id, errno, rcptlst_fname); + sockprintf(socket,client.protocol,session,smtp_error, "fopen error"); break; } rcpt_count=0; @@ -4348,7 +4429,7 @@ static void smtp_thread(void* arg) sockprintf(socket,client.protocol,session,ok_rsp); badcmds=0; - lprintf(LOG_INFO,"%04d %s Session reset",socket, client.protocol); + lprintf(LOG_INFO,"%04d %s %s Session reset",socket, client.protocol, client_id); continue; } if(!strnicmp(buf,"MAIL FROM:",10) @@ -4370,8 +4451,8 @@ static void smtp_thread(void* arg) /* If MAIL FROM address is in dnsbl_exempt.cfg, clear DNSBL results */ if(dnsbl_result.s_addr && email_addr_is_exempt(reverse_path)) { - lprintf(LOG_INFO,"%04d %s Ignoring DNSBL results for exempt sender: %s" - ,socket, client.protocol,reverse_path); + lprintf(LOG_INFO,"%04d %s %s Ignoring DNSBL results for exempt sender: %s" + ,socket, client.protocol, client_id, reverse_path); dnsbl_result.s_addr=0; } @@ -4394,9 +4475,9 @@ static void smtp_thread(void* arg) /* reset recipient list */ if((rcptlst=freopen(rcptlst_fname,"w+",rcptlst))==NULL) { - lprintf(LOG_ERR,"%04d %s !ERROR %d re-opening %s" - ,socket, client.protocol, errno, rcptlst_fname); - sockprintf(socket,client.protocol,session,sys_error); + lprintf(LOG_ERR,"%04d %s %s !ERROR %d re-opening %s" + ,socket, client.protocol, client_id, errno, rcptlst_fname); + sockprintf(socket,client.protocol,session,smtp_error, "fopen error"); break; } rcpt_count=0; @@ -4421,7 +4502,7 @@ static void smtp_thread(void* arg) if(!strnicmp(buf,"RCPT TO:",8)) { if(state<SMTP_STATE_MAIL_FROM) { - lprintf(LOG_WARNING,"%04d %s !MISSING 'MAIL' command",socket, client.protocol); + lprintf(LOG_WARNING,"%04d %s %s !MISSING 'MAIL' command",socket, client.protocol, client_id); sockprintf(socket,client.protocol,session, badseq_rsp); continue; } @@ -4451,8 +4532,8 @@ static void smtp_thread(void* arg) } if(*p==0) { - lprintf(LOG_NOTICE,"%04d !SMTP NO RECIPIENT SPECIFIED" - ,socket); + lprintf(LOG_NOTICE,"%04d %s %s !NO RECIPIENT SPECIFIED" + ,socket, client.protocol, client_id); sockprintf(socket,client.protocol,session, "500 No recipient specified"); continue; } @@ -4463,8 +4544,8 @@ static void smtp_thread(void* arg) /* Check recipient counter */ if(startup->max_recipients) { if(rcpt_count>=startup->max_recipients) { - lprintf(LOG_NOTICE,"%04d %s !MAXIMUM RECIPIENTS (%d) REACHED" - ,socket, client.protocol, startup->max_recipients); + lprintf(LOG_NOTICE,"%04d %s %s !MAXIMUM RECIPIENTS (%d) REACHED" + ,socket, client.protocol, client_id, startup->max_recipients); SAFEPRINTF(tmp,"Maximum recipient count (%d)",startup->max_recipients); spamlog(&scfg, (char*)client.protocol, "REFUSED", tmp ,host_name, host_ip, rcpt_addr, reverse_path); @@ -4474,8 +4555,8 @@ static void smtp_thread(void* arg) } if(relay_user.number!=0 && !(relay_user.exempt&FLAG('M')) && rcpt_count+(waiting=getmail(&scfg,relay_user.number,/* sent: */TRUE, /* SPAM: */FALSE)) > startup->max_recipients) { - lprintf(LOG_NOTICE,"%04d %s !MAXIMUM PENDING SENT EMAILS (%lu) REACHED for User #%u (%s)" - ,socket, client.protocol, waiting, relay_user.number, relay_user.alias); + lprintf(LOG_NOTICE,"%04d %s %s !MAXIMUM PENDING SENT EMAILS (%lu) REACHED for User #%u (%s)" + ,socket, client.protocol, client_id, waiting, relay_user.number, relay_user.alias); sockprintf(socket,client.protocol,session, "452 Too many pending emails sent"); stats.msgs_refused++; continue; @@ -4484,8 +4565,8 @@ static void smtp_thread(void* arg) if(relay_user.number && (relay_user.etoday+rcpt_count) >= scfg.level_emailperday[relay_user.level] && !(relay_user.exempt&FLAG('M'))) { - lprintf(LOG_NOTICE,"%04d %s !EMAILS PER DAY LIMIT (%u) REACHED FOR USER #%u (%s)" - ,socket, client.protocol, scfg.level_emailperday[relay_user.level], relay_user.number, relay_user.alias); + lprintf(LOG_NOTICE,"%04d %s %s !EMAILS PER DAY LIMIT (%u) REACHED FOR USER #%u (%s)" + ,socket, client.protocol, client_id, scfg.level_emailperday[relay_user.level], relay_user.number, relay_user.alias); SAFEPRINTF2(tmp,"Maximum emails per day (%u) for %s" ,scfg.level_emailperday[relay_user.level], relay_user.alias); spamlog(&scfg, (char*)client.protocol, "REFUSED", tmp @@ -4494,18 +4575,18 @@ static void smtp_thread(void* arg) stats.msgs_refused++; continue; } - + /* Check for SPAM bait recipient */ if((spam_bait_result=findstr(rcpt_addr,spam_bait))==TRUE) { char reason[256]; SAFEPRINTF(reason,"SPAM BAIT (%s) taken", rcpt_addr); - lprintf(LOG_NOTICE,"%04d %s %s by: %s" - ,socket, client.protocol, reason, reverse_path); + lprintf(LOG_NOTICE,"%04d %s %s %s by: %s" + ,socket, client.protocol, client_id, reason, reverse_path); if(relay_user.number==0) { strcpy(tmp,"IGNORED"); if(dnsbl_result.s_addr==0 /* Don't double-filter */ && !spam_block_exempt) { - lprintf(LOG_NOTICE,"%04d !BLOCKING IP ADDRESS: %s in %s", socket, host_ip, spam_block); + lprintf(LOG_NOTICE,"%04d %s !BLOCKING IP ADDRESS: %s in %s", socket, client.protocol, client_id, spam_block); filter_ip(&scfg, client.protocol, reason, host_name, host_ip, reverse_path, spam_block); strcat(tmp," and BLOCKED"); } @@ -4527,8 +4608,8 @@ static void smtp_thread(void* arg) } if(relay_user.number==0 && dnsbl_result.s_addr && startup->options&MAIL_OPT_DNSBL_BADUSER) { - lprintf(LOG_NOTICE,"%04d %s !REFUSED MAIL from blacklisted server (%lu total)" - ,socket, client.protocol, ++stats.sessions_refused); + lprintf(LOG_NOTICE,"%04d %s %s !REFUSED MAIL from blacklisted server (%lu total)" + ,socket, client.protocol, client_id, ++stats.sessions_refused); SAFEPRINTF2(str,"Listed on %s as %s", dnsbl, inet_ntoa(dnsbl_result)); spamlog(&scfg, (char*)client.protocol, "REFUSED", str, host_name, host_ip, rcpt_addr, reverse_path); sockprintf(socket,client.protocol,session @@ -4547,8 +4628,8 @@ static void smtp_thread(void* arg) /* Check for full address aliases */ p=alias(&scfg,p,alias_buf); if(p==alias_buf) - lprintf(LOG_DEBUG,"%04d %s ADDRESS ALIAS: %s (for %s)" - ,socket, client.protocol,p,rcpt_addr); + lprintf(LOG_DEBUG,"%04d %s %s ADDRESS ALIAS: %s (for %s)" + ,socket, client.protocol, client_id, p, rcpt_addr); tp=strrchr(p,'@'); if(cmd==SMTP_CMD_MAIL && tp!=NULL) { @@ -4578,8 +4659,8 @@ static void smtp_thread(void* arg) faddr.net = net; faddr.zone = zone; - lprintf(LOG_INFO,"%04d %s %s relaying to FidoNet address: %s (%s)" - ,socket, client.protocol, relay_user.alias, tp+1, smb_faddrtoa(&faddr, NULL)); + lprintf(LOG_INFO,"%04d %s %s %s relaying to FidoNet address: %s (%s)" + ,socket, client.protocol, client_id, relay_user.alias, tp+1, smb_faddrtoa(&faddr, NULL)); fprintf(rcptlst,"[%u]\n",rcpt_count++); fprintf(rcptlst,"%s=%s\n",smb_hfieldtype(RECIPIENT),rcpt_addr); @@ -4621,8 +4702,8 @@ static void smtp_thread(void* arg) || relay_user.rest&(FLAG('G')|FLAG('M'))) && !findstr(host_name,relay_list) && !findstr(host_ip,relay_list)) { - lprintf(LOG_WARNING,"%04d %s !ILLEGAL RELAY ATTEMPT from %s [%s] to %s" - ,socket, client.protocol, reverse_path, host_ip, p); + lprintf(LOG_WARNING,"%04d %s %s !ILLEGAL RELAY ATTEMPT from %s [%s] to %s" + ,socket, client.protocol, client_id, reverse_path, host_ip, p); SAFEPRINTF(tmp,"Relay attempt to: %s", p); spamlog(&scfg, (char*)client.protocol, "REFUSED", tmp, host_name, host_ip, rcpt_addr, reverse_path); if(startup->options&MAIL_OPT_ALLOW_RELAY) @@ -4639,8 +4720,8 @@ static void smtp_thread(void* arg) if(relay_user.number==0) SAFECOPY(relay_user.alias,"Unknown User"); - lprintf(LOG_INFO,"%04d %s %s relaying to external mail service: %s" - ,socket, client.protocol, relay_user.alias, tp+1); + lprintf(LOG_INFO,"%04d %s %s %s relaying to external mail service: %s" + ,socket, client.protocol, client_id, relay_user.alias, tp+1); fprintf(rcptlst,"[%u]\n",rcpt_count++); fprintf(rcptlst,"%s=%s\n",smb_hfieldtype(RECIPIENT),rcpt_addr); @@ -4670,8 +4751,8 @@ static void smtp_thread(void* arg) p=alias(&scfg,p,name_alias_buf); if(p==name_alias_buf) - lprintf(LOG_DEBUG,"%04d %s NAME ALIAS: %s (for %s)" - ,socket, client.protocol,p,rcpt_addr); + lprintf(LOG_DEBUG,"%04d %s %s NAME ALIAS: %s (for %s)" + ,socket, client.protocol, client_id, p, rcpt_addr); /* Check if message is to be processed by one or more external mail processors */ mailproc_match = INT_MAX; // no match, by default @@ -4699,8 +4780,8 @@ static void smtp_thread(void* arg) if(!stricmp(p,scfg.sub[i]->code)) break; if(i>=scfg.total_subs) { - lprintf(LOG_NOTICE,"%04d %s !UNKNOWN SUB-BOARD: %s", socket, client.protocol, p); - sockprintf(socket,client.protocol,session, "550 Unknown sub-board: %s", p); + lprintf(LOG_NOTICE,"%04d %s %s !UNKNOWN SUB-BOARD: %s", socket, client.protocol, client_id, p); + sockprintf(socket,client.protocol, session, "550 Unknown sub-board: %s", p); continue; } subnum=i; @@ -4719,8 +4800,8 @@ static void smtp_thread(void* arg) #if 0 /* should we fall-through to the sysop account? */ fprintf(rcptlst,"%s=%u\n",smb_hfieldtype(RECIPIENTEXT),1); #endif - lprintf(LOG_INFO,"%04d %s Routing mail for %s to External Mail Processor: %s" - ,socket, client.protocol, rcpt_addr, mailproc_list[mailproc_match].name); + lprintf(LOG_INFO,"%04d %s %s Routing mail for %s to External Mail Processor: %s" + ,socket, client.protocol, client_id, rcpt_addr, mailproc_list[mailproc_match].name); sockprintf(socket,client.protocol,session,ok_rsp); state=SMTP_STATE_RCPT_TO; continue; @@ -4738,8 +4819,8 @@ static void smtp_thread(void* arg) } if(i<scfg.total_qhubs) { /* found matching QWKnet Hub */ - lprintf(LOG_INFO,"%04d %s Routing mail for %s <%s> to QWKnet Hub: %s" - ,socket, client.protocol, rcpt_addr, p, scfg.qhub[i]->id); + lprintf(LOG_INFO,"%04d %s %s Routing mail for %s <%s> to QWKnet Hub: %s" + ,socket, client.protocol, client_id, rcpt_addr, p, scfg.qhub[i]->id); fprintf(rcptlst,"[%u]\n",rcpt_count++); fprintf(rcptlst,"%s=%s\n",smb_hfieldtype(RECIPIENT),rcpt_addr); @@ -4754,7 +4835,7 @@ static void smtp_thread(void* arg) } if((p==alias_buf || p==name_alias_buf || startup->options&MAIL_OPT_ALLOW_RX_BY_NUMBER) - && isdigit((uchar)*p)) { + && IS_DIGIT(*p)) { usernum=atoi(p); /* RX by user number */ /* verify usernum */ username(&scfg,usernum,str); @@ -4785,48 +4866,48 @@ static void smtp_thread(void* arg) if(!usernum && startup->default_user[0]) { usernum=matchuser(&scfg,startup->default_user,TRUE /* sysop_alias */); if(usernum) - lprintf(LOG_INFO,"%04d %s Forwarding mail for UNKNOWN USER to default user-recipient: '%s' #%u" - ,socket, client.protocol,startup->default_user,usernum); + lprintf(LOG_INFO,"%04d %s %s Forwarding mail for UNKNOWN USER to default user-recipient: '%s' #%u" + ,socket, client.protocol, client_id,startup->default_user,usernum); else - lprintf(LOG_WARNING,"%04d %s !UNKNOWN DEFAULT USER-RECIPIENT: '%s'" - ,socket, client.protocol,startup->default_user); + lprintf(LOG_WARNING,"%04d %s %s !UNKNOWN DEFAULT USER-RECIPIENT: '%s'" + ,socket, client.protocol, client_id, startup->default_user); } if(usernum==UINT_MAX) { - lprintf(LOG_INFO,"%04d %s Blocked tag: %s", socket, client.protocol, rcpt_to); + lprintf(LOG_INFO,"%04d %s %s Blocked tag: %s", socket, client.protocol, client_id, rcpt_to); sockprintf(socket,client.protocol,session, "550 Unknown User: %s", rcpt_to); continue; } if(!usernum) { - lprintf(LOG_WARNING,"%04d %s !UNKNOWN USER-RECIPIENT: '%s'", socket, client.protocol, rcpt_to); + lprintf(LOG_WARNING,"%04d %s %s !UNKNOWN USER-RECIPIENT: '%s'", socket, client.protocol, client_id, rcpt_to); sockprintf(socket,client.protocol,session, "550 Unknown User: %s", rcpt_to); continue; } user.number=usernum; if((i=getuserdat(&scfg, &user))!=0) { - lprintf(LOG_ERR,"%04d %s !ERROR %d getting data on user-recipient #%u (%s)" - ,socket, client.protocol, i, usernum, p); + lprintf(LOG_ERR,"%04d %s %s !ERROR %d getting data on user-recipient #%u (%s)" + ,socket, client.protocol, client_id, i, usernum, p); sockprintf(socket,client.protocol,session, "550 Unknown User: %s", rcpt_to); continue; } if(user.misc&(DELETED|INACTIVE)) { - lprintf(LOG_WARNING,"%04d %s !DELETED or INACTIVE user-recipient #%u (%s)" - ,socket, client.protocol, usernum, p); + lprintf(LOG_WARNING,"%04d %s %s !DELETED or INACTIVE user-recipient #%u (%s)" + ,socket, client.protocol, client_id, usernum, p); sockprintf(socket,client.protocol,session, "550 Unknown User: %s", rcpt_to); continue; } if(cmd==SMTP_CMD_MAIL) { if((user.rest&FLAG('M')) && relay_user.number==0) { - lprintf(LOG_NOTICE,"%04d %s !M-restricted user-recipient #%u (%s) cannot receive unauthenticated SMTP mail" - ,socket, client.protocol, user.number, user.alias); + lprintf(LOG_NOTICE,"%04d %s %s !M-restricted user-recipient #%u (%s) cannot receive unauthenticated SMTP mail" + ,socket, client.protocol, client_id, user.number, user.alias); sockprintf(socket,client.protocol,session, "550 Closed mailbox: %s", rcpt_to); stats.msgs_refused++; continue; } if(startup->max_msgs_waiting && !(user.exempt&FLAG('W')) && (waiting=getmail(&scfg, user.number, /* sent: */FALSE, /* spam: */FALSE)) > startup->max_msgs_waiting) { - lprintf(LOG_NOTICE,"%04d %s !User-recipient #%u (%s) mailbox (%lu msgs) exceeds the maximum (%u) msgs waiting" - ,socket, client.protocol, user.number, user.alias, waiting, startup->max_msgs_waiting); + lprintf(LOG_NOTICE,"%04d %s %s !User-recipient #%u (%s) mailbox (%lu msgs) exceeds the maximum (%u) msgs waiting" + ,socket, client.protocol, client_id, user.number, user.alias, waiting, startup->max_msgs_waiting); sockprintf(socket,client.protocol,session, "450 Mailbox full: %s", rcpt_to); stats.msgs_refused++; continue; @@ -4840,8 +4921,8 @@ static void smtp_thread(void* arg) break; } if(i>=scfg.sys_nodes) { - lprintf(LOG_WARNING,"%04d %s !Attempt to send telegram to unavailable user-recipient #%u (%s)" - ,socket, client.protocol, user.number, user.alias); + lprintf(LOG_WARNING,"%04d %s %s !Attempt to send telegram to unavailable user-recipient #%u (%s)" + ,socket, client.protocol, client_id, user.number, user.alias); sockprintf(socket,client.protocol,session,"450 User unavailable"); continue; } @@ -4862,8 +4943,8 @@ static void smtp_thread(void* arg) && (user.misc&NETMAIL || forward) && tp!=NULL && smb_netaddr_type(user.netmail)==NET_INTERNET && !strstr(tp,scfg.sys_inetaddr)) { - lprintf(LOG_INFO,"%04d %s Forwarding to: %s" - ,socket, client.protocol, user.netmail); + lprintf(LOG_INFO,"%04d %s %s Forwarding to: %s" + ,socket, client.protocol, client_id, user.netmail); fprintf(rcptlst,"%s=%u\n",smb_hfieldtype(RECIPIENTNETTYPE),NET_INTERNET); fprintf(rcptlst,"%s=%s\n",smb_hfieldtype(RECIPIENTNETADDR),user.netmail); sockprintf(socket,client.protocol,session,ok_rsp); // used to be a 251 response, changed per RFC2821 @@ -4881,7 +4962,7 @@ static void smtp_thread(void* arg) /* Message Data (header and body) */ if(!strnicmp(buf,"DATA",4)) { if(state<SMTP_STATE_RCPT_TO) { - lprintf(LOG_WARNING,"%04d %s !MISSING 'RCPT TO' command", socket, client.protocol); + lprintf(LOG_WARNING,"%04d %s %s !MISSING 'RCPT TO' command", socket, client.protocol, client_id); sockprintf(socket,client.protocol,session, badseq_rsp); continue; } @@ -4890,8 +4971,8 @@ static void smtp_thread(void* arg) } remove(msgtxt_fname); if((msgtxt=fopen(msgtxt_fname,"w+b"))==NULL) { - lprintf(LOG_ERR,"%04d %s !ERROR %d opening %s" - ,socket, client.protocol, errno, msgtxt_fname); + lprintf(LOG_ERR,"%04d %s %s !ERROR %d opening %s" + ,socket, client.protocol, client_id, errno, msgtxt_fname); sockprintf(socket,client.protocol,session, insuf_stor); continue; } @@ -4914,15 +4995,15 @@ static void smtp_thread(void* arg) state=SMTP_STATE_DATA_BODY; /* No RFC headers in Telegrams */ else state=SMTP_STATE_DATA_HEADER; - lprintf(LOG_INFO,"%04d %s Receiving %s message from: %s to %s" - ,socket, client.protocol, telegram ? "telegram":"mail", reverse_path, rcpt_addr); + lprintf(LOG_INFO,"%04d %s %s Receiving %s message from %s to <%s>" + ,socket, client.protocol, client_id, telegram ? "telegram":"mail", reverse_path, rcpt_addr); hdr_lines=0; continue; } if(session == -1 && !stricmp(buf,"STARTTLS")) { if (get_ssl_cert(&scfg, &estr, &level) == -1) { if (estr) { - lprintf(level, "%04d %s !%s", socket, client.protocol, estr); + lprintf(level, "%04d %s %s !%s", socket, client.protocol, client_id, estr); free_crypt_attrstr(estr); } sockprintf(socket, client.protocol, session, "454 TLS not available"); @@ -4944,7 +5025,7 @@ static void smtp_thread(void* arg) if ((cstat=cryptSetAttribute(session, CRYPT_SESSINFO_PRIVATEKEY, scfg.tls_certificate)) != CRYPT_OK) { unlock_ssl_cert(); GCES(cstat, "SMTPS", socket, session, "setting private key"); - lprintf(LOG_ERR, "%04d !SMTP Unable to set private key", socket); + lprintf(LOG_ERR, "%04d SMTPS %s !Unable to set private key", socket, client_id); cryptDestroySession(session); session = -1; sockprintf(socket, client.protocol, session, "454 TLS not available"); @@ -4979,9 +5060,9 @@ static void smtp_thread(void* arg) continue; } sockprintf(socket,client.protocol,session,"500 Syntax error"); - lprintf(LOG_WARNING,"%04d %s !UNSUPPORTED COMMAND: '%s'", socket, client.protocol, buf); - if(++badcmds>9) { - lprintf(LOG_WARNING,"%04d %s !TOO MANY INVALID COMMANDS (%lu)",socket, client.protocol, badcmds); + lprintf(LOG_WARNING,"%04d %s %s !UNSUPPORTED COMMAND: '%s'", socket, client.protocol, client_id, buf); + if(++badcmds > SMTP_MAX_BAD_CMDS) { + lprintf(LOG_WARNING,"%04d %s %s !TOO MANY INVALID COMMANDS (%lu)",socket, client.protocol, client_id, badcmds); break; } } @@ -5002,14 +5083,15 @@ static void smtp_thread(void* arg) status(STATUS_WFC); + listRemoveTaggedNode(¤t_logins, socket, /* free_data */TRUE); protected_uint32_adjust(&active_clients, -1); update_clients(); client_off(socket); { int32_t remain = thread_down(); - lprintf(LOG_INFO,"%04d %s Session thread terminated (%u threads remain, %lu clients served)" - ,socket, client.protocol, remain, ++stats.smtp_served); + lprintf(LOG_INFO,"%04d %s %s Session thread terminated (%u threads remain, %lu clients served)" + ,socket, client.protocol, client_id, remain, ++stats.smtp_served); } free(mailproc_to_match); @@ -5150,7 +5232,7 @@ static int remove_msg_intransit(smb_t* smb, smbmsg_t* msg) msg->hdr.netattr&=~MSG_INTRANSIT; i=smb_putmsghdr(smb,msg); smb_unlockmsghdr(smb,msg); - + if(i!=0) lprintf(LOG_ERR,"0000 SEND !ERROR %d (%s) writing message header #%u" ,i, smb->last_error, msg->idx.number); @@ -5164,7 +5246,7 @@ void get_dns_server(char* dns_server, size_t len) size_t count; sprintf(dns_server,"%.*s",(int)len-1,startup->dns_server); - if(!isalnum(dns_server[0])) { + if(!IS_ALPHANUMERIC(dns_server[0])) { if((list=getNameServerList())!=NULL) { if((count=strListCount(list))>0) { sprintf(dns_server,"%.*s",(int)len,list[xp_random(count)]); @@ -5225,9 +5307,7 @@ static SOCKET sendmail_negotiate(CRYPT_SESSION *session, smb_t *smb, smbmsg_t *m ulong nb = 0; int status; char buf[512]; - char err[1024]; - - strcpy(err,"UNKNOWN ERROR"); + char err[1024] = "UNKNOWN ERROR"; for (tls_retry = 0; tls_retry < 2; tls_retry++) { if (!sendmail_open_socket(&sock, session)) @@ -5246,7 +5326,7 @@ static SOCKET sendmail_negotiate(CRYPT_SESSION *session, smb_t *smb, smbmsg_t *m ip_addr=resolve_ip(server); if(ip_addr==INADDR_NONE) { SAFEPRINTF(err, "Error resolving hostname %s", server); - lprintf(LOG_WARNING,"%04d SEND !failure resolving hostname: %s", sock, server); + lprintf(LOG_WARNING,"%04d SEND !Failure resolving hostname: %s", sock, server); continue; } @@ -5329,7 +5409,7 @@ static SOCKET sendmail_negotiate(CRYPT_SESSION *session, smb_t *smb, smbmsg_t *m lprintf(LOG_DEBUG, "%04d SEND Starting TLS session", sock); if(get_ssl_cert(&scfg, &estr, &level) == -1) { if (estr) { - lprintf(level, "%04d !SEND/TLS %s", sock, estr); + lprintf(level, "%04d SEND/TLS !%s", sock, estr); free_crypt_attrstr(estr); } continue; @@ -5407,9 +5487,9 @@ static void sendmail_thread(void* arg) char err[1024]; char buf[512]; char str[128]; + char tmp[256]; char resp[512]; char toaddr[256]; - char fromext[128]; char fromaddr[256]; char challenge[256]; char secret[64]; @@ -5539,11 +5619,29 @@ static void sendmail_thread(void* arg) smb_unlockmsghdr(&smb,&msg); continue; } + if(msg.from_net.type==NET_INTERNET && msg.reverse_path!=NULL) + angle_bracket(fromaddr, sizeof(fromaddr), msg.reverse_path); + else + angle_bracket(fromaddr, sizeof(fromaddr), usermailaddr(&scfg, str, msg.from)); + + char sender_info[512]; + if(msg.from_ext != NULL) + SAFEPRINTF2(sender_info, "'%s' #%s", msg.from, msg.from_ext); + else if(strstr(fromaddr, msg.from) == fromaddr + 1) + SAFECOPY(sender_info, fromaddr); + else + SAFEPRINTF2(sender_info, "'%s' %s", msg.from, fromaddr); + + char rcpt_info[512]; + if(compare_addrs(msg.to, (char*)msg.to_net.addr) == 0) + angle_bracket(rcpt_info, sizeof(rcpt_info), msg.to); + else + safe_snprintf(rcpt_info, sizeof(rcpt_info), "'%s' %s", msg.to, angle_bracket(tmp, sizeof(tmp), (char*)msg.to_net.addr)); if(!(startup->options&MAIL_OPT_SEND_INTRANSIT) && msg.hdr.netattr&MSG_INTRANSIT) { smb_unlockmsghdr(&smb,&msg); lprintf(LOG_NOTICE,"0000 SEND Message #%u from %s to %s - in transit" - ,msg.hdr.number, msg.from, (char*)msg.to_net.addr); + ,msg.hdr.number, sender_info, rcpt_info); continue; } msg.hdr.netattr|=MSG_INTRANSIT; /* Prevent another sendmail thread from sending this msg */ @@ -5552,18 +5650,8 @@ static void sendmail_thread(void* arg) active_sendmail=1, update_clients(); - fromext[0]=0; - if(msg.from_ext) - SAFEPRINTF(fromext," #%s", msg.from_ext); - if(msg.from_net.type==NET_INTERNET && msg.reverse_path!=NULL) - SAFECOPY(fromaddr,msg.reverse_path); - else - usermailaddr(&scfg,fromaddr,msg.from); - truncstr(fromaddr," "); - - lprintf(LOG_INFO,"0000 SEND Message #%u (%u of %u) from %s%s %s to %s [%s]" - ,msg.hdr.number, u+1, msgs, msg.from, fromext, fromaddr - ,msg.to, (char*)msg.to_net.addr); + lprintf(LOG_INFO,"0000 SEND Message #%u (%u of %u) from %s to %s" + ,msg.hdr.number, u+1, msgs, sender_info, rcpt_info); SAFEPRINTF2(str,"Sending (%u of %u)", u+1, msgs); status(str); #ifdef _WIN32 @@ -5745,10 +5833,7 @@ static void sendmail_thread(void* arg) } /* MAIL */ - if(fromaddr[0]=='<') - sockprintf(sock,prot,session,"MAIL FROM: %s",fromaddr); - else - sockprintf(sock,prot,session,"MAIL FROM: <%s>",fromaddr); + sockprintf(sock,prot,session,"MAIL FROM:%s",fromaddr); if(!sockgetrsp(sock,prot,session,"250", buf, sizeof(buf))) { remove_msg_intransit(&smb,&msg); SAFEPRINTF3(err,badrsp_err,server,buf,"250"); @@ -5769,10 +5854,7 @@ static void sendmail_thread(void* arg) && tp > p) *tp=0; /* Remove ":port" designation from envelope */ } - if(*toaddr == '<') - sockprintf(sock,prot,session,"RCPT TO: %s", toaddr); - else - sockprintf(sock,prot,session,"RCPT TO: <%s>", toaddr); + sockprintf(sock, prot, session, "RCPT TO:%s", angle_bracket(tmp, sizeof(tmp), toaddr)); if(!sockgetrsp(sock,prot,session,"25", buf, sizeof(buf))) { remove_msg_intransit(&smb,&msg); SAFEPRINTF3(err,badrsp_err,server,buf,"25*"); @@ -5802,9 +5884,8 @@ static void sendmail_thread(void* arg) continue; } } - lprintf(LOG_INFO, "%04d %s Successfully sent message #%u (%lu bytes, %lu lines) from %s%s %s to %s [%s]" - ,sock, prot, msg.hdr.number, bytes, lines, msg.from, fromext, fromaddr - ,msg.to, toaddr); + lprintf(LOG_INFO, "%04d %s Successfully sent message #%u (%lu bytes, %lu lines) from %s to '%s' %s" + ,sock, prot, msg.hdr.number, bytes, lines, sender_info, msg.to, toaddr); /* Now lets mark this message for deletion without corrupting the index */ if((msg.hdr.netattr & MSG_KILLSENT) || msg.from_ext == NULL) @@ -5823,7 +5904,7 @@ static void sendmail_thread(void* arg) mail_close_socket(&sock, &session); if(msg.from_agent==AGENT_PERSON && !(startup->options&MAIL_OPT_NO_AUTO_EXEMPT)) - exempt_email_addr("SEND Auto-exempting",msg.from,fromext,fromaddr,toaddr); + exempt_email_addr("SEND Auto-exempting", sender_info, toaddr); } status(STATUS_WFC); /* Free up resources here */ @@ -5887,8 +5968,15 @@ static void cleanup(int code) mail_set=NULL; terminated=TRUE; + while(savemsg_mutex_created && pthread_mutex_destroy(&savemsg_mutex)==EBUSY) + mswait(1); + savemsg_mutex_created = false; + update_clients(); /* active_clients is destroyed below */ + listFree(¤t_logins); + listFree(¤t_connections); + if(protected_uint32_value(active_clients)) lprintf(LOG_WARNING,"!!!! Terminating with %d active clients", protected_uint32_value(active_clients)); else @@ -5903,6 +5991,8 @@ static void cleanup(int code) if(terminate_server || code) { char str[1024]; sprintf(str,"%lu connections served", stats.connections_served); + if(stats.connections_exceeded) + sprintf(str+strlen(str),", %lu exceeded max", stats.connections_exceeded); if(stats.connections_refused) sprintf(str+strlen(str),", %lu refused", stats.connections_refused); if(stats.connections_ignored) @@ -5932,7 +6022,7 @@ const char* DLLCALL mail_ver(void) DESCRIBE_COMPILER(compiler); - sscanf("$Revision: 1.734 $", "%*s %s", revision); + sscanf("$Revision: 1.735 $", "%*s %s", revision); sprintf(ver,"%s %s%s SMBLIB %s " "Compiled %s %s with %s" @@ -5971,7 +6061,7 @@ void DLLCALL mail_server(void* arg) smtp_t* smtp; FILE* fp; str_list_t sec_list; - void *cbdata; + char* servprot = "N/A"; CRYPT_SESSION session = -1; mail_ver(); @@ -6012,6 +6102,8 @@ void DLLCALL mail_server(void* arg) SetThreadName("sbbs/mailServer"); protected_uint32_init(&thread_count, 0); + listInit(¤t_logins, LINK_LIST_MUTEX); + listInit(¤t_connections, LINK_LIST_MUTEX); do { protected_uint32_init(&active_clients, 0); @@ -6160,30 +6252,30 @@ void DLLCALL mail_server(void* arg) } terminated=FALSE; if(!xpms_add_list(mail_set, PF_UNSPEC, SOCK_STREAM, 0, startup->interfaces - , startup->smtp_port, "SMTP Transfer Agent", mail_open_socket, startup->seteuid, "smtp")) + , startup->smtp_port, "SMTP Transfer Agent", mail_open_socket, startup->seteuid, (void*)servprot_smtp)) lprintf(LOG_INFO,"SMTP No extra interfaces listening"); if(startup->options&MAIL_OPT_USE_SUBMISSION_PORT) { xpms_add_list(mail_set, PF_UNSPEC, SOCK_STREAM, 0, startup->interfaces - , startup->submission_port, "SMTP Submission Agent", mail_open_socket, startup->seteuid, "submission"); + , startup->submission_port, "SMTP Submission Agent", mail_open_socket, startup->seteuid, (void*)servprot_submission); } if(startup->options&MAIL_OPT_TLS_SUBMISSION) { xpms_add_list(mail_set, PF_UNSPEC, SOCK_STREAM, 0, startup->interfaces, startup->submissions_port - , "SMTPS Submission Agent", mail_open_socket, startup->seteuid, "submissions"); + , "SMTPS Submission Agent", mail_open_socket, startup->seteuid, (void*)servprot_submissions); } if(startup->options&MAIL_OPT_ALLOW_POP3) { /* open a socket and wait for a client */ if(!xpms_add_list(mail_set, PF_UNSPEC, SOCK_STREAM, 0, startup->pop3_interfaces, startup->pop3_port - , "POP3 Server", mail_open_socket, startup->seteuid, "pop3")) + , "POP3 Server", mail_open_socket, startup->seteuid, (void*)servprot_pop3)) lprintf(LOG_INFO,"POP3 No extra interfaces listening"); } if(startup->options&MAIL_OPT_TLS_POP3) { /* open a socket and wait for a client */ if(!xpms_add_list(mail_set, PF_UNSPEC, SOCK_STREAM, 0, startup->pop3_interfaces - , startup->pop3s_port, "POP3S Server", mail_open_socket, startup->seteuid, "pop3s")) + , startup->pop3s_port, "POP3S Server", mail_open_socket, startup->seteuid, (void*)servprot_pop3s)) lprintf(LOG_INFO,"POP3S No extra interfaces listening"); } @@ -6209,6 +6301,9 @@ void DLLCALL mail_server(void* arg) semfile_list_check(&initialized,shutdown_semfiles); } + pthread_mutex_init(&savemsg_mutex, NULL); + savemsg_mutex_created = true; + /* signal caller that we've started up successfully */ if(startup->started!=NULL) startup->started(startup->cbdata); @@ -6242,13 +6337,30 @@ void DLLCALL mail_server(void* arg) /* now wait for connection */ client_addr_len = sizeof(client_addr); - client_socket = xpms_accept(mail_set,&client_addr, &client_addr_len, startup->sem_chk_freq*1000, &cbdata); + client_socket = xpms_accept(mail_set,&client_addr, &client_addr_len, startup->sem_chk_freq*1000, (void**)&servprot); if(client_socket != INVALID_SOCKET) { + bool is_smtp = (servprot != servprot_pop3 && servprot != servprot_pop3s); if(startup->socket_open!=NULL) startup->socket_open(startup->cbdata,TRUE); stats.sockets++; inet_addrtop(&client_addr, host_ip, sizeof(host_ip)); + + if(startup->max_concurrent_connections > 0) { + int ip_len = strlen(host_ip)+1; + int connections = listCountMatches(¤t_connections, host_ip, ip_len); + int logins = listCountMatches(¤t_logins, host_ip, ip_len); + + if(connections - logins >= (int)startup->max_concurrent_connections + && !is_host_exempt(&scfg, host_ip, /* host_name */NULL)) { + lprintf(LOG_NOTICE, "%04d %s [%s] !Maximum concurrent connections without login (%u) exceeded (%lu total)" + ,client_socket, servprot, host_ip, startup->max_concurrent_connections, ++stats.connections_exceeded); + sockprintf(client_socket, servprot, session, is_smtp ? smtp_error : pop_error, "Maximum connections exceeded"); + mail_close_socket(&client_socket, &session); + continue; + } + } + if(trashcan(&scfg,host_ip,"ip-silent")) { mail_close_socket(&client_socket, &session); stats.connections_ignored++; @@ -6257,8 +6369,8 @@ void DLLCALL mail_server(void* arg) if(protected_uint32_value(active_clients)>=startup->max_clients) { lprintf(LOG_WARNING,"%04d %s !MAXIMUM CLIENTS (%u) reached, access denied (%lu total)" - ,client_socket, (char *)cbdata, startup->max_clients, ++stats.connections_refused); - sockprintf(client_socket, cbdata, session,"-ERR Maximum active clients reached, please try again later."); + ,client_socket, servprot, startup->max_clients, ++stats.connections_refused); + sockprintf(client_socket, servprot, session, is_smtp ? smtp_error : pop_error, "Maximum active clients reached"); mswait(3000); mail_close_socket(&client_socket, &session); continue; @@ -6268,17 +6380,18 @@ void DLLCALL mail_server(void* arg) if((i=ioctlsocket(client_socket, FIONBIO, &l))!=0) { lprintf(LOG_CRIT,"%04d %s !ERROR %d (%d) disabling blocking on socket" - ,client_socket, (char *)cbdata, i, ERROR_VALUE); - sockprintf(client_socket, cbdata, session,"-ERR System error, please try again later."); + ,client_socket, servprot, i, ERROR_VALUE); + sockprintf(client_socket, servprot, session, is_smtp ? smtp_error : pop_error, "ioctlsocket error"); mswait(3000); mail_close_socket(&client_socket, &session); continue; } - if(strcmp((char *)cbdata, "pop3") && strcmp((char *)cbdata, "pop3s")) { /* Not POP3 */ + if(is_smtp) { if((smtp=malloc(sizeof(smtp_t)))==NULL) { lprintf(LOG_CRIT,"%04d SMTP !ERROR allocating %lu bytes of memory for smtp_t" ,client_socket, (ulong)sizeof(smtp_t)); + sockprintf(client_socket, servprot, session, smtp_error, "malloc failure"); mail_close_socket(&client_socket, &session); continue; } @@ -6286,14 +6399,14 @@ void DLLCALL mail_server(void* arg) smtp->socket=client_socket; memcpy(&smtp->client_addr, &client_addr, client_addr_len); smtp->client_addr_len=client_addr_len; - smtp->tls_port = (strcmp((char *)cbdata, "submissions") == 0); + smtp->tls_port = (servprot == servprot_submissions); protected_uint32_adjust(&thread_count,1); _beginthread(smtp_thread, 0, smtp); stats.connections_served++; } else { if((pop3=malloc(sizeof(pop3_t)))==NULL) { - lprintf(LOG_CRIT,"%04d !POP3 ERROR allocating %lu bytes of memory for pop3_t" + lprintf(LOG_CRIT,"%04d POP3 !ERROR allocating %lu bytes of memory for pop3_t" ,client_socket,(ulong)sizeof(pop3_t)); sockprintf(client_socket, "POP3", session,"-ERR System error, please try again later."); mswait(3000); @@ -6304,7 +6417,7 @@ void DLLCALL mail_server(void* arg) pop3->socket=client_socket; memcpy(&pop3->client_addr, &client_addr, client_addr_len); pop3->client_addr_len=client_addr_len; - pop3->tls_port = (strcmp((char *)cbdata, "pop3s") == 0); + pop3->tls_port = (servprot == servprot_pop3s); protected_uint32_adjust(&thread_count,1); _beginthread(pop3_thread, 0, pop3); stats.connections_served++; diff --git a/src/sbbs3/mailsrvr.h b/src/sbbs3/mailsrvr.h index 8e23387f351285160e83cf9319f00109a2e3cf9d..95791bbd40636375d81e5abb1215a6f540ac8296 100644 --- a/src/sbbs3/mailsrvr.h +++ b/src/sbbs3/mailsrvr.h @@ -126,6 +126,7 @@ typedef struct { /* Login Attempt parameters */ struct login_attempt_settings login_attempt; link_list_t* login_attempt_list; + uint max_concurrent_connections; } mail_startup_t; diff --git a/src/sbbs3/main.cpp b/src/sbbs3/main.cpp index 38dc48a68b7976c0bf01ccaddfa18cb39e0d6b6b..13866c396958c642fabab5be4f38924f0140c226 100644 --- a/src/sbbs3/main.cpp +++ b/src/sbbs3/main.cpp @@ -425,7 +425,7 @@ u_long resolve_ip(char *addr) return((u_long)INADDR_NONE); for(p=addr;*p;p++) - if(*p!='.' && !isdigit((uchar)*p)) + if(*p!='.' && !IS_DIGIT(*p)) break; if(!(*p)) return(inet_addr(addr)); @@ -4538,7 +4538,8 @@ void node_thread(void* arg) if(sbbs->answer()) { login_success = true; - listAddNodeData(¤t_logins, sbbs->client.addr, strlen(sbbs->client.addr)+1, sbbs->cfg.node_num, LAST_NODE); + if(sbbs->useron.pass[0]) + listAddNodeData(¤t_logins, sbbs->client.addr, strlen(sbbs->client.addr)+1, sbbs->cfg.node_num, LAST_NODE); if(sbbs->sys_status&SS_QWKLOGON) { sbbs->getsmsg(sbbs->useron.number); sbbs->qwk_sec(); @@ -4716,7 +4717,7 @@ bool sbbs_t::backup(const char* fname, int backup_level, bool rename) if(!fexist(fname)) return false; - lprintf(LOG_DEBUG, "Backing-up %s (%lu bytes)", fname, flength(fname)); + lprintf(LOG_DEBUG, "Backing-up %s (%lu bytes)", fname, (long)flength(fname)); return ::backup(fname, backup_level, rename) ? true : false; } diff --git a/src/sbbs3/msgdate.c b/src/sbbs3/msgdate.c index d5c564e3fa4e1f0921ee1d516173df5b96e10e6c..34a2028455d0d3c8b9718260e22679ad973328c2 100644 --- a/src/sbbs3/msgdate.c +++ b/src/sbbs3/msgdate.c @@ -86,10 +86,10 @@ when_t DLLCALL rfc822date(char* date) memset(&when,0,sizeof(when)); while(*p && *p<=' ') p++; - while(*p && !isdigit(*p)) p++; + while(*p && !IS_DIGIT(*p)) p++; /* DAY */ tm.tm_mday=atoi(p); - while(*p && isdigit(*p)) p++; + while(*p && IS_DIGIT(*p)) p++; /* MONTH */ while(*p && *p<=' ') p++; sprintf(month,"%3.3s",p); @@ -125,23 +125,23 @@ when_t DLLCALL rfc822date(char* date) else if(tm.tm_year>1900) tm.tm_year-=1900; - while(*p && isdigit(*p)) p++; + while(*p && IS_DIGIT(*p)) p++; /* HOUR */ while(*p && *p<=' ') p++; tm.tm_hour=atoi(p); - while(*p && isdigit(*p)) p++; + while(*p && IS_DIGIT(*p)) p++; /* MINUTE */ if(*p) p++; tm.tm_min=atoi(p); - while(*p && isdigit(*p)) p++; + while(*p && IS_DIGIT(*p)) p++; /* SECONDS */ if(*p) p++; tm.tm_sec=atoi(p); - while(*p && isdigit(*p)) p++; + while(*p && IS_DIGIT(*p)) p++; /* TIME ZONE */ while(*p && *p<=' ') p++; if(*p) { - if(isdigit(*p) || *p=='-' || *p=='+') { /* [+|-]HHMM format */ + if(IS_DIGIT(*p) || *p=='-' || *p=='+') { /* [+|-]HHMM format */ if(*p=='+') p++; sprintf(str,"%.*s",*p=='-'? 3:2,p); when.zone=atoi(str)*60; diff --git a/src/sbbs3/netmail.cpp b/src/sbbs3/netmail.cpp index 5e6f206c2c18d3f81bd46fb9d68bed507d565a52..eab9d211cddb2a309b1e3123f133de1841ad7a84 100644 --- a/src/sbbs3/netmail.cpp +++ b/src/sbbs3/netmail.cpp @@ -428,11 +428,11 @@ void sbbs_t::qwktonetmail(FILE *rep, char *block, char *into, uchar fromhub) p=strrchr(to,'@'); /* Find '@' in name@addr */ - if(p && !isdigit(*(p+1)) && !strchr(p,'.') && !strchr(p,':')) { /* QWKnet */ + if(p && !IS_DIGIT(*(p+1)) && !strchr(p,'.') && !strchr(p,':')) { /* QWKnet */ qnet=1; *p=0; } - else if(p==NULL || !isdigit(*(p+1)) || !cfg.total_faddrs) { + else if(p==NULL || !IS_DIGIT(*(p+1)) || !cfg.total_faddrs) { if(cfg.inetmail_misc&NMAIL_ALLOW) { /* Internet */ inet=1; } else { diff --git a/src/sbbs3/newuser.cpp b/src/sbbs3/newuser.cpp index a06d1a91a1be0266893b27e1ce9e25a36c5e0cfd..f462e72fe84bdd4fcde64c2b7f75c062cc94bb3a 100644 --- a/src/sbbs3/newuser.cpp +++ b/src/sbbs3/newuser.cpp @@ -154,7 +154,7 @@ BOOL sbbs_t::newuser() while(text[HitYourBackspaceKey][0] && !(useron.misc&(PETSCII|SWAP_DELETE)) && online) { bputs(text[HitYourBackspaceKey]); - uchar key = getkey(K_NONE); + uchar key = getkey(K_CTRLKEYS); bprintf(text[CharacterReceivedFmt], key, key); if(key == '\b') break; @@ -179,7 +179,8 @@ BOOL sbbs_t::newuser() } if(useron.misc&ANSI) { - useron.rows=0; /* Auto-rows */ + useron.rows = TERM_ROWS_AUTO; + useron.cols = TERM_COLS_AUTO; if(!(cfg.uq&UQ_COLORTERM) || useron.misc&(RIP|WIP|HTML) || yesno(text[ColorTerminalQ])) useron.misc|=COLOR; else @@ -382,7 +383,7 @@ BOOL sbbs_t::newuser() c=0; while(c < RAND_PASS_LEN) { /* Create random password */ useron.pass[c]=sbbs_random(43)+'0'; - if(isalnum(useron.pass[c])) + if(IS_ALPHANUMERIC(useron.pass[c])) c++; } useron.pass[c]=0; diff --git a/src/sbbs3/pack_qwk.cpp b/src/sbbs3/pack_qwk.cpp index 110cbf3ebfe2abc5392ac6d6d4e0b8dd317252d8..1645895e470dc86b5cc22e256132a72331f295e9 100644 --- a/src/sbbs3/pack_qwk.cpp +++ b/src/sbbs3/pack_qwk.cpp @@ -712,7 +712,7 @@ bool sbbs_t::pack_qwk(char *packet, ulong *msgcnt, bool prepack) for(i=0;i<(uint)g.gl_pathc;i++) { /* Copy BLT-*.* files */ fname=getfname(g.gl_pathv[i]); padfname(fname,str); - if(isdigit(str[4]) && isdigit(str[9])) { + if(IS_DIGIT(str[4]) && IS_DIGIT(str[9])) { SAFEPRINTF2(str,"%sQWK/%s",cfg.text_dir,fname); SAFEPRINTF2(tmp2,"%s%s",cfg.temp_dir,fname); mv(str,tmp2,/* copy: */TRUE); diff --git a/src/sbbs3/postmsg.cpp b/src/sbbs3/postmsg.cpp index e54a2921f45db0adc84fb813e1b615a6bcebbd5e..20ef5cf5656ae46ddae37c0b87a3e4252c95130d 100644 --- a/src/sbbs3/postmsg.cpp +++ b/src/sbbs3/postmsg.cpp @@ -63,6 +63,16 @@ int msgbase_open(scfg_t* cfg, smb_t* smb, unsigned int subnum, int* storage, lon return i; } +static uchar* findsig(char* msgbuf) +{ + char* tail = strstr(msgbuf, "\n-- \r\n"); + if(tail != NULL) { + *tail = '\0'; + tail++; + truncsp(msgbuf); + } + return (uchar*)tail; +} /****************************************************************************/ /* Posts a message on sub-board number 'subnum' */ @@ -313,7 +323,7 @@ bool sbbs_t::postmsg(uint subnum, long wm_mode, smb_t* resmb, smbmsg_t* remsg) if(tags[0]) smb_hfield_str(&msg, SMB_TAGS, tags); - i=smb_addmsg(&smb,&msg,storage,dupechk_hashes,xlat,(uchar*)msgbuf,NULL); + i=smb_addmsg(&smb,&msg,storage,dupechk_hashes,xlat,(uchar*)msgbuf, findsig(msgbuf)); free(msgbuf); if(i==SMB_DUPE_MSG) { @@ -402,7 +412,7 @@ extern "C" int DLLCALL msg_client_hfields(smbmsg_t* msg, client_t* client) return SMB_SUCCESS; } -/* Note: support MSG_BODY only, no tails or other data fields (dfields) */ +/* Note: finds signature delimiter automatically and (if applicable) separates msgbuf into body and tail */ /* Adds/generates Message-IDs when needed */ extern "C" int DLLCALL savemsg(scfg_t* cfg, smb_t* smb, smbmsg_t* msg, client_t* client, const char* server, char* msgbuf, smbmsg_t* remsg) { @@ -484,7 +494,10 @@ extern "C" int DLLCALL savemsg(scfg_t* cfg, smb_t* smb, smbmsg_t* msg, client_t* || (msg->subj != NULL && !str_is_ascii(msg->subj) && utf8_str_is_valid(msg->subj))) msg->hdr.auxattr |= MSG_HFIELDS_UTF8; - if((i=smb_addmsg(smb,msg,smb_storage_mode(cfg, smb),dupechk_hashes,xlat,(uchar*)msgbuf, /* tail: */NULL))==SMB_SUCCESS + msgbuf = strdup(msgbuf); + if(msgbuf == NULL) + return SMB_FAILURE; + if((i=smb_addmsg(smb,msg,smb_storage_mode(cfg, smb),dupechk_hashes,xlat,(uchar*)msgbuf, findsig(msgbuf)))==SMB_SUCCESS && msg->to!=NULL /* no recipient means no header created at this stage */) { if(smb->subnum == INVALID_SUB) { if(msg->to_net.type == NET_FIDO && cfg->netmail_sem[0]) @@ -519,6 +532,7 @@ extern "C" int DLLCALL savemsg(scfg_t* cfg, smb_t* smb, smbmsg_t* msg, client_t* } } } + free(msgbuf); return(i); } diff --git a/src/sbbs3/putmsg.cpp b/src/sbbs3/putmsg.cpp index 6b8709908b5d1a25f5b42de0efa92d85395f8799..a18df8a2eb4fa57737fee43f29c75543d553b4fa 100644 --- a/src/sbbs3/putmsg.cpp +++ b/src/sbbs3/putmsg.cpp @@ -89,6 +89,7 @@ char sbbs_t::putmsgfrag(const char* buf, long* mode, long org_cols, JSObject* ob char tmp2[256],tmp3[128]; char* str=(char*)buf; uchar exatr=0; + char mark = '\0'; int i; ulong l=0; uint lines_printed = 0; @@ -158,11 +159,49 @@ char sbbs_t::putmsgfrag(const char* buf, long* mode, long org_cols, JSObject* ob } break; } + if((*mode) & P_MARKUP) { + if(((mark == 0) && (str[l] == '*' || str[l] == '/' || str[l] == '_' || str[l] == '#')) || str[l] == mark) { + char* next= NULL; + if(mark == 0) + next = strchr(str + l + 1, str[l]); + char *blank = strstr(str + l + 1, "\n\r"); + if(((l < 1 || IS_WHITESPACE(str[l - 1]) || IS_PUNCTUATION(str[l - 1])) + && IS_ALPHANUMERIC(str[l + 1]) && mark == 0 && next != NULL && (*(next + 1) == '\0' || IS_WHITESPACE(*(next + 1)) || IS_PUNCTUATION(*(next+1))) + && (blank == NULL || next < blank)) + || str[l] == mark) { + if(mark == 0) + mark = str[l]; + else { + mark = 0; + if(!((*mode) & P_HIDEMARKS)) + outchar(str[l]); + } + switch(str[l]) { + case '*': + attr(curatr ^ HIGH); + break; + case '/': + attr(curatr ^ BLINK); + break; + case '_': + attr(curatr ^ (HIGH|BLINK)); + break; + case '#': + attr(((curatr&0x0f) << 4) | ((curatr&0xf0) >> 4)); + break; + } + if(mark != 0 && !((*mode) & P_HIDEMARKS)) + outchar(str[l]); + l++; + continue; + } + } + } if(str[l]==CTRL_A && str[l+1]!=0) { if(str[l+1]=='"' && !(sys_status&SS_NEST_PF) && !((*mode)&P_NOATCODES)) { /* Quote a file */ l+=2; i=0; - while(i<(int)sizeof(tmp2)-1 && isprint((unsigned char)str[l]) && str[l]!='\\' && str[l]!='/') + while(i<(int)sizeof(tmp2)-1 && IS_PRINTABLE(str[l]) && str[l]!='\\' && str[l]!='/') tmp2[i++]=str[l++]; if(i > 0) { tmp2[i]=0; @@ -195,7 +234,7 @@ char sbbs_t::putmsgfrag(const char* buf, long* mode, long org_cols, JSObject* ob } else if(!((*mode)&P_NOXATTRS) && (cfg.sys_misc&SM_PCBOARD) && str[l]=='@' && str[l+1]=='X' - && isxdigit((unsigned char)str[l+2]) && isxdigit((unsigned char)str[l+3])) { + && IS_HEXDIGIT(str[l+2]) && IS_HEXDIGIT(str[l+3])) { sprintf(tmp2,"%.2s",str+l+2); ulong val = ahtoul(tmp2); // @X00 saves the current color and @XFF restores that saved color @@ -216,15 +255,15 @@ char sbbs_t::putmsgfrag(const char* buf, long* mode, long org_cols, JSObject* ob } else if(!((*mode)&P_NOXATTRS) && (cfg.sys_misc&SM_WILDCAT) && str[l]=='@' && str[l+3]=='@' - && isxdigit((unsigned char)str[l+1]) && isxdigit((unsigned char)str[l+2])) { + && IS_HEXDIGIT(str[l+1]) && IS_HEXDIGIT(str[l+2])) { sprintf(tmp2,"%.2s",str+l+1); attr(ahtoul(tmp2)); // exatr=1; l+=4; } else if(!((*mode)&P_NOXATTRS) - && (cfg.sys_misc&SM_RENEGADE) && str[l]=='|' && isdigit((unsigned char)str[l+1]) - && isdigit((unsigned char)str[l+2]) && !(useron.misc&RIP)) { + && (cfg.sys_misc&SM_RENEGADE) && str[l]=='|' && IS_DIGIT(str[l+1]) + && IS_DIGIT(str[l+2]) && !(useron.misc&RIP)) { sprintf(tmp2,"%.2s",str+l+1); i=atoi(tmp2); if(i>=16) { /* setting background */ @@ -239,7 +278,7 @@ char sbbs_t::putmsgfrag(const char* buf, long* mode, long org_cols, JSObject* ob l+=3; /* Skip |xx */ } else if(!((*mode)&P_NOXATTRS) - && (cfg.sys_misc&SM_CELERITY) && str[l]=='|' && isalpha((unsigned char)str[l+1]) + && (cfg.sys_misc&SM_CELERITY) && str[l]=='|' && IS_ALPHA(str[l+1]) && !(useron.misc&RIP)) { switch(str[l+1]) { case 'k': @@ -298,7 +337,7 @@ char sbbs_t::putmsgfrag(const char* buf, long* mode, long org_cols, JSObject* ob l+=2; /* Skip |x */ } /* Skip second digit if it exists */ else if(!((*mode)&P_NOXATTRS) - && (cfg.sys_misc&SM_WWIV) && str[l]==CTRL_C && isdigit((unsigned char)str[l+1])) { + && (cfg.sys_misc&SM_WWIV) && str[l]==CTRL_C && IS_DIGIT(str[l+1])) { exatr=1; switch(str[l+1]) { default: diff --git a/src/sbbs3/qwktomsg.cpp b/src/sbbs3/qwktomsg.cpp index f8eedf254091428ecc1d98661255097950a21e49..7bf457d277ea0a2158addb0c68d04cafed3ccd20 100644 --- a/src/sbbs3/qwktomsg.cpp +++ b/src/sbbs3/qwktomsg.cpp @@ -366,10 +366,9 @@ bool sbbs_t::qwk_import_msg(FILE *qwk_fp, char *hdrblk, ulong blocks if(!bodylen && !taillen) /* Ignore blank lines at top of message */ continue; if(!taillen && col==3 && bodylen>=3 && body[bodylen-3]=='-' - && body[bodylen-2]=='-' && body[bodylen-1]=='-') { + && body[bodylen-2]=='-' && (body[bodylen-1]=='-' || body[bodylen-1]==' ')) { + taillen = sprintf(tail, "--%c", body[bodylen-1]); /* DO NOT USE SAFECOPY */ bodylen-=3; - strcpy(tail,"---"); /* DO NOT USE SAFECOPY */ - taillen=3; } col=0; if(taillen) { diff --git a/src/sbbs3/readmsgs.cpp b/src/sbbs3/readmsgs.cpp index 4fcf265ec2a1267c733f6deb354161f2d2768f9d..1cb29d9ec21a95c8027f83557aa57aa01d0a13ae 100644 --- a/src/sbbs3/readmsgs.cpp +++ b/src/sbbs3/readmsgs.cpp @@ -802,7 +802,7 @@ int sbbs_t::scanposts(uint subnum, long mode, const char *find) domsg = true; continue; } - if(thread_mode && (isalpha(l) || l=='?')) { + if(thread_mode && (IS_ALPHA(l) || l=='?')) { thread_mode = false; domsg = true; } diff --git a/src/sbbs3/readtext.c b/src/sbbs3/readtext.c index 3454b53e2464334f9292ebe9696c9c66cb4dc47a..e92c1e962a3c5e0f5be27e4eac6bc81f8c43df3f 100644 --- a/src/sbbs3/readtext.c +++ b/src/sbbs3/readtext.c @@ -50,10 +50,10 @@ char *readtext(long *line,FILE *stream,long dflt) for(i=1,j=0;i<k && j<sizeof(str)-1;j++) { if(buf[i]=='\\') { /* escape */ i++; - if(isdigit(buf[i])) { + if(IS_DIGIT(buf[i])) { str[j]=atoi(buf+i); /* decimal, NOT octal */ - if(isdigit(buf[++i])) /* skip up to 3 digits */ - if(isdigit(buf[++i])) + if(IS_DIGIT(buf[++i])) /* skip up to 3 digits */ + if(IS_DIGIT(buf[++i])) i++; continue; } diff --git a/src/sbbs3/release.bat b/src/sbbs3/release.bat index c7e6716189e2166d00baee0c7d85829c92e05170..928d02cb898c6e0883ef9e15bc5e0b283ea832fa 100644 --- a/src/sbbs3/release.bat +++ b/src/sbbs3/release.bat @@ -1,2 +1,2 @@ @echo off -call build.bat "/p:Configuration=Release" \ No newline at end of file +call build.bat "/p:Configuration=Release" %* \ No newline at end of file diff --git a/src/sbbs3/sbbs.h b/src/sbbs3/sbbs.h index b9ee228a36428cae4d79cd823db7920886746949..d5328abd56b2a806339df2e963128b5b9da0d8ea 100644 --- a/src/sbbs3/sbbs.h +++ b/src/sbbs3/sbbs.h @@ -784,6 +784,7 @@ public: long term_supports(long cmp_flags=0); const char* term_type(long term_supports = -1); const char* term_charset(long term_supports = -1); + bool update_nodeterm(void); int backfill(const char* str, float pct, int full_attr, int empty_attr); void progress(const char* str, int count, int total, int interval=1); bool saveline(void); @@ -893,7 +894,7 @@ public: char* parse_login(char*); /* answer.cpp */ - bool answer(); + bool answer(void); /* logon.ccp */ bool logon(void); @@ -1212,6 +1213,7 @@ extern "C" { DLLEXPORT char ctrl_a_to_ascii_char(char code); DLLEXPORT char * truncstr(char* str, const char* set); DLLEXPORT char * ascii_str(uchar* str); + DLLEXPORT char * condense_whitespace(char* str); DLLEXPORT char exascii_to_ascii_char(uchar ch); DLLEXPORT BOOL findstr(const char *insearch, const char *fname); DLLEXPORT BOOL findstr_in_string(const char* insearchof, char* string); @@ -1220,6 +1222,7 @@ extern "C" { DLLEXPORT BOOL trashcan(scfg_t* cfg, const char *insearch, const char *name); DLLEXPORT char * trashcan_fname(scfg_t* cfg, const char *name, char* fname, size_t); DLLEXPORT str_list_t trashcan_list(scfg_t* cfg, const char* name); + DLLEXPORT char * strip_ansi(char* str); DLLEXPORT char * strip_exascii(const char *str, char* dest); DLLEXPORT char * strip_space(const char *str, char* dest); DLLEXPORT char * prep_file_desc(const char *str, char* dest); diff --git a/src/sbbs3/sbbs_ini.c b/src/sbbs3/sbbs_ini.c index e0bd769973b0bab5f24158b788e7499e169aae10..c6d8fd182e0e4493a3591ec13693de9065d5e63e 100644 --- a/src/sbbs3/sbbs_ini.c +++ b/src/sbbs3/sbbs_ini.c @@ -591,6 +591,7 @@ void sbbs_read_ini( mail->bind_retry_count=iniGetInteger(list,section,strBindRetryCount,global->bind_retry_count); mail->bind_retry_delay=iniGetInteger(list,section,strBindRetryDelay,global->bind_retry_delay); mail->login_attempt = get_login_attempt_settings(list, section, global); + mail->max_concurrent_connections = iniGetInteger(list, section, "MaxConcurrentConnections", 0); } /***********************************************************************/ @@ -1042,6 +1043,8 @@ BOOL sbbs_write_ini( break; if(!iniSetInteger(lp,section,"ConnectTimeout",mail->connect_timeout,&style)) break; + if(!iniSetInteger(lp,section,"MaxConcurrentConnections",mail->max_concurrent_connections,&style)) + break; if(strcmp(mail->host_name,global->host_name)==0 || (bbs != NULL && strcmp(bbs->host_name,cfg->sys_inetaddr)==0)) diff --git a/src/sbbs3/sbbscon.c b/src/sbbs3/sbbscon.c index c603e9f9331dbaad4c37f82342695a75ad972700..205c69dff3798fc8693abc811bbd73fffc0914c6 100644 --- a/src/sbbs3/sbbscon.c +++ b/src/sbbs3/sbbscon.c @@ -1723,7 +1723,7 @@ int main(int argc, char** argv) mail_startup.options=strtoul(arg,NULL,0); break; case 'S': /* SMTP/SendMail */ - if(isdigit(*arg)) { + if(IS_DIGIT(*arg)) { mail_startup.smtp_port=atoi(arg); break; } @@ -1737,7 +1737,7 @@ int main(int argc, char** argv) } break; case 'P': /* POP3 */ - if(isdigit(*arg)) { + if(IS_DIGIT(*arg)) { mail_startup.pop3_port=atoi(arg); break; } diff --git a/src/sbbs3/sbbsdefs.h b/src/sbbs3/sbbsdefs.h index 3790189074abbec58dbab0092c42041f25f8e8b7..2d475447d147b37094c6bcc69accc1f5d4fa0be1 100644 --- a/src/sbbs3/sbbsdefs.h +++ b/src/sbbs3/sbbsdefs.h @@ -530,7 +530,9 @@ typedef enum { /* Values for xtrn_t.event */ #define LEN_FDESC 58 /* File description */ #define LEN_FCDT 9 /* 9 digits for file credit values */ #define LEN_TITLE 70 /* Message title */ -#define LEN_MAIN_CMD 34 /* Storage in user.dat for custom commands */ +#define LEN_MAIN_CMD 28 /* Unused Storage in user.dat */ +#define LEN_COLS 3 +#define LEN_ROWS 3 #define LEN_PASS 40 #define MIN_PASS_LEN 4 #define RAND_PASS_LEN 8 @@ -592,14 +594,16 @@ typedef enum { /* Values for xtrn_t.event */ #define U_FLAGS2 U_TL+2 #define U_EXEMPT U_FLAGS2+8 #define U_REST U_EXEMPT+8 -#define U_ROWS U_REST+8+2 /* Number of Rows on user's monitor */ -#define U_SEX U_ROWS+2 /* Sex, Del, ANSI, color etc. */ +#define U_OLDROWS U_REST+8+2 /* Number of Rows on user's monitor */ +#define U_SEX U_OLDROWS+2 /* Sex, Del, ANSI, color etc. */ #define U_MISC U_SEX+1 /* Miscellaneous flags in 8byte hex */ #define U_OLDXEDIT U_MISC+8 /* External editor (Version 1 method */ #define U_LEECH U_OLDXEDIT+2 /* two hex digits - leech attempt count */ #define U_CURSUB U_LEECH+2 /* Current sub (internal code) */ #define U_CURXTRN U_CURSUB+16 /* Current xtrn (internal code) */ -#define U_MAIN_CMD U_CURXTRN+8+2 /* unused */ +#define U_ROWS U_CURXTRN+8+2 +#define U_COLS U_ROWS+LEN_ROWS +#define U_MAIN_CMD U_COLS+LEN_COLS /* unused */ #define U_PASS U_MAIN_CMD+LEN_MAIN_CMD #define U_SCAN_CMD U_PASS+LEN_PASS+2 /* unused */ #define U_IPADDR U_SCAN_CMD+LEN_SCAN_CMD /* unused */ @@ -690,11 +694,13 @@ typedef enum { /* Values for xtrn_t.event */ #define TERM_KEY_PAGEUP CTRL_P #define TERM_KEY_PAGEDN CTRL_N +#define TERM_COLS_AUTO 0 #define TERM_COLS_MIN 40 -#define TERM_COLS_MAX 255 +#define TERM_COLS_MAX 999 #define TERM_COLS_DEFAULT 80 +#define TERM_ROWS_AUTO 0 #define TERM_ROWS_MIN 8 // Amstrad NC100 has an 8-line display -#define TERM_ROWS_MAX 255 +#define TERM_ROWS_MAX 999 #define TERM_ROWS_DEFAULT 24 /* Online status (online) */ @@ -761,6 +767,7 @@ typedef enum { /* Values for xtrn_t.event */ #define K_NOSPIN (1L<<21) /* Do not honor the user's spinning cursor */ #define K_ANSI_CPR (1L<<22) /* Expect ANSI Cursor Position Report */ #define K_TRIM (1L<<23) /* Trimmed white-space */ +#define K_CTRLKEYS (1L<<24) /* No control-key handling/eating in inkey()*/ /* Bits in 'mode' for putmsg and printfile */ #define P_NONE 0 /* No mode flags */ @@ -781,6 +788,8 @@ typedef enum { /* Values for xtrn_t.event */ #define P_UTF8 (1<<13) /* Message is UTF-8 */ #define P_AUTO_UTF8 (1<<14) /* Message may be UTF-8, auto-detect */ #define P_NOXATTRS (1<<15) /* No "Extra Attribute Codes" supported */ +#define P_MARKUP (1<<16) /* Support StyleCodes/Rich/StructuredText */ +#define P_HIDEMARKS (1<<17) /* Hide the mark-up characters */ /* Bits in 'mode' for listfiles */ #define FL_ULTIME (1<<0) /* List files by upload time */ @@ -1026,10 +1035,12 @@ typedef struct { /* Users information */ uchar level, /* Security level */ sex, /* Sex - M or F */ - rows, /* Rows of text */ prot, /* Default transfer protocol */ leech; /* Leech attempt counter */ + int rows, /* Rows on terminal (0 = auto-detect) */ + cols; /* Columns on terminal (0 = auto-detect) */ + ulong misc, /* Misc. bits - ANSI, Deleted etc. */ qwk, /* QWK settings */ chat, /* Chat defaults */ diff --git a/src/sbbs3/sbbsecho.c b/src/sbbs3/sbbsecho.c index 165012b157f71edb018e82f778ad6b60843c8d4b..09f3d24afba10e14281eda524ff029095dde628f 100644 --- a/src/sbbs3/sbbsecho.c +++ b/src/sbbs3/sbbsecho.c @@ -849,7 +849,7 @@ int write_flofile(const char *infile, fidoaddr_t dest, bool bundle, bool use_out infile++; #ifdef __unix__ - if(isalpha(infile[0]) && infile[1] == ':') // Ignore "C:" prefix + if(IS_ALPHA(infile[0]) && infile[1] == ':') // Ignore "C:" prefix infile += 2; #endif SAFECOPY(attachment, infile); @@ -2282,7 +2282,7 @@ char* process_areafix(fidoaddr_t addr, char* inbuf, const char* password, const } } - if(((tp=strstr(p,"---\r"))!=NULL || (tp=strstr(p,"--- "))!=NULL) && + if(((tp=strstr(p,"---\r"))!=NULL || (tp=strstr(p,"--- "))!=NULL || (tp=strstr(p,"-- \r"))!=NULL) && (*(tp-1)=='\r' || *(tp-1)=='\n')) *tp=0; @@ -2317,7 +2317,7 @@ char* process_areafix(fidoaddr_t addr, char* inbuf, const char* password, const add_area=strListInit(); del_area=strListInit(); for(l=0;l<m;l++) { - while(*(p+l) && isspace((uchar)*(p+l))) l++; + while(*(p+l) && IS_WHITESPACE(*(p+l))) l++; while(*(p+l)==CTRL_A) { /* Ignore kludge lines June-13-2004 */ while(*(p+l) && *(p+l)!='\r') l++; continue; @@ -3107,7 +3107,7 @@ time32_t fmsgtime(const char *str) memset(&tm,0,sizeof(tm)); tm.tm_isdst=-1; /* Do not adjust for DST */ - if(isdigit((uchar)str[1])) { /* Regular format: "01 Jan 86 02:34:56" */ + if(IS_DIGIT(str[1])) { /* Regular format: "01 Jan 86 02:34:56" */ tm.tm_mday=atoi(str); sprintf(month,"%3.3s",str+3); if(!stricmp(month,"jan")) @@ -3503,7 +3503,8 @@ int fmsgtosmsg(char* fbuf, fmsghdr_t* hdr, uint user, uint subnum) if(ch == '\n') continue; if(cr && (!strncmp(fbuf+l,"--- ",4) - || !strncmp(fbuf+l,"---\r",4))) + || !strncmp(fbuf+l,"---\r",4) + || !strncmp(fbuf+l,"-- \r",4))) done=1; /* tear line and down go into tail */ else if(cr && !strncmp(fbuf+l," * Origin: ",11) && subnum != INVALID_SUB) { p=(char*)fbuf+l+11; @@ -6207,7 +6208,7 @@ int main(int argc, char **argv) else { if(strchr(argv[i],'.')!=NULL && fexist(argv[i])) SAFECOPY(cfg.cfgfile,argv[i]); - else if(isdigit((uchar)argv[i][0])) + else if(IS_DIGIT(argv[i][0])) nodeaddr = atofaddr(argv[i]); else sub_code = argv[i]; @@ -6399,7 +6400,7 @@ int main(int argc, char **argv) SKIP_WHITESPACE(p); /* Skip white space */ while(*p && *p!=';') { - if(!isdigit(*p)) { + if(!IS_DIGIT(*p)) { printf("\n"); lprintf(LOG_WARNING, "Invalid Area File line, expected link address(es) after echo-tag: '%s'", str); break; diff --git a/src/sbbs3/scfg/scfg.c b/src/sbbs3/scfg/scfg.c index e6ca0748c3290e09d048e67303918d8cf3043910..9b43ad3bf3d3a7c14a08f78cae988f2a6c2c329c 100644 --- a/src/sbbs3/scfg/scfg.c +++ b/src/sbbs3/scfg/scfg.c @@ -233,7 +233,7 @@ int main(int argc, char **argv) umask(strtoul(argv[i]+2,NULL,8)); break; case 'G': - if(isalpha(argv[i][2])) + if(IS_ALPHA(argv[i][2])) grpname = argv[i]+2; else grpnum = atoi(argv[i]+2); diff --git a/src/sbbs3/scfg/scfgnet.c b/src/sbbs3/scfg/scfgnet.c index eb3ac852c194c6450a033e6fbc0252a56dbdf207..d2305c2e6eb69a0f059d6999c6d9e2784da3507b 100644 --- a/src/sbbs3/scfg/scfgnet.c +++ b/src/sbbs3/scfg/scfgnet.c @@ -980,7 +980,7 @@ void qhub_edit(int num) ; if(uifc.input(WIN_MID|WIN_SAV,0,0 ,"Node to Perform Call-out",str,3,K_EDIT) > 0) { - if(isdigit(*str)) + if(IS_DIGIT(*str)) cfg.qhub[num]->node=atoi(str); else cfg.qhub[num]->node = NODE_ANY; diff --git a/src/sbbs3/scfg/scfgsub.c b/src/sbbs3/scfg/scfgsub.c index 1df9769b76cabba36b501941ba53c0b1b8c3bebd..5e0cb7fae8db281f5ffca50da8a7eb977429b70d 100644 --- a/src/sbbs3/scfg/scfgsub.c +++ b/src/sbbs3/scfg/scfgsub.c @@ -560,6 +560,8 @@ void sub_cfg(uint grpnum) #endif sprintf(opt[n++],"%-27.27s%s","Compress Messages (LZH)" ,cfg.sub[i]->misc&SUB_LZH ? "Yes" : "No"); + sprintf(opt[n++],"%-27.27s%s","Apply Markup Codes" + ,cfg.sub[i]->pmode&P_MARKUP ? ((cfg.sub[i]->pmode&P_HIDEMARKS) ? "Hide" : "Yes") : "No"); sprintf(opt[n++],"%-27.27s%s","Extra Attribute Codes" ,cfg.sub[i]->pmode&P_NOXATTRS ? "No" : "Yes"); sprintf(opt[n++],"%-27.27s%s","Word-wrap Messages" @@ -581,7 +583,7 @@ void sub_cfg(uint grpnum) if(n==-1) break; switch(n) { - case 0: + case __COUNTER__: if(cfg.sub[i]->misc&SUB_PONLY) n=2; else @@ -620,7 +622,7 @@ void sub_cfg(uint grpnum) cfg.sub[i]->misc|=(SUB_PRIV|SUB_PONLY); } break; - case 1: + case __COUNTER__: if(cfg.sub[i]->misc&SUB_AONLY) n=2; else @@ -659,7 +661,7 @@ void sub_cfg(uint grpnum) cfg.sub[i]->misc|=(SUB_ANON|SUB_AONLY); } break; - case 2: + case __COUNTER__: n=(cfg.sub[i]->misc&SUB_NAME) ? 0:1; uifc.helpbuf= "`User Real Names in Posts on Sub-board:`\n" @@ -682,7 +684,7 @@ void sub_cfg(uint grpnum) cfg.sub[i]->misc&=~SUB_NAME; } break; - case 3: + case __COUNTER__: if(cfg.sub[i]->misc&SUB_EDITLAST) n=2; else @@ -727,7 +729,7 @@ void sub_cfg(uint grpnum) break; } break; - case 4: + case __COUNTER__: if(cfg.sub[i]->misc&SUB_DELLAST) n=2; else @@ -768,7 +770,7 @@ void sub_cfg(uint grpnum) cfg.sub[i]->misc|=(SUB_DEL|SUB_DELLAST); } break; - case 5: + case __COUNTER__: n=(cfg.sub[i]->misc&SUB_NSDEF) ? 0:1; uifc.helpbuf= "`Default On for New Scan:`\n" @@ -790,7 +792,7 @@ void sub_cfg(uint grpnum) cfg.sub[i]->misc&=~SUB_NSDEF; } break; - case 6: + case __COUNTER__: n=(cfg.sub[i]->misc&SUB_FORCED) ? 0:1; uifc.helpbuf= "`Forced On for New Scan:`\n" @@ -813,7 +815,7 @@ void sub_cfg(uint grpnum) cfg.sub[i]->misc&=~SUB_FORCED; } break; - case 7: + case __COUNTER__: n=(cfg.sub[i]->misc&SUB_SSDEF) ? 0:1; uifc.helpbuf= "`Default On for Your Scan:`\n" @@ -835,7 +837,7 @@ void sub_cfg(uint grpnum) cfg.sub[i]->misc&=~SUB_SSDEF; } break; - case 8: + case __COUNTER__: n=(cfg.sub[i]->misc&SUB_TOUSER) ? 0:1; uifc.helpbuf= "`Prompt for 'To' User on Public Posts:`\n" @@ -858,7 +860,7 @@ void sub_cfg(uint grpnum) cfg.sub[i]->misc&=~SUB_TOUSER; } break; - case 9: + case __COUNTER__: n=(cfg.sub[i]->misc&SUB_NOVOTING) ? 1:0; uifc.helpbuf= "`Allow Message Voting:`\n" @@ -880,7 +882,7 @@ void sub_cfg(uint grpnum) cfg.sub[i]->misc ^= SUB_NOVOTING; } break; - case 10: + case __COUNTER__: n=(cfg.sub[i]->misc&SUB_QUOTE) ? 0:1; uifc.helpbuf= "`Allow Message Quoting:`\n" @@ -902,7 +904,7 @@ void sub_cfg(uint grpnum) cfg.sub[i]->misc&=~SUB_QUOTE; } break; - case 11: + case __COUNTER__: n=(cfg.sub[i]->misc&SUB_MSGTAGS) ? 0:1; uifc.helpbuf= "`Allow Message Tagging:`\n" @@ -924,7 +926,7 @@ void sub_cfg(uint grpnum) cfg.sub[i]->misc&=~SUB_MSGTAGS; } break; - case 12: + case __COUNTER__: n=(cfg.sub[i]->misc&SUB_NOUSERSIG) ? 0:1; uifc.helpbuf= "Suppress User Signatures:\n" @@ -946,7 +948,7 @@ void sub_cfg(uint grpnum) cfg.sub[i]->misc&=~SUB_NOUSERSIG; } break; - case 13: + case __COUNTER__: n=(cfg.sub[i]->misc&SUB_SYSPERM) ? 0:1; uifc.helpbuf= "`Operator Messages Automatically Permanent:`\n" @@ -1008,7 +1010,7 @@ void sub_cfg(uint grpnum) } break; #endif - case 14: + case __COUNTER__: n=(cfg.sub[i]->misc&SUB_LZH) ? 0:1; uifc.helpbuf= "`Compress Messages with LZH Encoding:`\n" @@ -1037,7 +1039,44 @@ void sub_cfg(uint grpnum) cfg.sub[i]->misc&=~SUB_LZH; } break; - case 15: + case __COUNTER__: + n = (cfg.sub[i]->pmode&P_MARKUP) ? (cfg.sub[i]->pmode&P_HIDEMARKS ? 1 : 0) : 2; + uifc.helpbuf= + "`Interpret/Display Markup Codes in Messages:`\n" + "\n" + "Markup codes are called 'StyleCodes' in GoldEd, 'Rich Text' in SemPoint,\n" + "and 'Structured Text' in Mozilla/Thunderbird.\n" + "\n" + "`*Bold Text*`\n" + "/Italic Text/\n" + "~#Inverse Text#~\n" + "_Underlined Text_\n" + "\n" + "Markup character cannot be combined.\n" + ; + strcpy(opt[0],"Yes"); + strcpy(opt[1],"Yes and Hide the Markup Characters"); + strcpy(opt[2],"No"); + opt[3][0]=0; + n=uifc.list(WIN_SAV|WIN_MID,0,0,0,&n,0 + ,"Interpret/Display Markup Codes in Messages", opt); + if(n==-1) + break; + if(n == 0 && (cfg.sub[i]->pmode&(P_MARKUP|P_HIDEMARKS)) != P_MARKUP) { + uifc.changes = TRUE; + cfg.sub[i]->pmode |= P_MARKUP; + cfg.sub[i]->pmode &= ~P_HIDEMARKS; + } + else if(n == 1 && (cfg.sub[i]->pmode&(P_MARKUP|P_HIDEMARKS)) != (P_MARKUP|P_HIDEMARKS)) { + uifc.changes = TRUE; + cfg.sub[i]->pmode |= (P_MARKUP|P_HIDEMARKS); + } + else if(n == 2 && (cfg.sub[i]->pmode&(P_MARKUP|P_HIDEMARKS)) != 0) { + uifc.changes = TRUE; + cfg.sub[i]->pmode &= ~(P_MARKUP|P_HIDEMARKS); + } + break; + case __COUNTER__: n=(cfg.sub[i]->pmode&P_NOXATTRS) ? 1:0; uifc.helpbuf= "`Extra Attribute Codes:`\n" @@ -1059,7 +1098,7 @@ void sub_cfg(uint grpnum) cfg.sub[i]->pmode ^= P_NOXATTRS; } break; - case 16: + case __COUNTER__: n=(cfg.sub[i]->n_pmode&P_WORDWRAP) ? 1:0; uifc.helpbuf= "`Word-wrap Message Text:`\n" @@ -1081,7 +1120,7 @@ void sub_cfg(uint grpnum) cfg.sub[i]->n_pmode ^= P_WORDWRAP; } break; - case 17: + case __COUNTER__: n=(cfg.sub[i]->pmode&P_AUTO_UTF8) ? 0:1; uifc.helpbuf= "`Automatically Detect UTF-8 Message Text:`\n" @@ -1105,7 +1144,7 @@ void sub_cfg(uint grpnum) cfg.sub[i]->pmode ^= P_AUTO_UTF8; } break; - case 18: + case __COUNTER__: n=(cfg.sub[i]->misc&SUB_TEMPLATE) ? 0:1; uifc.helpbuf= "`Use this Sub-board as a Template for New Subs:`\n" diff --git a/src/sbbs3/scfg/scfgxtrn.c b/src/sbbs3/scfg/scfgxtrn.c index 98a3a31df30180cca2d5bee1b5ca7290c1468e08..3155544035ca03dff2784a5af4e8063a38429d56 100644 --- a/src/sbbs3/scfg/scfgxtrn.c +++ b/src/sbbs3/scfg/scfgxtrn.c @@ -623,7 +623,7 @@ void tevents_cfg() SAFEPRINTF(str, "%u", cfg.event[i]->node); if(uifc.input(WIN_MID|WIN_SAV,0,0,"Execution Node Number (or Any)" ,str,3,K_EDIT) > 0) { - if(isdigit(*str)) + if(IS_DIGIT(*str)) cfg.event[i]->node=atoi(str); else cfg.event[i]->node = NODE_ANY; @@ -643,7 +643,7 @@ void tevents_cfg() for(p=str;*p;p++) { if(atoi(p)) { cfg.event[i]->months|=(1<<(atoi(p)-1)); - while(*p && isdigit(*p)) + while(*p && IS_DIGIT(*p)) p++; } else { for(j=0;j<12;j++) @@ -672,7 +672,7 @@ void tevents_cfg() if(!isdigit(*p)) continue; cfg.event[i]->mdays|=(1<<atoi(p)); - while(*p && isdigit(*p)) + while(*p && IS_DIGIT(*p)) p++; } break; diff --git a/src/sbbs3/services.c b/src/sbbs3/services.c index 14aa6c479235a0cbb8b7ea81d62cd86ca4091bb4..cbb6372c9806b91ea21ec1e88eabc5f46afc8042 100644 --- a/src/sbbs3/services.c +++ b/src/sbbs3/services.c @@ -44,7 +44,6 @@ #include <stdlib.h> /* ltoa in GNU C lib */ #include <stdarg.h> /* va_list */ #include <string.h> /* strrchr */ -#include <ctype.h> /* isdigit */ #include <fcntl.h> /* Open flags */ #include <errno.h> /* errno */ @@ -386,7 +385,7 @@ js_login(JSContext *cx, uintN argc, jsval *arglist) putmsgptrs(&scfg, &client->user, client->subscan); } - if(isdigit(*user)) + if(IS_DIGIT(*user)) client->user.number=atoi(user); else if(*user) client->user.number=matchuser(&scfg,user,FALSE); @@ -1575,7 +1574,7 @@ static service_t* read_services_ini(const char* services_ini, service_t* service SAFECOPY(serv.cmd,iniGetString(list,sec_list[i],"Command","",cmd)); p=iniGetString(list,sec_list[i],"Port",serv.protocol,portstr); - if(isdigit(*p)) + if(IS_DIGIT(*p)) serv.port=(ushort)strtol(p,NULL,0); else { struct servent* servent = getservbyname(p,serv.options&SERVICE_OPT_UDP ? "udp":"tcp"); diff --git a/src/sbbs3/sexyz.c b/src/sbbs3/sexyz.c index dd9ff75f429ff4d3e8e31f4ecc23230587ed76b1..ee1c77a52da226f9ec9af51367ec1ea855a98737 100644 --- a/src/sbbs3/sexyz.c +++ b/src/sbbs3/sexyz.c @@ -1656,7 +1656,7 @@ int main(int argc, char **argv) for(i=1;i<argc;i++) { - if(sock==INVALID_SOCKET && isdigit(argv[i][0])) { + if(sock==INVALID_SOCKET && IS_DIGIT(argv[i][0])) { sock=atoi(argv[i]); continue; } diff --git a/src/sbbs3/smbutil.c b/src/sbbs3/smbutil.c index 3b17537b46f45bf79d34ec7b2ba7be9827e936e9..f651220e6bf503d400ab76a8e60715fe230d83ac 100644 --- a/src/sbbs3/smbutil.c +++ b/src/sbbs3/smbutil.c @@ -53,7 +53,6 @@ const char *mon[]={"Jan","Feb","Mar","Apr","May","Jun" #endif #if defined(_WIN32) - #include <ctype.h> /* isdigit() */ #include <conio.h> /* getch() */ #endif @@ -447,7 +446,7 @@ void config(void) printf("Last Message =%-6"PRIu32" New Value (CR=No Change): " ,smb.status.last_msg); gets(str); - if(isdigit(str[0])) + if(IS_DIGIT(str[0])) last_msg = atol(str); printf("Header offset =%-5"PRIu32" New value (CR=No Change): " ,smb.status.header_offset); @@ -479,15 +478,15 @@ void config(void) } if(last_msg != 0) smb.status.last_msg = last_msg; - if(isdigit(max_msgs[0])) + if(IS_DIGIT(max_msgs[0])) smb.status.max_msgs=atol(max_msgs); - if(isdigit(max_crcs[0])) + if(IS_DIGIT(max_crcs[0])) smb.status.max_crcs=atol(max_crcs); - if(isdigit(max_age[0])) + if(IS_DIGIT(max_age[0])) smb.status.max_age=atoi(max_age); - if(isdigit(header_offset[0])) + if(IS_DIGIT(header_offset[0])) smb.status.header_offset=atol(header_offset); - if(isdigit(attr[0])) + if(IS_DIGIT(attr[0])) smb.status.attr=atoi(attr); i=smb_putstatus(&smb); smb_unlocksmbhdr(&smb); @@ -1511,7 +1510,7 @@ short str2tzone(const char* str) char tmp[32]; short zone; - if(isdigit(*str) || *str=='-' || *str=='+') { /* [+|-]HHMM format */ + if(IS_DIGIT(*str) || *str=='-' || *str=='+') { /* [+|-]HHMM format */ if(*str=='+') str++; sprintf(tmp,"%.*s",*str=='-'? 3:2,str); zone=atoi(tmp)*60; @@ -1626,7 +1625,7 @@ int main(int argc, char **argv) argv[x][0]=='/' || /* for backwards compatibilty */ #endif argv[x][0]=='-') { - if(isdigit(argv[x][1])) { + if(IS_DIGIT(argv[x][1])) { count=strtol(argv[x]+1,NULL,10); continue; } diff --git a/src/sbbs3/str.cpp b/src/sbbs3/str.cpp index c3732489c0e378403b4781b995bc5718967aa3da..d5286bf4b9552119d7be21dc89a92457d6429c99 100644 --- a/src/sbbs3/str.cpp +++ b/src/sbbs3/str.cpp @@ -255,15 +255,15 @@ void sbbs_t::sif(char *fname, char *answers, long len) cr=1; m++; } - if(isdigit((uchar)buf[m+1])) { + if(IS_DIGIT(buf[m+1])) { max=buf[++m]&0xf; - if(isdigit((uchar)buf[m+1])) + if(IS_DIGIT(buf[m+1])) max=max*10+(buf[++m]&0xf); } - if(buf[m+1]=='.' && isdigit((uchar)buf[m+2])) { + if(buf[m+1]=='.' && IS_DIGIT(buf[m+2])) { m++; min=buf[++m]&0xf; - if(isdigit((uchar)buf[m+1])) + if(IS_DIGIT(buf[m+1])) min=min*10+(buf[++m]&0xf); } if(buf[m+1]=='"') { @@ -402,15 +402,15 @@ void sbbs_t::sof(char *fname, char *answers, long len) cr=1; m++; } - if(isdigit((uchar)buf[m+1])) { + if(IS_DIGIT(buf[m+1])) { max=buf[++m]&0xf; - if(isdigit((uchar)buf[m+1])) + if(IS_DIGIT(buf[m+1])) max=max*10+(buf[++m]&0xf); } - if(buf[m+1]=='.' && isdigit((uchar)buf[m+2])) { + if(buf[m+1]=='.' && IS_DIGIT(buf[m+2])) { m++; min=buf[++m]&0xf; - if(isdigit((uchar)buf[m+1])) + if(IS_DIGIT(buf[m+1])) min=min*10+(buf[++m]&0xf); } if(buf[m+1]=='"') { @@ -542,9 +542,9 @@ size_t sbbs_t::gettmplt(char *strout, const char *templt, long mode) } } else if(c<t) { - if(tmplt[c]=='N' && !isdigit((uchar)ch)) + if(tmplt[c]=='N' && !IS_DIGIT(ch)) continue; - if(tmplt[c]=='A' && !isalpha((uchar)ch)) + if(tmplt[c]=='A' && !IS_ALPHA(ch)) continue; outchar(ch); str[c++]=ch; @@ -980,7 +980,7 @@ void sbbs_t::xfer_prot_menu(enum XFER_TYPE type) continue; if(type==XFER_BIDIR && cfg.prot[i]->bicmd[0]==0) continue; - if(printed && (printed%2)==0) + if(printed && (cols < 80 || (printed%2)==0)) CRLF; bprintf(text[TransferProtLstFmt],cfg.prot[i]->mnemonic,cfg.prot[i]->name); printed++; diff --git a/src/sbbs3/str_util.c b/src/sbbs3/str_util.c index e8b3f1f65876da8e7226cf657a09525c9c3c494f..e64133be0ea701cc35a4c71e3e4d14708eb74948 100644 --- a/src/sbbs3/str_util.c +++ b/src/sbbs3/str_util.c @@ -89,6 +89,25 @@ char* strip_ctrl(const char *str, char* dest) return dest; } +char* strip_ansi(char* str) +{ + char* s = str; + char* d = str; + while(*s != '\0') { + if(*s == ESC && *(s + 1) == '[') { + s += 2; + while(*s != '\0' && (*s < '@' || *s > '~')) + s++; + if(*s != '\0') // Skip "final byte"" + s++; + } else { + *(d++) = *(s++); + } + } + *d = '\0'; + return str; +} + char* strip_exascii(const char *str, char* dest) { int i,j; @@ -109,7 +128,7 @@ char* strip_space(const char *str, char* dest) if(dest==NULL && (dest=strdup(str))==NULL) return NULL; for(i=j=0;str[i];i++) - if(!isspace((unsigned char)str[i])) + if(!IS_WHITESPACE(str[i])) dest[j++]=str[i]; dest[j]=0; return dest; @@ -136,6 +155,7 @@ char* prep_file_desc(const char *str, char* dest) if(dest==NULL && (dest=strdup(str))==NULL) return NULL; + strip_ansi(dest); for(i=j=0;str[i];i++) if(str[i]==CTRL_A && str[i+1]!=0) { i++; @@ -147,7 +167,7 @@ char* prep_file_desc(const char *str, char* dest) } else if(j && str[i]<=' ' && dest[j-1]==' ') continue; - else if(i && !isalnum((unsigned char)str[i]) && str[i]==str[i-1]) + else if(i && !IS_ALPHANUMERIC(str[i]) && str[i]==str[i-1]) continue; else if((uchar)str[i]>=' ') dest[j++]=str[i]; @@ -496,7 +516,7 @@ uint hptoi(const char *str) if(!str[1] || toupper(str[0])<='F') return(ahtoul(str)); - strcpy(tmp,str); + SAFECOPY(tmp,str); tmp[0]='F'; i=ahtoul(tmp)+((toupper(str[0])-'F')*0x10); return(i); @@ -643,6 +663,25 @@ char* ascii_str(uchar* str) return((char*)str); } +/****************************************************************************/ +/* Condense consecutive white-space chars in a string to single spaces */ +/****************************************************************************/ +char* condense_whitespace(char* str) +{ + char* s = str; + char* d = str; + while(*s != '\0') { + if(IS_WHITESPACE(*s)) { + *(d++) = ' '; + SKIP_WHITESPACE(s); + } else { + *(d++) = *(s++); + } + } + *d = '\0'; + return str; +} + uint32_t str_to_bits(uint32_t val, const char *str) { /* op can be 0 for replace, + for add, or - for remove */ diff --git a/src/sbbs3/text.h b/src/sbbs3/text.h index 8357736798594951d28dd93dffd128528130f5b1..0578967d3928e2c284ada20927740b0b16c097e7 100644 --- a/src/sbbs3/text.h +++ b/src/sbbs3/text.h @@ -853,6 +853,7 @@ enum { ,SpinningCursor7 ,SpinningCursor8 ,SpinningCursor9 + ,HowManyColumns ,TOTAL_TEXT }; diff --git a/src/sbbs3/text_defaults.c b/src/sbbs3/text_defaults.c index c39e5bf8ac00c10fa6ebe7c9db90b3c6409d5e06..9261f22165e9060c2e1dfa88a8dd8b797021afb3 100644 --- a/src/sbbs3/text_defaults.c +++ b/src/sbbs3/text_defaults.c @@ -558,7 +558,7 @@ const char * const text_defaults[TOTAL_TEXT]={ ,"\x01\x5f\x01\x62\x01\x68\x5b\x01\x63\x40\x43\x48\x45\x43\x4b\x4d\x41\x52\x4b\x40\x01\x62\x5d\x20\x01\x79\x45\x6e\x74\x65\x72\x20" "\x79\x6f\x75\x72\x20\x76\x6f\x69\x63\x65\x20\x70\x68\x6f\x6e\x65\x20\x6e\x75\x6d\x62\x65\x72\x01\x5c\x3a\x20\x01\x77" // 344 EnterYourPhoneNumber ,"\x01\x5f\x01\x62\x01\x68\x5b\x01\x63\x40\x43\x48\x45\x43\x4b\x4d\x41\x52\x4b\x40\x01\x62\x5d\x20\x01\x79\x45\x6e\x74\x65\x72\x20" - "\x79\x6f\x75\x72\x20\x62\x69\x72\x74\x68\x64\x61\x79\x20\x28\x59\x59\x59\x59\x2f\x4d\x4d\x2f\x44\x44\x29\x01\x5c\x3a\x20\x01\x77" + "\x79\x6f\x75\x72\x20\x62\x69\x72\x74\x68\x64\x61\x79\x20\x28\x40\x42\x44\x41\x54\x45\x46\x4d\x54\x40\x29\x01\x5c\x3a\x20\x01\x77" "" // 345 EnterYourBirthday ,"\x01\x5f\x01\x62\x01\x68\x5b\x01\x63\x40\x43\x48\x45\x43\x4b\x4d\x41\x52\x4b\x40\x01\x62\x5d\x20\x01\x79\x45\x6e\x74\x65\x72\x20" "\x79\x6f\x75\x72\x20\x6c\x6f\x63\x61\x74\x69\x6f\x6e\x01\x5c\x20\x28\x65\x2e\x67\x2e\x20\x63\x69\x74\x79\x2c\x20\x73\x74\x61\x74" @@ -692,8 +692,7 @@ const char * const text_defaults[TOTAL_TEXT]={ ,"\x01\x6e\x01\x63\x52\x65\x61\x6c\x20\x4e\x61\x6d\x65\x20\x3a\x20\x01\x68\x25\x2d\x33\x30\x2e\x33\x30\x73\x20\x20\x01\x6e\x01\x63" "\x50\x68\x6f\x6e\x65\x20\x6e\x75\x6d\x62\x65\x72\x20\x3a\x20\x01\x68\x25\x73\x0d\x0a" // 422 UeditRealNamePhone ,"\x01\x6e\x01\x63\x41\x64\x64\x72\x65\x73\x73\x20\x20\x20\x3a\x20\x01\x68\x25\x2d\x33\x30\x2e\x33\x30\x73\x20\x20\x01\x6e\x01\x63" - "\x41\x67\x65\x2f\x53\x65\x78\x2f\x42\x44\x61\x79\x20\x3a\x20\x01\x68\x25\x32\x64\x20\x25\x63\x20\x25\x2e\x30\x73\x25\x30\x34\x75" - "\x2f\x25\x30\x32\x75\x2f\x25\x30\x32\x75\x0d\x0a" // 423 UeditAddressBirthday + "\x41\x67\x65\x2f\x53\x65\x78\x2f\x42\x44\x61\x79\x20\x3a\x20\x01\x68\x25\x32\x64\x20\x25\x63\x20\x25\x73\x0d\x0a" // 423 UeditAddressBirthday ,"\x01\x6e\x01\x63\x4c\x6f\x63\x61\x74\x69\x6f\x6e\x20\x20\x3a\x20\x01\x68\x25\x2d\x33\x30\x2e\x33\x30\x73\x20\x20\x01\x6e\x01\x63" "\x5a\x69\x70\x20\x43\x6f\x64\x65\x20\x20\x20\x20\x20\x3a\x20\x01\x68\x25\x73\x0d\x0a" // 424 UeditLocationZipcode ,"\x01\x6e\x01\x63\x4e\x6f\x74\x65\x20\x20\x20\x20\x20\x20\x3a\x20\x01\x68\x25\x2d\x33\x30\x2e\x33\x30\x73\x20\x20\x01\x6e\x01\x63" @@ -780,8 +779,8 @@ const char * const text_defaults[TOTAL_TEXT]={ "\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x01\x6e\x01\x62\x01\x5c\x3a\x20\x01\x63\x25\x73\x0d\x0a" // 475 UserDefaultsTerminal ,"\x01\x6e\x01\x62\x5b\x01\x68\x01\x77\x45\x01\x6e\x01\x62\x5d\x20\x01\x68\x45\x78\x74\x65\x72\x6e\x61\x6c\x20\x45\x64\x69\x74\x6f" "\x72\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x01\x6e\x01\x62\x01\x5c\x3a\x20\x01\x63\x25\x73\x0d\x0a" // 476 UserDefaultsXeditor - ,"\x01\x6e\x01\x62\x5b\x01\x68\x01\x77\x4c\x01\x6e\x01\x62\x5d\x20\x01\x68\x53\x63\x72\x65\x65\x6e\x20\x4c\x65\x6e\x67\x74\x68\x20" - "\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x01\x6e\x01\x62\x01\x5c\x3a\x20\x01\x63\x25\x73\x20\x25\x73\x0d\x0a" + ,"\x01\x6e\x01\x62\x5b\x01\x68\x01\x77\x4c\x01\x6e\x01\x62\x5d\x20\x01\x68\x54\x65\x72\x6d\x69\x6e\x61\x6c\x20\x44\x69\x6d\x65\x6e" + "\x73\x69\x6f\x6e\x73\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x01\x6e\x01\x62\x01\x5c\x3a\x20\x01\x63\x25\x73\x20\x25\x73\x0d\x0a" "" // 477 UserDefaultsRows ,"\x01\x6e\x01\x62\x5b\x01\x68\x01\x77\x58\x01\x6e\x01\x62\x5d\x20\x01\x68\x45\x78\x70\x65\x72\x74\x20\x4d\x65\x6e\x75\x20\x4d\x6f" "\x64\x65\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x01\x6e\x01\x62\x3a\x20\x01\x63\x25\x73\x0d\x0a" // 478 UserDefaultsMenuMode @@ -820,9 +819,8 @@ const char * const text_defaults[TOTAL_TEXT]={ ,"\x0d\x0a\x01\x6e\x01\x68\x01\x62\x57\x68\x69\x63\x68\x20\x6f\x72\x20\x5b\x01\x77\x51\x01\x62\x5d\x75\x69\x74\x3a\x20\x01\x63" // 494 UserDefaultsWhich ,"\x4f\x6e" // 495 On ,"\x4f\x66\x66" // 496 Off - ,"\x0d\x0a\x01\x5f\x01\x62\x01\x68\x5b\x01\x63\x40\x43\x48\x45\x43\x4b\x4d\x41\x52\x4b\x40\x01\x62\x5d\x20\x01\x79\x48\x6f\x77\x20" - "\x6d\x61\x6e\x79\x20\x72\x6f\x77\x73\x20\x6f\x6e\x20\x79\x6f\x75\x72\x20\x6d\x6f\x6e\x69\x74\x6f\x72\x20\x5b\x01\x77\x41\x75\x74" - "\x6f\x20\x44\x65\x74\x65\x63\x74\x01\x79\x5d\x3a\x20" // 497 HowManyRows + ,"\x01\x5f\x01\x62\x01\x68\x5b\x01\x63\x40\x43\x48\x45\x43\x4b\x4d\x41\x52\x4b\x40\x01\x62\x5d\x20\x01\x79\x54\x65\x72\x6d\x69\x6e" + "\x61\x6c\x20\x72\x6f\x77\x73\x20\x5b\x01\x77\x41\x75\x74\x6f\x01\x79\x5d\x3a\x20\x01\x6e" // 497 HowManyRows ,"\x0d\x0a\x01\x5f\x01\x79\x01\x68\x43\x75\x72\x72\x65\x6e\x74\x20\x50\x61\x73\x73\x77\x6f\x72\x64\x3a\x20\x01\x77" // 498 CurrentPassword ,"\x46\x6f\x72\x77\x61\x72\x64\x20\x70\x65\x72\x73\x6f\x6e\x61\x6c\x20\x65\x2d\x6d\x61\x69\x6c\x20\x74\x6f\x20\x6e\x65\x74\x77\x6f" "\x72\x6b\x20\x6d\x61\x69\x6c\x20\x61\x64\x64\x72\x65\x73\x73" // 499 ForwardMailQ @@ -1385,4 +1383,6 @@ const char * const text_defaults[TOTAL_TEXT]={ ,"\xdc\xde\xdf\xdd" // 840 SpinningCursor7 ,"\xdc\xdd\xdf\xde" // 841 SpinningCursor8 ,"\xfa\xf9\xfe\xf9" // 842 SpinningCursor9 + ,"\x01\x5f\x01\x62\x01\x68\x5b\x01\x63\x40\x43\x48\x45\x43\x4b\x4d\x41\x52\x4b\x40\x01\x62\x5d\x20\x01\x79\x54\x65\x72\x6d\x69\x6e" + "\x61\x6c\x20\x63\x6f\x6c\x75\x6d\x6e\x73\x20\x5b\x01\x77\x41\x75\x74\x6f\x01\x79\x5d\x3a\x20\x01\x6e" // 843 HowManyColumns }; diff --git a/src/sbbs3/textgen.c b/src/sbbs3/textgen.c index d8318d7b36a8a0165e330604c601e44897d710ad..476d0c60e124032a5f2f77d8ec30f7f8d4babc2b 100644 --- a/src/sbbs3/textgen.c +++ b/src/sbbs3/textgen.c @@ -27,7 +27,7 @@ char *readtext(FILE *stream, char **comment_ret) } comment[0]=0; if(*(p+1)=='\\') { /* merge multiple lines */ - for(cp=p+2; *cp && isspace(*cp); cp++); + for(cp=p+2; *cp && IS_WHITESPACE(*cp); cp++); truncsp(cp); strcat(comment, cp); while(strlen(buf)<2000) { @@ -39,7 +39,7 @@ char *readtext(FILE *stream, char **comment_ret) strcpy(p,p2+1); p=strrchr(p,'"'); if(p && *(p+1)=='\\') { - for(cp=p+2; *cp && isspace(*cp); cp++); + for(cp=p+2; *cp && IS_WHITESPACE(*cp); cp++); truncsp(cp); strcat(comment, cp); continue; @@ -48,7 +48,7 @@ char *readtext(FILE *stream, char **comment_ret) } } else { - for(cp=p+2; *cp && isspace(*cp); cp++); + for(cp=p+2; *cp && IS_WHITESPACE(*cp); cp++); strcat(comment, cp); truncsp(comment); } @@ -57,10 +57,10 @@ char *readtext(FILE *stream, char **comment_ret) for(i=1,j=0;i<k;j++) { if(buf[i]=='\\') { /* escape */ i++; - if(isdigit(buf[i])) { + if(IS_DIGIT(buf[i])) { str[j]=atoi(buf+i); /* decimal, NOT octal */ - if(isdigit(buf[++i])) /* skip up to 3 digits */ - if(isdigit(buf[++i])) + if(IS_DIGIT(buf[++i])) /* skip up to 3 digits */ + if(IS_DIGIT(buf[++i])) i++; continue; } @@ -227,7 +227,7 @@ int main(int argc, char **argv) fprintf(stderr,"Error creating C string! for %d\n", i+1); } lno=strtoul(comment, ¯o, 10); - while(isspace(*macro)) + while(IS_WHITESPACE(*macro)) macro++; if((int)lno != i) { fprintf(stderr,"Mismatch! %s has %ld... should be %d\n", comment, lno, i); diff --git a/src/sbbs3/uedit/uedit.c b/src/sbbs3/uedit/uedit.c index 09be4db916541cf32c88cea6cb2bbd646583a89f..6cf2fa35422d6c3efe35c202588414d1d6dfe13d 100644 --- a/src/sbbs3/uedit/uedit.c +++ b/src/sbbs3/uedit/uedit.c @@ -235,9 +235,9 @@ int edit_terminal(scfg_t *cfg, user_t *user) char **opt; char str[256]; - if((opt=(char **)alloca(sizeof(char *)*(10+1)))==NULL) - allocfail(sizeof(char *)*(10+1)); - for(i=0;i<(10+1);i++) + if((opt=(char **)alloca(sizeof(char *)*(11+1)))==NULL) + allocfail(sizeof(char *)*(11+1)); + for(i=0;i<11;i++) if((opt[i]=(char *)alloca(MAX_OPLN))==NULL) allocfail(MAX_OPLN); @@ -254,9 +254,11 @@ int edit_terminal(scfg_t *cfg, user_t *user) sprintf(opt[i++],"Pause %s",user->misc & UPAUSE?"Yes":"No"); sprintf(opt[i++],"Hot Keys %s",user->misc & COLDKEYS?"No":"Yes"); sprintf(opt[i++],"Spinning Cursor %s",user->misc & SPIN?"Yes":"No"); + sprintf(str,"%u",user->cols); + sprintf(opt[i++],"Screen Columns %s",user->cols?str:"Auto"); sprintf(str,"%u",user->rows); - sprintf(opt[i++],"Number of Rows %s",user->rows?str:"Auto"); - opt[i][0]=0; + sprintf(opt[i++],"Screen Rows %s",user->rows?str:"Auto"); + opt[i] = NULL; switch(uifc.list(WIN_MID|WIN_ACT|WIN_SAV,0,0,0,&j,0,"Terminal Settings",opt)) { case -1: return(0); @@ -307,12 +309,21 @@ int edit_terminal(scfg_t *cfg, user_t *user) putuserrec(cfg,user->number,U_MISC,8,ultoa(user->misc,str,16)); break; case 9: + /* Columns */ + SAFEPRINTF(str,"%u",user->cols); + uifc.input(WIN_MID|WIN_ACT|WIN_SAV,0,0, "Columns (0=auto-detect)", str, LEN_COLS, K_EDIT|K_NUMBER); + if(uifc.changes) { + user->cols=strtoul(str,NULL,10); + putuserrec(cfg,user->number,U_COLS,0,ultoa(user->cols,str,10)); + } + break; + case 10: /* Rows */ - sprintf(str,"%u",user->rows); - uifc.input(WIN_MID|WIN_ACT|WIN_SAV,0,0,"Rows",str,2,K_EDIT|K_NUMBER); + SAFEPRINTF(str,"%u",user->rows); + uifc.input(WIN_MID|WIN_ACT|WIN_SAV,0,0, "Rows (0=auto-detect)", str, LEN_ROWS, K_EDIT|K_NUMBER); if(uifc.changes) { user->rows=strtoul(str,NULL,10); - putuserrec(cfg,user->number,U_ROWS,2,ultoa(user->rows,str,10)); + putuserrec(cfg,user->number,U_ROWS,0,ultoa(user->rows,str,10)); } break; } diff --git a/src/sbbs3/umonitor/umonitor.c b/src/sbbs3/umonitor/umonitor.c index b89118e6e2b5beae8f04b89d130b5f0d9b607acf..305fb77b039debc9ee83ccf1cc0ae1468a9baa5a 100644 --- a/src/sbbs3/umonitor/umonitor.c +++ b/src/sbbs3/umonitor/umonitor.c @@ -643,57 +643,53 @@ int run_events(scfg_t *cfg) int recycle_servers(scfg_t *cfg) { - char str[1024]; + char str[MAX_PATH + 1]; char **opt; int i=0; + const int opt_count = 6; - if((opt=(char **)alloca(sizeof(char *)*(5+1)))==NULL) - allocfail(sizeof(char *)*(5+1)); - for(i=0;i<(5+1);i++) - if((opt[i]=(char *)alloca(MAX_OPLN))==NULL) - allocfail(MAX_OPLN); + if((opt=(char **)alloca(sizeof(char *)*(opt_count+1)))==NULL) + allocfail(sizeof(char *)*(opt_count+1)); - i=0; - strcpy(opt[i++],"FTP server"); - strcpy(opt[i++],"Mail server"); - strcpy(opt[i++],"Services"); - strcpy(opt[i++],"Telnet server"); - strcpy(opt[i++],"Web server"); - opt[i][0]=0; + opt[i++] = "All Servers"; + opt[i++] = "Terminal Server"; + opt[i++] = "Mail Server"; + opt[i++] = "FTP Server"; + opt[i++] = "Web Server"; + opt[i++] = "Services"; + opt[i] = NULL; uifc.helpbuf= "`Recycle Servers\n" "`---------------\n\n" - "To rerun a server, highlight it and press Enter.\n" + "To recycle a server, highlight it and press Enter.\n" "This will reload the configuration files for selected\n" "server."; i=0; while(1) { + const char* ext = ""; switch(uifc.list(WIN_MID|WIN_SAV,0,0,0,&i,0,"Recycle Servers",opt)) { case -1: return(0); break; - case 0: - sprintf(str,"%sftpsrvr.rec",cfg->ctrl_dir); - ftouch(str); - break; case 1: - sprintf(str,"%smailsrvr.rec",cfg->ctrl_dir); - ftouch(str); + ext = ".term"; break; case 2: - sprintf(str,"%sservices.rec",cfg->ctrl_dir); - ftouch(str); + ext = ".mail"; break; case 3: - sprintf(str,"%stelnet.rec",cfg->ctrl_dir); - ftouch(str); + ext = ".ftp"; break; case 4: - sprintf(str,"%swebsrvr.rec",cfg->ctrl_dir); - ftouch(str); + ext = ".web"; + break; + case 5: + ext = ".services"; break; } + SAFEPRINTF2(str, "%srecycle%s", cfg->ctrl_dir, ext); + ftouch(str); } return(0); } diff --git a/src/sbbs3/upload.cpp b/src/sbbs3/upload.cpp index 4733ad1cabb11c9298b033bb6089e9c731805568..13e6c2a9f50023695e82f72b8cb3819aabf0dc08 100644 --- a/src/sbbs3/upload.cpp +++ b/src/sbbs3/upload.cpp @@ -174,7 +174,7 @@ bool sbbs_t::uploadfile(file_t *f) strip_exascii(desc, desc); prep_file_desc(desc, desc); for(i=0;desc[i];i++) - if(isalnum(desc[i])) + if(IS_ALPHANUMERIC(desc[i])) break; sprintf(f->desc,"%.*s",LEN_FDESC,desc+i); } @@ -412,7 +412,7 @@ bool sbbs_t::upload(uint dirnum) SYNC; bputs(text[RateThisFile]); ch=getkey(K_ALPHA); - if(!isalpha(ch) || sys_status&SS_ABORT) + if(!IS_ALPHA(ch) || sys_status&SS_ABORT) return(false); CRLF; sprintf(descbeg,text[Rated],toupper(ch)); diff --git a/src/sbbs3/userdat.c b/src/sbbs3/userdat.c index 81d4de981f4acd9af6d00e90b0721a2242130eac..c90ad560b1d7657d437f8dfc86f286977bcf08d5 100644 --- a/src/sbbs3/userdat.c +++ b/src/sbbs3/userdat.c @@ -338,9 +338,15 @@ int parseuserdat(scfg_t* cfg, char *userdat, user_t *user) getrec(userdat,U_FLAGS4,8,str); user->flags4=ahtoul(str); getrec(userdat,U_EXEMPT,8,str); user->exempt=ahtoul(str); getrec(userdat,U_REST,8,str); user->rest=ahtoul(str); - getrec(userdat,U_ROWS,2,str); user->rows=atoi(str); - if(user->rows && user->rows<10) - user->rows=10; + if(getrec(userdat,U_OLDROWS,2,str) <= 0) // Moved to new location + getrec(userdat, U_ROWS, LEN_ROWS, str); + user->rows = atoi(str); + if(user->rows && user->rows < TERM_ROWS_MIN) + user->rows = TERM_ROWS_MIN; + getrec(userdat, U_COLS, LEN_COLS, str); + user->cols = atoi(str); + if(user->cols && user->cols < TERM_COLS_MIN) + user->cols = TERM_COLS_MIN; user->sex=userdat[U_SEX]; if(!user->sex) user->sex=' '; /* fix for v1b04 that could save as 0 */ @@ -574,7 +580,8 @@ int putuserdat(scfg_t* cfg, user_t* user) putrec(userdat,U_REST,8,ultoa(user->rest,str,16)); putrec(userdat,U_REST+8,2,crlf); - putrec(userdat,U_ROWS,2,ultoa(user->rows,str,10)); + putrec(userdat, U_ROWS, LEN_ROWS, ultoa(user->rows,str,10)); + putrec(userdat, U_COLS, LEN_COLS, ultoa(user->cols,str,10)); userdat[U_SEX]=user->sex; userdat[U_PROT]=user->prot; putrec(userdat,U_MISC,8,ultoa(user->misc,str,16)); @@ -738,7 +745,7 @@ int putusername(scfg_t* cfg, int number, char *name) int getbirthyear(const char* birth) { - if(isdigit(birth[2])) // CCYYMMYY format + if(IS_DIGIT(birth[2])) // CCYYMMYY format return DECVAL(birth[0], 1000) + DECVAL(birth[1], 100) + DECVAL(birth[2], 10) @@ -757,7 +764,7 @@ int getbirthyear(const char* birth) int getbirthmonth(scfg_t* cfg, const char* birth) { - if(isdigit(birth[5])) // CCYYMMYY format + if(IS_DIGIT(birth[5])) // CCYYMMYY format return DECVAL(birth[4], 10) + DECVAL(birth[5], 1); if(cfg->sys_misc & SM_EURODATE) { // DD/MM/YY format return DECVAL(birth[3], 10) + DECVAL(birth[4], 1); @@ -768,7 +775,7 @@ int getbirthmonth(scfg_t* cfg, const char* birth) int getbirthday(scfg_t* cfg, const char* birth) { - if(isdigit(birth[5])) // CCYYMMYY format + if(IS_DIGIT(birth[5])) // CCYYMMYY format return DECVAL(birth[6], 10) + DECVAL(birth[7], 1); if(cfg->sys_misc & SM_EURODATE) { // DD/MM/YY format return DECVAL(birth[0], 10) + DECVAL(birth[1], 1); @@ -2868,12 +2875,15 @@ int user_rec_len(int offset) /* 3 char strings */ case U_TMPEXT: return(3); + case U_ROWS: + return LEN_ROWS; + case U_COLS: + return LEN_COLS; - /* 2 digits integers (0-99) */ + /* 2 digit integers (0-99 or 00-FF) */ case U_LEVEL: case U_TL: - case U_ROWS: - case U_LEECH: /* actually, 2 hex digits */ + case U_LEECH: return(2); /* Single digits chars */ @@ -3118,7 +3128,7 @@ BOOL check_name(scfg_t* cfg, const char* name) return FALSE; if ( name[0] <= ' ' /* begins with white-space? */ || name[len-1] <= ' ' /* ends with white-space */ - || !isalpha(name[0]) + || !IS_ALPHA(name[0]) || !stricmp(name,cfg->sys_id) || strchr(name,0xff) || matchuser(cfg,name,TRUE /* sysop_alias */) @@ -3253,7 +3263,7 @@ ulong loginFailure(link_list_t* list, const union xp_sockaddr* addr, const char* if((node=login_attempted(list, addr)) != NULL) { attempt=node->data; /* Don't count consecutive duplicate attempts (same name and password): */ - if((user!=NULL && strcmp(attempt->user,user)==0) && (pass==NULL || strcmp(attempt->pass,pass)==0)) + if((user!=NULL && strcmp(attempt->user,user)==0) && (pass!=NULL && strcmp(attempt->pass,pass)==0)) attempt->dupes++; } SAFECOPY(attempt->prot,prot); diff --git a/src/sbbs3/useredit.cpp b/src/sbbs3/useredit.cpp index f4a8a237973e4d1aa71147afd932d784cec2cc0f..07f7176d0895558d3fd54c39765afe961614eec1 100644 --- a/src/sbbs3/useredit.cpp +++ b/src/sbbs3/useredit.cpp @@ -38,6 +38,7 @@ /*******************************************************************/ #include "sbbs.h" +#include "petdefs.h" #define SEARCH_TXT 0 #define SEARCH_ARS 1 @@ -292,7 +293,7 @@ void sbbs_t::useredit(int usernumber) menu(str); continue; } - if(isdigit(c)) { + if(IS_DIGIT(c)) { i=c&0xf; continue; } @@ -336,13 +337,13 @@ void sbbs_t::useredit(int usernumber) putuserrec(&cfg,user.number,U_FLAGS4,8 ,ultoa(user.flags4,tmp,16)); break; - } + } } break; case 'G': bputs(text[GoToUser]); if(getstr(str,LEN_ALIAS,K_UPPER|K_LINE)) { - if(isdigit(str[0])) { + if(IS_DIGIT(str[0])) { i=atoi(str); if(i>lastuser(&cfg)) break; @@ -502,7 +503,7 @@ void sbbs_t::useredit(int usernumber) ASYNC; bputs(text[QuickValidatePrompt]); c=getkey(0); - if(!isdigit(c)) + if(!IS_DIGIT(c)) break; i=c&0xf; user.level=cfg.val_level[i]; @@ -597,7 +598,7 @@ void sbbs_t::useredit(int usernumber) user.min+=l; putuserrec(&cfg,user.number,U_MIN,10,ultoa(user.min,tmp,10)); break; - case '#': /* read new user questionaire */ + case '#': /* read new user questionnaire */ SAFEPRINTF2(str,"%suser/%4.4u.dat", cfg.data_dir,user.number); if(!cfg.new_sof[0] || !fexist(str)) break; @@ -805,14 +806,17 @@ void sbbs_t::maindflts(user_t* user) while(online) { CLS; getuserdat(&cfg,user); - if(user->rows) - rows=user->rows; + if(user->rows != TERM_ROWS_AUTO) + rows = user->rows; + if(user->cols != TERM_COLS_AUTO) + cols = user->cols; bprintf(text[UserDefaultsHdr],user->alias,user->number); + if(user == &useron) + update_nodeterm(); long term = (user == &useron) ? term_supports() : user->misc; if(term&PETSCII) - safe_snprintf(str,sizeof(str),"%sPETSCII %lu %s" - ,user->misc&AUTOTERM ? text[TerminalAutoDetect]:nulstr - ,cols, text[TerminalColumns]); + safe_snprintf(str,sizeof(str),"%sCBM/PETSCII" + ,user->misc&AUTOTERM ? text[TerminalAutoDetect]:nulstr); else safe_snprintf(str,sizeof(str),"%s%s / %s %s%s%s" ,user->misc&AUTOTERM ? text[TerminalAutoDetect]:nulstr @@ -823,12 +827,10 @@ void sbbs_t::maindflts(user_t* user) ,term&SWAP_DELETE ? "DEL=BS" : nulstr); add_hotspot('T'); bprintf(text[UserDefaultsTerminal], truncsp(str)); - if(user->rows) - ultoa(user->rows,tmp,10); - else - SAFEPRINTF2(tmp,"%s%ld", text[TerminalAutoDetect], rows); + safe_snprintf(str, sizeof(str), "%s%ld %s,", user->cols ? nulstr:text[TerminalAutoDetect], cols, text[TerminalColumns]); + safe_snprintf(tmp, sizeof(tmp), "%s%ld %s", user->rows ? nulstr:text[TerminalAutoDetect], rows, text[TerminalRows]); add_hotspot('L'); - bprintf(text[UserDefaultsRows], tmp, text[TerminalRows]); + bprintf(text[UserDefaultsRows], str, tmp); if(cfg.total_shells>1) { add_hotspot('K'); bprintf(text[UserDefaultsCommandSet] @@ -975,9 +977,9 @@ void sbbs_t::maindflts(user_t* user) else user->misc&=~NO_EXASCII; user->misc &= ~SWAP_DELETE; - while(text[HitYourBackspaceKey][0] && !(user->misc&SWAP_DELETE) && online) { + while(text[HitYourBackspaceKey][0] && !(user->misc&(PETSCII|SWAP_DELETE)) && online) { bputs(text[HitYourBackspaceKey]); - uchar key = getkey(K_NONE); + uchar key = getkey(K_CTRLKEYS); bprintf(text[CharacterReceivedFmt], key, key); if(key == '\b') break; @@ -985,6 +987,12 @@ void sbbs_t::maindflts(user_t* user) if(text[SwapDeleteKeyQ][0] == 0 || yesno(text[SwapDeleteKeyQ])) user->misc |= SWAP_DELETE; } + else if(key == PETSCII_DELETE) { + autoterm |= PETSCII; + user->misc |= PETSCII; + outcom(PETSCII_UPPERLOWER); + bputs(text[PetTerminalDetected]); + } else bprintf(text[InvalidBackspaceKeyFmt], key, key); } @@ -1030,13 +1038,21 @@ void sbbs_t::maindflts(user_t* user) putuserrec(&cfg,user->number,U_TMPEXT,3,cfg.fcomp[i]->ext); break; case 'L': + bputs(text[HowManyColumns]); + if((i = getnum(TERM_COLS_MAX)) < 0) + break; + putuserrec(&cfg,user->number,U_COLS,0,ultoa(i,tmp,10)); + if(user==&useron) { + useron.cols = i; + ansi_getlines(); + } bputs(text[HowManyRows]); - if((ch=(char)getnum(99))!=-1) { - putuserrec(&cfg,user->number,U_ROWS,2,ultoa(ch,tmp,10)); - if(user==&useron) { - useron.rows=ch; - ansi_getlines(); - } + if((i = getnum(TERM_ROWS_MAX)) < 0) + break; + putuserrec(&cfg,user->number,U_ROWS,0,ultoa(i,tmp,10)); + if(user==&useron) { + useron.rows = i; + ansi_getlines(); } break; case 'P': @@ -1175,7 +1191,7 @@ void sbbs_t::maindflts(user_t* user) default: clear_hotspots(); return; - } + } } } diff --git a/src/sbbs3/websrvr.c b/src/sbbs3/websrvr.c index 3ae6bf3df5cf6a38e6df11f57afa658c52e84cc3..92062d890e9d8548836b1c385682a5074243e65d 100644 --- a/src/sbbs3/websrvr.c +++ b/src/sbbs3/websrvr.c @@ -1421,7 +1421,7 @@ static BOOL send_headers(http_session_t *session, const char *status, int chunke if(session->req.range_start || session->req.range_end) { switch(stat_code) { case 206: /* Partial reply */ - safe_snprintf(header,sizeof(header),"%s: bytes %ld-%ld/%ld",get_header(HEAD_CONTENT_RANGE),session->req.range_start,session->req.range_end,stats.st_size); + safe_snprintf(header,sizeof(header),"%s: bytes %ld-%ld/%ld",get_header(HEAD_CONTENT_RANGE),session->req.range_start,session->req.range_end,(long)stats.st_size); safecat(headers,header,MAX_HEADERS_SIZE); break; default: @@ -2279,7 +2279,7 @@ static void unescape(char *p) dst=p; for(;*p;p++) { - if(*p=='%' && isxdigit((uchar)*(p+1)) && isxdigit((uchar)*(p+2))) { + if(*p=='%' && IS_HEXDIGIT(*(p+1)) && IS_HEXDIGIT(*(p+2))) { sprintf(code,"%.2s",p+1); *(dst++)=(char)strtol(code,NULL,16); p+=2; @@ -2528,7 +2528,7 @@ static char *get_token_value(char **p) } } end_of_text: - while(*pos==',' || isspace(*pos)) + while(*pos==',' || IS_WHITESPACE(*pos)) pos++; *out=0; *p=pos; @@ -2602,7 +2602,7 @@ static BOOL parse_headers(http_session_t * session) session->req.auth.type=AUTHENTICATION_DIGEST; /* Parse out values one at a time and store */ while(p != NULL && *p) { - while(isspace(*p)) + while(IS_WHITESPACE(*p)) p++; if(strnicmp(p,"username=",9)==0) { p+=9; @@ -2865,7 +2865,7 @@ static BOOL parse_js_headers(http_session_t * session) p=value; while((key=strtok_r(p,"=",&last))!=NULL) { - while(isspace(*key)) + while(IS_WHITESPACE(*key)) key++; p=NULL; if((val=strtok_r(p,";\t\n\v\f\r ",&last))!=NULL) { /* Whitespace */ @@ -2954,7 +2954,7 @@ static char * split_port_part(char *host) char *ret = NULL; char *p=strchr(host, 0)-1; - if (isdigit(*p)) { + if (IS_DIGIT(*p)) { /* * If the first and last : are not the same, and it doesn't * start with '[', there's no port part. @@ -2969,7 +2969,7 @@ static char * split_port_part(char *host) ret = p+1; break; } - if (!isdigit(*p)) + if (!IS_DIGIT(*p)) break; } } @@ -5460,7 +5460,7 @@ js_login(JSContext *cx, uintN argc, jsval *arglist) memset(&user,0,sizeof(user)); - if(isdigit((uchar)*username)) + if(IS_DIGIT(*username)) user.number=atoi(username); else if(*username) user.number=matchuser(&scfg,username,FALSE); diff --git a/src/sbbs3/wordwrap.c b/src/sbbs3/wordwrap.c index 8b6a4f7b90f633d6315b633a8335e8351e0228be..1885a7fbe72527899cd554657cbf543a4de771ee 100644 --- a/src/sbbs3/wordwrap.c +++ b/src/sbbs3/wordwrap.c @@ -214,7 +214,7 @@ static struct section_len get_ws_len(char *buf, int col) for(ret.bytes=0; ; ret.bytes++) { if (!buf[ret.bytes]) break; - if (!isspace((unsigned char)buf[ret.bytes])) + if (!IS_WHITESPACE(buf[ret.bytes])) break; if(buf[ret.bytes] == '\t') { ret.len++; @@ -246,7 +246,7 @@ static struct section_len get_word_len(char *buf, int maxlen, BOOL is_utf8) len = 1; if (!buf[ret.bytes]) break; - else if (isspace((unsigned char)buf[ret.bytes])) + else if (IS_WHITESPACE(buf[ret.bytes])) break; else if (buf[ret.bytes]==DEL) continue; diff --git a/src/sbbs3/writemsg.cpp b/src/sbbs3/writemsg.cpp index 5a31310774affa0d81c638976b05cc7d1a237252..5c77a025671b1018ae5a7b46f92ee1273c38b814 100644 --- a/src/sbbs3/writemsg.cpp +++ b/src/sbbs3/writemsg.cpp @@ -422,7 +422,7 @@ bool sbbs_t::writemsg(const char *fname, const char *top, char *subj, long mode, continue; } - if(!isdigit(quote[0])) + if(!IS_DIGIT(quote[0])) break; p=quote; while(p) { @@ -716,7 +716,7 @@ bool sbbs_t::writemsg(const char *fname, const char *top, char *subj, long mode, while(!feof(sig)) { if(!fgets(str,sizeof(str),sig)) break; - truncsp(str); + truncnl(str); if(utf8) { char buf[sizeof(str)*4]; cp437_to_utf8_str(str, buf, sizeof(buf) - 1, /* minval: */'\x02'); diff --git a/src/sbbs3/xtrn.cpp b/src/sbbs3/xtrn.cpp index 9d0f49e983a8f9122d295369fd11648d18aff352..9c8b6dee3cd574deb3d865016d92b508396a6f6f 100644 --- a/src/sbbs3/xtrn.cpp +++ b/src/sbbs3/xtrn.cpp @@ -1673,8 +1673,12 @@ int sbbs_t::external(const char* cmdline, long mode, const char* startup_dir) timeout.tv_sec=0; timeout.tv_usec=1000; } - if(i && !(mode&EX_NOLOG)) - lprintf(LOG_NOTICE,"%.*s",i,buf); /* lprintf mangles i? */ + if(i > 0) { + buf[i] = '\0'; + truncsp((char*)buf); + if(*buf) + lprintf(LOG_NOTICE, "%s", buf); + } /* Eat stderr if mode is EX_BIN */ if(mode&EX_BIN) { @@ -1782,7 +1786,10 @@ int sbbs_t::external(const char* cmdline, long mode, const char* startup_dir) if((rd=read(err_pipe[0],bp,1))>0) { i+=rd; if(*bp=='\n') { - lprintf(LOG_NOTICE,"%.*s",i-1,buf); + buf[i] = '\0'; + truncsp((char*)buf); + if(*buf) + lprintf(LOG_NOTICE, "%s", buf); i=0; bp=buf; } @@ -1792,8 +1799,12 @@ int sbbs_t::external(const char* cmdline, long mode, const char* startup_dir) else break; } - if(i) - lprintf(LOG_NOTICE,"%.*s",i,buf); + if(i > 0) { + buf[i] = '\0'; + truncsp((char*)buf); + if(*buf) + lprintf(LOG_NOTICE, "%s", buf); + } } } if(!(mode&EX_OFFLINE)) { /* !off-line execution */ @@ -1831,7 +1842,7 @@ const char* quoted_string(const char* str, char* buf, size_t maxlen) } #define QUOTED_STRING(ch, str, buf, maxlen) \ - ((isalpha(ch) && isupper(ch)) ? str : quoted_string(str,buf,maxlen)) + ((IS_ALPHA(ch) && IS_UPPERCASE(ch)) ? str : quoted_string(str,buf,maxlen)) /*****************************************************************************/ /* Returns command line generated from instr with %c replacements */ @@ -1853,7 +1864,7 @@ char* sbbs_t::cmdstr(const char *instr, const char *fpath, const char *fspec, ch cmd[j]=0; int avail = maxlen - j; char ch=instr[i]; - if(isalpha(ch)) + if(IS_ALPHA(ch)) ch=toupper(ch); switch(ch) { case 'A': /* User alias */ @@ -1989,7 +2000,7 @@ char* sbbs_t::cmdstr(const char *instr, const char *fpath, const char *fspec, ch strncat(cmd, ARCHITECTURE_DESC, avail); break; default: /* unknown specification */ - if(isdigit(instr[i])) { + if(IS_DIGIT(instr[i])) { sprintf(str,"%0*d",instr[i]&0xf,useron.number); strncat(cmd,str, avail); } break; } @@ -2022,7 +2033,7 @@ char* DLLCALL cmdstr(scfg_t* cfg, user_t* user, const char* instr, const char* f cmd[j]=0; int avail = maxlen - j; char ch=instr[i]; - if(isalpha(ch)) + if(IS_ALPHA(ch)) ch=toupper(ch); switch(ch) { case 'A': /* User alias */ @@ -2157,7 +2168,7 @@ char* DLLCALL cmdstr(scfg_t* cfg, user_t* user, const char* instr, const char* f strncat(cmd, ARCHITECTURE_DESC, avail); break; default: /* unknown specification */ - if(isdigit(instr[i]) && user!=NULL) { + if(IS_DIGIT(instr[i]) && user!=NULL) { sprintf(str,"%0*d",instr[i]&0xf,user->number); strncat(cmd,str, avail); } diff --git a/src/sbbs3/xtrn_sec.cpp b/src/sbbs3/xtrn_sec.cpp index 82c09f099dfae4a1fedc070fda2474dde949608a..d6654bcb95c6e47f5c2135571e4ab4ed279f189e 100644 --- a/src/sbbs3/xtrn_sec.cpp +++ b/src/sbbs3/xtrn_sec.cpp @@ -1246,7 +1246,7 @@ void sbbs_t::moduserdat(uint xtrnnum) for(i=0;i<15;i++) /* skip first 14 lines */ if(!fgets(str,128,stream)) break; - if(i==15 && isdigit(str[0])) { + if(i==15 && IS_DIGIT(str[0])) { mod=atoi(str); if(mod<SYSOP_LEVEL) { useron.level=(char)mod; @@ -1265,11 +1265,11 @@ void sbbs_t::moduserdat(uint xtrnnum) for(;i<25;i++) if(!fgets(str,128,stream)) break; - if(i==25 && isdigit(str[0]) && isdigit(str[1]) + if(i==25 && IS_DIGIT(str[0]) && IS_DIGIT(str[1]) && (str[2]=='/' || str[2]=='-') /* xx/xx/xx or xx-xx-xx */ - && isdigit(str[3]) && isdigit(str[4]) + && IS_DIGIT(str[3]) && IS_DIGIT(str[4]) && (str[5]=='/' || str[5]=='-') - && isdigit(str[6]) && isdigit(str[7])) { /* valid expire date */ + && IS_DIGIT(str[6]) && IS_DIGIT(str[7])) { /* valid expire date */ useron.expire=(ulong)dstrtounix(&cfg,str); putuserrec(&cfg,useron.number,U_EXPIRE,8,ultoa((ulong)useron.expire,tmp,16)); } @@ -1296,7 +1296,7 @@ void sbbs_t::moduserdat(uint xtrnnum) for(;i<42;i++) if(!fgets(str,128,stream)) break; - if(i==42 && isdigit(str[0])) { /* Time Credits in Minutes */ + if(i==42 && IS_DIGIT(str[0])) { /* Time Credits in Minutes */ useron.min=atol(str); putuserrec(&cfg,useron.number,U_MIN,10,ultoa(useron.min,tmp,10)); } @@ -1351,7 +1351,7 @@ void sbbs_t::moduserdat(uint xtrnnum) } if(fgets(str,81,stream)) { /* main level */ mod=atoi(str); - if(isdigit(str[0]) && mod<SYSOP_LEVEL) { + if(IS_DIGIT(str[0]) && mod<SYSOP_LEVEL) { useron.level=(uchar)mod; putuserrec(&cfg,useron.number,U_LEVEL,2,ultoa(useron.level,tmp,10)); } @@ -1647,6 +1647,11 @@ bool sbbs_t::exec_xtrn(uint xtrnnum) thisnode.aux=0; putnodedat(cfg.node_num,&thisnode); + if(cfg.xtrn[xtrnnum]->misc & XTRN_PAUSE) + pause(); + else + lncntr = 0; + return(true); } diff --git a/src/smblib/smballoc.c b/src/smblib/smballoc.c index 1d51cff4a95ff8773375b992e931ad39646aa1bc..f1c00722ecaee9264839f325f0313f9a47312bdb 100644 --- a/src/smblib/smballoc.c +++ b/src/smblib/smballoc.c @@ -326,7 +326,7 @@ int SMBCALL smb_freemsghdr(smb_t* smb, ulong offset, ulong length) } if(fseek(smb->sha_fp, sha_offset, SEEK_SET)) { - safe_snprintf(smb->last_error,sizeof(smb->last_error),"%s seeking to %ld", __FUNCTION__, sha_offset); + safe_snprintf(smb->last_error,sizeof(smb->last_error),"%s seeking to %ld", __FUNCTION__, (long)sha_offset); return(SMB_ERR_SEEK); } for(l=0;l<blocks;l++) diff --git a/src/smblib/smbstr.c b/src/smblib/smbstr.c index 47c7a02da5b38e578b4961f00c18fa2b71e05f91..d73662d411cc6a0b121ac39bdde2ce4c93d0d3f8 100644 --- a/src/smblib/smbstr.c +++ b/src/smblib/smbstr.c @@ -131,7 +131,7 @@ uint16_t SMBCALL smb_hfieldtypelookup(const char* str) { uint16_t type; - if(isdigit(*str)) + if(IS_DIGIT(*str)) return((uint16_t)strtol(str,NULL,0)); for(type=0;type<=UNUSED;type++) @@ -395,13 +395,13 @@ enum smb_net_type SMBCALL smb_get_net_type_by_addr(const char* addr) char* colon = strchr(p,':'); char* slash = strchr(p,'/'); - if(at == NULL && isalpha(*p) && dot == NULL && colon == NULL) + if(at == NULL && IS_ALPHA(*p) && dot == NULL && colon == NULL) return NET_QWK; char last = 0; for(tp = p; *tp != '\0'; tp++) { last = *tp; - if(isdigit(*tp)) + if(IS_DIGIT(*tp)) continue; if(*tp == ':') { if(tp != colon) @@ -426,7 +426,7 @@ enum smb_net_type SMBCALL smb_get_net_type_by_addr(const char* addr) } break; } - if(at == NULL && isdigit(*p) && *tp == '\0' && isdigit(last)) + if(at == NULL && IS_DIGIT(*p) && *tp == '\0' && IS_DIGIT(last)) return NET_FIDO; if(slash == NULL && (isalnum(*p) || p == colon)) return NET_INTERNET; diff --git a/src/smblib/smbtxt.c b/src/smblib/smbtxt.c index 84a4aab9d59b76c86b3e690e7ace56a769493e7c..1f1219c004bd16db6a68b9a64a4824be8a74ad04 100644 --- a/src/smblib/smbtxt.c +++ b/src/smblib/smbtxt.c @@ -234,7 +234,7 @@ char* qp_decode(char* buf) break; if(*p == '\n') continue; - if(isxdigit(*p) && isxdigit(*(p+1))) { + if(IS_HEXDIGIT(*p) && IS_HEXDIGIT(*(p+1))) { uchar ch = HEX_CHAR_TO_INT(*p) << 4; p++; ch |= HEX_CHAR_TO_INT(*p); diff --git a/src/xpdev/dirwrap.c b/src/xpdev/dirwrap.c index 2882ddaadf80f9809df2996a6ebe1922a82e8b50..49006c6a5a21dd05503b6fa4293938b0e03d7ba7 100644 --- a/src/xpdev/dirwrap.c +++ b/src/xpdev/dirwrap.c @@ -612,7 +612,7 @@ BOOL DLLCALL fexistcase(char *path) SAFECOPY(fname,p); *p=0; for(i=0;fname[i];i++) { - if(isalpha(fname[i])) + if(IS_ALPHA(fname[i])) sprintf(tmp,"[%c%c]",toupper(fname[i]),tolower(fname[i])); else sprintf(tmp,"%c",fname[i]); @@ -733,7 +733,7 @@ int removecase(const char *path) p=getfname(inpath); fname[0]=0; for(i=0;p[i];i++) { - if(isalpha(p[i])) + if(IS_ALPHA(p[i])) sprintf(tmp,"[%c%c]",toupper(p[i]),tolower(p[i])); else sprintf(tmp,"%c",p[i]); @@ -1099,7 +1099,7 @@ BOOL DLLCALL isfullpath(const char* filename) { return(filename[0]=='/' #ifdef WIN32 - || filename[0]=='\\' || (isalpha(filename[0]) && filename[1]==':') + || filename[0]=='\\' || (IS_ALPHA(filename[0]) && filename[1]==':') #endif ); } diff --git a/src/xpdev/gen_defs.h b/src/xpdev/gen_defs.h index c38856ac7518e23653aa6f64ca6e501abfac2bb7..68decddfa2bc1589fac5773d09c08e5a44835f04 100644 --- a/src/xpdev/gen_defs.h +++ b/src/xpdev/gen_defs.h @@ -416,33 +416,42 @@ typedef struct { #define SAFEPRINTF4(dst,fmt,a1,a2,a3,a4) snprintf(dst,sizeof(dst),fmt,a1,a2,a3,a4), TERMINATE(dst) #endif -/* Replace every occurance of c1 in str with c2, using p as a temporary char pointer */ +/* Replace every occurrence of c1 in str with c2, using p as a temporary char pointer */ #define REPLACE_CHARS(str,c1,c2,p) for((p)=(str);*(p);(p)++) if(*(p)==(c1)) *(p)=(c2); /* ASCIIZ char* parsing helper macros */ -#define SKIP_WHITESPACE(p) while(*(p) && isspace((unsigned char)*(p))) (p)++; -#define FIND_WHITESPACE(p) while(*(p) && !isspace((unsigned char)*(p))) (p)++; -#define SKIP_CHAR(p,c) while(*(p)==c) (p)++; -#define FIND_CHAR(p,c) while(*(p) && *(p)!=c) (p)++; -#define SKIP_CHARSET(p,s) while(*(p) && strchr(s,*(p))!=NULL) (p)++; -#define FIND_CHARSET(p,s) while(*(p) && strchr(s,*(p))==NULL) (p)++; +/* These (unsigned char) typecasts defeat MSVC debug assertion when passed a negative value */ +#define IS_WHITESPACE(c) isspace((unsigned char)(c)) +#define IS_CONTROL(c) iscntrl((unsigned char)(c)) +#define IS_ALPHA(c) isalpha((unsigned char)(c)) +#define IS_ALPHANUMERIC(c) isalnum((unsigned char)(c)) +#define IS_UPPERCASE(c) isupper((unsigned char)(c)) +#define IS_LOWERCASE(c) islower((unsigned char)(c)) +#define IS_PUNCTUATION(c) ispunct((unsigned char)(c)) +#define IS_PRINTABLE(c) isprint((unsigned char)(c)) +#define IS_DIGIT(c) isdigit((unsigned char)(c)) +#define IS_HEXDIGIT(c) isxdigit((unsigned char)(c)) +#define IS_OCTDIGIT(c) ((c) >= '0' && (c) <= '7') +#define SKIP_WHITESPACE(p) while(*(p) && IS_WHITESPACE(*(p))) (p)++; +#define FIND_WHITESPACE(p) while(*(p) && !IS_WHITESPACE(*(p))) (p)++; +#define SKIP_CHAR(p,c) while(*(p)==c) (p)++; +#define FIND_CHAR(p,c) while(*(p) && *(p)!=c) (p)++; +#define SKIP_CHARSET(p,s) while(*(p) && strchr(s,*(p))!=NULL) (p)++; +#define FIND_CHARSET(p,s) while(*(p) && strchr(s,*(p))==NULL) (p)++; #define SKIP_CRLF(p) SKIP_CHARSET(p, "\r\n") #define FIND_CRLF(p) FIND_CHARSET(p, "\r\n") -#define SKIP_ALPHA(p) while(*(p) && isalpha((unsigned char)*(p))) (p)++; -#define FIND_ALPHA(p) while(*(p) && !isalpha((unsigned char)*(p))) (p)++; -#define SKIP_ALPHANUMERIC(p) while(*(p) && isalnum((unsigned char)*(p))) (p)++; -#define FIND_ALPHANUMERIC(p) while(*(p) && !isalnum((unsigned char)*(p))) (p)++; -#define SKIP_DIGIT(p) while(*(p) && isdigit((unsigned char)*(p))) (p)++; -#define FIND_DIGIT(p) while(*(p) && !isdigit((unsigned char)*(p))) (p)++; -#define SKIP_HEXDIGIT(p) while(*(p) && isxdigit((unsigned char)*(p))) (p)++; -#define FIND_HEXDIGIT(p) while(*(p) && !isxdigit((unsigned char)*(p))) (p)++; +#define SKIP_ALPHA(p) while(*(p) && IS_ALPHA(*(p))) (p)++; +#define FIND_ALPHA(p) while(*(p) && !IS_ALPHA(*(p))) (p)++; +#define SKIP_ALPHANUMERIC(p) while(*(p) && IS_ALPHANUMERIC(*(p))) (p)++; +#define FIND_ALPHANUMERIC(p) while(*(p) && !IS_ALPHANUMERIC(*(p))) (p)++; +#define SKIP_DIGIT(p) while(*(p) && IS_DIGIT(*(p))) (p)++; +#define FIND_DIGIT(p) while(*(p) && !IS_DIGIT(*(p))) (p)++; +#define SKIP_HEXDIGIT(p) while(*(p) && IS_HEXDIGIT(*(p))) (p)++; +#define FIND_HEXDIGIT(p) while(*(p) && !IS_HEXDIGIT(*(p))) (p)++; #define HEX_CHAR_TO_INT(ch) (((ch)&0xf)+(((ch)>>6)&1)*9) #define DEC_CHAR_TO_INT(ch) ((ch)&0xf) #define OCT_CHAR_TO_INT(ch) ((ch)&0x7) -#ifndef isodigit -#define isodigit(ch) ((ch) >= '0' && (ch) <= '7') -#endif /* Variable/buffer initialization (with zeros) */ #define ZERO_VAR(var) memset(&(var),0,sizeof(var)) diff --git a/src/xpdev/genwrap.c b/src/xpdev/genwrap.c index a9b0b31320ab4bb3c2d984f56874cd1cc979f577..5a72fee45c3f57c0f7f06b9ede47977157eee0ad 100644 --- a/src/xpdev/genwrap.c +++ b/src/xpdev/genwrap.c @@ -157,27 +157,27 @@ char DLLCALL c_unescape_char_ptr(const char* str, char** endptr) int digits = 0; // \x## for hexadecimal character literals (only 2 digits supported) ++str; ch = 0; - while(digits < 2 && isxdigit(*str)) { + while(digits < 2 && IS_HEXDIGIT(*str)) { ch *= 0x10; ch += HEX_CHAR_TO_INT(*str); str++; digits++; } #ifdef C_UNESCAPE_OCTAL_SUPPORT - } else if(isodigit(*str)) { + } else if(IS_OCTDIGIT(*str)) { int digits = 0; // \### for octal character literals (only 3 digits supported) ch = 0; - while(digits < 3 && isodigit(*str)) { + while(digits < 3 && IS_OCTDIGIT(*str)) { ch *= 8; ch += OCT_CHAR_TO_INT(*str); str++; digits++; } #else - } else if(isdigit(*str)) { - int digits = 0; // \### for decimal charater literals (only 3 digits supported) + } else if(IS_DIGIT(*str)) { + int digits = 0; // \### for decimal character literals (only 3 digits supported) ch = 0; - while(digits < 3 && isdigit(*str)) { + while(digits < 3 && IS_DIGIT(*str)) { ch *= 10; ch += DEC_CHAR_TO_INT(*str); str++; @@ -725,7 +725,7 @@ char* DLLCALL truncsp(char* str) if(str!=NULL) { i=len=strlen(str); - while(i && isspace((unsigned char)str[i-1])) + while(i && IS_WHITESPACE(str[i-1])) i--; if(i!=len) str[i]=0; /* truncate */ diff --git a/src/xpdev/ini_file.c b/src/xpdev/ini_file.c index 074be46920fe0ee1a9347c13327ba1b484762daf..b096a82450e8092b456ebec83aa5069f54bbd335 100644 --- a/src/xpdev/ini_file.c +++ b/src/xpdev/ini_file.c @@ -1358,7 +1358,7 @@ static BOOL isTrue(const char* value) char* p; BOOL is_true; - if(!isalpha(*value)) + if(!IS_ALPHA(*value)) return FALSE; if((str=strdup(value)) == NULL) @@ -1933,7 +1933,7 @@ static unsigned parseEnum(const char* value, str_list_t names, unsigned deflt) return(i); i=strtoul(val, &endptr, 0); - if(*endptr != 0 && !isspace(*endptr)) + if(*endptr != 0 && !IS_WHITESPACE(*endptr)) return deflt; if(i>=count) i=count-1; diff --git a/src/xpdev/netwrap.c b/src/xpdev/netwrap.c index b212c986b92b4cfd76262d79ce2f6ad7ca7a2a70..e4f13a637de09abc962618ab6945b551d7066837 100644 --- a/src/xpdev/netwrap.c +++ b/src/xpdev/netwrap.c @@ -40,7 +40,6 @@ #include "netwrap.h" /* verify prototypes */ #include <stdlib.h> /* malloc() */ -#include <ctype.h> /* isspace() */ #if defined(_WIN32) #include <iphlpapi.h> /* GetNetworkParams */ diff --git a/webv4/components/twit-button.xjs b/webv4/components/twit-button.xjs index 94af80f7dbb662cf70d88451b7588163fe536a2a..d9ce9178d0f842d0d5f0206de624c4c0765c98fa 100644 --- a/webv4/components/twit-button.xjs +++ b/webv4/components/twit-button.xjs @@ -1,4 +1,4 @@ <? var _bs = locale.get('button_block_sender', 'page_forum'); ?> -<button id="bsb-%s" class="btn btn-default icon" aria-label="<? write(_bs); ?>" title="<? write(_bs); ?>" onclick="blockSender('%s', '%s', '%s')"> +<button id="bsb-%s" class="btn btn-default icon" aria-label="<? write(_bs); ?>" title="<? write(_bs); ?>" onclick="if (confirm('Permanently block this sender?')) { blockSender('%s', '%s', '%s') }"> <span class="glyphicon glyphicon-ban-circle"></span> </button> \ No newline at end of file diff --git a/webv4/lib/pages.js b/webv4/lib/pages.js index fc962ef983ea87ec6bd7de7c84adb73fd6eafa82..8ad898cb99ec08814a2cc0117fa5b29f1693bc93 100644 --- a/webv4/lib/pages.js +++ b/webv4/lib/pages.js @@ -70,7 +70,7 @@ function getCtrlLine(file) { f.close(); break; default: - ctrl = file_getname(file); + ctrl = pageName(file_getname(file)); break; } @@ -153,7 +153,7 @@ function _getPageList(dir) { } function pageName(p) { - return p.replace(/^\d*-/, ''); + return p.replace(/^\d*-/, '').replace(/\..*$/, ''); } function mergePageLists(stock, mods) { diff --git a/webv4/pages/003-games.xjs b/webv4/pages/003-games.xjs index 9f6ae7423737a8c2122bd22c84a48cb127478bc0..7b7604d8bb2b03cb992b44b613676ba42b0569e2 100644 --- a/webv4/pages/003-games.xjs +++ b/webv4/pages/003-games.xjs @@ -41,7 +41,7 @@ </div> </div> -<?xjs write('<script id="fTelnetScript" src="//embed-v2.ftelnet.ca/js/ftelnet-loader.norip.noxfer.js?v=' + (new Date()).getTime() + '"></script>'); ?> +<script id="fTelnetScript" src="<?xjs write(get_url()); ?>"></script> <script type="text/javascript"> var wsp = <?xjs write(settings.wsp || GetWebSocketServicePort()); ?>; var wssp = <?xjs write(settings.wssp || GetWebSocketServicePort(true)); ?>; diff --git a/xtrn/bbsfinder.net/bbsfinder.js b/xtrn/bbsfinder.net/bbsfinder.js deleted file mode 100644 index 6a84e8d1592634de9b280fb02777ce7bd560aa37..0000000000000000000000000000000000000000 --- a/xtrn/bbsfinder.net/bbsfinder.js +++ /dev/null @@ -1,60 +0,0 @@ -/* bbsfinder.net updater for Synchronet BBS 3.15+ - echicken -at- bbs.electronicchicken.com */ - -load('sbbsdefs.js'); -load('event-timer.js'); -load('http.js'); - -var delay = 240000; - -function loadSettings() { - - var f = new File(system.ctrl_dir + 'modopts.ini'); - f.open('r'); - if (!f.is_open) { - throw 'Unable to open ' + system.ctrl_dir + 'modopts.ini for reading.' - } - opts = f.iniGetObject('bbsfinder'); - f.close(); - - if (!opts.hasOwnProperty('username') || !opts.hasOwnProperty('password')) { - throw 'BBSfinder account info could not be read from modopts.ini.' - } - - opts.username = encodeURIComponent(opts.username); - opts.password = encodeURIComponent(opts.password); - - return opts; - -} - -function update() { - try { - var opts = loadSettings(); - var ret = (new HTTPRequest()).Get( - format( - 'http://www.bbsfinder.net/update.asp?un=%s&pw=%s', - opts.username, opts.password - ) - ); - } catch (e) { - log(LOG_INFO, 'BBSfinder HTTP error: ' + e); - } - if(ret == 0) { - log(LOG_INFO, 'BBSfinder update succeded.'); - } else { - log(LOG_INFO, 'BBSfinder update failed.'); - log(LOG_DEBUG, ret); - } -} - -update(); - -if (argc > 0 && argv[0] === '-l') { - var timer = new Timer(); - timer.addEvent(delay, true, update); - while (!js.terminated) { - timer.cycle(); - mswait(1000); - } -} \ No newline at end of file diff --git a/xtrn/bbsfinder.net/readme.txt b/xtrn/bbsfinder.net/readme.txt deleted file mode 100644 index cb01859425184e9a4bba048d2e207d48e206ea20..0000000000000000000000000000000000000000 --- a/xtrn/bbsfinder.net/readme.txt +++ /dev/null @@ -1,77 +0,0 @@ -BBSfinder.net updater for Synchronet 3.15+ -echicken -at- bbs.electronicchicken.com - -Requirements: -------------- - -It's recommended that you grab the latest copies of the following files from -the Synchronet CVS at cvs.synchro.net: - -exec/load/http.js -exec/load/event-timer.js -xtrn/bbsfinder.net/bbsfinder.js -xtrn/bbsfinder.net/readme.txt - - -Installation: -------------- - -I'm going to assume that your copy of bbsfinder.js is located at: - -/sbbs/xtrn/bbsfinder.net/bbsfinder.js - -Add the following section to your ctrl/modopts.ini file: - -[bbsfinder] -username = <username> -password = <password> - - -Usage: ------- - -Method #1: Running as a timed event - - Launch scfg (that's BBS->Configure from the Synchronet Control Panel in - Windows,) select "External Programs", then "Timed Events", and create a - new item as follows: - - Event Internal Code: BBSFINDR - - Edit the timed event that you've just created so that it looks like this: - - BBSFINDR Timed Event - ---------------------------------------------------------- - �Internal Code BBSFINDR - �Start-up Directory /sbbs/xtrn/bbsfinder.net - �Command Line ?bbsfinder.js - �Enabled Yes - �Execution Node 1 - �Execution Months Any - �Execution Days of Month Any - �Execution Days of Week All - �Execution Frequency 360 times a day - �Requires Exclusive Execution No - �Force Users Off-line For Event No - �Native Executable No - �Use Shell to Execute No - �Background Execution No - �Always Run After Init/Re-init Yes - - Hint: to set the "Execution frequency" to "360 times a day", select - "Execution frequency" and answer "No" at the "Execute at a specific time?" - prompt. We want this event to run every four minutes, so (24*60)/4 = 360. - -Method #2: Running from jsexec - - From a command prompt, execute the following, substituting paths as - required: - - /sbbs/exec/jsexec /sbbs/xtrn/bbsfinder.net/bbsfinder.js -l - - -Support: --------- - -Post a message to 'echicken' in DOVENet's Synchronet Sysops echo, or find me -in #synchronet on irc.synchro.net. \ No newline at end of file diff --git a/xtrn/bullshit/bullshit.js b/xtrn/bullshit/bullshit.js index 2210c52d58c01e2814b4b01aee72ea9975d53128..9fc597358c4e0a32b5fb4f013bb6b530ce4288ea 100644 --- a/xtrn/bullshit/bullshit.js +++ b/xtrn/bullshit/bullshit.js @@ -271,10 +271,22 @@ function init() { } function main() { - const settings = lib.loadSettings(argv[0]); + var settings = lib.loadSettings(argv[0]); + + // if you set newOnly to logon, then on login time, it will treat it as newOnly=true and + // only show if new bulletins, but at all other times, treat it as newOnly=false + // (so always display them when called from external program menu context) + if ((settings.newOnly == "logon") && (bbs.node_action != NODE_LOGN)) { + settings.newOnly = false; + } + const list = lib.loadList(settings); - if (!list.length && settings.newOnly) return; - const disp = initDisplay(settings, list); + + if (!list.length && settings.newOnly) { + return; + } + + const disp = initDisplay(settings, list); displayList(list, disp.tree); var ret; var viewer; diff --git a/xtrn/bullshit/readme.txt b/xtrn/bullshit/readme.txt index c2e162850315df7e5a4c870ff7f6c64749deec63..6501301a192d9a48f1074cd94d6e1276443e1a34 100644 --- a/xtrn/bullshit/readme.txt +++ b/xtrn/bullshit/readme.txt @@ -90,6 +90,12 @@ Contents is available to be displayed to the user. Bullshit will exit silently. + If 'newOnly' is set to the string "logon", then only new bulletins + will be shown to the user at logon time (and will silently exit + if none are available), but all bulletins will be shown at other + times (for example, adding bullshit to the external programs menu) + + In the 'colors' section: - 'title' and 'text' are the colors used when viewing an item diff --git a/xtrn/knk/knk.js b/xtrn/knk/knk.js index 77498732117b2c55a7bed4848d0f2ec4b913d54b..30579383b8b56796fb323ef5ca6371648f64916a 100644 --- a/xtrn/knk/knk.js +++ b/xtrn/knk/knk.js @@ -1424,7 +1424,7 @@ function update_userfile(player, computer, won) var lines=[]; var line; var now=new Date(); - var nowmonth=['January','February','March','April','May','June','July','August','September','Optober','November','December'][now.getMonth()]; + var nowmonth=['January','February','March','April','May','June','July','August','September','October','November','December'][now.getMonth()]; var all_ud=[]; if(!Lock(f.name, dk.connection.node, true, 1)) diff --git a/xtrn/sdk/xsdk.c b/xtrn/sdk/xsdk.c index 87c06ca157bf1c1a089b4d398a66fb3d25cea789..52549135666e1da830568f5b60f6f6c75c1b18a6 100644 --- a/xtrn/sdk/xsdk.c +++ b/xtrn/sdk/xsdk.c @@ -2247,7 +2247,7 @@ uint usernumber(char *username) char *ultoac(ulong l, char *string) { char str[81]; - char i,j,k; + int i,j,k; sprintf(str,"%lu",l); i=strlen(str)-1; diff --git a/xtrn/sdk/xsdkdefs.h b/xtrn/sdk/xsdkdefs.h index f7b91a2109a60a134590b4bdfba1a380c77b758e..6160313094fa3d14f0895eca479b13cd35c434e4 100644 --- a/xtrn/sdk/xsdkdefs.h +++ b/xtrn/sdk/xsdkdefs.h @@ -288,6 +288,44 @@ enum { /* Node Action */ #ifndef _SBBSDEFS_H #define KEY_BUFSIZE 256 +#endif + +#ifndef USE_XPDEV +enum { + CTRL_AT // NUL + ,CTRL_A // SOH + ,CTRL_B // STX + ,CTRL_C // ETX + ,CTRL_D // EOT + ,CTRL_E // ENQ + ,CTRL_F // ACK + ,CTRL_G // BEL + ,CTRL_H // BS + ,CTRL_I // HT + ,CTRL_J // LF + ,CTRL_K // VT + ,CTRL_L // FF + ,CTRL_M // CR + ,CTRL_N // SO + ,CTRL_O // SI + ,CTRL_P // DLE + ,CTRL_Q // DC1 + ,CTRL_R // DC2 + ,CTRL_S // DC3 + ,CTRL_T // DC4 + ,CTRL_U // NAK + ,CTRL_V // SYN + ,CTRL_W // ETB + ,CTRL_X // CAN + ,CTRL_Y // EM + ,CTRL_Z // SUB + ,CTRL_OPEN_BRACKET // ESC + ,CTRL_BACKSLASH // FS + ,CTRL_CLOSE_BRACKET // GS + ,CTRL_CARET // RS + ,CTRL_UNDERSCORE // US + ,CTRL_QUESTION_MARK = 0x7f // DEL +}; #endif /* Special terminal key mappings */