Guest User

Modified xtrn_sec.js

a guest
Dec 14th, 2025
47
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 12.00 KB | None | 0 0
  1. // xtrn_sec.js
  2. //
  3. // Synchronet External Program Section (Telnet/RLogin/SSH)
  4. //
  5. // Custom behavior added:
  6. // - Show security-level menu: xtrn_sec_<SL>.* (e.g. xtrn_sec_50.ans)
  7. // fallback: xtrn_sec.*
  8. // - If custom menu shown, DO NOT draw built-in section list.
  9. // Instead, accept numeric input (console.getnum) and launch the selected section.
  10. //
  11. // Options (ctrl/modopts.ini [xtrn_sec]):
  12. // sec_level_menu_prefix = "xtrn_sec_"
  13. // sec_level_menu_fallback = "xtrn_sec"
  14. // sec_level_menu_show_every_time = true/false (default: true)
  15. // sec_level_menu_replace_section_list = true/false (default: true)
  16.  
  17. "use strict";
  18.  
  19. require("sbbsdefs.js", "P_NOERROR");
  20. require("text.js", "XtrnProgLstFmt");
  21.  
  22. /* See if an xtrn section code was passed as an argument */
  23. /* must parse argv before calling load() */
  24. var xsec = -1;
  25. {
  26. var i, j;
  27. for (i in argv) {
  28. for (j in xtrn_area.sec_list) {
  29. if (argv[i].toLowerCase() == xtrn_area.sec_list[j].code)
  30. xsec = j;
  31. }
  32. }
  33. }
  34.  
  35. var options;
  36. if ((options = load({}, "modopts.js", "xtrn_sec")) == null)
  37. options = { multicolumn: true, sort: false }; // default values
  38.  
  39. if (options.multicolumn === undefined)
  40. options.multicolumn = true;
  41.  
  42. if (options.multicolumn_separator === undefined)
  43. options.multicolumn_separator = " ";
  44.  
  45. if (options.multicolumn_fmt === undefined)
  46. options.multicolumn_fmt = bbs.text(XtrnProgLstFmt);
  47.  
  48. if (options.singlecolumn_fmt === undefined)
  49. options.singlecolumn_fmt = "\x01h\x01c%3u \xb3 \x01n\x01c%s\x01h ";
  50.  
  51. if (options.singlecolumn_margin == undefined)
  52. options.singlecolumn_margin = 7;
  53.  
  54. if (options.singlecolumn_height == undefined)
  55. options.singlecolumn_height = console.screen_rows - options.singlecolumn_margin;
  56.  
  57. if (console.screen_columns < 80) {
  58. options.multicolumn = false;
  59. options.center = false;
  60. }
  61.  
  62. if (options.restricted_user_msg === undefined)
  63. options.restricted_user_msg = bbs.text(R_ExternalPrograms);
  64.  
  65. if (options.no_programs_msg === undefined)
  66. options.no_programs_msg = bbs.text(NoXtrnPrograms);
  67.  
  68. if (options.header_fmt === undefined)
  69. options.header_fmt = bbs.text(XtrnProgLstHdr);
  70.  
  71. if (options.titles === undefined)
  72. options.titles = bbs.text(XtrnProgLstTitles);
  73.  
  74. if (options.underline === undefined)
  75. options.underline = bbs.text(XtrnProgLstUnderline);
  76.  
  77. if (options.which === undefined)
  78. options.which = bbs.text(WhichXtrnProg);
  79.  
  80. if (options.clear_screen === undefined)
  81. options.clear_screen = true;
  82.  
  83. if (options.section_fmt === undefined)
  84. options.section_fmt = bbs.text(SelectItemFmt);
  85.  
  86. if (options.multicolumn_section_fmt === undefined)
  87. options.multicolumn_section_fmt = "\x01g\x01h%3d: \x01n\x01g%-32.32s ";
  88.  
  89. if (options.section_header_fmt === undefined)
  90. options.section_header_fmt = bbs.text(SelectItemHdr);
  91.  
  92. if (options.section_which === undefined)
  93. options.section_which = bbs.text(SelectItemWhich);
  94.  
  95. if (options.section_header_title === undefined)
  96. options.section_header_title = "External Program Section";
  97.  
  98. /* ------------------------------------------
  99. Security-level menu feature
  100. ------------------------------------------ */
  101.  
  102. if (options.sec_level_menu_prefix === undefined)
  103. options.sec_level_menu_prefix = "xtrn_sec_";
  104.  
  105. if (options.sec_level_menu_fallback === undefined)
  106. options.sec_level_menu_fallback = "xtrn_sec";
  107.  
  108. if (options.sec_level_menu_show_every_time === undefined)
  109. options.sec_level_menu_show_every_time = true;
  110.  
  111. if (options.sec_level_menu_replace_section_list === undefined)
  112. options.sec_level_menu_replace_section_list = true;
  113.  
  114. function show_security_level_menu_once()
  115. {
  116. if (!options.sec_level_menu_show_every_time) {
  117. if (js.global.__xtrn_sec_level_menu_shown)
  118. return false;
  119. js.global.__xtrn_sec_level_menu_shown = true;
  120. }
  121.  
  122. var primary = options.sec_level_menu_prefix + user.security.level;
  123.  
  124. if (bbs.menu_exists(primary)) {
  125. bbs.menu(primary, P_NOERROR);
  126. return true;
  127. }
  128.  
  129. if (options.sec_level_menu_fallback && bbs.menu_exists(options.sec_level_menu_fallback)) {
  130. bbs.menu(options.sec_level_menu_fallback, P_NOERROR);
  131. return true;
  132. }
  133.  
  134. return false;
  135. }
  136.  
  137. /* -------------------------------
  138. Existing functionality
  139. ------------------------------- */
  140.  
  141. function sort_by_name(a, b)
  142. {
  143. if (a.name.toLowerCase() > b.name.toLowerCase()) return 1;
  144. if (a.name.toLowerCase() < b.name.toLowerCase()) return -1;
  145. return 0;
  146. }
  147.  
  148. function digits(n)
  149. {
  150. if (n / 10 == 0)
  151. return 1;
  152. return 1 + digits(Math.floor(n / 10));
  153. }
  154.  
  155. function external_program_menu(xsec)
  156. {
  157. var i, j;
  158.  
  159. js.global.xtrn_sec = xtrn_area.sec_list[xsec].name;
  160.  
  161. while (bbs.online) {
  162.  
  163. console.aborted = false;
  164. if (user.security.restrictions & UFLAG_X) {
  165. write(options.restricted_user_msg);
  166. break;
  167. }
  168.  
  169. var prog_list = xtrn_area.sec_list[xsec].prog_list.slice();
  170.  
  171. if (!prog_list.length) {
  172. write(options.no_programs_msg);
  173. console.pause();
  174. break;
  175. }
  176.  
  177. if (options.autoexec && prog_list.length == 1) {
  178. bbs.exec_xtrn(prog_list[0].code);
  179. break;
  180. }
  181.  
  182. if (options.clear_screen)
  183. console.clear(LIGHTGRAY);
  184.  
  185. var show_header = true;
  186. var secnum = xtrn_area.sec_list[xsec].number + 1;
  187. var seccode = xtrn_area.sec_list[xsec].code;
  188.  
  189. if (bbs.menu("xtrn" + secnum + "_head", P_NOERROR)) {
  190. show_header = false;
  191. } else if (bbs.menu("xtrn" + seccode + "_head", P_NOERROR)) {
  192. show_header = false;
  193. } else {
  194. bbs.menu("xtrn_head", P_NOERROR);
  195. }
  196.  
  197. if (bbs.menu("xtrn" + secnum, P_NOERROR) || bbs.menu("xtrn" + seccode, P_NOERROR)) {
  198. if (!bbs.menu("xtrn" + secnum + "_tail", P_NOERROR) &&
  199. !bbs.menu("xtrn" + seccode + "_tail", P_NOERROR)) {
  200. bbs.menu("xtrn_tail", P_NOERROR);
  201. }
  202. }
  203. else {
  204. var multicolumn = options.multicolumn && prog_list.length > options.singlecolumn_height;
  205. var center = options.center && !multicolumn;
  206. var margin = center ? format("%*s", (console.screen_columns * 0.25) - 1, "") : "";
  207.  
  208. if (options.sort)
  209. prog_list.sort(sort_by_name);
  210.  
  211. if (show_header)
  212. write(margin, format(options.header_fmt, xtrn_area.sec_list[xsec].name));
  213.  
  214. if (options.titles.trimRight() != '')
  215. write(margin, options.titles);
  216.  
  217. if (multicolumn) {
  218. write(options.multicolumn_separator);
  219. if (options.titles.trimRight() != '')
  220. write(options.titles);
  221. }
  222.  
  223. if (options.underline.trimRight() != '') {
  224. console.crlf();
  225. write(margin, options.underline);
  226. }
  227.  
  228. if (multicolumn) {
  229. write(options.multicolumn_separator);
  230. if (options.underline.trimRight() != '')
  231. write(options.underline);
  232. }
  233.  
  234. console.crlf();
  235.  
  236. var n = multicolumn
  237. ? Math.floor(prog_list.length / 2) + (prog_list.length & 1)
  238. : prog_list.length;
  239.  
  240. var max_digits = digits(prog_list.length);
  241. for (i = 0; i < n && !console.aborted; i++) {
  242. write(margin);
  243. var hotspot = i + 1;
  244. if (digits(hotspot) < digits(prog_list.length))
  245. hotspot += '\r';
  246. console.add_hotspot(hotspot);
  247.  
  248. if (options.align_prog_list)
  249. printf("%*s", max_digits - digits(i + 1), "");
  250.  
  251. printf(multicolumn ? options.multicolumn_fmt : options.singlecolumn_fmt,
  252. i + 1,
  253. prog_list[i].name,
  254. prog_list[i].cost
  255. );
  256.  
  257. if (multicolumn) {
  258. j = Math.floor(prog_list.length / 2) + i + (prog_list.length & 1);
  259. if (j < prog_list.length) {
  260. write(options.multicolumn_separator);
  261. hotspot = j + 1;
  262. if (digits(hotspot) < digits(prog_list.length))
  263. hotspot += '\r';
  264. console.add_hotspot(hotspot);
  265.  
  266. if (options.align_prog_list)
  267. printf("%*s", max_digits - digits(j + 1), "");
  268.  
  269. printf(options.multicolumn_fmt,
  270. j + 1,
  271. prog_list[j].name,
  272. prog_list[j].cost
  273. );
  274. }
  275. }
  276. console.crlf();
  277. }
  278.  
  279. if (!bbs.menu("xtrn" + secnum + "_tail", P_NOERROR)
  280. && !bbs.menu("xtrn" + seccode + "_tail", P_NOERROR)) {
  281. bbs.menu("xtrn_tail", P_NOERROR);
  282. }
  283.  
  284. bbs.node_sync();
  285.  
  286. if (margin) {
  287. console.crlf();
  288. write(margin);
  289. console.mnemonics(options.which.trimLeft());
  290. } else
  291. console.mnemonics(options.which);
  292. }
  293.  
  294. system.node_list[bbs.node_num - 1].aux = 0;
  295. bbs.node_action = NODE_XTRN;
  296. bbs.node_sync();
  297.  
  298. if ((i = console.getnum(prog_list.length)) < 1)
  299. break;
  300. i--;
  301.  
  302. bbs.exec_xtrn(prog_list[i].code);
  303. }
  304. }
  305.  
  306. function external_section_menu()
  307. {
  308. var i, j;
  309. var xsec = 0;
  310. var longest = 0;
  311.  
  312. for (i = 0; i < xtrn_area.sec_list.length; i++)
  313. longest = Math.max(xtrn_area.sec_list[i].name.length, longest);
  314.  
  315. while (bbs.online) {
  316.  
  317. console.aborted = false;
  318. if (user.security.restrictions & UFLAG_X) {
  319. write(options.restricted_user_msg);
  320. break;
  321. }
  322.  
  323. if (!xtrn_area.sec_list.length) {
  324. write(options.no_programs_msg);
  325. break;
  326. }
  327.  
  328. var sec_list = xtrn_area.sec_list.slice();
  329.  
  330. system.node_list[bbs.node_num - 1].aux = 0;
  331. bbs.node_action = NODE_XTRN;
  332. bbs.node_sync();
  333.  
  334. if (options.clear_screen)
  335. console.clear(LIGHTGRAY);
  336.  
  337. // Show your custom per-SL menu (or fallback)
  338. var custom_shown = show_security_level_menu_once();
  339.  
  340. // If you want your ANSI to be the section list UI, do not draw the built-in list.
  341. // But we STILL accept numeric input and launch the selected section.
  342. if (custom_shown && options.sec_level_menu_replace_section_list) {
  343. // Keep node state correct
  344. system.node_list[bbs.node_num - 1].aux = 0;
  345. bbs.node_action = NODE_XTRN;
  346. bbs.node_sync();
  347.  
  348. // Read a number (your ANSI already instructs them what to type)
  349. var num = console.getnum(sec_list.length);
  350.  
  351. if (num < 0)
  352. break;
  353. if (num === 0)
  354. break;
  355.  
  356. xsec = num - 1;
  357. external_program_menu(sec_list[xsec].index);
  358. continue;
  359. }
  360.  
  361. // Otherwise, show built-in section list UI
  362. var show_header = !bbs.menu("xtrn_sec_head", P_NOERROR);
  363.  
  364. if (bbs.menu_exists("xtrn_sec")) {
  365. bbs.menu("xtrn_sec");
  366. bbs.menu("xtrn_sec_tail", P_NOERROR);
  367. xsec = undefined;
  368. }
  369. else {
  370. if (options.sort)
  371. sec_list.sort(sort_by_name);
  372.  
  373. var multicolumn = options.multicolumn && sec_list.length > options.singlecolumn_height;
  374. var center = options.center && !multicolumn;
  375. var margin = center ? format("%*s", ((console.screen_columns - longest) / 2) - 5, "") : "";
  376.  
  377. if (show_header)
  378. printf(margin + options.section_header_fmt.replace('\x01l', ''), options.section_header_title);
  379.  
  380. var n = multicolumn
  381. ? Math.floor(sec_list.length / 2) + (sec_list.length & 1)
  382. : sec_list.length;
  383.  
  384. var max_digits = digits(sec_list.length);
  385.  
  386. for (i = 0; i < n && !console.aborted; i++) {
  387. var hotspot = i + 1;
  388. if (digits(hotspot) < digits(sec_list.length))
  389. hotspot += '\r';
  390. console.add_hotspot(hotspot);
  391.  
  392. if (options.align_section_list)
  393. printf("%*s", max_digits - digits(i + 1), "");
  394.  
  395. printf(margin + (multicolumn ? options.multicolumn_section_fmt : options.section_fmt),
  396. i + 1, sec_list[i].name);
  397.  
  398. if (multicolumn) {
  399. j = Math.floor(sec_list.length / 2) + i + (sec_list.length & 1);
  400. if (j < sec_list.length) {
  401. write(options.multicolumn_separator);
  402. hotspot = j + 1;
  403. if (digits(hotspot) < digits(sec_list.length))
  404. hotspot += '\r';
  405. console.add_hotspot(hotspot);
  406.  
  407. if (options.align_section_list)
  408. printf("%*s", max_digits - digits(j + 1), "");
  409.  
  410. printf(options.multicolumn_section_fmt, j + 1, sec_list[j].name);
  411. }
  412. console.crlf();
  413. }
  414. }
  415.  
  416. bbs.menu("xtrn_sec_tail", P_NOERROR);
  417.  
  418. bbs.node_sync();
  419. if (center) {
  420. console.crlf();
  421. write(margin);
  422. console.mnemonics(format(options.section_which, xsec + 1).trimLeft());
  423. } else
  424. console.mnemonics(format(options.section_which, xsec + 1));
  425. }
  426.  
  427. bbs.node_sync();
  428. var num2 = console.getnum(sec_list.length);
  429. if (num2 < 0)
  430. break;
  431. if (xsec === undefined && num2 == 0)
  432. break;
  433. if (num2 > 0)
  434. xsec = num2 - 1;
  435.  
  436. external_program_menu(sec_list[xsec].index);
  437. }
  438. }
  439.  
  440. /* main: */
  441. if (xsec >= 0)
  442. external_program_menu(xsec);
  443. else {
  444. if (xtrn_area.sec_list.length == 1)
  445. external_program_menu(0);
  446. else
  447. external_section_menu();
  448. }
  449.  
Advertisement
Add Comment
Please, Sign In to add comment