From 73d04378dce6c28b2bc14f33689251d4dfe21799 Mon Sep 17 00:00:00 2001 From: NuSkooler Date: Sat, 5 Feb 2022 06:30:33 +0000 Subject: [PATCH] deploy: f0a8aa0c9caf437c234466d0d5f8aeca71b31464 --- .nojekyll | 0 404.html | 2301 +++++++++++++ admin/administration.html | 2330 +++++++++++++ admin/oputil.html | 2733 +++++++++++++++ admin/updating.html | 2325 +++++++++++++ art/general.html | 2504 ++++++++++++++ art/mci.html | 3003 +++++++++++++++++ art/themes.html | 2538 ++++++++++++++ art/views/button_view.html | 2388 +++++++++++++ art/views/edit_text_view.html | 2366 +++++++++++++ art/views/full_menu_view.html | 2588 ++++++++++++++ art/views/horizontal_menu_view.html | 2431 +++++++++++++ art/views/mask_edit_text_view.html | 2431 +++++++++++++ art/views/multi_line_edit_text_view.html | 2383 +++++++++++++ art/views/predefined_label_view.html | 2363 +++++++++++++ art/views/spinner_menu_view.html | 2441 ++++++++++++++ art/views/text_view.html | 2365 +++++++++++++ art/views/toggle_menu_view.html | 2403 +++++++++++++ art/views/vertical_menu_view.html | 2445 ++++++++++++++ assets/css/style.css | 154 + assets/css/style.css.map | 18 + assets/images/bkg.png | Bin 0 -> 1218 bytes assets/images/blacktocat.png | Bin 0 -> 268 bytes assets/images/bullet.png | Bin 0 -> 603 bytes assets/images/button_view_example1.gif | Bin 0 -> 5255 bytes assets/images/colour-codes.png | Bin 0 -> 15677 bytes assets/images/cp437.png | Bin 0 -> 308 bytes assets/images/edit_text_view_example1.gif | Bin 0 -> 4346 bytes assets/images/enigma-bbs.png | Bin 0 -> 6814 bytes assets/images/enigma-logo.png | Bin 0 -> 16643 bytes assets/images/favicon-16x16.png | Bin 0 -> 885 bytes assets/images/favicon-32x32.png | Bin 0 -> 2849 bytes assets/images/full_menu_view_example1.gif | Bin 0 -> 7198 bytes assets/images/full_menu_view_example2.gif | Bin 0 -> 7832 bytes assets/images/full_menu_view_example3.gif | Bin 0 -> 28011 bytes .../images/horizontal_menu_view_example1.gif | Bin 0 -> 7832 bytes .../images/mask_edit_text_view_example1.gif | Bin 0 -> 7222 bytes assets/images/mci-example1.png | Bin 0 -> 317 bytes assets/images/microknight.png | Bin 0 -> 401 bytes assets/images/microknight_plus.png | Bin 0 -> 467 bytes assets/images/mo_soul.png | Bin 0 -> 316 bytes .../multi_line_edit_text_view_example1.gif | Bin 0 -> 13256 bytes assets/images/pot_noodle.png | Bin 0 -> 340 bytes .../images/predefined_label_view_example1.png | Bin 0 -> 3342 bytes assets/images/spinner_menu_view_example1.gif | Bin 0 -> 3982 bytes assets/images/text-format-example1.png | Bin 0 -> 496 bytes assets/images/text_label_view_example1.png | Bin 0 -> 1479 bytes assets/images/toggle_menu_view_example1.gif | Bin 0 -> 3639 bytes assets/images/topaz.png | Bin 0 -> 270 bytes assets/images/topaz_plus.png | Bin 0 -> 347 bytes assets/images/vertical_menu_view_example1.gif | Bin 0 -> 7198 bytes assets/images/vtxclient.png | Bin 0 -> 130515 bytes configuration/acs.html | 2469 ++++++++++++++ configuration/archivers.html | 2350 +++++++++++++ configuration/colour-codes.html | 2312 +++++++++++++ configuration/config-files.html | 2490 ++++++++++++++ configuration/config-hjson.html | 2344 +++++++++++++ configuration/creating-config.html | 2303 +++++++++++++ configuration/directory-structure.html | 2362 +++++++++++++ configuration/email.html | 2337 +++++++++++++ configuration/event-scheduler.html | 2396 +++++++++++++ configuration/external-binaries.html | 2451 ++++++++++++++ configuration/file-transfer-protocols.html | 2344 +++++++++++++ configuration/hjson.html | 2369 +++++++++++++ configuration/menu-hjson.html | 2778 +++++++++++++++ configuration/security.html | 2366 +++++++++++++ configuration/sysop-setup.html | 2295 +++++++++++++ favicon.ico | Bin 0 -> 15406 bytes filebase/acs.html | 2322 +++++++++++++ filebase/first-file-area.html | 2418 +++++++++++++ filebase/index.html | 2324 +++++++++++++ filebase/network-mounts-and-symlinks.html | 2318 +++++++++++++ filebase/tic-support.html | 2388 +++++++++++++ filebase/uploads.html | 2313 +++++++++++++ filebase/web-access.html | 2301 +++++++++++++ index.html | 2310 +++++++++++++ installation/docker.html | 2398 +++++++++++++ installation/hardware/rpi.html | 2324 +++++++++++++ installation/hardware/windows.html | 2371 +++++++++++++ installation/install-script.html | 2313 +++++++++++++ installation/installation-methods.html | 2325 +++++++++++++ installation/manual.html | 2361 +++++++++++++ installation/network.html | 2303 +++++++++++++ installation/production.html | 2302 +++++++++++++ installation/testing.html | 2344 +++++++++++++ messageareas/bso-import-export.html | 2615 ++++++++++++++ messageareas/configuring-a-message-area.html | 2454 ++++++++++++++ messageareas/ftn.html | 2419 +++++++++++++ messageareas/message-networks.html | 2318 +++++++++++++ messageareas/netmail.html | 2324 +++++++++++++ messageareas/qwk.html | 2355 +++++++++++++ misc/user-interrupt.html | 2308 +++++++++++++ modding/autosig-edit.html | 2313 +++++++++++++ modding/bbs-list.html | 2318 +++++++++++++ modding/door-servers.html | 2348 +++++++++++++ modding/existing-mods.html | 2324 +++++++++++++ modding/file-area-list.html | 2405 +++++++++++++ modding/file-base-download-manager.html | 2317 +++++++++++++ modding/file-base-web-download-manager.html | 2320 +++++++++++++ modding/file-transfer-protocol-select.html | 2305 +++++++++++++ modding/last-callers.html | 2342 +++++++++++++ modding/local-doors.html | 2642 +++++++++++++++ modding/menu-modules.html | 2303 +++++++++++++ modding/msg-area-list.html | 2311 +++++++++++++ modding/msg-conf-list.html | 2312 +++++++++++++ modding/node-msg.html | 2343 +++++++++++++ modding/onelinerz.html | 2313 +++++++++++++ modding/rumorz.html | 2304 +++++++++++++ modding/set-newscan-date.html | 2329 +++++++++++++ modding/show-art.html | 2358 +++++++++++++ modding/telnet-bridge.html | 2386 +++++++++++++ modding/top-x.html | 2366 +++++++++++++ modding/user-2fa-otp-config.html | 2396 +++++++++++++ modding/user-list.html | 2315 +++++++++++++ modding/whos-online.html | 2310 +++++++++++++ robots.txt | 1 + servers/contentservers/gopher.html | 2392 +++++++++++++ servers/contentservers/nntp.html | 2420 +++++++++++++ servers/contentservers/web-server.html | 2431 +++++++++++++ servers/loginservers/ssh.html | 2385 +++++++++++++ servers/loginservers/telnet.html | 2344 +++++++++++++ servers/loginservers/websocket.html | 2410 +++++++++++++ sitemap.xml | 346 ++ troubleshooting/monitoring-logs.html | 2333 +++++++++++++ 124 files changed, 208046 insertions(+) create mode 100644 .nojekyll create mode 100644 404.html create mode 100644 admin/administration.html create mode 100644 admin/oputil.html create mode 100644 admin/updating.html create mode 100644 art/general.html create mode 100644 art/mci.html create mode 100644 art/themes.html create mode 100644 art/views/button_view.html create mode 100644 art/views/edit_text_view.html create mode 100644 art/views/full_menu_view.html create mode 100644 art/views/horizontal_menu_view.html create mode 100644 art/views/mask_edit_text_view.html create mode 100644 art/views/multi_line_edit_text_view.html create mode 100644 art/views/predefined_label_view.html create mode 100644 art/views/spinner_menu_view.html create mode 100644 art/views/text_view.html create mode 100644 art/views/toggle_menu_view.html create mode 100644 art/views/vertical_menu_view.html create mode 100644 assets/css/style.css create mode 100644 assets/css/style.css.map create mode 100644 assets/images/bkg.png create mode 100644 assets/images/blacktocat.png create mode 100644 assets/images/bullet.png create mode 100644 assets/images/button_view_example1.gif create mode 100644 assets/images/colour-codes.png create mode 100644 assets/images/cp437.png create mode 100644 assets/images/edit_text_view_example1.gif create mode 100644 assets/images/enigma-bbs.png create mode 100644 assets/images/enigma-logo.png create mode 100644 assets/images/favicon-16x16.png create mode 100644 assets/images/favicon-32x32.png create mode 100644 assets/images/full_menu_view_example1.gif create mode 100644 assets/images/full_menu_view_example2.gif create mode 100644 assets/images/full_menu_view_example3.gif create mode 100644 assets/images/horizontal_menu_view_example1.gif create mode 100644 assets/images/mask_edit_text_view_example1.gif create mode 100644 assets/images/mci-example1.png create mode 100644 assets/images/microknight.png create mode 100644 assets/images/microknight_plus.png create mode 100644 assets/images/mo_soul.png create mode 100644 assets/images/multi_line_edit_text_view_example1.gif create mode 100644 assets/images/pot_noodle.png create mode 100644 assets/images/predefined_label_view_example1.png create mode 100644 assets/images/spinner_menu_view_example1.gif create mode 100644 assets/images/text-format-example1.png create mode 100644 assets/images/text_label_view_example1.png create mode 100644 assets/images/toggle_menu_view_example1.gif create mode 100644 assets/images/topaz.png create mode 100644 assets/images/topaz_plus.png create mode 100644 assets/images/vertical_menu_view_example1.gif create mode 100644 assets/images/vtxclient.png create mode 100644 configuration/acs.html create mode 100644 configuration/archivers.html create mode 100644 configuration/colour-codes.html create mode 100644 configuration/config-files.html create mode 100644 configuration/config-hjson.html create mode 100644 configuration/creating-config.html create mode 100644 configuration/directory-structure.html create mode 100644 configuration/email.html create mode 100644 configuration/event-scheduler.html create mode 100644 configuration/external-binaries.html create mode 100644 configuration/file-transfer-protocols.html create mode 100644 configuration/hjson.html create mode 100644 configuration/menu-hjson.html create mode 100644 configuration/security.html create mode 100644 configuration/sysop-setup.html create mode 100644 favicon.ico create mode 100644 filebase/acs.html create mode 100644 filebase/first-file-area.html create mode 100644 filebase/index.html create mode 100644 filebase/network-mounts-and-symlinks.html create mode 100644 filebase/tic-support.html create mode 100644 filebase/uploads.html create mode 100644 filebase/web-access.html create mode 100644 index.html create mode 100644 installation/docker.html create mode 100644 installation/hardware/rpi.html create mode 100644 installation/hardware/windows.html create mode 100644 installation/install-script.html create mode 100644 installation/installation-methods.html create mode 100644 installation/manual.html create mode 100644 installation/network.html create mode 100644 installation/production.html create mode 100644 installation/testing.html create mode 100644 messageareas/bso-import-export.html create mode 100644 messageareas/configuring-a-message-area.html create mode 100644 messageareas/ftn.html create mode 100644 messageareas/message-networks.html create mode 100644 messageareas/netmail.html create mode 100644 messageareas/qwk.html create mode 100644 misc/user-interrupt.html create mode 100644 modding/autosig-edit.html create mode 100644 modding/bbs-list.html create mode 100644 modding/door-servers.html create mode 100644 modding/existing-mods.html create mode 100644 modding/file-area-list.html create mode 100644 modding/file-base-download-manager.html create mode 100644 modding/file-base-web-download-manager.html create mode 100644 modding/file-transfer-protocol-select.html create mode 100644 modding/last-callers.html create mode 100644 modding/local-doors.html create mode 100644 modding/menu-modules.html create mode 100644 modding/msg-area-list.html create mode 100644 modding/msg-conf-list.html create mode 100644 modding/node-msg.html create mode 100644 modding/onelinerz.html create mode 100644 modding/rumorz.html create mode 100644 modding/set-newscan-date.html create mode 100644 modding/show-art.html create mode 100644 modding/telnet-bridge.html create mode 100644 modding/top-x.html create mode 100644 modding/user-2fa-otp-config.html create mode 100644 modding/user-list.html create mode 100644 modding/whos-online.html create mode 100644 robots.txt create mode 100644 servers/contentservers/gopher.html create mode 100644 servers/contentservers/nntp.html create mode 100644 servers/contentservers/web-server.html create mode 100644 servers/loginservers/ssh.html create mode 100644 servers/loginservers/telnet.html create mode 100644 servers/loginservers/websocket.html create mode 100644 sitemap.xml create mode 100644 troubleshooting/monitoring-logs.html diff --git a/.nojekyll b/.nojekyll new file mode 100644 index 00000000..e69de29b diff --git a/404.html b/404.html new file mode 100644 index 00000000..7a43d6c9 --- /dev/null +++ b/404.html @@ -0,0 +1,2301 @@ + + + + + + + + + + + +ENiGMA½ BBS Software | ENiGMA½ BBS is modern open source BBS software with a nostalgic flair, written in Node.js. + + + + + + + + + + + + + + + +
+ +
+
+
+ + + + +
+

404

+ +

Page not found :(

+

The requested page could not be found.

+
+ + + +
+
+
+
+ + + + diff --git a/admin/administration.html b/admin/administration.html new file mode 100644 index 00000000..8311c718 --- /dev/null +++ b/admin/administration.html @@ -0,0 +1,2330 @@ + + + + + + + + + + + +Administration | ENiGMA½ BBS Software + + + + + + + + + + + + + + + + + +
+ +
+
+
+ + +
+

Administration

+

Administration

+ +

Keeping Up to Date

+

See Updating.

+ +

Viewing Logs

+

See Monitoring Logs.

+ +

Managing Users

+

User management is currently handled via the oputil CLI.

+ +

Backing Up Your System

+

It is highly recommended to perform regular backups of your system. Nothing is worse than spending a lot of time setting up a system only to have to go away unexpectedly!

+ +

In general, simply creating a copy/archive of your system is enough for the default configuration. If you have changed default paths to point outside of your main ENiGMA½ installation take special care to ensure these are preserved as well. Database files may be in a state of flux when simply copying files. See Database Backups below for details on consistent backups.

+ +

Database Backups

+

SQLite’s CLI backup command can be used for creating database backup files. This can be performed as an additional step to a full backup to ensure the database is backed up in a consistent state (whereas simply copying the files does not make any guarantees).

+ +

As an example, consider the following Bash script that creates foo.sqlite3.backup files:

+ +
for dbfile in /path/to/enigma-bbs/db/*.sqlite3; do
+    sqlite3 $dbfile ".backup '/path/to/db_backup/$(basename $dbfile).backup'"
+done
+
+ +

Backup Tools

+

There are many backup solutions available across all platforms. Configuration of such tools is outside the scope of this documentation. With that said, the author has had great success with Borg.

+ +

General Maintenance Tasks

+

Vacuuming Database Files

+

SQLite database files become less performant over time and waste space. It is recommended to periodically vacuum your databases. Before proceeding, you should make a backup!

+ +

Example:

+
sqlite3 ./db/message.sqlite3 "vacuum;"
+
+ +
+ + +
+
+
+
+ + + + diff --git a/admin/oputil.html b/admin/oputil.html new file mode 100644 index 00000000..2611ae42 --- /dev/null +++ b/admin/oputil.html @@ -0,0 +1,2733 @@ + + + + + + + + + + + +oputil | ENiGMA½ BBS Software + + + + + + + + + + + + + + + + + +
+ +
+
+
+ + +
+

oputil

+

The oputil CLI

+

ENiGMA½ comes with oputil.js henceforth known as oputil, a command line interface (CLI) tool for sysops to perform general system and user administration. You likely used oputil to do the initial ENiGMA configuration.

+ +

Let’s look the main help output as per this writing:

+ +
usage: oputil.js [--version] [--help]
+                  <command> [<arguments>]
+
+Global arguments:
+  -c, --config PATH         Specify config path (default is ./config/)
+  -n, --no-prompt           Assume defaults (don't prompt for input where possible)
+  --verbose                 Verbose output, where applicable
+
+Commands:
+  user                      User management
+  config                    Configuration management
+  fb                        File base management
+  mb                        Message base management
+
+ +

Commands break up operations by groups:

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
CommandDescription
userUser management
configSystem configuration and maintenance
fbFile base configuration and management
mbMessage base configuration and management
+ +

Global arguments apply to most commands and actions:

+
    +
  • --config: Specify configuration directory if it is not the default of ./config/.
  • +
  • --no-prompt: Assume defaults and do not prompt when posisible.
  • +
+ +

Type ./oputil.js <command> --help for additional help on a particular command. The following sections will describe them.

+ +

User

+

The user command covers various user operations.

+ +
usage: oputil.js user <action> [<arguments>]
+
+Actions:
+  info USERNAME                Display information about a user
+
+  pw USERNAME PASSWORD         Set a user's password
+  (passwd|password)
+
+  rm USERNAME                  Permanently removes user from system
+  (del|delete|remove)
+
+  rename USERNAME NEWNAME      Rename a user
+  (mv)
+
+  2fa-otp USERNAME SPEC        Enable 2FA/OTP for the user
+  (otp)
+
+  The system supports various implementations of Two Factor Authentication (2FA)
+  One Time Password (OTP) authentication.
+
+  Valid specs:
+    disable : Removes 2FA/OTP from the user
+    google  : Google Authenticator
+    hotp    : HMAC-Based One-Time Password Algorithm (RFC-4266)
+    totp    : Time-Based One-Time Password Algorithm (RFC-6238)
+
+  activate USERNAME            Set a user's status to "active"
+
+  deactivate USERNAME          Set a user's status to "inactive"
+
+  disable USERNAME             Set a user's status to "disabled"
+
+  lock USERNAME                Set a user's status to "locked"
+
+  group USERNAME [+|~]GROUP    Adds (+) or removes (~) user from a group
+
+  list [FILTER]                List users with optional FILTER.
+
+  Valid filters:
+    all      : All users (default).
+    disabled : Disabled users.
+    inactive : Inactive users.
+    active   : Active (regular) users.
+    locked   : Locked users.
+
+info arguments:
+  --security                   Include security information in output
+
+2fa-otp arguments:
+  --qr-type TYPE               Specify QR code type
+
+  Valid QR types:
+    ascii : Plain ASCII (default)
+    data  : HTML data URL
+    img   : HTML image tag
+    svg   : SVG image
+
+  --out PATH                   Path to write QR code to. defaults to stdout
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ActionDescriptionExamplesAliases
infoDisplay user information./oputil.js user info joeuserN/A
pwSet password./oputil.js user pw joeuser s3cr37passwd, password
rmRemoves user./oputil.js user del joeuserremove, del, delete
renameRenames a user./oputil.js user rename joeuser joemv
2fa-otpManage 2FA/OTP for a user./oputil.js user 2fa-otp joeuser googleAuthotp
activateActivates user./oputil.js user activate joeuserN/A
deactivateDeactivates user./oputil.js user deactivate joeuserN/A
disableDisables user (user will not be able to login)./oputil.js user disable joeuserN/A
lockLocks the user account (prevents logins)./oputil.js user lock joeuserN/A
groupModifies users group membershipAdd to group: ./oputil.js user group joeuser +derp
Remove from group: ./oputil.js user group joeuser ~derp
N/A
+ +

Manage 2FA/OTP

+

While oputil.js can be used to manage a user’s 2FA/OTP, it is highly recommended to require users to opt-in themselves. See Security for details.

+ +

Configuration

+

The config command allows sysops to perform various system configuration and maintenance tasks.

+ +
usage: oputil.js config <action> [<arguments>]
+
+Actions:
+  new                      Generate a new / default configuration
+
+  cat                      Write current configuration to stdout
+
+cat arguments:
+  --no-color               Disable color
+  --no-comments            Strip any comments
+
+ + + + + + + + + + + + + + + + + + + + + +
ActionDescriptionExamples
newGenerates a new/initial configuration./oputil.js config new (follow the prompts)
catPretty prints current config.hjson configuration to stdout../oputil.js config cat
+ +

File Base Management

+

The fb command provides a powerful file base management interface.

+ +
usage: oputil.js fb <action> [<arguments>]
+
+Actions:
+  scan AREA_TAG[@STORAGE_TAG]  Scan specified area
+
+  May contain optional GLOB as last parameter.
+  Example: ./oputil.js fb scan d0pew4r3z *.zip
+
+  info CRITERIA                Display information about areas and/or files
+
+  mv SRC [SRC...] DST          Move matching entry(s)
+  (move)
+
+  Source may be any of the following:
+    - Filename including '*' wildcards
+    - SHA-1
+    - File ID
+    - Area tag with optional @storageTag suffix
+  Destination is area tag with optional @storageTag suffix
+
+  rm SRC [SRC...]              Remove entry(s) from the system
+  (del|delete|remove)
+
+  Source may be any of the following:
+    - Filename including '*' wildcards
+    - SHA-1
+    - File ID
+    - Area tag with optional @storageTag suffix
+
+  desc CRITERIA                Updates an file base entry's description
+
+  Launches an external editor using $VISUAL, $EDITOR, or vim/notepad.
+
+  import-areas FILEGATE.ZXX    Import file base areas using FileGate RAID type format
+
+scan arguments:
+  --tags TAG1,TAG2,...         Specify hashtag(s) to assign to discovered entries
+
+  --desc-file [PATH]           Prefer file descriptions from supplied input file
+
+  If a file description can be found in the supplied input file, prefer that description
+  over other sources such related FILE_ID.DIZ. Path must point to a valid FILES.BBS or
+  DESCRIPT.ION file.
+
+  --update                     Attempt to update information for existing entries
+  --full                       Perform a full scan (default is quick)
+
+info arguments:
+  --show-desc                  Display short description, if any
+
+remove arguments:
+  --phys-file                  Also remove underlying physical file
+
+import-areas arguments:
+  --type TYPE                  Sets import areas type
+
+  Valid types are are "zxx" or "na".
+
+  --create-dirs                Also create backing storage directories
+
+General Information:
+  Generally an area tag can also include an optional storage tag. For example, the
+  area of 'bbswarez' stored using 'bbswarez_main': bbswarez@bbswarez_main
+
+  When performing an initial import of a large area or storage backing, --full
+  is the best option. If re-scanning an area for updates a standard / quick scan is
+  generally good enough.
+
+  File ID's are those found in file.sqlite3.
+
+ +

Scan File Area

+

The scan action can (re)scan a file area for new entries as well as update (--update) existing entry records (description, etc.). When scanning, a valid area tag must be specified. Optionally, storage tag may also be supplied in order to scan a specific filesystem location using the @the_storage_tag syntax. If a GLOB is supplied as the last argument, only file entries with filenames matching will be processed.

+ +
Examples
+

Performing a quick scan of a specific area’s storage location (“retro_warez”, “retro_warez_games) matching only *.zip extensions:

+
# note that we must quote the wildcard to prevent shell expansion
+$ ./oputil.js fb scan --quick retro_warez@retro_warez_games "*.zip"`
+
+ +

Update all entries in the “artscene” area supplying the file tags “artscene”, and “textmode”.

+
$ ./oputil.js fb scan --update --quick --tags artscene,textmode artscene`
+
+ +

Scan “oldschoolbbs” area using the description file at “/path/to/DESCRIPT.ION”:

+
$ ./oputil.js fb scan --desc-file /path/to/DESCRIPT.ION oldschoolbbs
+
+ +

Retrieve Information

+

The info action can retrieve information about an area or file entry(s).

+ +
Examples
+

Information about a particular area:

+
./oputil.js fb info retro_pc
+areaTag: retro_pc
+name: Retro PC
+desc: Oldschool / retro PC
+storageTag: retro_pc_tdc_1990 => /file_base/dos/tdc/1990
+storageTag: retro_pc_tdc_1991 => /file_base/dos/tdc/1991
+storageTag: retro_pc_tdc_1992 => /file_base/dos/tdc/1992
+storageTag: retro_pc_tdc_1993 => /file_base/dos/tdc/1993
+
+ +

Perhaps we want to fetch some information about a file in which we know piece of the filename:

+
./oputil.js fb info "impulse*"
+file_id: 143
+sha_256: 547299301254ccd73eba4c0ec9cd6ab8c5929fbb655e72c4cc842f11332792d4
+area_tag: impulse_project
+storage_tag: impulse_project
+path: /file_base/impulse_project/impulseproject01.tar.gz
+hashTags: impulse.project,8bit.music,cid
+uploaded: 2018-03-10T11:36:41-07:00
+dl_count: 23
+archive_type: application/gzip
+byte_size: 114313
+est_release_year: 2015
+file_crc32: fc6655d
+file_md5: 3455f74bbbf9539e69bd38f45e039a4e
+file_sha1: 558fab3b49a8ac302486e023a3c2a86bd4e4b948
+
+ +

Importing FileGate RAID Style Areas

+

Given a FileGate “RAID” style FILEGATE.ZXX file, one can import areas. This format also often comes in FTN-style info packs in the form of a .NA file i.e.: FILEBONE.NA.

+ +

Example

+
./oputil.js fb import-areas FILEGATE.ZXX --create-dirs
+
+ +

-or-

+ +
# fsxNet info packs contain a FSX_FILE.NA file
+./oputil.js fb import-areas FSX_FILE.NA --create-dirs --type NA
+
+ +

The above command will process FILEGATE.ZXX creating areas and backing directories. Directories created are relative to the fileBase.areaStoragePrefix config.hjson setting.

+ +

Message Base Management

+

The mb command provides various Message Base related tools:

+ +
usage: oputil.js mb <action> [<arguments>]
+
+Actions:
+  areafix CMD1 CMD2 ... ADDR  Sends an AreaFix NetMail
+
+  NetMail is sent to supplied address  with the supplied command(s). Multi-part commands
+  such as "%COMPRESS ZIP" should be quoted.
+
+  import-areas PATH           Import areas using FidoNet *.NA or AREAS.BBS file
+
+  qwk-dump PATH               Dumps a QWK packet to stdout.
+  qwk-export [AREA_TAGS] PATH Exports one or more configured message area to a QWK
+                              packet in the directory specified by PATH. The QWK
+                              BBS ID will be obtained by the final component of PATH.
+
+import-areas arguments:
+  --conf CONF_TAG             Conference tag in which to import areas
+  --network NETWORK           Network name/key to associate FTN areas
+  --uplinks UL1,UL2,...       One or more uplinks (comma separated)
+  --type TYPE                 Area import type
+
+  Valid types are "bbs" and "na".
+
+qwk-export arguments:
+  --user USER                 User in which to export for. Defaults to the SysOp.
+  --after TIMESTAMP           Export only messages with a timestamp later than
+                              TIMESTAMP.
+  --no-qwke                   Disable QWKE extensions.
+  --no-synchronet             Disable Synchronet style extensions.
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ActionDescriptionExamples
import-areasImports areas using a FidoNet style *.NA or AREAS.BBS formatted file. Optionally maps areas to FTN networks../oputil.js config import-areas /some/path/l33tnet.na
areafixUtility for sending AreaFix mails without logging into the system 
qwk-dumpDump a QWK packet to stdout./oputil.js mb qwk-dump /path/to/XIBALBA.QWK
qwk-exportExport messages to a QWK packet./oputil.js mb qwk-export /path/to/XIBALBA.QWK
+ +

When using the import-areas action, you will be prompted for any missing additional arguments described in “import-areas args”.

+ +
+ + +
+
+
+
+ + + + diff --git a/admin/updating.html b/admin/updating.html new file mode 100644 index 00000000..a3f68959 --- /dev/null +++ b/admin/updating.html @@ -0,0 +1,2325 @@ + + + + + + + + + + + +Updating | ENiGMA½ BBS Software + + + + + + + + + + + + + + + + + +
+ +
+
+
+ + +
+

Updating

+

Updating

+

Keeping your system up to date ensures you have the latest fixes, features, and general improvements. Updating ENiGMA½ can be a bit of a learning curve compared to traditional binary-release systems you may be used to, especially when running from Git cloned source.

+ +

Updating From Source

+

If you have installed using Git source (if you used the install.sh script) follow these general steps to update your system:

+ +
    +
  1. +Back up your system!
  2. +
  3. Pull down the latest source: +
    +
    cd /path/to/enigma-bbs
    +git pull
    +
    +
  4. +
  5. +:bulb: Review WHATSNEW.md and UPDATE.md for any specific instructions or changes to be aware of.
  6. +
  7. Update your dependencies: +
    +
    npm install # or 'yarn'
    +
    +
  8. +
  9. Merge updates from config/menu_template.hjson to your config/yourbbsname-menu.hjson file (or simply use the template as a reference to spot any newly added default menus that you may wish to have on your system as well!).
  10. +
  11. If there are updates to the art/themes/luciano_blocktronics/theme.hjson file and you have a custom theme, you may want to look at them as well.
  12. +
  13. Finally, restart your running ENiGMA½ instance.
  14. +
+ +

:information_source: Visual diff tools such as DiffMerge (free, works on all major platforms) can be very helpful for the tasks outlined above!

+ +

:bulb: It is recommended to monitor logs and poke around a bit after an update!

+ + +
+ + +
+
+
+
+ + + + diff --git a/art/general.html b/art/general.html new file mode 100644 index 00000000..53c19d41 --- /dev/null +++ b/art/general.html @@ -0,0 +1,2504 @@ + + + + + + + + + + + +General Art Information | ENiGMA½ BBS Software + + + + + + + + + + + + + + + + + +
+ +
+
+
+ + +
+

General Art Information

+

General Art Information

+

One of the most basic elements of BBS customization is through it’s artwork. ENiGMA½ supports a variety of ways to select, display, and manage art.

+ +

Art File Locations

+

As a general rule, art files live in one of two places:

+ +
    +
  1. The art/general directory. This is where you place common/non-themed art files.
  2. +
  3. Within a theme such as art/themes/super_fancy_theme.
  4. +
+ +

MCI Codes

+

All art can contain MCI Codes.

+ +

Art in Menus

+

While art can be displayed programmatically such as from a custom module, the most basic and common form is via menu.hjson entries. This usually falls into one of two forms:

+ +

Standard

+

A “standard” entry where a single art spec is utilized:

+
{
+    mainMenu: {
+        art: main_menu.ans
+    }
+}
+
+ +

Module Specific / Multiple Art

+

An entry for a custom module where multiple pieces are declared and used. The second style usually takes the form of a config.art block with two or more entries:

+
{
+    nodeMessage: {
+        config: {
+            art: {
+                header: node_msg_header
+                footer: node_msg_footer
+            }
+        }
+    }
+}
+
+ +

A menu entry has a few elements that control how art is selected and displayed. First, the art spec tells the system how to look for the art asset. Second, the config block can further control aspects of lookup and display. The following table describes such entries:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ItemDescription
fontSets the SyncTERM style font to use when displaying this art. If unset, the system will use the art’s embedded SAUCE record if present or simply use the current font. See Fonts below.
pauseIf set to true, pause after displaying.
baudRateSet a SyncTERM style emulated baud rate when displaying this art. In other words, slow down the display.
clsClear the screen before display if set to true.
randomSet to false to explicitly disable random lookup.
typesAn optional array of types (aka file extensions) to consider for lookup. For example : [ '.ans', '.asc' ] +
readSauceMay be set to false if you need to explicitly disable SAUCE support.
+ +

Art Spec

+

In the section above it is mentioned that the art member is a spec. The value of a art spec controls how the system looks for an asset. The following forms are supported:

+ +
    +
  • +FOO: The system will look for FOO.ANS, FOO.ASC, FOO.TXT, etc. using the default search path. Unless otherwise specified if FOO1.ANS, FOO2.ANS, and so on exist, a random selection will be made.
  • +
  • +FOO.ANS: By specifying an extension, only the exact match will be searched for.
  • +
  • +rel/path/to/BAR.ANS: Only match a path (relative to the system’s art directory).
  • +
  • +/path/to/BAZ.ANS: Exact path only.
  • +
+ +

ENiGMA½ uses a fallback system for art selection. When a menu entry calls for a piece of art, the following search is made:

+ +
    +
  1. If a direct or relative path is supplied, look there first.
  2. +
  3. In the users current theme directory.
  4. +
  5. In the system default theme directory.
  6. +
  7. In the art/general directory.
  8. +
+ +

ACS-Driven Conditionals

+

The ACS system can be used to make conditional art selection choices. To do this, provide an array of possible values in your art spec. As an example:

+
{
+    fancyMenu: {
+        art: [
+            {
+                acs: GM[l33t]
+                art: leet_art.ans
+            }
+            {
+                //  default
+                art: newb.asc
+            }
+        ]
+    }
+}
+
+ +

SyncTERM Style Fonts

+

ENiGMA½ can set a SyncTERM style font for art display. This is supported by many other popular BBS terminals as well. A common usage is for displaying Amiga style fonts for example. The system will use the font specifier or look for a font declared in an artworks SAUCE record (unless readSauce is false).

+ +

The most common fonts are probably as follows:

+ +
    +
  • cp437
  • +
  • c64_upper
  • +
  • c64_lower
  • +
  • c128_upper
  • +
  • c128_lower
  • +
  • atari
  • +
  • pot_noodle
  • +
  • mo_soul
  • +
  • microknight_plus
  • +
  • topaz_plus
  • +
  • microknight
  • +
  • topaz
  • +
+ +

…and some examples:

+ +

cp437
+ pot_noodle
+ mo_soul
+ microknight_plus
+ topaz_plus
+ microknight
+ topaz

+ +

Other “fonts” also available:

+
    +
  • cp1251
  • +
  • koi8_r
  • +
  • iso8859_2
  • +
  • iso8859_4
  • +
  • cp866
  • +
  • iso8859_9
  • +
  • haik8
  • +
  • iso8859_8
  • +
  • koi8_u
  • +
  • iso8859_15
  • +
  • iso8859_4
  • +
  • koi8_r_b
  • +
  • iso8859_4
  • +
  • iso8859_5
  • +
  • ARMSCII_8
  • +
  • iso8859_15
  • +
  • cp850
  • +
  • cp850
  • +
  • cp885
  • +
  • cp1251
  • +
  • iso8859_7
  • +
  • koi8-r_c
  • +
  • iso8859_4
  • +
  • iso8859_1
  • +
  • cp866
  • +
  • cp437
  • +
  • cp866
  • +
  • cp885
  • +
  • cp866_u
  • +
  • iso8859_1
  • +
  • cp1131
  • +
+ +

:information_source: See this specification for more information.

+ +

SyncTERM Style Baud Rates

+

The baudRate member can set a SyncTERM style emulated baud rate. May be 300, 600, 1200, 2400, 4800, 9600, 19200, 38400, 57600, 76800, or 115200. A value of ulimited, off, or 0 resets (disables) the rate.

+ +

:information_source: See this specification for more information.

+ +

Common Example

+
fullLogoffSequenceRandomBoardAd: {
+    art: OTHRBBS
+    desc: Logging Off
+    next: logoff
+    config: {
+        baudRate: 57600
+        pause: true
+        cls: true
+    }
+}
+
+ +

See Also

+

See also the Show Art Module for more advanced art display!

+ +
+ + +
+
+
+
+ + + + diff --git a/art/mci.html b/art/mci.html new file mode 100644 index 00000000..00c2b2e3 --- /dev/null +++ b/art/mci.html @@ -0,0 +1,3003 @@ + + + + + + + + + + + +MCI Codes | ENiGMA½ BBS Software + + + + + + + + + + + + + + + + + +
+ +
+
+
+ + +
+

MCI Codes

+

MCI Codes

+

ENiGMA½ supports a variety of MCI codes. Some predefined codes produce information about the current user, system, or other statistics while others are used to instantiate a View.

+ +

General Information

+

MCI codes are composed of two characters and are prefixed with a percent (%) symbol.

+ +

:information_source: To explicitly tie a MCI to a specific View ID, suffix the MCI code with a number. For example: %BN1.

+ +

:information_source: Standard (non-focus) and focus colors are set by placing duplicate codes back to back in art files:

+ +

Example

+ +

Some MCI codes have additional options that may be set directly from the code itself while others – and more advanced options – are controlled via the current theme.

+ +

Relationship with Menus, Art, and Themes

+

A MCI code that appears in a menu.hjson entry corresponds to that found in it’s associated art file. This same MCI code can be referenced in the theme.hjson in order to apply a theme.

+ +

See Menus and Themes for more information.

+ +

Predefined Codes

+

There are many predefined MCI codes that can be used anywhere on the system (placed in any art file).

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CodeDescription
BNBoard Name
VLVersion label, e.g. “ENiGMA½ v0.0.12-beta”
VNVersion number, eg.. “0.0.12-beta”
SNSysOp username
SRSysOp real name
SLSysOp location
SASysOp affiliations
SSSysOp sex
SESysOp email address
UNCurrent user’s username
UICurrent user’s user ID
UGCurrent user’s group membership(s)
URCurrent user’s real name
LOCurrent user’s location
UACurrent user’s age
BDCurrent user’s birthday (using theme date format)
USCurrent user’s sex
UECurrent user’s email address
UWCurrent user’s web address
UFCurrent user’s affiliations
UTCurrent user’s theme name
UDCurrent user’s theme ID (e.g. “luciano_blocktronics”)
UCCurrent user’s login/call count
NDCurrent user’s connected node number
IPCurrent user’s IP address
STCurrent user’s connected server name (e.g. “Telnet” or “SSH”)
FNCurrent user’s active file base filter name
DNCurrent user’s number of downloads
DKCurrent user’s download amount (formatted to appropriate bytes/megs/etc.)
UPCurrent user’s number of uploads
UKCurrent user’s upload amount (formatted to appropriate bytes/megs/etc.)
NRCurrent user’s upload/download ratio
KRCurrent user’s upload/download bytes ratio
MSCurrent user’s account creation date (using theme date format)
PSCurrent user’s post count
PCCurrent user’s post/call ratio
MDCurrent user’s status/viewing menu/activity
MACurrent user’s active message area name
MCCurrent user’s active message conference name
MLCurrent user’s active message area description
CMCurrent user’s active message conference description
SHCurrent user’s term height
SWCurrent user’s term width
ACCurrent user’s total achievements
APCurrent user’s total achievement points
DRCurrent user’s number of door runs
DMCurrent user’s total amount of time spent in doors
DTCurrent date (using theme date format)
CTCurrent time (using theme time format)
OSSystem OS (Linux, Windows, etc.)
OASystem architecture (x86, x86_64, arm, etc.)
SCSystem CPU model
NVSystem underlying Node.js version
ANCurrent active node count
TCTotal login/calls to the system ever +
TTTotal login/calls to the system today +
RRDisplays a random rumor
SDTotal downloads, system wide
SOTotal downloaded amount, system wide (formatted to appropriate bytes/megs/etc.)
SUTotal uploads, system wide
SPTotal uploaded amount, system wide (formatted to appropriate bytes/megs/etc.)
TFTotal number of files on the system
TBTotal amount of files on the system (formatted to appropriate bytes/megs/gigs/etc.)
TPTotal messages posted/imported to the system currently +
PTTotal messages posted/imported to the system today +
+ +

Some additional special case codes also exist:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CodeDescription
CF##Moves the cursor position forward ## characters
CB##Moves the cursor position back ## characters
CU##Moves the cursor position up ## characters
CD##Moves the cursor position down ## characters
XYA special code that may be utilized for placement identification when creating menus or to extend an otherwise empty space in an art file down the screen.
+ +

:information_source: More are added all +the time so also check out core/predefined_mci.js +for a full listing.

+ +

:memo: Many codes attempt to pay homage to Oblivion/2, iNiQUiTY, etc.

+ +

Views

+

A View is a control placed on a form that can display variable data or collect input. One example of a View is +a Vertical Menu (%VM): Old-school BBSers may recognize this as a lightbar menu.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CodeNameDescriptionNotes
TLText LabelDisplays textStatic content. See Text View +
ETEdit TextCollect user inputSingle line entry. See Edit Text +
MEMasked Edit TextCollect user input using a mask +See Masked Edit and Mask Edits below.
MTMulti Line Text EditMulti line edit controlUsed for FSE, display of FILE_ID.DIZ, etc. See Multiline Text Edit +
BTButtonA button…it’s a button. See Button +
VMVertical MenuA vertical menuAKA a vertical lightbar; Useful for lists. See Vertical Menu +
HMHorizontal MenuA horizontal menuAKA a horizontal lightbar. See Horizontal Menu +
FMFull MenuA menu that can go both vertical and horizontal.See Full Menu +
SMSpinner MenuA spinner input controlSelect one from multiple options. See Spinner Menu +
TMToggle MenuA toggle menuCommonly used for Yes/No style input. See Toggle Menu +
PLPredefined LabelShow environment informationSee Predefined Label +
KEKey EntryA single key input controlThink hotkeys
+ +

:information_source: Peek at /core/mci_view_factory.js to see additional information.

+ +

Mask Edits

+

Mask Edits (%ME) use the special maskPattern property to control a mask. This can be useful for gathering dates, phone numbers, so on.

+ +

maskPattern’s can be composed of the following characters:

+
    +
  • +#: Numeric 0-9
  • +
  • +A: Alpha a-z, A-Z
  • +
  • +@: Alphanumeric (combination of the previous patterns)
  • +
  • +&: Any “printable” character
  • +
+ +

Any other characters are literals.

+ +

An example of a mask for a date may look like this: ##/##/####.

+ +

Additionally, the following theme stylers can be applied:

+
    +
  • +styleSGR1: Controls literal character colors for non-focused controls
  • +
  • +styleSGR2: Controls literal character colors for focused controls
  • +
  • +styleSGR3: Controls fill colors (characters that have not yet received input).
  • +
+ +

All of the style properties can take pipe codes such as |00|08.

+ +

View Identifiers

+

As mentioned above, MCI codes can (and often should) be explicitly tied to a View Identifier. Simply speaking this is a number representing the particular view. These can be useful to reference in code, apply themes, etc.

+ +

A view ID is tied to a MCI code by specifying it after the code. For example: %VM1 or %SM10.

+ +

Properties & Theming

+

Predefined MCI codes and other Views can have properties set via menu.hjson and further themed via theme.hjson. See Themes for more information on this subject.

+ +

Common Properties

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyDescription
textStyleSets the standard (non-focus) text style. See Text Styles below
focusTextStyleSets focus text style. See Text Styles below.
itemSpacingUsed to separate items in menus such as Vertical Menu and Horizontal Menu Views.
heightSets the height of views such as menus that may be > 1 character in height
widthSets the width of a view
focusIf set to true, establishes initial focus
text(initial) text of a view
submitIf set to true any accept action upon this view will submit the encompassing form +
itemFormatSets the format for a list entry. See Entry Formatting below
focusItemFormatSets the format for a focused list entry. See Entry Formatting below
+ +

These are just a few of the properties set on various views. Use the source Luke, as well as taking a look at the default menu.hjson and theme.hjson files!

+ +

Custom Properties

+

Often a module will provide custom properties that receive format objects (See Entry Formatting below). Custom property formatting can be declared in the config block. For example, browseInfoFormat10N (where N is up to 99) in the file_area_list module received a fairly extensive format object that contains {fileName}, {estReleaseYear}, etc.

+ +

Text Styles

+ +

Standard style types available for textStyle and focusTextStyle:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
StyleDescription
normalLeaves text as-is. This is the default.
upperENIGMA BULLETIN BOARD SOFTWARE
lowerenigma bulletin board software
titleEnigma Bulletin Board Software
first lowereNIGMA bULLETIN bOARD sOFTWARE
small vowelseNiGMa BuLLeTiN BoaRD SoFTWaRe
big vowelsEniGMa bUllEtIn bOArd sOftwArE
small iENiGMA BULLETiN BOARD SOFTWARE
mixedEnIGma BUlLEtIn BoaRd SOfTWarE (randomly assigned)
l33t3n1gm4 bull371n b04rd 50f7w4r3
+ +

Entry Formatting

+

Various strings can be formatted using a syntax that allows width & precision specifiers, text styling, etc. Depending on the context, various elements can be referenced by {name}. Additional text styles can be supplied as well. The syntax is largely modeled after Python’s string format mini language.

+ +

Additional Text Styles

+

Some of the text styles mentioned above are also available in the mini format language:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
StyleDescription
normalLeaves text as-is. This is the default.
+toUpperCase or styleUpper +ENIGMA BULLETIN BOARD SOFTWARE
+toLowerCase or styleLower +enigma bulletin board software
styleTitleEnigma Bulletin Board Software
styleFirstLowereNIGMA bULLETIN bOARD sOFTWARE
styleSmallVowelseNiGMa BuLLeTiN BoaRD SoFTWaRe
styleBigVowelsEniGMa bUllEtIn bOArd sOftwArE
styleSmallIENiGMA BULLETiN BOARD SOFTWARE
styleMixedEnIGma BUlLEtIn BoaRd SOfTWarE (randomly assigned)
styleL33t3n1gm4 bull371n b04rd 50f7w4r3
+ +

Additional text styles are available for numbers:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
StyleDescription
sizeWithAbbrFile size (converted from bytes) with abbreviation such as 1 MB, 2.2 GB, 34 KB, etc.
sizeWithoutAbbrJust the file size (converted from bytes) without the abbreviation. For example: 1024 becomes 1.
sizeAbbrJust the abbreviation given a file size (converted from bytes) such as MB or GB.
countWithAbbrCount with abbreviation such as 100 K, 4.3 B, etc.
countWithoutAbbrJust the count
countAbbrJust the abbreviation such as M for millions.
durationHoursConverts the provided hours value to something friendly such as 4 hours, or 4 days.
durationMinutesConverts the provided minutes to something friendly such as 10 minutes or 2 hours +
durationSecondsConverts the provided seconds to something friendly such as 23 seconds or 2 minutes +
+ +

Examples

+

Suppose a format object contains the following elements: userName and affils. We could create a itemFormat entry that builds a item to our specifications: |04{userName!styleFirstLower} |08- |13{affils}. This may produce a string such as this:

+ +

Example

+ +

:bulb: Remember that a Python string format mini language style syntax is available for widths, alignment, number prevision, etc. as well. A number can be made to be more human readable for example: {byteSize:,} may yield “1,123,456”.

+ +
+ + +
+
+
+
+ + + + diff --git a/art/themes.html b/art/themes.html new file mode 100644 index 00000000..aa64576c --- /dev/null +++ b/art/themes.html @@ -0,0 +1,2538 @@ + + + + + + + + + + + +Themes | ENiGMA½ BBS Software + + + + + + + + + + + + + + + + + +
+ +
+
+
+ + +
+

Themes

+

Themes

+

ENiGMA½ comes with an advanced theming system allowing system operators to highly customize the look and feel of their boards. A given installation can have as many themes as you like for your users to choose from.

+ +

General Information

+

Themes live in art/themes/. Each theme (and thus it’s theme ID) is a directory within the themes directory. The theme itself is simply a collection of art files, and a theme.hjson file that further defines layout, colors & formatting, etc.

+ +

ENiGMA½ comes with a default theme by Luciano Ayres of Blocktronics called Mystery Skull. This theme is in art/themes/luciano_blocktronics, and thus it’s theme ID is luciano_blocktronics.

+ +

Art

+

For information on art files, see General Art Information. In general, to theme a piece of art, create a version of it in your themes directory.

+ +

:memo: Remember that by default, the system will allow for randomly selecting art (in one of the directories mentioned above) by numbering it: FOO1.ANS, FOO2.ANS, etc.!

+ +

Theme Sections

+

Themes are some important sections to be aware of:

+ + + + + + + + + + + + + + + + + + +
Config ItemDescription
infoThis section describes the theme.
customizationThe beef!
+ +

Info Block

+

The info configuration block describes the theme itself.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ItemRequiredDescription
name:+1:Name of the theme. Be creative!
author:+1:Author of the theme/artwork.
group:-1:Group/affils of author.
enabled:-1:Boolean of enabled state. If set to false, this theme will not be available to your users. If a user currently has this theme selected, the system default will be selected for them at next login.
+ +

Customization Block

+

The customization block in is itself broken up into major parts:

+ + + + + + + + + + + + + + + + + + + + + + +
ItemDescription
defaultsDefault values to use when this theme is active. These values override system defaults, but can still be overridden themselves in specific areas of your theme.
menusThe bulk of what you theme in the system will be here. Any menu (that is, anything you find in menu.hjson) can be tweaked.
promptsSimilar to menus, this section themes prompts.
+ +

Defaults

+

Override system defaults.

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
ItemDescription
passwordCharCharacter to display in password fields. Defaults to * +
dateFormatSets the moment.js style short and/or long format for dates.
timeFormatSets the moment.js style short and/or long format for times.
dateTimeFormatSets the moment.js style short and/or long format for date/time combinations.
+ +

Example:

+
defaults: {
+    dateTimeFormat: {
+        short:  MMM Do h:mm a
+    }
+}
+
+ + +

Each key in the menus block matches up with a key found in your menu.hjson. For example, consider a matrix menu defined in menu.hjson. In addition to perhaps providing a MATRIX.ANS in your themes directory, you can also theme other parts of the menu via a matrix entry in theme.hjson.

+ +

Major areas to override/theme:

+
    +
  • +config: Override and/or provide additional theme information over that found in the menu.hjson’s entry. Common entries here are for further overriding date/time formats, and custom range info formats (<someFormName>InfoFormat<num>). See Entry Formatting in MCI Codes and Custom Range Info Formatting below.
  • +
  • +mci: Set per-MCI code properties such as height, width, text styles, etc. See MCI Codes for a more information.
  • +
+ +

Two formats for mci blocks are allowed:

+
    +
  • Shorthand if only a single/first form is needed.
  • +
  • Verbose where a form ID(s) are supplied (required if multiple forms are used)
  • +
+ +

Example: Shorthand mci format:

+
matrix: {
+    mci: {
+        VM1: {
+            itemFormat: "|03{text}"
+            focusItemFormat: "|11{text!styleFirstLower}"
+        }
+    }
+}
+
+ +

Example: Verbose mci with form IDs:

+
newUserFeedbackToSysOp: {
+    0: {
+        mci: {
+            TL1: { width: 19, textOverflow: "..." }
+            ET2: { width: 19, textOverflow: "..." }
+            ET3: { width: 19, textOverflow: "..." }
+        }
+    }
+    1: {
+        mci: {
+            MT1: { height: 14 }
+        }
+    }
+}
+
+ +
Custom Range Info Formatting
+

Many modules support “custom range” MCI items. These are MCI codes that are left to the user to define using a format object specific to the module. For example, consider the msg_area_list module: This module sets MCI codes 10+ (%TL10, %TL11, etc.) as “custom range”. When theming you can place these MCI codes in your artwork then define the format in theme.hjson:

+ +
messageAreaChangeCurrentArea: {
+    config: {
+        areaListInfoFormat10: "|15{name}|07: |03{desc}"
+    }
+}
+
+ +

Creating Your Own

+

:warning: IMPORTANT! Do not make any customizations to the included `luciano_blocktronics’ theme. Instead, create your own and make changes to that instead:

+ +
    +
  1. Copy /art/themes/luciano_blocktronics to art/themes/your_board_theme +
  2. +
  3. Update the info block at the top of the theme.hjson file: +
    info: {
    + name: Awesome Theme
    + author: Cool Artist
    + group: Sick Group
    + enabled: true // default
    +}
    +
    +
  4. +
  5. If desired, you may make this the default system theme in config.hjson via theme.default. theme.preLogin may be set if you want this theme used for pre-authenticated users. Both of these values also accept * if you want the system to randomly pick. +
    theme: {
    + default: your_board_theme
    + preLogin: *
    +}
    +
    +
  6. +
+ +

Theming Example

+

Let’s run through an example!

+ +

Consider the following menu.hjson entry:

+
superFancyMenu: {
+    art: FANCY.ANS
+    // ...some other stuff...
+}
+
+ +

With a file of FANCY.ANS in art/themes/fancy_theme containing the following MCI codes:

+
    +
  • TL1 (Generic text label)
  • +
  • BN2 (Predefined: Board Name)
  • +
+ +

An entry in your theme.hjson could look like this:

+
superFancyMenu: {
+    mci: {
+        TL1: {
+            //  supply the full format of the TL1 View
+            text: |02ENiGMA|10½ |08v|03|VN
+        }
+        BN2: {
+            //  Make Board Name l33t style
+            style: l33t
+        }
+    }
+}
+
+ +
+ + +
+
+
+
+ + + + diff --git a/art/views/button_view.html b/art/views/button_view.html new file mode 100644 index 00000000..6340e675 --- /dev/null +++ b/art/views/button_view.html @@ -0,0 +1,2388 @@ + + + + + + + + + + + +Button View | ENiGMA½ BBS Software + + + + + + + + + + + + + + + + + +
+ +
+
+
+ + +
+

Button View

+

Button View

+

A button view supports displaying a button on a screen.

+ +

General Information

+ +

:information_source: A button view is defined with a percent (%) and the characters BT, followed by the view number. For example: %BT1

+ +

:information_source: See MCI for general information on how to use views and common configuration properties available for them.

+ +

Properties

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyDescription
textSets the text to display on the button
textStyleSets the standard (non-focus) text style. See Text Styles in MCI +
focusTextStyleSets focus text style. See Text Styles in MCI +
widthSets the width of a view to display one or more columns horizontally (default 15)
focusIf set to true, establishes initial focus
submitIf set to true any accept action upon this view will submit the encompassing form +
argNameSets the argument name for this selection in the form
justifySets the justification of each item in the list. Options: left (default), right, center
fillCharSpecifies a character to fill extra space longer than the text length. Defaults to an empty space
textOverflowIf the button text cannot be displayed due to width, set overflow characters. See Text Overflow below
+ +

Text Overflow

+ +

The textOverflow option is used to specify what happens when a text string is too long to fit in the width defined.

+ +

:information_source: If textOverflow is not specified at all, a button can become wider than the width if needed to display the text value.

+ +

:information_source: Setting textOverflow to an empty string textOverflow: "" will cause the item to be truncated if necessary without any characters displayed

+ +

:information_source: Otherwise, setting textOverflow to one or more characters will truncate the value if necessary and display those characters at the end. i.e. textOverflow: ...

+ +

Example

+ +

Example

+ +
+Configuration fragment (expand to view) +
+
+
BT1: {
+  submit: true
+  justify: center
+  argName: btnSelect
+  width: 17
+  focusTextStyle: upper
+  text: Centered button
+}
+
+
+
+ +
+ + +
+
+
+
+ + + + diff --git a/art/views/edit_text_view.html b/art/views/edit_text_view.html new file mode 100644 index 00000000..f57ea173 --- /dev/null +++ b/art/views/edit_text_view.html @@ -0,0 +1,2366 @@ + + + + + + + + + + + +Edit Text View | ENiGMA½ BBS Software + + + + + + + + + + + + + + + + + +
+ +
+
+
+ + +
+

Edit Text View

+

Edit Text View

+

An edit text view supports editing form values on a screen. This can be for new entry as well as editing existing values defined by the module.

+ +

General Information

+ +

:information_source: An edit text view is defined with a percent (%) and the characters ET, followed by the view number. For example: %ET1. This is generally used on a form in order to allow a user to enter or edit a text value.

+ +

:information_source: See MCI for general information on how to use views and common configuration properties available for them.

+ +

Properties

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyDescription
textStyleSets the standard (non-focus) text style. See Text Styles in MCI +
focusTextStyleSets the focus text style. See Text Styles in MCI +
widthSets the width of a view for the text edit (default 15)
argNameSets the argument name for this value in the form
maxLengthSets the maximum number of characters that can be entered
focusSet to true to capture initial focus
justifySets the justification of the text entry. Options: left (default), right, center
fillCharSpecifies a character to fill extra space in the text entry with. Defaults to an empty space
+ +

Example

+ +

Example

+ +
+Configuration fragment (expand to view) +
+
+
ET1: {
+  maxLength: @config:users.usernameMax
+  argName: username
+  focus: true
+}
+
+
+
+ +
+ + +
+
+
+
+ + + + diff --git a/art/views/full_menu_view.html b/art/views/full_menu_view.html new file mode 100644 index 00000000..3bde3a92 --- /dev/null +++ b/art/views/full_menu_view.html @@ -0,0 +1,2588 @@ + + + + + + + + + + + +Full Menu View | ENiGMA½ BBS Software + + + + + + + + + + + + + + + + + +
+ +
+
+
+ + +
+

Full Menu View

+

Full Menu View

+

A full menu view supports displaying a list of times on a screen in a very configurable manner. A full menu view supports either a single row or column of values, similar to Horizontal Menu (HM) and Vertical Menu (VM), or in multiple columns.

+ +

General Information

+ +

Items can be selected on a menu via the cursor keys, Page Up, Page Down, Home, and End, or by selecting them via a hotKey - see Hot Keys below.

+ +

:information_source: A full menu view is defined with a percent (%) and the characters FM, followed by the view number. For example: %FM1

+ +

:information_source: See MCI for general information on how to use views and common configuration properties available for them.

+ +

Properties

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyDescription
textStyleSets the standard (non-focus) text style. See Text Styles in MCI +
focusTextStyleSets focus text style. See Text Styles in MCI +
itemSpacingUsed to separate items vertically in the menu
itemHorizSpacingUsed to separate items horizontally in the menu
heightSets the height of views to display multiple items vertically (default 1)
widthSets the width of a view to display one or more columns horizontally (default 15)
focusIf set to true, establishes initial focus
submitIf set to true any accept action upon this view will submit the encompassing form +
hotKeysSets hot keys to activate specific items. See Hot Keys below
hotKeySubmitSet to submit a form on hotkey selection
argNameSets the argument name for this selection in the form
justifySets the justification of each item in the list. Options: left (default), right, center
itemFormatSets the format for a list entry. See Entry Formatting in MCI +
fillCharSpecifies a character to fill extra space in the menu with. Defaults to an empty space
textOverflowIf a single column cannot be displayed due to width, set overflow characters. See Text Overflow below
itemsList of items to show in the menu. See Items below.
focusItemFormatSets the format for a focused list entry. See Entry Formatting in MCI +
+ +

Hot Keys

+ +

A set of hotKeys are used to allow the user to press a character on the keyboard to select that item, and optionally submit the form.

+ +

Example:

+ +
hotKeys: { A: 0, B: 1, C: 2, D: 3 }
+hotKeySubmit: true
+
+

This would select and submit the first item if A is typed, second if B, etc.

+ +

Items

+ +

A full menu, similar to other menus, take a list of items to display in the menu. For example:

+ +
items: [
+  {
+      text: First Item
+      data: first
+  }
+  {
+      text: Second Item
+      data: second
+  }
+]
+
+ +

If the list is for display only (there is no form action associated with it) you can omit the data element, and include the items as a simple list:

+ +
["First item", "Second item", "Third Item"]
+
+ +

Text Overflow

+ +

The textOverflow option is used to specify what happens when a text string is too long to fit in the width defined. Note, because columns are automatically calculated, this can only occur when the text is too long to fit the width using a single column.

+ +

:information_source: If textOverflow is not specified at all, a menu can become wider than the width if needed to display a single column.

+ +

:information_source: Setting textOverflow to an empty string textOverflow: "" will cause the item to be truncated if necessary without any characters displayed

+ +

:information_source: Otherwise, setting textOverflow to one or more characters will truncate the value if necessary and display those characters at the end. i.e. textOverflow: ...

+ +

Examples

+ +

A simple vertical menu - similar to VM

+ +

Example

+ +
+Configuration fragment (expand to view) +
+
+
FM1: {
+  submit: true
+  argName: navSelect
+  width: 1
+  items: [
+    {
+      text: login
+      data: login
+    }
+    {
+      text: apply
+      data: new user
+    }
+    {
+      text: about
+      data: about
+    }
+    {
+      text: log off
+      data: logoff
+    }
+  ]
+}
+
+
+
+
+ +

A simple horizontal menu - similar to HM

+ +

Example

+ +
+Configuration fragment (expand to view) +
+
+
FM2: {
+  focus: true
+  height: 1
+  width: 60 // set as desired
+  submit: true
+  argName: navSelect
+  items: [
+    "prev", "next", "details", "toggle queue", "rate", "help", "quit"
+  ]
+}
+
+
+
+ +

A multi-column navigation menu with hotkeys

+ +

Example

+ +
+Configuration fragment (expand to view) +
+
+
FM1: {
+  focus: true
+  height: 6
+  width: 60
+  submit: true
+  argName: navSelect
+  hotKeys: { M: 0, E: 1, D: 2 ,F: 3,!: 4, A: 5, C: 6, Y: 7, S: 8, R: 9, O: 10, L:11, U:12, W: 13, B:14, G:15, T: 16, Q:17  }
+  hotKeySubmit: true
+  items: [
+    {
+      text: M) message area
+      data: message
+    }
+    {
+      text: E) private email
+      data: email
+    }
+    {
+      text: D) doors
+      data: doors
+    }
+    {
+      text: F) file base
+      data: files
+    }
+    {
+      text: !) global newscan
+      data: newscan
+    }
+    {
+      text: A) achievements
+      data: achievements
+    }
+    {
+      text: C) configuration
+      data: config
+    }
+    {
+      text: Y) user stats
+      data: userstats
+    }
+    {
+      text: S) system stats
+      data: systemstats
+    }
+    {
+      text: R) rumorz
+      data: rumorz
+    }
+    {
+      text: O) onelinerz
+      data: onelinerz
+    }
+    {
+      text: L) last callers
+      data: callers
+    }
+    {
+      text: U) user list
+      data: userlist
+    }
+    {
+      text: W) whos online
+      data: who
+    }
+    {
+      text: B) bbs list
+      data: bbslist
+    }
+    {
+      text: G) node-to-node messages
+      data: nodemessages
+    }
+    {
+      text: T) multi relay chat
+      data: mrc
+    }
+    {
+      text: Q) quit
+      data: quit
+    }
+  ]
+}
+
+
+
+ + +
+ + +
+
+
+
+ + + + diff --git a/art/views/horizontal_menu_view.html b/art/views/horizontal_menu_view.html new file mode 100644 index 00000000..e8879aef --- /dev/null +++ b/art/views/horizontal_menu_view.html @@ -0,0 +1,2431 @@ + + + + + + + + + + + +Horizontal Menu View | ENiGMA½ BBS Software + + + + + + + + + + + + + + + + + +
+ +
+
+
+ + +
+

Horizontal Menu View

+

Horizontal Menu View

+

A horizontal menu view supports displaying a list of times on a screen horizontally (side to side, in a single row) similar to a lightbox.

+ +

General Information

+ +

Items can be selected on a menu via the cursor keys, Page Up, Page Down, Home, and End, or by selecting them via a hotKey - see Hot Keys below.

+ +

:information_source: A horizontal menu view is defined with a percent (%) and the characters HM, followed by the view number (if used.) For example: %HM1

+ +

:information_source: See MCI for general information on how to use views and common configuration properties available for them.

+ +

Properties

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyDescription
textStyleSets the standard (non-focus) text style. See Text Styles in MCI +
focusTextStyleSets focus text style. See Text Styles in MCI +
itemSpacingUsed to separate items horizontally in the menu
widthSets the width of a view to display one or more columns horizontally (default 15)
focusIf set to true, establishes initial focus
submitIf set to true any accept action upon this view will submit the encompassing form +
hotKeysSets hot keys to activate specific items. See Hot Keys below
hotKeySubmitSet to submit a form on hotkey selection
argNameSets the argument name for this selection in the form
justifySets the justification of each item in the list. Options: left (default), right, center
itemFormatSets the format for a list entry. See Entry Formatting in MCI +
fillCharSpecifies a character to fill extra space in the menu with. Defaults to an empty space
itemsList of items to show in the menu. See Items below.
focusItemFormatSets the format for a focused list entry. See Entry Formatting in MCI +
+ +

Hot Keys

+ +

A set of hotKeys are used to allow the user to press a character on the keyboard to select that item, and optionally submit the form.

+ +

Example:

+ +
hotKeys: { A: 0, B: 1, C: 2, D: 3 }
+hotKeySubmit: true
+
+

This would select and submit the first item if A is typed, second if B, etc.

+ +

Items

+ +

A horizontal menu, similar to other menus, take a list of items to display in the menu. For example:

+ +
items: [
+  {
+      text: First Item
+      data: first
+  }
+  {
+      text: Second Item
+      data: second
+  }
+]
+
+ +

If the list is for display only (there is no form action associated with it) you can omit the data element, and include the items as a simple list:

+ +
["First item", "Second item", "Third Item"]
+
+ +

Example

+ +

Example

+ +
+Configuration fragment (expand to view) +
+
+
HM2: {
+  focus: true
+  width: 60 // set as desired
+  submit: true
+  argName: navSelect
+  items: [
+    "prev", "next", "details", "toggle queue", "rate", "help", "quit"
+  ]
+}
+
+
+
+ +
+ + +
+
+
+
+ + + + diff --git a/art/views/mask_edit_text_view.html b/art/views/mask_edit_text_view.html new file mode 100644 index 00000000..e963cdbf --- /dev/null +++ b/art/views/mask_edit_text_view.html @@ -0,0 +1,2431 @@ + + + + + + + + + + + +Mask Edit Text View | ENiGMA½ BBS Software + + + + + + + + + + + + + + + + + +
+ +
+
+
+ + +
+

Mask Edit Text View

+

Mask Edit Text View

+

A mask edit text view supports editing form values on a screen. This can be for new entry as well as editing existing values. Unlike a edit text view, the mask edit text view uses a mask pattern to specify what format the values should be entered in.

+ +

General Information

+ +

:information_source: A mask edit text view is defined with a percent (%) and the characters ME, followed by the view number. For example: %ME1. This is generally used on a form in order to allow a user to enter or edit a text value.

+ +

:information_source: See MCI for general information on how to use views and common configuration properties available for them.

+ +

Properties

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyDescription
textStyleSets the standard (non-focus) text style. See Text Styles in MCI +
focusTextStyleSets the focus text style. See Text Styles in MCI +
argNameSets the argument name for this value in the form
maxLengthSets the maximum number of characters that can be entered. Not normally useful, set the mask pattern as needed instead +
focusSet to true to capture initial focus
maskPatternSets the mask pattern. See Mask Pattern below
fillCharSpecifies a character to fill extra space in the text entry with. Defaults to an empty space
+ +

Mask Pattern

+ +

A maskPattern must be set on a mask edit text view (not doing so will cause the view to be focusable, but no text can be input). The maskPattern is a set of characters used to define input, as well as optional literal characters that can be entered into the pattern that will always be entered into the input. The following mask characters are supported:

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Mask CharacterDescription
#Numeric input, one of 0 through 9
AAlphabetic, one of a through z or A through Z
@Alphanumeric, matches one of either Numeric or Alphabetic above
&Printable, matches one printable character including spaces
+ +

Any value other than the entries above is treated like a literal value to be displayed in the patter. Multiple pattern characters are combined for longer inputs. Some examples could include:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PatternDescription
AAMatches up to two alphabetic characters, for example a state name (i.e. “CA”)
###Matches up to three numeric characters, for example an age (i.e. 25)
###-###-####A pattern matching a phone number with area code
##/##/####Matches a date of type month/day/year or day/month/year (i.e. 01/01/2000)
##-AAA-####Matches a date of type day-month-year (i.e. 01-MAR-2010)
# foot ## inchesMatches a height in feet and inches (i.e. 6 foot 2 inches)
+ +

Example

+ +

Example

+ +
+Configuration fragment (expand to view) +
+
+
ME1: {
+  argName: height
+  fillChar: "#"
+  maskPattern: "# ft. ## in."
+}
+
+
+
+ +
+ + +
+
+
+
+ + + + diff --git a/art/views/multi_line_edit_text_view.html b/art/views/multi_line_edit_text_view.html new file mode 100644 index 00000000..663a26f9 --- /dev/null +++ b/art/views/multi_line_edit_text_view.html @@ -0,0 +1,2383 @@ + + + + + + + + + + + +Multi Line Edit Text View | ENiGMA½ BBS Software + + + + + + + + + + + + + + + + + +
+ +
+
+
+ + +
+

Multi Line Edit Text View

+

Multi Line Edit Text View

+

A text display / editor designed to edit or display a message.

+ +

General Information

+ +

:information_source: A multi line edit text view is defined with a percent (%) and the characters MT, followed by the view number. For example: %MT1

+ +

:information_source: See MCI for general information on how to use views and common configuration properties available for them.

+ +

Properties

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyDescription
textSets the text to display - only useful for read-only and preview, otherwise use a specific module
widthSets the width of a view to display horizontally (default 15)
heightSets the height of a view to display vertically
argNameSets the argument name for the form
modeOne of edit, preview, or read-only. See Mode below
+ +

Mode

+ +

The mode of a multi line edit text view controls how the view behaves. The following modes are allowed:

+ + + + + + + + + + + + + + + + + + + + + + +
ModeDescription
editedit the contents of the view
previewpreview the text, including scrolling
read-onlyNo scrolling or editing the view
+ +

:information_source: If mode is not set, the default mode is “edit”

+ +

:information_source: With mode preview, scrolling the contents is allowed, but is not with read-only.

+ +

Example

+ +

Example

+ +
+Configuration fragment (expand to view) +
+
+
ML1: {
+  width: 79
+  argName: message
+  mode: edit
+}
+
+
+
+ +
+ + +
+
+
+
+ + + + diff --git a/art/views/predefined_label_view.html b/art/views/predefined_label_view.html new file mode 100644 index 00000000..37ced1a4 --- /dev/null +++ b/art/views/predefined_label_view.html @@ -0,0 +1,2363 @@ + + + + + + + + + + + +Predefined Label View | ENiGMA½ BBS Software + + + + + + + + + + + + + + + + + +
+ +
+
+
+ + +
+

Predefined Label View

+

Predefined Label View

+

A predefined label view supports displaying a predefined MCI label on a screen.

+ +

General Information

+ +

:information_source: A predefined label view is defined with a percent (%) and the characters PL, followed by the view number and then the predefined MCI value in parenthesis. For example: %PL1(VL) to display the Version Label. NOTE: this is an alternate way of placing MCI codes, as the MCI can also be placed on the art page directly with the code. For example %VL. The difference between these is that the PL version can have additional formatting options applied to it.

+ +

:information_source: See Predefined Codes in MCI for the list of available MCI codes.

+ +

:information_source: See MCI for general information on how to use views and common configuration properties available for them.

+ +

Properties

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyDescription
textStyleSets the standard (non-focus) text style. See Text Styles in MCI +
justifySets the justification of the MCI value text. Options: left (default), right, center
fillCharSpecifies a character to fill extra space in the view. Defaults to an empty space
widthSpecifies the width that the value should be displayed in (default 3)
textOverflowIf the MCI is wider than width, set overflow characters. See Text Overflow below
+ +

Text Overflow

+ +

The textOverflow option is used to specify what happens when a predefined MCI string is too long to fit in the width defined.

+ +

:information_source: If textOverflow is not specified at all, a predefined label view can become wider than the width if needed to display the MCI value.

+ +

:information_source: Setting textOverflow to an empty string textOverflow: "" will cause the item to be truncated if necessary without any characters displayed

+ +

:information_source: Otherwise, setting textOverflow to one or more characters will truncate the value if necessary and display those characters at the end. i.e. textOverflow: ...

+ +

Example

+ +

Example

+ +
+Configuration fragment (expand to view) +
+
+
PL1: {
+  textStyle: upper
+}
+
+
+
+ +
+ + +
+
+
+
+ + + + diff --git a/art/views/spinner_menu_view.html b/art/views/spinner_menu_view.html new file mode 100644 index 00000000..eaec1637 --- /dev/null +++ b/art/views/spinner_menu_view.html @@ -0,0 +1,2441 @@ + + + + + + + + + + + +Spinner Menu View | ENiGMA½ BBS Software + + + + + + + + + + + + + + + + + +
+ +
+
+
+ + +
+

Spinner Menu View

+

Spinner Menu View

+

A spinner menu view supports displaying a set of times on a screen as a list, with one item displayed at a time. This is generally used to pick one option from a list. Some examples could include selecting from a list of states, themes, etc.

+ +

General Information

+ +

Items can be selected on a menu via the cursor keys or by selecting them via a hotKey - see Hot Keys below.

+ +

:information_source: A spinner menu view is defined with a percent (%) and the characters SM, followed by the view number (if used.) For example: %SM1

+ +

:information_source: See MCI for general information on how to use views and common configuration properties available for them.

+ +

Properties

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyDescription
textStyleSets the standard (non-focus) text style. See Text Styles in MCI +
focusTextStyleSets focus text style. See Text Styles in MCI +
focusIf set to true, establishes initial focus
widthSets the width of a view on the display (default 15)
submitIf set to true any accept action upon this view will submit the encompassing form +
hotKeysSets hot keys to activate specific items. See Hot Keys below
hotKeySubmitSet to submit a form on hotkey selection
argNameSets the argument name for this selection in the form
justifySets the justification of each item in the list. Options: left (default), right, center
itemFormatSets the format for a list entry. See Entry Formatting in MCI +
fillCharSpecifies a character to fill extra space in the menu with. Defaults to an empty space
itemsList of items to show in the menu. See Items below.
focusItemFormatSets the format for a focused list entry. See Entry Formatting in MCI +
+ +

Hot Keys

+ +

A set of hotKeys are used to allow the user to press a character on the keyboard to select that item, and optionally submit the form.

+ +

Example:

+ +
hotKeys: { A: 0, B: 1, C: 2, D: 3 }
+hotKeySubmit: true
+
+

This would select and submit the first item if A is typed, second if B, etc.

+ +

Items

+ +

A spinner menu, similar to other menus, take a list of items to display in the menu. For example:

+ +
items: [
+  {
+      text: First Item
+      data: first
+  }
+  {
+      text: Second Item
+      data: second
+  }
+]
+
+ +

If the list is for display only (there is no form action associated with it) you can omit the data element, and include the items as a simple list:

+ +
["First item", "Second item", "Third Item"]
+
+ +

Example

+ +

Example

+ +
+Configuration fragment (expand to view) +
+
+
SM1: {
+  submit: true
+  argName: themeSelect
+  items: [
+    {
+      text: Light
+      data: light
+    }
+    {
+      text: Dark
+      data: dark
+    }
+    {
+      text: Rainbow
+      data: rainbow
+    }
+    {
+      text: Gruvbox
+      data: gruvbox
+    }
+  ]
+}
+
+
+
+
+ +
+ + +
+
+
+
+ + + + diff --git a/art/views/text_view.html b/art/views/text_view.html new file mode 100644 index 00000000..01b1585d --- /dev/null +++ b/art/views/text_view.html @@ -0,0 +1,2365 @@ + + + + + + + + + + + +Text View | ENiGMA½ BBS Software + + + + + + + + + + + + + + + + + +
+ +
+
+
+ + +
+

Text View

+

Text View

+

A text label view supports displaying simple text on a screen.

+ +

General Information

+ +

:information_source: A text label view is defined with a percent (%) and the characters TL, followed by the view number. For example: %TL1

+ +

:information_source: See MCI for general information on how to use views and common configuration properties available for them.

+ +

Properties

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyDescription
textSets the text to display on the label
textStyleSets the standard (non-focus) text style. See Text Styles in MCI +
widthSets the width of a view to display horizontally (default 15)
justifySets the justification of the text in the view. Options: left (default), right, center
fillCharSpecifies a character to fill extra space in the view with. Defaults to an empty space
textOverflowSet overflow characters to display in case the text length is less than the width. See Text Overflow below
+ +

Text Overflow

+ +

The textOverflow option is used to specify what happens when a text string is too long to fit in the width defined.

+ +

:information_source: If textOverflow is not specified at all, a text label can become wider than the width if needed to display the text value.

+ +

:information_source: Setting textOverflow to an empty string textOverflow: "" will cause the item to be truncated if necessary without any characters displayed

+ +

:information_source: Otherwise, setting textOverflow to one or more characters will truncate the value if necessary and display those characters at the end. i.e. textOverflow: ...

+ +

Example

+ +

Example

+ +
+Configuration fragment (expand to view) +
+
+
TL1: {
+  text: Text label
+}
+
+
+
+ +
+ + +
+
+
+
+ + + + diff --git a/art/views/toggle_menu_view.html b/art/views/toggle_menu_view.html new file mode 100644 index 00000000..b488225e --- /dev/null +++ b/art/views/toggle_menu_view.html @@ -0,0 +1,2403 @@ + + + + + + + + + + + +Toggle Menu View | ENiGMA½ BBS Software + + + + + + + + + + + + + + + + + +
+ +
+
+
+ + +
+

Toggle Menu View

+

Toggle Menu View

+

A toggle menu view supports displaying a list of options on a screen horizontally (side to side, in a single row) similar to a Horizontal Menu. It is designed to present one of two choices easily.

+ +

General Information

+ +

Items can be selected on a menu via the left and right cursor keys, or by selecting them via a hotKey - see Hot Keys below.

+ +

:information_source: A toggle menu view is defined with a percent (%) and the characters TM, followed by the view number (if used.) For example: %TM1

+ +

:information_source: See MCI for general information on how to use views and common configuration properties available for them.

+ +

Properties

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyDescription
textStyleSets the standard (non-focus) text style. See Text Styles in MCI +
focusTextStyleSets focus text style. See Text Styles in MCI +
focusIf set to true, establishes initial focus
submitIf set to true any accept action upon this view will submit the encompassing form +
hotKeysSets hot keys to activate specific items. See Hot Keys below
hotKeySubmitSet to submit a form on hotkey selection
argNameSets the argument name for this selection in the form
itemsList of items to show in the menu. Must include exactly two (2) items. See Items below.
+ +

Hot Keys

+ +

A set of hotKeys are used to allow the user to press a character on the keyboard to select that item, and optionally submit the form.

+ +

Example:

+ +
hotKeys: { A: 0, B: 1, Q: 1 }
+hotKeySubmit: true
+
+

This would select and submit the first item if A is typed, second if B, etc.

+ +

Items

+ +

A toggle menu, similar to other menus, take a list of items to display in the menu. Unlike other menus, however, there must be exactly two items in a toggle menu. For example:

+ +
items: [
+  {
+      text: First Item
+      data: first
+  }
+  {
+      text: Second Item
+      data: second
+  }
+]
+
+ +

If the list is for display only (there is no form action associated with it) you can omit the data element, and include the items as a simple list:

+ +
["First item", "Second item"]
+
+ +

Example

+ +

Example

+ +
+Configuration fragment (expand to view) +
+
+
TM2: {
+  focus: true
+  submit: true
+  argName: navSelect
+  focusTextStyle: upper
+  items: [ "yes", "no" ]
+}
+
+
+
+ +
+ + +
+
+
+
+ + + + diff --git a/art/views/vertical_menu_view.html b/art/views/vertical_menu_view.html new file mode 100644 index 00000000..173b0a06 --- /dev/null +++ b/art/views/vertical_menu_view.html @@ -0,0 +1,2445 @@ + + + + + + + + + + + +Vertical Menu View | ENiGMA½ BBS Software + + + + + + + + + + + + + + + + + +
+ +
+
+
+ + +
+

Vertical Menu View

+

Vertical Menu View

+

A vertical menu view supports displaying a list of times on a screen vertically in a single column, similar to a lightbar. This type of control is often useful for lists of items or menu controls.

+ +

General Information

+ +

Items can be selected on a menu via the cursor keys, Page Up, Page Down, Home, and End, or by selecting them via a hotKey - see Hot Keys below.

+ +

:information_source: A vertical menu view is defined with a percent (%) and the characters VM, followed by the view number (if used.) For example: %VM1.

+ +

:information_source: See MCI for general information on how to use views and common configuration properties available for them.

+ +

Properties

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyDescription
textStyleSets the standard (non-focus) text style. See Text Styles in MCI +
focusTextStyleSets focus text style. See Text Styles in MCI +
itemSpacingUsed to separate items vertically in the menu
heightSets the height of views to display multiple items vertically (default 1)
focusIf set to true, establishes initial focus
submitIf set to true any accept action upon this view will submit the encompassing form +
hotKeysSets hot keys to activate specific items. See Hot Keys below
hotKeySubmitSet to submit a form on hotkey selection
argNameSets the argument name for this selection in the form
justifySets the justification of each item in the list. Options: left (default), right, center
itemFormatSets the format for a list entry. See Entry Formatting in MCI +
fillCharSpecifies a character to fill extra space in the menu with. Defaults to an empty space
itemsList of items to show in the menu. See Items below.
focusItemFormatSets the format for a focused list entry. See Entry Formatting in MCI +
+ +

Hot Keys

+ +

A set of hotKeys are used to allow the user to press a character on the keyboard to select that item, and optionally submit the form.

+ +

Example:

+ +
hotKeys: { A: 0, B: 1, C: 2, D: 3 }
+hotKeySubmit: true
+
+

This would select and submit the first item if A is typed, second if B, etc.

+ +

Items

+ +

A vertical menu, similar to other menus, take a list of items to display in the menu. For example:

+ +
items: [
+  {
+      text: First Item
+      data: first
+  }
+  {
+      text: Second Item
+      data: second
+  }
+]
+
+ +

If the list is for display only (there is no form action associated with it) you can omit the data element, and include the items as a simple list:

+ +
["First item", "Second item", "Third Item"]
+
+ +

Example

+ +

Example

+ +
+Configuration fragment (expand to view) +
+
+
VM1: {
+  submit: true
+  argName: navSelect
+  items: [
+    {
+      text: login
+      data: login
+    }
+    {
+      text: apply
+      data: new user
+    }
+    {
+      text: about
+      data: about
+    }
+    {
+      text: log off
+      data: logoff
+    }
+  ]
+}
+
+
+
+
+ +
+ + +
+
+
+
+ + + + diff --git a/assets/css/style.css b/assets/css/style.css new file mode 100644 index 00000000..736c4e3b --- /dev/null +++ b/assets/css/style.css @@ -0,0 +1,154 @@ +/* generated by rouge http://rouge.jneen.net/ original base16 by Chris Kempson (https://github.com/chriskempson/base16) */ +.highlight { color: #d0d0d0; } + +.highlight table td { padding: 5px; } + +.highlight table pre { margin: 0; } + +.highlight .w { color: #d0d0d0; } + +.highlight .err { color: #151515; background-color: #ac4142; } + +.highlight .c, .highlight .cd, .highlight .cm, .highlight .c1, .highlight .cs { color: #888; } + +.highlight .cp { color: #f4bf75; } + +.highlight .o, .highlight .ow { color: #f4bf75; } + +.highlight .p, .highlight .pi { color: #d0d0d0; } + +.highlight .gi { color: #90a959; } + +.highlight .gd { color: #ac4142; } + +.highlight .gh { color: #6a9fb5; font-weight: bold; } + +.highlight .k, .highlight .kn, .highlight .kp, .highlight .kr, .highlight .kv { color: #aa759f; } + +.highlight .kc, .highlight .kt, .highlight .kd { color: #d28445; } + +.highlight .s, .highlight .sb, .highlight .sc, .highlight .sd, .highlight .s2, .highlight .sh, .highlight .sx, .highlight .s1 { color: #90a959; } + +.highlight .sr { color: #75b5aa; } + +.highlight .si, .highlight .se { color: #8f5536; } + +.highlight .nt, .highlight .nn, .highlight .nc, .highlight .no { color: #f4bf75; } + +.highlight .na { color: #6a9fb5; } + +.highlight .m, .highlight .mf, .highlight .mh, .highlight .mi, .highlight .il, .highlight .mo, .highlight .mb, .highlight .mx { color: #90a959; } + +.highlight .ss { color: #90a959; } + +body { margin: 0; padding: 0; background: #151515 url("../images/bkg.png") 0 0; color: #eaeaea; font-size: 16px; line-height: 1.5; font-family: Monaco, "Bitstream Vera Sans Mono", "Lucida Console", Terminal, monospace; } + +/* General & 'Reset' Stuff */ +.container { width: 90%; /*max-width: 1000px;*/ margin: 0 auto; } + +section { display: block; margin: 0 0 20px 0; } + +h1, h2, h3, h4, h5, h6 { margin: 0 0 20px; } + +li { line-height: 1.4; } + +/* Header,
header - container h1 - project name h2 - project description */ +header { background: rgba(0, 0, 0, 0.1); width: 100%; border-bottom: 1px dashed #b5e853; padding: 20px 0; margin: 0 0 40px 0; text-align: center; } + +header h1 { font-size: 30px; line-height: 1.5; margin: 0 0 0 -40px; font-weight: bold; font-family: Monaco, "Bitstream Vera Sans Mono", "Lucida Console", Terminal, monospace; color: #b5e853; text-shadow: 0 1px 1px rgba(0, 0, 0, 0.1), 0 0 5px rgba(181, 232, 83, 0.1), 0 0 10px rgba(181, 232, 83, 0.1); letter-spacing: -1px; -webkit-font-smoothing: antialiased; } + +header h1:before { content: "./ "; font-size: 24px; } + +header h2 { font-size: 18px; font-weight: 300; color: #666; } + +header img { padding: 0px; margin: 0px; max-width: 100%; } + +#downloads .btn { display: inline-block; text-align: center; margin: 0; } + +/* Main Content +*/ +.sidebar { position: fixed; top: 0; left: 0; bottom: 0; width: 22rem; height: 100%; text-align: left; border-right: 1px dashed #b5e853; overflow-y: scroll; display: block; float: left; } + +.sidebar .logo { padding-top: 20px; max-width: 100%; } + +.sidebar ul { padding-bottom: 0px; } + +.sidebar ul li { margin-bottom: 0px; padding-top: 5px; } + +.main_area { padding-left: 22em; padding-top: 20px; } + +#main_content { -webkit-font-smoothing: antialiased; } + +section img { max-width: 100%; } + +h1, h2, h3, h4, h5, h6 { font-weight: normal; font-family: Monaco, "Bitstream Vera Sans Mono", "Lucida Console", Terminal, monospace; color: #b5e853; letter-spacing: -0.03em; text-shadow: 0 1px 1px rgba(0, 0, 0, 0.1), 0 0 5px rgba(181, 232, 83, 0.1), 0 0 10px rgba(181, 232, 83, 0.1); } + +#main_content h1 { font-size: 30px; } + +#main_content h2 { font-size: 24px; } + +#main_content h3 { font-size: 18px; } + +#main_content h4 { font-size: 14px; } + +#main_content h5 { font-size: 12px; text-transform: uppercase; margin: 0 0 5px 0; } + +#main_content h6 { font-size: 12px; text-transform: uppercase; color: #999; margin: 0 0 5px 0; } + +dt { font-style: italic; font-weight: bold; } + +ul { padding-bottom: 5px; } + +ul li { list-style-image: url("../images/bullet.png"); margin-bottom: 10px; padding-top: 10px; } + +nav { text-align: left; } + +nav ul { list-style: none; margin-left: 0; padding-left: 0; margin-top: 20; margin-bottom: 0; padding-bottom: 0; } + +nav ul li { display: inline-block; margin-left: 0.5em; padding-right: 20px; } + +nav ul li a { color: #8900aa; text-decoration: none; } + +nav ul li a:hover { color: #aa759f; } + +blockquote { color: #aaa; padding-left: 10px; border-left: 1px dotted #666; } + +pre { background: rgba(0, 0, 0, 0.9); border: 1px solid rgba(255, 255, 255, 0.15); padding: 10px; font-size: 16px; color: #b5e853; border-radius: 2px; text-wrap: normal; overflow: auto; overflow-y: hidden; } + +code.highlighter-rouge { background: rgba(0, 0, 0, 0.9); border: 1px solid rgba(255, 255, 255, 0.15); padding: 0px 3px; margin: 0px -3px; color: #aa759f; border-radius: 2px; } + +table { width: 100%; margin: 0 0 20px 0; } + +th { text-align: left; border-bottom: 1px dashed #b5e853; padding: 5px 10px; } + +td { padding: 5px 10px; } + +hr { height: 0; border: 0; border-bottom: 1px dashed #b5e853; color: #b5e853; } + +/* Buttons +*/ +.btn { display: inline-block; background: -webkit-linear-gradient(top, rgba(40, 40, 40, 0.3), rgba(35, 35, 35, 0.3) 50%, rgba(10, 10, 10, 0.3) 50%, rgba(0, 0, 0, 0.3)); padding: 8px 18px; border-radius: 50px; border: 2px solid rgba(0, 0, 0, 0.7); border-bottom: 2px solid rgba(0, 0, 0, 0.7); border-top: 2px solid black; color: rgba(255, 255, 255, 0.8); font-family: Helvetica, Arial, sans-serif; font-weight: bold; font-size: 13px; text-decoration: none; text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.75); box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05); } + +.btn:hover { background: -webkit-linear-gradient(top, rgba(40, 40, 40, 0.6), rgba(35, 35, 35, 0.6) 50%, rgba(10, 10, 10, 0.8) 50%, rgba(0, 0, 0, 0.8)); } + +.btn .icon { display: inline-block; width: 16px; height: 16px; margin: 1px 8px 0 0; float: left; } + +.btn-github .icon { opacity: 0.6; background: url("../images/blacktocat.png") 0 0 no-repeat; } + +/* Links a, a:hover, a:visited */ +a { color: #63c0f5; text-shadow: 0 0 5px rgba(104, 182, 255, 0.5); } + +/* Clearfix */ +.cf:before, .cf:after { content: ""; display: table; } + +.cf:after { clear: both; } + +.cf { zoom: 1; } + +.active-nav { font-weight: bolder; } + +@media (max-width: 767px) { html { scroll-behavior: smooth; } .mobile-divide { border-top: 1px dashed #b5e853; } .sidebar { order: 2; float: none; width: 100%; position: relative !important; } .main_area { padding-left: 0px !important; } #container { display: flex; flex-direction: column; display: flex; } } + +@media (min-width: 768px) { .menu_button { display: none; } .mobile-divide { display: none; } } + +/*# sourceMappingURL=style.css.map */ \ No newline at end of file diff --git a/assets/css/style.css.map b/assets/css/style.css.map new file mode 100644 index 00000000..75fcfdc6 --- /dev/null +++ b/assets/css/style.css.map @@ -0,0 +1,18 @@ +{ + "version": 3, + "file": "style.css", + "sources": [ + "style.scss", + "docs/_sass/jekyll-theme-hacker.scss", + "docs/_sass/rouge-base16-dark.scss", + "docs/_sass/_default_colors.scss" + ], + "sourcesContent": [ + "@import 'jekyll-theme-hacker';\n\n.active-nav {\n font-weight: bolder;\n}\n\n@media (max-width: 767px) {\n html {\n scroll-behavior: smooth;\n }\n\n .mobile-divide {\n border-top: 1px dashed #b5e853;\n }\n\n .sidebar {\n order: 2;\n float: none;\n width: 100%;\n position: relative !important;\n }\n\n .main_area {\n padding-left: 0px !important;\n }\n\n #container {\n display: flex;\n flex-direction: column;\n display:flex;\n }\n\n}\n\n@media (min-width: 768px) {\n .menu_button {\n display: none;\n }\n\n .mobile-divide {\n display: none;\n }\n}\n", + "@import \"rouge-base16-dark\";\n@import \"default_colors\";\n\n$body-background: $cod-grey !default;\n$body-foreground: $gallery !default;\n$header: $conifer !default;\n$blockquote-color: $silver-chalice !default;\n$blockquote-border: $dove-grey !default;\n\nbody {\n margin: 0;\n padding: 0;\n background: $body-background url(\"../images/bkg.png\") 0 0;\n color: $body-foreground;\n font-size: 16px;\n line-height: 1.5;\n font-family: Monaco, \"Bitstream Vera Sans Mono\", \"Lucida Console\", Terminal, monospace;\n}\n\n/* General & 'Reset' Stuff */\n\n.container {\n width: 90%;\n /*max-width: 1000px;*/\n margin: 0 auto;\n}\n\nsection {\n display: block;\n margin: 0 0 20px 0;\n}\n\nh1, h2, h3, h4, h5, h6 {\n margin: 0 0 20px;\n}\n\nli {\n line-height: 1.4 ;\n}\n\n/* Header,
\n header - container\n h1 - project name\n h2 - project description\n*/\n\nheader {\n background: rgba(0, 0, 0, 0.1);\n width: 100%;\n border-bottom: 1px dashed $conifer; //header;\n padding: 20px 0;\n margin: 0 0 40px 0;\n text-align: center;\n}\n\nheader h1 {\n font-size: 30px;\n line-height: 1.5;\n margin: 0 0 0 -40px;\n font-weight: bold;\n font-family: Monaco, \"Bitstream Vera Sans Mono\", \"Lucida Console\", Terminal, monospace;\n color: $conifer;//$header;\n text-shadow: 0 1px 1px rgba(0, 0, 0, 0.1),\n 0 0 5px rgba(181, 232, 83, 0.1),\n 0 0 10px rgba(181, 232, 83, 0.1);\n letter-spacing: -1px;\n -webkit-font-smoothing: antialiased;\n}\n\nheader h1:before {\n content: \"./ \";\n font-size: 24px;\n}\n\nheader h2 {\n font-size: 18px;\n font-weight: 300;\n color: #666;\n}\n\nheader img {\n padding: 0px;\n margin: 0px;\n max-width: 100%;\n}\n\n#downloads .btn {\n display: inline-block;\n text-align: center;\n margin: 0;\n}\n\n/* Main Content\n*/\n.sidebar {\n position: fixed;\n top: 0;\n left: 0;\n bottom: 0;\n width: 22rem;\n height: 100%;\n text-align: left;\n border-right: 1px dashed $conifer; //header;\n overflow-y: scroll;\n display: block;\n float: left;\n\n .logo {\n padding-top: 20px;\n max-width: 100%;\n }\n\n ul {\n padding-bottom: 0px;\n }\n ul li {\n margin-bottom: 0px;\n padding-top: 5px;\n }\n}\n\n.main_area {\n padding-left: 22em;\n padding-top: 20px;\n}\n\n#main_content {\n\n -webkit-font-smoothing: antialiased;\n}\nsection img {\n max-width: 100%\n}\n\nh1, h2, h3, h4, h5, h6 {\n font-weight: normal;\n font-family: Monaco, \"Bitstream Vera Sans Mono\", \"Lucida Console\", Terminal, monospace;\n color: $header;\n letter-spacing: -0.03em;\n text-shadow: 0 1px 1px rgba(0, 0, 0, 0.1),\n 0 0 5px rgba(181, 232, 83, 0.1),\n 0 0 10px rgba(181, 232, 83, 0.1);\n}\n\n#main_content h1 {\n font-size: 30px;\n}\n\n#main_content h2 {\n font-size: 24px;\n}\n\n#main_content h3 {\n font-size: 18px;\n}\n\n#main_content h4 {\n font-size: 14px;\n}\n\n#main_content h5 {\n font-size: 12px;\n text-transform: uppercase;\n margin: 0 0 5px 0;\n}\n\n#main_content h6 {\n font-size: 12px;\n text-transform: uppercase;\n color: #999;\n margin: 0 0 5px 0;\n}\n\ndt {\n font-style: italic;\n font-weight: bold;\n}\n\nul {\n padding-bottom: 5px;\n}\n\nul li {\n list-style-image:url('../images/bullet.png');\n margin-bottom: 10px;\n padding-top: 10px;\n}\n\nnav {\n text-align: left;\n\n ul {\n list-style: none;\n margin-left: 0;\n padding-left: 0;\n margin-top: 20;\n margin-bottom: 0;\n padding-bottom: 0;\n\n li {\n display: inline-block;\n margin-left: 0.5em;\n padding-right: 20px;\n\n a {\n color: $enigma-purple;\n text-decoration: none;\n }\n\n a:hover {\n color: $bouquet;\n }\n }\n }\n}\n\n\nblockquote {\n color: $blockquote-color;\n padding-left: 10px;\n border-left: 1px dotted $blockquote-border;\n}\n\npre {\n background: rgba(0, 0, 0, 0.9);\n border: 1px solid rgba(255, 255, 255, 0.15);\n padding: 10px;\n font-size: 16px;\n color: #b5e853;\n border-radius: 2px;\n text-wrap: normal;\n overflow: auto;\n overflow-y: hidden;\n}\n\ncode.highlighter-rouge {\n background: rgba(0,0,0,0.9);\n border: 1px solid rgba(255, 255, 255, 0.15);\n padding: 0px 3px;\n margin: 0px -3px;\n color: #aa759f;\n border-radius: 2px;\n}\n\ntable {\n width: 100%;\n margin: 0 0 20px 0;\n}\n\nth {\n text-align: left;\n border-bottom: 1px dashed #b5e853;\n padding: 5px 10px;\n}\n\ntd {\n padding: 5px 10px;\n}\n\nhr {\n height: 0;\n border: 0;\n border-bottom: 1px dashed #b5e853;\n color: #b5e853;\n}\n\n/* Buttons\n*/\n\n.btn {\n display: inline-block;\n background: -webkit-linear-gradient(top, rgba(40, 40, 40, 0.3), rgba(35, 35, 35, 0.3) 50%, rgba(10, 10, 10, 0.3) 50%, rgba(0, 0, 0, 0.3));\n padding: 8px 18px;\n border-radius: 50px;\n border: 2px solid rgba(0, 0, 0, 0.7);\n border-bottom: 2px solid rgba(0, 0, 0, 0.7);\n border-top: 2px solid rgba(0, 0, 0, 1);\n color: rgba(255, 255, 255, 0.8);\n font-family: Helvetica, Arial, sans-serif;\n font-weight: bold;\n font-size: 13px;\n text-decoration: none;\n text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.75);\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05);\n}\n\n.btn:hover {\n background: -webkit-linear-gradient(top, rgba(40, 40, 40, 0.6), rgba(35, 35, 35, 0.6) 50%, rgba(10, 10, 10, 0.8) 50%, rgba(0, 0, 0, 0.8));\n}\n\n.btn .icon {\n display: inline-block;\n width: 16px;\n height: 16px;\n margin: 1px 8px 0 0;\n float: left;\n}\n\n.btn-github .icon {\n opacity: 0.6;\n background: url(\"../images/blacktocat.png\") 0 0 no-repeat;\n}\n\n/* Links\n a, a:hover, a:visited\n*/\n\na {\n color: #63c0f5;\n text-shadow: 0 0 5px rgba(104, 182, 255, 0.5);\n}\n\n/* Clearfix */\n\n.cf:before, .cf:after {\n content:\"\";\n display:table;\n}\n\n.cf:after {\n clear:both;\n}\n\n.cf {\n zoom:1;\n}\n", + "/*\n generated by rouge http://rouge.jneen.net/\n original base16 by Chris Kempson (https://github.com/chriskempson/base16)\n*/\n\n@import \"default_colors\";\n\n.highlight {\n\n $plaintext: $alto !default;\n $string: $chelsea-cucumber !default;\n $literal: $chelsea-cucumber !default;\n $keyword: $bouquet !default;\n $error-foreground: $cod-grey !default;\n $error-background: $apple-blossom !default;\n $comment: $grey !default;\n $preprocessor: $rajah !default;\n $name-space: $rajah !default;\n $name-attribute: $hippie-blue !default;\n $operator: $rajah !default;\n $keyword-type: $raw-sienna !default;\n $regex: $gulf-stream !default;\n $string-escape: $potters-clay !default;\n $deleted: $apple-blossom !default;\n $header: $hippie-blue !default;\n\n color: $plaintext;\n\n table td { padding: 5px; }\n table pre { margin: 0; }\n .w {\n color: $plaintext;\n }\n .err {\n color: $error-foreground;\n background-color: $error-background;\n }\n .c, .cd, .cm, .c1, .cs {\n color: $comment;\n }\n .cp {\n color: $preprocessor;\n }\n .o, .ow {\n color: $operator;\n }\n .p, .pi {\n color: $plaintext;\n }\n .gi {\n color: $string;\n }\n .gd {\n color: $deleted;\n }\n .gh {\n color: $header;\n font-weight: bold;\n }\n .k, .kn, .kp, .kr, .kv {\n color: $keyword;\n }\n .kc, .kt, .kd {\n color: $keyword-type;\n }\n .s, .sb, .sc, .sd, .s2, .sh, .sx, .s1 {\n color: $string;\n }\n .sr {\n color: $regex;\n }\n .si, .se {\n color: $string-escape;\n }\n .nt, .nn, .nc, .no{\n color: $name-space;\n }\n .na {\n color: $name-attribute;\n }\n .m, .mf, .mh, .mi, .il, .mo, .mb, .mx {\n color: $literal;\n }\n .ss {\n color: $string;\n }\n}\n", + "$apple-blossom: #ac4142;\n$alto: #d0d0d0;\n$bouquet: #aa759f;\n$enigma-purple: #8900aa;\n$chelsea-cucumber: #90a959;\n$cod-grey: #151515;\n$conifer: #b5e853;\n$dove-grey: #666;\n$gallery: #eaeaea;\n$grey: #888;\n$gulf-stream: #75b5aa;\n$hippie-blue: #6a9fb5;\n$potters-clay: #8f5536;\n$rajah: #f4bf75;\n$raw-sienna: #d28445;\n$silver-chalice: #aaa;\n" + ], + "names": [], + "mappings": "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" +} \ No newline at end of file diff --git a/assets/images/bkg.png b/assets/images/bkg.png new file mode 100644 index 0000000000000000000000000000000000000000..d10e5caf1adb7466673bc9cef83621fe855caa3f GIT binary patch literal 1218 zcmeAS@N?(olHy`uVBq!ia0y~yU=jggMrNQ$#TNBtK#DEEC&X1sN=jNkczmscWgJUHsE1R2ws}X9=R$~%X@*3=-vhL@-NfkR)!pBoqVTzzlmJ$gw$h( za!N&gzAjH}?UE-yuB@->I#KvPao+dRzrL@oCvVpee)R8SO|Rip8+r3Dza~8XxNqSP zmGuR0<=?XLN*y=&ko@A*R?n;zmFGjmpL|X=el)GDnT?nCc-hJ9h-*>(U-v7SP21O( zoNu0S!J*))p{S5clIq(!Rnv%W88O`}e-}D7AF~mxZfpV+3kwX-$FQx)Y;JvA%`)@d zWYLYgd8JI0aw{r!Iv89Q>eyImcyRi@1&bblZJ%(NN9SER*F|RI`9Vy^n|kYj&a|m< zH+i{|PR}_n7 z-gd`kwp)J%TC%IUg`6V4t}fWH9jMCX-LAENwM{str7XO1;E!GNEuasI-gOzw-pnlj z>{){B-p0ScV3upi-pM7+*5to^wpdM0Lo6uhXKvGLxTUb-aiDN)U^44#klW=8|4*sV zntfrzKU=lq{IC4u?*i3*Ut)0K@G9flAeW??UW>QI-$6b&yzF|LRw2jj$QO!RxR2R@ z!p-JEk`UjzM%QUGt5 zsq{^Wh=(VtSvB4F14E?hZ{X9Y?R-}fa@G1cS_4|1{K5DvW*TQF%BQWRm-W8rcnHXW5F_LnOa!0te-Gud{_`k1m{6m9unPa(^B$ zKx8W_XRUv@r+&lLzc+3*l|BZA<&8P3LiGe?mL9UxX48rf2YHj@p3l_yh=pvc)~tHC z{nO?fprlo3bGdkWi`e7f5A45eIR!{NSV4~V*iRMLf15OnS&>IfjrQ$5*USNy<-2E*PZ71vSAxg$R}ir z*HrJV2QIesUSGbBCF#9c#svfK2|7o#H8-glPWYpw_zvjL75X#RJY~u`5Y-X(HrD(= zUCM<84_%p-W@|H8MF_Nfy!EQ%2FOzxtQJYFtLINQ#Ng@b=d#Wzp$P!*bu5qo literal 0 HcmV?d00001 diff --git a/assets/images/blacktocat.png b/assets/images/blacktocat.png new file mode 100644 index 0000000000000000000000000000000000000000..9759d7762ca84fd279f8bd59706641e13c1926f0 GIT binary patch literal 268 zcmV+n0rUQeP)_yxDRcl8_oH}KY@N>TT1a{44=<&$4$p^ zC0ICT$pbdEYvno{KSou>!krh=N_9R{CeAf*BB#+UjGZ;AZi3Y`MhCJsH?yrf4($-OfLDgK%x| SfwxWo00007${dCd>QY`6?zK#qG8~eHcB(ehe3dtTp zz6=aiY77hwEes65fI&pI+kyVsc_(xbi&_G6SPZ!4!i_=@D?9F0w6md%rmzMVCWO3ZMStxs>APeV` z6HToPk{)y4eARTTV}i&**7yU5F8RqPByJ7f7l(V(z*fP#y%N{ZA*k8}SM*o+)sk0^| zVWo&jS?rFxude<7%Cf>m>EMbm?l6Vrx6ksBe>HsTzdZg`C*I{YbAygX z`No(wBmKJvw3*sg? literal 0 HcmV?d00001 diff --git a/assets/images/button_view_example1.gif b/assets/images/button_view_example1.gif new file mode 100644 index 0000000000000000000000000000000000000000..c7e36d02faa31f4a053121c4a8edf9a6337fbd72 GIT binary patch literal 5255 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 Zy}f$pT-*{Y{WbY--yRQV((flO{T~a2Wn};W literal 0 HcmV?d00001 diff --git a/assets/images/cp437.png b/assets/images/cp437.png new file mode 100644 index 0000000000000000000000000000000000000000..fa0a511ff99db999ca12907354a6e089d02b43fc GIT binary patch literal 308 zcmV-40n7f0P)sXx`vKA^KOp}CZlGLwFBUX^B^>`pnlCm>vqJG2MMZGWm zo#de1lQc>C|H3D(AmflG3DYEDnk3)&mw$s5iZlTL?rj6XGjWbcO1!ZE0000G75?;4!8xRilr(zQQsht z2oz#M5D_o|qY<^-1JkZbATA+Lbx|uW;9{xR^$O^))LF-Uad)9#n6Yc^_JilsJ9Fke z=ehiU|L3d`MsfqT+9Eu_KM=kEUatTGfj}aWC=|-d%F5c>+Q!Dl*47q{Mq@A-EEbEy z;T#+s@OV6dKp>GwWHQ;w$%#UtP^nZJjkb94VrOS(7Z(>-S64STH#(ipU@+X>-B~P_ zhlhu!r>B>fm$$dKkB<+B!}0a?UAb~4m&*+Z2nY-e3=R$s2?<%fdNq&7b7xjo*6!WA_w3oTckkYu zoE(WnvVZ^ng9i^n5G0jKb8~a^^YaS|3S=^wTrNL+_;68CQE_o`Nl8g*Y3Y$8N0dsX zN~J0*D^si0<>lp-m6cUhRn^tiH8nL_t+uwdwyv&Dr_<^6`uh6%^XJbuG&D3dH8nRk zx3;#nwY3=xhK`Po3l}b2ym--QG@48%v)OF1So-?6l)trm z(0YJCI|~{$#zSZ#JHgzj?Uv!0qAEdC?d2lMiu7S~Q(aFfonPoIY(CkmVy&-F=xx^Z z9pxljs)Q}4zB$g#dNADEa{B6t&_i}EqE`K1>I5qG7E9}y>!)MtMAf3U`kQCtTGB@> zZD(&aBy|_ML>bQAZb`jfzopM`eyBZj%u*fI{^iKm+0Pz~^tCtq?Gl8-x~}bLyxT1& zE>G<5Xd3HLFr!XU@$>N7AXqTNFwbZ!0FSk|*$4nsfCDJ_C=&38sDeg1MQUT8sOf6d z^4SQ)+Z_E1M!Dco^Wo#>+lWH`_QOU4CqRO$UI6(2qzV*C3IMAwykcvgR<_wtmJ^qv zy`1OZz(`0MkGWj5XazeZ8I@v|Axf6|V*JLe{CCDB_Rnxm_2*NmtxY*ZriISm$0m7@ z+%0*YAE7^_L9(9XHr^?J%4FDFKE5&S-BI9!A7e__kZXaw(?%mhwuK zvJ%V+Eg@L8WcoI7odqhOkZE$t8orgkvQ< z-@qyR%?2-u7grc_EUMjG1^wj3vY-d-0{?|64R%BP;E1iLzSE$g$BoyukFN@6j}dl4unRw6gaFBDVguj>}0ix8=Gwa-463=i$l%iK4Ar2e*2F>uPY1sxT;B-u1@lnNi8~9R z&^R!D^~9{Wao4_Abm!x33wF(LzU!i949=WMb*!b9xR4J7kp`G%C2CDADd#htMUDPL z7l}pu@DSE%fNRP@Z2O=vR9Lj2KlpsNwS9p^X;{;S;6@IPl5^j7YA|2g#Z8m literal 0 HcmV?d00001 diff --git a/assets/images/enigma-bbs.png b/assets/images/enigma-bbs.png new file mode 100644 index 0000000000000000000000000000000000000000..85e30f695a34d61fa8f21d4dc7474fb34d1d0f49 GIT binary patch literal 6814 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 QzB_@AAGJ0sJ%YLXU)mj~lmGw# literal 0 HcmV?d00001 diff --git a/assets/images/enigma-logo.png b/assets/images/enigma-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..94f652aeabed0302d06b927b41c59c473ba745cb GIT binary patch literal 16643 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 IWft~702|8K8UO$Q literal 0 HcmV?d00001 diff --git a/assets/images/favicon-16x16.png b/assets/images/favicon-16x16.png new file mode 100644 index 0000000000000000000000000000000000000000..0a49c7f65447a341e2ecd3ac2144e9f918b1c454 GIT binary patch literal 885 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 literal 0 HcmV?d00001 diff --git a/assets/images/full_menu_view_example1.gif b/assets/images/full_menu_view_example1.gif new file mode 100644 index 0000000000000000000000000000000000000000..7366d8130dbada70680437908d58f1ad98b2c0aa GIT binary patch literal 7198 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 qQnD>jAWeF4 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 literal 0 HcmV?d00001 diff --git a/assets/images/full_menu_view_example3.gif b/assets/images/full_menu_view_example3.gif new file mode 100644 index 0000000000000000000000000000000000000000..b57375fade714995f74fea72d9902dd31dccf7d0 GIT binary patch literal 28011 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 BMRNcE literal 0 HcmV?d00001 diff --git a/assets/images/horizontal_menu_view_example1.gif b/assets/images/horizontal_menu_view_example1.gif new file mode 100644 index 0000000000000000000000000000000000000000..e02c60a44af7e108ac7c5834030d7bdccb0b4863 GIT binary patch literal 7832 zcmeI0XHb)CzwYle5<D>jAWeF4 z0fGcj45&*$Q9!z72@4S{FNbyZocFxveA}~T&+I+(-t&BW<|#AxbzS%M`&(IC>Kk~P zK()YES1qu=AOJuCfB^sp0096O07w8(0B{4q0{{j9UI2suzyW{jBLGYRFay9604o5j0k8$Y z4uB&7I0E1Vz%c-v0dN7p6##btyaDh9zz+a_00IFB1|SrGZ~!g+%a66cE%G6fzbP{#96*EQ~Y7;mmM& zbG!&uM3g2fc34czPE6chT*660(pgf9Aw~2i5`Bm={xUKFGO|Ik@?r7{5ef?D6_l?i zD_>PsiBVBus;I`PswSwar>JYBYiML>Xy<9`6zS;R)YZMMt5>3@SE{F9rLSMDZ%|`k zP-|d#&(NsV$hh6uxWkzI8=2fkrVLOhgA~(YQ?pSs^C#vO;}#Yi3(E;h%SlVC=T=s~ zTUpOo(`IS3H#D0$8=D0i+jq8yR}R~)+u6OhJM!_!kxxhH8}y@_M~`kDwf|yozin^- z)!yNogX4Ec#~+SPdrto&F5(`KorR-=8HH}4t*!~%w*nyU!V&0w`R%J1fWK_Auc?2V z`htfoJ&b($fl?`7bn59Zs zHVFWcv7BXUZleH_lm)HzU~IMWY5eZwc3xR80f92wOks| z3~Dq8Pkmzr-8-q?({8z>`Y|LWr=ED zi52-!i)m84K(oGFia2VqB=OQ3m2}NGh!W3JxS_aw9on=~l5Ky{aVeP*eM3f2j&D)M z`YQwm6u(ZF%v~NVhhXBqu92{1Z2c~RHm?c$XgZ_A3BjVH%3-IeCd_G=W1uGj0(-GH z%nvOb0hLKcnY7|Ms3&U(cUJ71H)WMOO%7B^?Pg!>K$q9%Rv3ne*W-VP1r|SybgsH@ zAQoTS(C4MH8u|qKxvs#)uKQl+>}j|%4sB$U)pFR-K(eiZlvZOUbcV8;y)>HkF@u#l z^U31v36-F(FE|@)gY;}w3OU0h^|3h6XRlpmVjMRrZ->tCS3`RvD;lX{Eae0~qd+O@ zWMyAtQU489`elBJk}%wSSHZ`8cx$7DAk4*s2^o7}t8+oV?9%(Q_FJlfky3o#I;KuA zY{X5w+A&?$JN2_)`teLO1n9kwHW!$E;Hx_NBdGtOTlMLT$jm>pqtEw>`0Vw58SsF* zVF#tGZ9^(?JhD{TY!E!hEHbHXvby-oN12?dppbz%+OT9>Thg1?yIh4oKgSB&AGqb( zuH~_93L|MTbf$FT)H!cW96rjth40RWyL~ zNPKc&NdA!-b3-D2@an0uxBuvg?0#-weZI$r{S^$886hJ+pBnfbaP;R4=0St(s<3PdDqM_LRC-WN_R#leew@mw}#L z&Db~ZNjv%?m681QGKmaxjD=;^_jFUjMe|!^dXuziwD%Re1t!_Pv0-dqZPft-;6zjc z5>Q+uI@3u3bFI1%f^PSWsazcUky_v!H3uHW5v)6>)J&*n>A~?d~>7}O%OP> zx17k-EO3Uul|Q6}WpoLETktZCd1roJbU@*k0b5>6P<>omAosaL*_W7I>z<#s=h|d* zmEuy={PeQV^@z&p$!zP>cUH&&gk)){B+PjMIF5~lQ?Vm^Onm2%nJgA16xsquQ%=j6 z_1WU$8#QFI{Lr})REm}vKFKQ)1#`2@P&9|d{!r2XDLX+i(4L@k50(nWDgx7@(%c+H zXYnChE4LbAo-(|m&|lC7Kf_6~3$4O9;q2Nyo@IDEjU&&#B<**otB(%fG`{C=eyS_s z1{65jeqqxiXvAW#&9Z2fHR?t(=1ARq9aQO|%hQ>J*t&>&To5y(p93*#1XextZmoM& z80bMS)=R0zxKjjTy3`3an8HP{JsLB>@oR*-1iHb1GgIhT1Co#o-KJq5UF68beo+Ck zwa14^`4D~-pMMphb?oRPx&?eQy&o8I4_>BiAisTUC*Xd9)5%;h0v^j;s(l!Y`6lzI@VxV$g*Ci> z7vh{z-p`0?Ji<4ahO*KJvZ;zdlSLGYX{?aa8#(&Sxmu`uXGk-%Dc#rho!G0LNBZMU zndcwBlls0hOy+COO0r!fiSM$hcFj2jj~C?+?T*kho3B^dE-5p1N1ex;^V=UUsbAV1 z^WeK*IBdJDeRKD*pWXeUmyehAx_3pM1ZUpAwPL$s_-c1NYW#lj*T*X+?XrY_DT~HX z&3%yC?~f=r=!C=nZ;Slzd4mt2_o)iI|GRsj^Zz;9i33OY{`c9w&}Y}9x_`E7k(9he z52Z>dZJwes8EvnpvP09j)ivzv{qCBB0&X?NgGDc51zFt0Iy5C7<5E`2K7CwV( zZkG0jzoSMGUqwY$)(u!#(Rhp;ypGa`d})f%-XO@Uu(78s(~m-kAw=Pe(k^(c@|h%? z`qH3iq9E=xYa~|bEX!3qk_WC%o~``B$_shb9+VK8oo36b>}ErG7snDFpDaI%l9Dfs z(t5=rxcAKE=&ZbdoPF?I+vrl5ZyohJ+PtWGZhbV>pOMJ8(cIs5?SiKC$h3~%1S&-w znG$8Q*^t3&S8GC@8^NjC+S_s5dcQ`*S7&{ixf0s6AT+0Oeuaqr^%RrRA{!gj9kKl8 z96O!FA(cniJIeGEPL1Ici8|@xRfK29&oWklgB=Dt2uYF>2p_}|u+FTA+q)16H*?~t zWOCPMd8`_BqQaFAv!%#^7;lS^DHJY$4j|U-42cDx!ntyxT1q~-uGb+IxyRAEiPzb8 zSC5Y{g7=Um>VJt zD6&rbZH{SB9xY)&zoy{LHi}$0C{R%xo99&`YyGFkH8oPe6<3}6`>Ig=b#ozac&?(@ zFyhVQ8!e=#*G-sul2Jlu9^x5ob?h#S6re8H5qhv6@jjmin&Q1g%75<|?|!<({6xej zRSnnWbxA*~bBeKE%MVnY^X4Ra75TYavYb5gT3t#|&$C}Z3lvC;{beSH<@_=_nn zYj^voDF~?9H=SyV(QsCX?CPZAWDgt44NsWl!#`rcXJUGm9`=p8Vmy}DV+gApu5(1j z;E*o<`LTmd`83V(+CLt7x9!Xj|GcDDFyH?wv{g0heM;=pl4s*?y$X?o z$6771(uy|(QZyGn{vtw2;5X-{Wj9i=!2|rh5~kbpNx4_vZTLz?@^I^8lU+aO%#jzh zqF#|3Sc@ZMp$EQ1Q%bOKLZWR*^35RWdTLg3)fexDKtvJNq9%sVb+_7rngDhLx+N>(EI z3kUgay7*q|9}$s2ZYp`>xS^E!VzNzeMOJ1F%h6W3H)I0s)f+>>s)aF0oJz%er8Y;H zPZGE(tsmsFq(Q3L=n%kY60p!#wB!5ww$KoAeLGZz4(VRk=ZFPVADtCD8N7jL=9C`g zh;aC}RGZyyF+VhMiYRn3PCbR*@hX%b`*-p!cVCH|e`e1Xr;OFN&lTwBC5^;^SRsK0 z#i@rS`&=P;Wt2TZ60s+&h3|94q6M!(TcGF-Gn#dtn7}Bxbh7+#((S0(4?7lu+TIr< z(ULP+l*5_EZ5^^o7BsE|-AsXl*617Kckx%bhDKjhPUKPZyfV;j0mC)NpU6M2X}f0u zp*hmzRF3b9H1toYmaOy00chwcdD*mJQ};ai=l^j1@#mb}qrbw8$`u-detz3JGJDa| zoE}LKIxOYwdHsoGcs$L(#}T}yYLJhOJM&@z=yGYURxc3b%@ z0ejdYC}apm3G`&fiW>!6+=2c~ITNNVeDhw5G~c^NO6)1(8!70}z^r0$eoFnlYxPk< zUB2?V4flR+y2*WQHMAtC;M=B+MzmS=^#tr>i07cE115$e5UN$)=xR<55%LI~h`|b8 z(cZl={T9-vrNXsOeF-6Qohs}|Zyv?>_Bda@qI%3$`9?^|pGTA$ zKIm|k(3kI%F`A8iOpLw}`I)0a79HX!tsC(SLf~vs9Cd<$DLOubK6Ubx!6UIi=`F;o z;Ia_x>yVypy;r^ZGh(k#cewKY@+$OH_*bzD!q8Q&3Op7P&a z67es!mi)+9dZA3K8=;SHCw>gf1!U% zA#z$Q&A2VvRVlmNx@aH$%ab3=+1@xLID?_J_>C89DCD@(LJ7Q;jO(a5lIPt#VOh1{ z3$#f@b|oyyFhSXg^is|JX3mek1jy7q@2dK<-?vpqnhj;X1U?s>R@H!h-(HlVH+XoL z!^aKMF%x}-I*11Ze^U?PRt76L1RA-C6U4U!u7%K5@lW$QUEc`sALN=S?|d9F_D$Dk ztZ;fVKbrC7)vd^j0yeO^m43z}UXoL$Z2_5X{1Fu&$oaD`yUzDKmx@pLS`O?U&)(ph zqVDt4jPP>}PZD~zXBJ-VJrb3e7FRFI`E5o+Ww&o>k0?lunGB)0MV;#`kaGKc1J7`t z+u(W;jZAsz7Wjv?KJnuEL4D$-J~@SbYz!vSj$}J8ob)h3u$`GmT9jK5W|TdY@OIW) zJXz2s%02NAx^*syA|^+_jQXNGC#Dh#A*8|Ng-&H}`uwtZ5jyXe<-c)sQ6};DMMdu< zJ+YKU3N5r>R@<))Rbi^-wgIsFpP%M}5}Be04t`3m%Ezup`4$Tuvzol~Yf!&0@B8_Y zgyLiBGm0ffli~7VWx?6jxyC;B$sxu*qeG+#-j+doM2IKc(E-zkK#HS>Ta+CR;QEAk zVNbdoYX#P5_JNH#`)+c%J6coQAEXu7^dP7|z&%!O|7f`^oJ+e4&7N`4@Cc@S^kj)R z0@xy-F6dm9*Ti=5_e7|7I^0sgc3~tu)O#`2Diht9!S94Fo|d7Q+8;UlvjPmXw6OfO(H49%)^dSQHTLnKdZEE!#AxIPGDExSU7`&ELc!s6%oyu4)+mb$QN7G+=?a67{Z_EwDRh>wj`z9w&`YG-KqXrZXv#le&?d7GPp zCp%o{L(>Ex(6p}C1bX$Pnlaois%r>-BvIx#MJ$CnSCQ@Edx3~@^eE5H7|3j$6G)3y zR_8HHv7!6Us?p)=!T$5>l*ZvR87*Nrm*eVvmN|#5Ipb7%vhe*`C^L<>%Sv0Jla4wqGEa+&jIt!ol5dB8{S;3iXBYDyGC|IYsH047Tmd;DR0bCD0uFXJFGq) zMF^bExxB~sgxs~VHYhG;^&r}F`ekb8%f-f8}N;20ImJI`AJOQ+|FWd+e{0EloaYys1cJ@as~@Un5g~chkfVo(k@$ zLsx94o4iMF>J#l25Q0P{Z)4uk9v7Xei8B7HTxwI<$!VGL=*d;8Q%X#n1WE;IDEF9IkzRdQLIfyX)ed>sFHcnc9y{w*&SCZXy4t*6`4ghaF6` zb|l?L3UB#AZwMfSS>n80d6q8{ABsLtbwzD&9Mihn=xs#_>dnKdonsClVEQCFHdBHx z=G`@Ji7gozGJc9bOHOQSNX&LSmUY6m2C{@lRP@W{a%Y72S6ut$4 mcu5JdHQ0?g$BL+H5wf>tN1VO>UQqn!1@rGG{?EYV(EkEIMc7{e literal 0 HcmV?d00001 diff --git a/assets/images/mask_edit_text_view_example1.gif b/assets/images/mask_edit_text_view_example1.gif new file mode 100644 index 0000000000000000000000000000000000000000..b12ba5ab2b91c785886fb6e39b249c4a425f10ab GIT binary patch literal 7222 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 OzAD_?m3(`1IP@>56y!+& literal 0 HcmV?d00001 diff --git a/assets/images/mci-example1.png b/assets/images/mci-example1.png new file mode 100644 index 0000000000000000000000000000000000000000..ca3ffbcb2eb94a5018c948f4cb26c31c837cb39f GIT binary patch literal 317 zcmeAS@N?(olHy`uVBq!ia0vp^RY0u5!2~2v?%!zwq?n7HJVQ7*IBq}me*olu^>lFz z$!L6g?IK^Z0#ED1O>aay&u3J4lqEV@9dS}BG5)##bX2-cww4l5F%Ya^J>RbC8LH}a z<*3HTSL>cF^}1IS%2|Ek=mzt9-!n4eX1#m*fhYRp#S_2!CM}-0b@tCfb0@8 z*K4;PZ<tH35=4?*^pS+O6oh^H2M;{nVs$ zrJlx~R<}x?u8Q3E-!*xi_pHj(?z7j$n4V7FE)4NOgZ($gptnUwxP;Y{Kq8*5elF{r G5}E*q2#o6h literal 0 HcmV?d00001 diff --git a/assets/images/microknight.png b/assets/images/microknight.png new file mode 100644 index 0000000000000000000000000000000000000000..831bde19af87e9a938db7ffa119153821f3c024b GIT binary patch literal 401 zcmeAS@N?(olHy`uVBq!ia0vp^r-0aqg9%7ZI(E4mNHG^Xd4_OsaNK_A|A2vk(bLn# zF{EP7+uMOzhYffbE~LHbuuXeEqpl>UO-T9pw97NU@AH~`qDY{x;PP!=pmqj^hNrpH zdv@LbzMn_#`V#?j``a6pzq!0V^JMi`rjFn^m7q8ktIsj(?fc{1kC*W*T`c(eQTWyK zI{j|@`j6PF+r2LS$uqO{YPZWNFxtEKy8o2s^qM7)C2zlWS@iXIzO3P-=f5r2evICn zd-nJ~@%gTm6Fn*?zNq$?azgHmcZ&M5y4-uAsd?_Z%We01sMMYRn<;v7`DBEFPq*4` zyU$+svoiFl%=h1R%RPVXUjud(&|y-W-mdKI;Vst0P; zjv*Cu-rn&JI&2`odcdL3rSGKd;X~XpoI%GveP+MB_sB$(FdJ3hlTXT+f!aB$Zs#uf z{rqqGmGys*$!@OSa#Qg7m$Gg7S#sx}@C4dc*jq8|VCrOH6yjuBReko~zRF#*?%q7V z)$Psd?XT*K>b8FR?)5+URk^L$`Lgnj`<|Z?-ti^tZ)L^FF0d9AA(k4REi=PiKF6l5 z4q7#b`Ahl6zfx(Bn#QYF#7+&)}0`SX0y{qEXAEFLNx6FdYA zf|Px=(xoP!I_b9mZQ0sq8$+}9Ed3brE8f`NJM_`b%Yh$l`fva8nJCK11hfaJM`Go~ zXTML|e*f-n86E5B^*<&5VtKA>69dHg$Iegu_hohR8cL&wJh_$v*hDv5H z>AIHpud-dL{`<@8+g|@ZALjM-=S%k)YiC6jZ~dz8f93!AtT#U^k8UhY8h zQq{HBKQDi2x4(_oEwPO;NkXCRV{}x|&KLjN6B{JhIuaZ9NWYE}yHI7m_y4+Mcfa?& zSh48w$*;fX7yOG}Ge=SZtYxk3;wj-Li)_zc|Eir@yK-HBm)%cE!+Cvom5S3KhRD2> zWGP*LYt>G{bdZ@6Y$sx?-L_p7JvTpD@8KB+Lmq*{43bxk-R3hd+MnWb{BqF!z3P_6 z4m`|93>>1a@4i_5?Zx~lKbE&Mm!FvlcBG=`B$buh_0RApPyD_9RRPfd44$rjF6*2U FngH0ng;D?j literal 0 HcmV?d00001 diff --git a/assets/images/multi_line_edit_text_view_example1.gif b/assets/images/multi_line_edit_text_view_example1.gif new file mode 100644 index 0000000000000000000000000000000000000000..acba094d96e0818938277fb1824b367dff3ef899 GIT binary patch literal 13256 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 literal 0 HcmV?d00001 diff --git a/assets/images/predefined_label_view_example1.png b/assets/images/predefined_label_view_example1.png new file mode 100644 index 0000000000000000000000000000000000000000..d46dbc79238b6f02fdfb74c7ea9dae973fb5fc70 GIT binary patch literal 3342 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 B#RdQX literal 0 HcmV?d00001 diff --git a/assets/images/text-format-example1.png b/assets/images/text-format-example1.png new file mode 100644 index 0000000000000000000000000000000000000000..387786f2315b77660d619b44cfe678d9f05d1443 GIT binary patch literal 496 zcmVwa>O7AhOyIEbbLm~hqM=I9V&w8Y7V=6R|!!h>mN`Tz%UHs z({Mwr6952s@fMJgTIS%!O{66qSGHq6&G+J5Eg^?oSzH{Okxd+d;b5vzt2k+U*?#b~ zBGg~J;$kh>Kh}!gj%iABD`i$(bjLN7)#%~*DymIrv)bY+Jh$7$7JW!cSNeVKdt__FFpSr*OlX`( m&i`uhNB_NM7=~dO=kf!ILiJ{EP+o`t0000ZgXgFbngSdJ^%m(SxH1eRCt{2 znomd@TNK8>G08+Ug|Vw57qqP)1QbgHBGs*e3lZE{K}uIHT(*mLVR0daZtSv9h^3^9 zC{Z!3iVGDLErmjfNU(I{pF&!+gs2Iv`E%alF}In_B${!W=PUOIcQNOj`R3f4&zU=k z5&(igkVV;l-GJcoAxt6AAxt6AAxt6AAxt6AAxt6AAxt6AVagN@4GoA!qi2rCj~`pz z@0moSQOmR%8yj_Vx+uANPN&m?PJc5xI;zq4`Furdm@3TgKHr|l zCTZ< zWCV3}b%wQ%9zDX&&JF;;@Ava~Z*Q-rE;lziI*RJ*YMq{1_vzCoJbU)6V4qgu^?G%; z>R2p>fq{X7=lOg-q|<3UeE1Mwzkb!_J32aW|Nec$bLZ#h@%r^^^Gz4v!ndn$-@X;R zy$%iz@_aNJrAQ<~kw}CxnGBC#y?T`Z(D(1(dCceYk=<@5S(a&TZjQ$zkq7~xwY4>_ zm5mzn`FtgNd~9!T^XncS9`gF9PoI(`NqHY1*{rUvlGEwrb=R(4&r z5()VIe%!cm!?No%H8okLbrvNxMIw{dIKg&5;4Z;;NXC7Y#3uyQBk3(%l^i5aBz?qW5gJvH#2C|T>KJ1r%QCM~6oq23 z7|(Zhc2akDx8|Js`g*FWsxsVY-n@B}7-RJL^JgA=|NcDz;Bz1%T3%k}>oztv#^dVi zxjL$pVX{KTnLYV&`t&6fT#GjOg$0*VMV)Zra=1Gpr>ddj9;m;jX%)ql3qD z7dp2WMNw#NZB0`X4u=g5bl!36)-A(+TUuH)b-AV``u97Q;o)I^?DcvLO_9sk*qBCp zYHBKP?ds|(DT<=0fAQjlVQo==?5Z=&V)Ua|DwRSyoz}!;S->4OEQQD<2m&h2ZZ){F9A9hcJaehcJaehcJaehcJaehcJae hhcJaehcJae$3NjrTwS|vRDb{g002ovPDHLkV1hD?)F%J{ literal 0 HcmV?d00001 diff --git a/assets/images/toggle_menu_view_example1.gif b/assets/images/toggle_menu_view_example1.gif new file mode 100644 index 0000000000000000000000000000000000000000..3944f658ce9ea9a512c6a9c3946205719fa47ffd GIT binary patch literal 3639 zcmeI!`8(9_8VB%u#%#74VltL*)-WM!M(d0%q#9#s2n`AeDT-3j5MzsyWIJ{VX$XlD z!^uv=5Ti}#+n!2X<&^K|T<3@L51i{dKYV+x*Kf}+&+}Z*`@Zj;_O?_DA3RDImQY53 ztQ9~3pin3@fEYqd3XuS+GK8SPNh;e18mu{W!tuG z+W~g$*g*rJ)9ID~RshxrYinBoTU*_Y6?2m}ZW z3=9GY1_%iW2?YoZ4Lu4F1`r+|9sv*$5pe?GB;w@B$jHbjfYYZ>M@L7W1vrN|cP<7X zCMG5p;5)6+9DGBN=&Gc&UQt^#Bu zva@q@bMpZ5^YaS;3JMAe0g8%>iUCSWN=gCB0LlR>5ET{I0V)xdl{WyY0BUP%Z{51Z zKYmv?%cW4+}zyK($d=6djJ0YwzjtR_I5s>-__OC)6>)2+uPUIH#j&rG&D3k zJS-3hMn*iJ3Bi!H}~q* zt2b}nynFZV{rmSHK79D}>C^oD{O8Y~zkK~NThSRd#s-FBC?pPQ-!WJTBofFE1o(GMkeB}*lHVcu`-X&obO?g79j~Y( zjb}w2`fJ)fBCE@tgvFNO70JbN@i68-Jga8RLFs9SdYmNB(J4dyNQi)rS2&xo+u}() z%85LX>g-`Ucx7A+)--djnGck)a%ER^u^i14V_7)5QSBU?eq6KuD#hj+TcF3iWPHh# z`;)^#HC@5QlDSEl-LwXsNnfTmLsnxgcI<+Uy!0PJx-6QHwpS8&6k<&0Sbkj@+(|W} zjDvBK8r|H^LW`;BiR&jF8hP!7^->q2#O>zS3)XSXtYj|DHH$+&S3gO?JVJEpPp8tF z6Y=z3Gr6Y`tHpf|Tc>W8xN-P6b2Fphl6SI81uyttx#f}g9EO#&=4<~-E3w)069)2G zKm7AE-9%N@wjGq}LLOsN#@f8g*Q+ClWQGXW(PR-^c0=)qVtsE=pYBa`fm2??qYom6 z0avA-)|3{S5>!`xQ6iMlcX6tQ<~y4;=~2@|iKDzVcFC0|i7)Ha&1Gox)1FU6AKmLA zB=pk~SjscrKrAt8T>X>7(p;;1riykU)>+giNHwfuP<~+UOE+(;277BXY*siTaBZ2eU&KCj+nF zToeW0`LH+@)~&zvB;s+%($lCy67jzc0f*8-`U27;2pAB%g#L%eeoPf|u5+sS4kcqSQ4sxRG0v8wB${mY}Uda=H7cq(9rBxIH%s zub!I2Lla_6zRFh@Qn!@pxo7C~Wm;wOJzHE}Ia-pWp5>E^dIsG5R2}#^LQQ7Lfiz>4 z<&if7+RVEi7hEYN;A05jnms^#fRpWWrMuMJGD^Ihgj*eY3D)rBO!i9CUSu^YNa!g0( z9M}(Q$Zi3RMK&{fXE%R)3$2dY%SK^%dttyq3s5$6PA@yMkmaKFH8owTT2LzNrrJS7PBlH^b5PoF=jdwao4x$7N&j^x6igu z%N`MW$I+K*YTi{Oo$F7f) z2Q6NjPXC#+kn|Pnuy3Kc_+&-eZCk4g@pxTFFC5S>pK6QY~JQYRz)TZIx-tk}soh|(UliuxF+sS3j^P{q+yE}=?bg@pk Qbot+DLB6!vs+ z45^s&_V&TPLkc3S7tDq23+*n~UvW*&NvYTuw0g#z%>@fZZdWmj7%(wBQvdnpQ~A#6 z*6FG%XMb4tukIJi4;w`X4gn@74h}_ymWB?CzrWx8iriMa{Cml5xvSduwSUh0^*Mi~ zg!TW8zpih6y5H&VKbs3e3M?Fq7o~-D_IlJ#vwnYg+Vwczub=kDZP11O`yvI>9I1uUsacZv}D~JYD@<);T3K0RVx=muvt4 literal 0 HcmV?d00001 diff --git a/assets/images/vertical_menu_view_example1.gif b/assets/images/vertical_menu_view_example1.gif new file mode 100644 index 0000000000000000000000000000000000000000..7366d8130dbada70680437908d58f1ad98b2c0aa GIT binary patch literal 7198 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 qQnwF69{tU|^_V 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

7h<34FTU<$wruVgQ$ci`;FTlE>QiwiTBzZu8 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 + + + + + + + + + + +Access Condition System (ACS) | ENiGMA½ BBS Software + + + + + + + + + + + + + + + + + +

+ +
+
+
+ + +
+

Access Condition System (ACS)

+

Access Condition System (ACS)

+

ENiGMA½ uses an Access Condition System (ACS) that is both familiar to oldschool BBS operators and has it’s own style. With ACS, SysOp’s are able to control access to various areas of the system based on various conditions such as group membership, connection type, etc. Various touch points in the system are configured to allow for acs checks. In some cases ACS is a simple boolean check while others (via ACS blocks) allow to define what conditions must be true for certain rights such as read and write (though others exist as well).

+ +

ACS Codes

+

The following are ACS codes available as of this writing:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CodeCondition
LCConnection is local
AGageUser’s age is >= age
ASstatus, AS[status,…]User’s account status is group or one of [group,…]
ECencodingTerminal encoding is set to encoding where 0 is CP437 and 1 is UTF-8
GM[group,…]User belongs to one of [group,…]
NNnode, NN[node,…]Current node is node or one of [node,…]
NPpostsUser’s number of message posts is >= posts
NCcallsUser’s number of calls is >= calls
SCConnection is considered secure (SSL, secure WebSockets, etc.)
THheightTerminal height is >= height
TWwidthTerminal width is >= width
TM[themeId,…]User’s current theme ID is one of [themeId,…] (e.g. luciano_blocktronics)
TT[termType,…]User’s current terminal type is one of [termType,…] (ANSI-BBS, utf8, xterm, etc.)
IDid, ID[id,…]User’s ID is id or oen of [id,…]
WDweekDay, WD[weekDay,…]Current day of week is weekDay or one of [weekDay,…] where 0 is Sunday, 1 is Monday, and so on.
AAdaysAccount is >= days old
BUbytesUser has uploaded >= bytes
UPuploadsUser has uploaded >= uploads files
BDbytesUser has downloaded >= bytes
DLdownloadsUser has downloaded >= downloads files
NRratioUser has upload/download count ratio >= ratio
KRratioUser has a upload/download byte ratio >= ratio
PCratioUser has a post/call ratio >= ratio
MMminutesIt is currently >= minutes past midnight (system time)
ACachievementCountUser has >= achievementCount achievements
APachievementPointsUser has >= achievementPoints achievement points
AFauthFactorUser’s current Authentication Factor is >= authFactor. Authentication factor 1 refers to username + password (or PubKey) while factor 2 refers to 2FA such as One-Time-Password authentication.
ARauthFactorReqCurrent user requires an Authentication Factor >= authFactorReq
PV[name,_value]Checks that the property by name for the current user is exactly value. This ACS allows arbitrary user property values to be checked. For example, PV[message_conf,local] checks that the user is currently in the “local” message conference.
+ +

ACS Strings

+

ACS strings are one or more ACS codes in addition to some basic language semantics.

+ +

The following logical operators are supported:

+
    +
  • ! NOT
  • +
  • | OR
  • +
  • & AND (this is the default)
  • +
+ +

ENiGMA½ also supports groupings using ( and ). Lastly, some ACS codes allow for lists of acceptable values using [ and ] — for example, GM[users,sysops].

+ +

Example ACS Strings

+
    +
  • NC2: User must have called two more more times for the check to return true (to pass)
  • +
  • ID1: User must be ID 1 (the +op)
  • +
  • GM[elite,power]: User must be a member of the elite or power user group (they could be both)
  • +
  • ID1|GM[co-op]: User must be ID 1 (SysOp!) or belong to the co-op group
  • +
  • !TH24: Terminal height must NOT be 24
  • +
+ +

ACS Blocks

+

Some areas of the system require more than a single ACS string. In these situations an ACS block is used to allow for finer grain control. As an example, consider the following file area acs block:

+
acs: {
+    read: GM[users]
+    write: GM[sysops,co-ops]
+    download: GM[elite-users]
+}
+
+ +

All users can read (see) the area, sysops and co-ops can write (upload), and only members of the elite-users group can download.

+ +

ACS Touch Points

+

The following touch points exist in the system. Many more are planned:

+ + + +

See the specific areas documentation for information on available ACS checks.

+ +
+ + +
+
+
+
+ + + + diff --git a/configuration/archivers.html b/configuration/archivers.html new file mode 100644 index 00000000..9579c623 --- /dev/null +++ b/configuration/archivers.html @@ -0,0 +1,2350 @@ + + + + + + + + + + + +Archivers | ENiGMA½ BBS Software + + + + + + + + + + + + + + + + + +
+ +
+
+
+ + +
+

Archivers

+

Archivers

+

ENiGMA½ can detect and process various archive formats such as zip and arj for a variety of tasks from file upload processing to EchoMail bundle compress/decompression. The archives section of config.hjson is used to override defaults, add new handlers, and so on.

+ +

Archivers are manged via the archives:archivers configuration block of config.hjson. Each entry in this section defines an external archiver that can be referenced in other sections of config.hjson as and in code. Entries define how to compress, decompress (a full archive), list, and extract (specific files from an archive).

+ +

:bulb: Generally you do not need to anything beyond installing supporting binaries. No config.hjson editing necessary; Please see External Binaries!

+ +

Archiver Configuration

+

Archiver entries in config.hjson are mostly self explanatory with the exception of list commands that require some additional information. The args member for an entry is an array of arguments to pass to cmd. Some variables are available to args that will be expanded by the system:

+ +
    +
  • +{archivePath} (all): Path to the archive
  • +
  • +{fileList} (compress, extract): List of file(s) to compress or extract
  • +
  • +{extractPath} (decompress, extract): Path to extract to +
  • +
+ +

For list commands, the entryMatch key must be provided. This key should provide a regular expression that matches two sub groups: One for uncompressed file byte sizes (sub group 1) and the other for file names (sub group 2). An optional entryGroupOrder can be supplied to change the default sub group order.

+ +

Example Archiver Configuration

+
7Zip: {
+	compress: {
+		cmd: 7za,
+		args: [ "a", "-tzip", "{archivePath}", "{fileList}" ]
+	}
+	decompress: {
+		cmd: 7za,
+		args: [ "e", "-o{extractPath}", "{archivePath}" ]
+	}
+	list: {
+		cmd: 7za,
+		args: [ "l", "{archivePath}" ]
+		entryMatch: "^[0-9]{4}-[0-9]{2}-[0-9]{2}\\s[0-9]{2}:[0-9]{2}:[0-9]{2}\\s[A-Za-z\\.]{5}\\s+([0-9]+)\\s+[0-9]+\\s+([^\\r\\n]+)$",
+	}
+	extract: {
+		cmd: 7za,
+		args [ "e", "-o{extractPath}", "{archivePath}", "{fileList}" ]
+	}
+}
+
+ +

Archive Formats

+

Archive formats can be defined such that ENiGMA½ can detect them by signature or extension, then utilize the correct archiver to process them. Formats are defined in the archives:formats key in config.hjson. Many differnet types come pre-configured (see core/config_default.js).

+ +

Example Archive Format Configuration

+
zip: {
+	sig: "504b0304" /* byte signature in HEX */
+	offset: 0
+	exts: [ "zip" ]
+	handler: 7Zip /* points to a defined archiver */
+	desc: "ZIP Archive"
+}
+
+ +
+ + +
+
+
+
+ + + + diff --git a/configuration/colour-codes.html b/configuration/colour-codes.html new file mode 100644 index 00000000..c683d783 --- /dev/null +++ b/configuration/colour-codes.html @@ -0,0 +1,2312 @@ + + + + + + + + + + + +Colour Codes | ENiGMA½ BBS Software + + + + + + + + + + + + + + + + + +
+ +
+
+
+ + +
+

Colour Codes

+

ENiGMA½ supports Renegade-style pipe colour codes for formatting strings. You’ll see them used throughout your configuration, and can also be used in places like onelinerz, rumourz, full screen editor etc.

+ +

Usage

+

When ENiGMA½ encounters colour codes in strings, they’ll be processed in order and combined where possible.

+ +

For example:

+ +

|15|17Example - white text on a blue background

+ +

|10|23Example - light green text on a light grey background

+ +

Colour Code Reference

+ +

:warning: Colour codes |24 to |31 are considered “blinking” or “iCE” colour codes. On terminals that support them they’ll +be shown as the correct colours - for terminals that don’t, or are that are set to “blinking” mode - they’ll blink!

+ +

Renegade style colour codes

+ + +
+ + +
+
+
+
+ + + + diff --git a/configuration/config-files.html b/configuration/config-files.html new file mode 100644 index 00000000..9b69fa5a --- /dev/null +++ b/configuration/config-files.html @@ -0,0 +1,2490 @@ + + + + + + + + + + + +Configuration Files | ENiGMA½ BBS Software + + + + + + + + + + + + + + + + + +
+ +
+
+
+ + +
+

Configuration Files

+

General Information

+

ENiGMA½ configuration files such as the system config, menus and themes are formatted in the HJSON format.

+ +

Hot-Reload

+

Nearly all of ENiGMA½’s configuration can be hot-reloaded. That is, a live system can have it’s configuration modified and it will be loaded in place.

+ +

:bulb: Monitoring live logs is useful when making live changes. The system will complain if something is wrong!

+ +

Common Directives

+

Includes

+

Most configuration files offer an includes directive that allows users to break up large configuration files into smaller and organized parts. For example, consider a system with many menus/screens. Instead of a single menu.hjson, the SysOp may break this into message-base.hjson, file-base.hjson, etc.

+ +

The includes directive may be used the top-level scope of a configuration file:

+
// menu.hjson
+{
+    includes: [
+        message-base.hjson
+        file-base.hjson
+    ]
+
+    menus: {
+        someOtherMenu: {
+            // ...
+        }
+    }
+}
+
+
// message-base.hjson
+{
+    menus: {
+        someMessageMenu: {
+            // ...
+        }
+    }
+}
+
+ +

References

+

Often times in a configuration you will find that you’re repeating yourself quite a bit. ENiGMA½ provides an @reference that can help with this in the form of @reference:dot.path.to.section.

+ +

Consider actionKeys in a menu. Often times you may show a screen and the user presses Q or ESC to fall back to the previous. Instead of repeating this in many menus, a generic block can be referenced:

+ +
{
+    //  note that 'recycle' here is arbitrary;
+    //  only 'menus' and 'prompts' is reserved at this level.
+    recycle: {
+        prevMenu: [
+            {
+                keys: [ "escape" ]
+                action: @systemMethod:prevMenu
+            }
+        ]
+    }
+
+    menus: {
+        someMenu: {
+            form: {
+                0: {
+                    actionKeys: @reference:recycle.prevMenu
+                }
+            }
+        }
+    }
+}
+
+ +

:information_source: An unresolved @reference will be left intact.

+ +

Environment Variables

+

Especially in a container environment such as Docker, environment variable access in configuration files can become very handy. ENiGMA½ provides a flexible way to access variables using the @environment directive. The most basic form of @environment:VAR_NAME produces a string value. Additionally a :type suffix can be supplied to coerece the value to a particular type. Variables pointing to a comma separated list can be turned to arrays using an additional :array suffix.

+ +

Below is a table of the various forms:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FormVariable ValueProduces
@environment:SOME_VAR“Foo” +"Foo" (without quotes)
@environment:SOME_VAR“123” +"123" (without quotes)
@environment:SOME_VAR:string“Bar” +"Bar" (without quotes)
@environment:SOME_VAR:string:array“Foo,Bar”[ 'Foo', 'Bar' ]
@environment:SOME_VAR:boolean“1”true
@environment:SOME_VAR:boolean“True”true
@environment:SOME_VAR:boolean“false”false
@environment:SOME_VAR:boolean“cat”false
@environment:SOME_VAR:boolean:array“True,false,TRUE”[ true, false, true ]
@environment:SOME_VAR:number“123”123
@environment:SOME_VAR:number:array“123,456”[ 123, 456 ]
@environment:SOME_VAR:number“kitten”(invalid)
@environment:SOME_VAR:object’{“a”:”b”}’{ 'a' : 'b' }
@environment:SOME_VAR:object:array’{“a”:”b”},{“c”:”d”}’[ { 'a' : 'b' }, { 'c' : 'd' } ]
@environment:SOME_VAR:timestamp“2020-01-05”A moment object representing 2020-01-05
@environment:SOME_VAR:timestamp:array“2020-01-05,2016-05-16T01:15:37’”An array of moment objects representing 2020-01-05 and 2016-05-16T01:15:37
+ +

:bulb: bool may be used as an alias to boolean.

+ +

:bulb: timestamp values can be in any form that moment can parse.

+ +

:information_source: An unresolved or invalid @environment will be left intact.

+ +

Consider the following fragment:

+
{
+    foo: {
+        bar: @environment:BAR_VAR:number
+    }
+}
+
+ +

If the environment has BAR_VAR=1337, this would produce:

+
{
+    foo: {
+        bar: 1337
+    }
+}
+
+ +

See Also

+ + +
+ + +
+
+
+
+ + + + diff --git a/configuration/config-hjson.html b/configuration/config-hjson.html new file mode 100644 index 00000000..131fd86a --- /dev/null +++ b/configuration/config-hjson.html @@ -0,0 +1,2344 @@ + + + + + + + + + + + +System Configuration | ENiGMA½ BBS Software + + + + + + + + + + + + + + + + + +
+ +
+
+
+ + +
+

System Configuration

+

System Configuration

+

The main system configuration file, config.hjson both overrides defaults and provides additional configuration such as message areas. Defaults lived in core/config_default.js.

+ +

The default path is /enigma-bbs/config/config.hjson though this can be overridden using the --config parameter when invoking main.js.

+ +

:information_source: See also Configuration Files. Additionally HJSON General Information may be helpful for more information on the HJSON format.

+ +

Creating a Configuration

+

Your initial configuration skeleton should be created using the oputil.js command line utility. From your enigma-bbs root directory:

+
./oputil.js config new
+
+ +

You will be asked a series of questions to create an initial configuration.

+ +

Overriding Defaults

+

The file core/config_default.js provides various defaults to the system that you can override via config.hjson. For example, the default system name is defined as follows:

+
general : {
+  boardName : 'Another Fine ENiGMA½ System'
+}
+
+ +

To override this for your own board, in config.hjson:

+
general: {
+  boardName: Super Fancy BBS
+}
+
+ +

(Note the very slightly HJSON different syntax. You can use standard JSON if you wish!)

+ +

While not everything that is available in your config.hjson file can be found defaulted in core/config_default.js, a lot is. Poke around and see what you can find!

+ +

Configuration Sections

+

Below is a list of various configuration sections. There are many more, but this should get you started:

+ + + + +
+ + +
+
+
+
+ + + + diff --git a/configuration/creating-config.html b/configuration/creating-config.html new file mode 100644 index 00000000..a13abfec --- /dev/null +++ b/configuration/creating-config.html @@ -0,0 +1,2303 @@ + + + + + + + + + + + +Creating Initial Config Files | ENiGMA½ BBS Software + + + + + + + + + + + + + + + + + +
+ +
+
+
+ + +
+

Creating Initial Config Files

+

Configuration files in ENiGMA½ are simple UTF-8 encoded HJSON files. HJSON is just like JSON but simplified and much more resilient to human error.

+ +

Initial Configuration

+

Your initial configuration skeleton can be created using the oputil.js command line utility. From your enigma-bbs root directory:

+
./oputil.js config new
+
+ +

You will be asked a series of questions to create an initial configuration, which will be saved to /enigma-bbs-install-path/config/config.hjson. This will also produce menu files under config/menus/. See Menu HJSON for more information.

+ + +
+ + +
+
+
+
+ + + + diff --git a/configuration/directory-structure.html b/configuration/directory-structure.html new file mode 100644 index 00000000..5b818dc3 --- /dev/null +++ b/configuration/directory-structure.html @@ -0,0 +1,2362 @@ + + + + + + + + + + + +Directory Structure | ENiGMA½ BBS Software + + + + + + + + + + + + + + + + + +
+ +
+
+
+ + +
+

Directory Structure

+

All paths mentioned here are relative to the ENiGMA½ checkout directory.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
DirectoryDescription
/art/generalNon-theme art - welcome ANSI, logoff ANSI, etc. See General Art.
/art/themesTheme art. Themes should be in their own subdirectory and contain a theme.hjson. See Themes.
/configconfig.hjson system configuration.
/config/menusmenu.hjson storage.
/config/securitySSL certificates and public/private keys.
/dbAll ENiGMA½ databases in SQLite3 format.
/docsThese docs ;-)
/dropfilesDropfiles created for local doors
/logsLogs. See Monitoring Logs
/miscStuff with no other home; reset password templates, common password lists, other random bits
/modsUser mods. See Modding
/node_modulesExternal libraries required by ENiGMA½, installed when you run npm install
/utilVarious tools used in running/debugging ENiGMA½
/wwwENiGMA½’s built in webserver root directory
+ +
+ + +
+
+
+
+ + + + diff --git a/configuration/email.html b/configuration/email.html new file mode 100644 index 00000000..dc5238a9 --- /dev/null +++ b/configuration/email.html @@ -0,0 +1,2337 @@ + + + + + + + + + + + +Email | ENiGMA½ BBS Software + + + + + + + + + + + + + + + + + +
+ +
+
+
+ + +
+

Email

+

Email Support

+

ENiGMA½ uses email to send password reset information to users. For it to work, you need to provide valid Nodemailer compatible email block in your config.hjson. Nodemailer supports SMTP in addition to many pre-defined services for ease of use. The transport block within email must be Nodemailer compatible.

+ +

Additional email support will come in the near future.

+ +

Services

+ +

If you don’t have an SMTP server to send from, Sendgrid and Zoho both provide reliable and free services.

+ +

Example Configurations

+ +

Example 1 - SMTP:

+
email: {
+    defaultFrom: sysop@bbs.awesome.com
+    
+    transport: {
+        host: smtp.awesomeserver.com
+            port: 587
+            secure: false
+            auth: {
+                user: leisuresuitlarry
+                pass: sierra123
+            }
+        }
+    }
+
+ +

Example 2 - Zoho

+
email: {
+    defaultFrom: sysop@bbs.awesome.com
+
+    transport: {
+        service: Zoho
+        auth: {
+            user: noreply@bbs.awesome.com
+            pass: yuspymypass
+        }
+    }
+}
+
+ +

Lockout Reset

+

If email is available on your system and you allow email-driven password resets, you may elect to allow unlocking accounts at the time of a password reset. This is controlled by the users.unlockAtEmailPwReset configuration option. If an account is locked due to too many failed login attempts, a user may reset their password to remedy the situation themselves.

+ +
+ + +
+
+
+
+ + + + diff --git a/configuration/event-scheduler.html b/configuration/event-scheduler.html new file mode 100644 index 00000000..6d18e253 --- /dev/null +++ b/configuration/event-scheduler.html @@ -0,0 +1,2396 @@ + + + + + + + + + + + +Event Scheduler | ENiGMA½ BBS Software + + + + + + + + + + + + + + + + + +
+ +
+
+
+ + +
+

Event Scheduler

+

Event Scheduler

+

The ENiGMA½ scheduler allows system operators to configure arbitrary events that can can fire based on date and/or time, or by watching for changes in a file. Events can kick off internal handlers, custom modules, or binaries & scripts.

+ +

Scheduling Events

+

To create a scheduled event, create a new configuration block in config.hjson under eventScheduler.events.

+ +

Events can have the following members:

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
ItemRequiredDescription
schedule:+1:A Later style parsable schedule string such as at 4:00 am, or every 24 hours. Can also be (or contain) an @watch clause. See Schedules below for details.
action:+1:Action to perform when the schedule is triggered. May be an @method or @execute spec. See Actions below.
args:-1:An array of arguments to pass along to the method or binary specified in action.
+ +

Schedules

+

As mentioned above, schedule may contain a Later style parsable schedule string and/or an @watch clause.

+ +

schedule examples:

+
    +
  • every 2 hours
  • +
  • on the last day of the week
  • +
  • after 12th hour
  • +
+ +

An @watch clause monitors a specified file for changes and takes the following form: @watch:<path> where <path> is a fully qualified path.

+ +

:bulb: If you would like to have a schedule and watch a file for changes, place the @watch clause second and separated with the word or. For example: every 24 hours or @watch:/path/to/somefile.txt.

+ +

Actions

+

Events can kick off actions by calling a method (function) provided by the system or custom module in addition to executing arbritary binaries or scripts.

+ +

Methods

+

An action with a @method can take the following forms:

+ +
    +
  • +@method:/full/path/to/module.js:methodName: Executes methodName at /full/path/to/module.js.
  • +
  • +@method:rel/path/to/module.js:methodName: Executes methodName using the relative path rel/path/to/module.js. Paths for @method are relative to the ENiGMA½ installation directory.
  • +
+ +

Methods are passed any supplied args in the order they are provided.

+ +
Method Signature
+

To create your own method, simply export a method with the following signature: (args, callback). Methods are executed asynchronously.

+ +

Example:

+
// my_custom_mod.js
+exports.myCustomMethod = (args, cb) => {
+    console.log(`Hello, ${args[0]}!`);
+    return cb(null);
+}
+
+ +

Executables

+

When using the @execute action, a binary or script can be executed. A full path or just the binary name is acceptable. If using the form without a path, the binary much be in ENiGMA½’s PATH.

+ +

Examples:

+
    +
  • @execute:/usr/bin/foo
  • +
  • @execute:foo
  • +
+ +

Just like with methods, any supplied args will be passed along.

+ +

Example Entries

+ +

Post a message to supplied networks every Monday night using the message post mod (see modding):

+
eventScheduler: {
+    events: {
+        enigmaAdToNetworks: {
+            schedule: at 10:35 pm on Mon
+            action: @method:mods/message_post_evt/message_post_evt.js:messagePostEvent
+            args: [
+                "fsx_bot"
+                "/home/enigma-bbs/ad.asc"
+            ]
+        }
+    }
+}
+
+ +
+ + +
+
+
+
+ + + + diff --git a/configuration/external-binaries.html b/configuration/external-binaries.html new file mode 100644 index 00000000..ab53612c --- /dev/null +++ b/configuration/external-binaries.html @@ -0,0 +1,2451 @@ + + + + + + + + + + + +External Support Binaries | ENiGMA½ BBS Software + + + + + + + + + + + + + + + + + +
+ +
+
+
+ + +
+

External Support Binaries

+

External Support Binaries

+

ENiGMA½ relies on various external binaries in order to perform common tasks such as processing file archives and extracting information from uploads/file imports, some legacy transfer protocols, etc.

+ +

:correct: Before using features such as the File Base or File Transfer Protocols it is highly recommended to install support binaries!

+ +

Archivers

+

Below is a table of pre-configured archivers. Remember that you can override settings or add new handlers! See Archivers.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Archiver (Key)File TypesMore InfoDebian/Ubuntu (apt/dep)Red Hat (yum/rpm)Windows
Arj.arjWikipediaarjarjARJ
7Zip.7z, .bzip2, .gzip/.gz, etc.
:warning: Does not attempt to handle zip files! See InfoZip!
http://www.7-zip.orgp7zip-fullp7zip-full7-zip
InfoZip.ziphttp://infozip.sourceforge.net
zip and unzip will need to be en ENiGMA’s PATH
+zip and unzip + +zip and unzip +InfoZip
Lha.lza, .lzh, etc. +Wikipedia
https://fragglet.github.io/lhasa/
lhasalhasaWin32 binaries
Lzx.lzxAmiga LZXunlzxunlzxSource
Rar.rarWikipediaunrarunrarRARLAB
TarGz.tar.gz, .gzipWikipediatartarTAR.EXE
+ +

:information_source: For more information see core/config_default.js

+ +

:information_source: For information on changing configuration or adding more archivers see Archivers.

+ +

File Transfer Protocols

+

Handlers for legacy file transfer protocols such as Z-Modem and Y-Modem.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Handler (Key)ProtocolMore InfoDebian/Ubuntu (apt/dep)Red Hat (yum/rpm)Windows
+xmodemSexyz
ymodemSexyz
zmodem8kSexyz +
X-Modem, Y-Modem and Z-Modem SEXYZSEXYZx86_64 Binaryx86_64 BinarySynchronet FTP
zmodem8kSzZ-Modem 8KWikipedialrzszlrzszUnknown
+ +

Information Extractors

+

Information extraction utilities can extract information from various file types such as PDF in order to (attempt) to come up with a good default description.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ExtractorFile TypesMore InfoDebian/Ubuntu (apt/dep)Red Hat (yum/rpm)Windows
ExifTool.mp3, .pdf, .mp4, .jpg, .gif, .png, many moreExifToollibimage-exiftool-perlperl-Image-ExifToolUnknown
XDMSAmiga DiskMasher images xdmsxdmsUnknown
+ +
+ + +
+
+
+
+ + + + diff --git a/configuration/file-transfer-protocols.html b/configuration/file-transfer-protocols.html new file mode 100644 index 00000000..3959fb5c --- /dev/null +++ b/configuration/file-transfer-protocols.html @@ -0,0 +1,2344 @@ + + + + + + + + + + + +File Transfer Protocols | ENiGMA½ BBS Software + + + + + + + + + + + + + + + + + +
+ +
+
+
+ + +
+

File Transfer Protocols

+

ENiGMA½ currently relies on external executable binaries for “legacy” file transfer protocols such as X, Y, and ZModem. Remember that ENiGMA½ also support modern web (HTTP/HTTPS) downloads!

+ +

File Transfer Protocols

+

File transfer protocols are managed via the fileTransferProtocols configuration block of config.hjson. Each entry defines an external protocol handler that can be used for uploads (recv), downloads (send), or both. Depending on the protocol and handler, batch receiving of files (uploads) may also be available.

+ +

Predefined File Transfer Protocols

+

Please see External Binaries for a table of built in / predefined protocol handlers. You will need to have the binaries in ENiGMA’s PATH.

+

SEXYZ

+

SEXYZ from Synchronet offers a nice X, Y, and ZModem implementation including ZModem-8k & works under *nix and Windows based systems. As of this writing, ENiGMA½ is pre-configured to support ZModem-8k, XModem, and YModem using SEXYZ. An x86_64 Linux binary, and hopefully more in the future, can be downloaded here.

+ +

sz/rz

+

ZModem-8k is configured using the standard Linux sz(1) and rz(1) binaries. Note that these binaries also support XModem and YModem, and as such adding the configurations to your system should be fairly straight forward.

+ +

Generally available as lrzsz under Apt or Yum type packaging.

+ +

File Transfer Protocol Configuration

+

The following top-level members are available to an external protocol configuration:

+
    +
  • name: Required; Display name of the protocol
  • +
  • type: Required; Currently must be external. This will be expanded upon in the future with built in protocols.
  • +
  • sort: Optional; Sort key. If not provided, name will be used for sorting.
  • +
+ +

For protocols of type external the following members may be defined:

+
    +
  • sendCmd: Required for protocols that can send (allow user downloads); The command/binary to execute.
  • +
  • sendArgs: Required if using sendCmd; An array of arguments. A placeholder of {fileListPath} may be used to supply a path to a file containing a list of files to send, or {filePaths} to supply 1:n individual file paths to send.
  • +
  • recvCmd: Required for protocols that can receive (allow user uploads); The command/binary to execute.
  • +
  • recvArgs: Required if using recvCmd and supporting batch uploads; An array of arguments. A placeholder of {uploadDir} may be used to supply the system provided upload directory. If {uploadDir} is not present, the system expects uploaded files to be placed in CWD which will be set to the upload directory.
  • +
  • recvArgsNonBatch: Required if using recvCmd and supporting non-batch (single file) uploads; A placeholder of {fileName} may be supplied to indicate to the protocol what the uploaded file should be named (this will be collected from the user before the upload starts).
  • +
  • escapeTelnet: Optional; If set to true, escape all internal Telnet related codes such as IAC’s. This option is required for external protocol handlers such as sz and rz that do not escape themselves.
  • +
+ +

Adding Your Own

+

Take a look a the example below as well as core/config_default.js.

+ +

Example File Transfer Protocol Configuration

+
zmodem8kSexyz : {
+    name		: 'ZModem 8k (SEXYZ)',
+    type		: 'external',
+    sort		: 1,
+    external	: {
+        sendCmd             : 'sexyz',
+        sendArgs            : [ '-telnet', '-8', 'sz', '@{fileListPath}' ],
+        recvCmd             : 'sexyz',
+        recvArgs            : [ '-telnet', '-8', 'rz', '{uploadDir}' ],
+        recvArgsNonBatch    : [ '-telnet', '-8', 'rz', '{fileName}' ],
+    }
+}
+
+ +
+ + +
+
+
+
+ + + + diff --git a/configuration/hjson.html b/configuration/hjson.html new file mode 100644 index 00000000..2d1b8121 --- /dev/null +++ b/configuration/hjson.html @@ -0,0 +1,2369 @@ + + + + + + + + + + + +HJSON Config Files | ENiGMA½ BBS Software + + + + + + + + + + + + + + + + + +
+ +
+
+
+ + +
+

HJSON Config Files

+

JSON for Humans!

+

HJSON is the configuration file format used by ENiGMA½ for System Configuration, Menus, etc. HJSON is is JSON for humans!

+ +

For those completely unfamiliar, JSON stands for JavaScript Object Notation. But don’t let that scare you! JSON is simply a text file format with a bit of structure ― kind of like a fancier INI file. HJSON on the other hand as mentioned previously, is JSON for humans. That is, it has the following features and more:

+ +
    +
  • More resilient to syntax errors such as missing a comma
  • +
  • Strings generally do not need to be quoted. Multi-line strings are also supported!
  • +
  • Comments are supported (JSON doesn’t allow this!): #, // and /* ... */ style comments are allowed.
  • +
  • Keys never need to be quoted
  • +
  • …much more! See the official HJSON website.
  • +
+ +

Terminology

+

Through the documentation, some terms regarding HJSON and configuration files will be used:

+ +
    +
  • +config.hjson: Refers to /path/to/enigma-bbs/config/config.hjson. See System Configuration.
  • +
  • +menu.hjson: Refers to /path/to/enigma-bbs/config/<yourBBSName>-menu.hjson. See Menus.
  • +
  • Configuration key: Elements in HJSON are name-value pairs where the name is the key. For example, provided foo: bar, foo is the key.
  • +
  • Configuration section or block (also commonly called an “Object” in code): This is referring to a section in a HJSON file that starts with a key. For example: +
    someSection: {
    +  foo: bar
    +}
    +
    +

    Note that someSection is the configuration section (or block) and foo: bar is within it.

    +
  • +
+ +

Editing HJSON

+

HJSON is a text file format, and ENiGMA½ configuration files should always be saved as UTF-8.

+ +

It is highly recommended to use a text editor that has HJSON support. A few (but not all!) examples include:

+ + +

See https://hjson.org/users.html for more more editors & plugins.

+ +

Hot-Reload A.K.A. Live Editing

+

ENiGMA½’s configuration, menu, and theme files can edited while your BBS is running. When a file is saved, it is hot-reloaded into the running system. If users are currently connected and you change a menu for example, the next reload of that menu will show the changes.

+ +

:information_source: See also Configuration Files

+ +

CaSe SeNsiTiVE

+

Configuration keys are case sensitive. That means if a configuration key is boardName for example, boardname, or BOARDNAME will not work.

+ +

Escaping

+

Some values need escaped. This is especially important to remember on Windows machines where file paths contain backslashes (\). To specify a path to C:\foo\bar\baz.exe for example, an entry may look like this in your configuration file:

+
something: {
+    path: "C:\\foo\\bar\\baz.exe" // note the extra \'s!
+}
+
+ +

Tips & Tricks

+

JSON Compatibility

+

Remember that standard JSON is fully compatible with HJSON. If you are more comfortable with JSON (or have an editor that works with JSON that you prefer) simply convert your config file(s) to JSON and use that instead!

+ +

HJSON can be converted to JSON with the hjson CLI:

+
cd /path/to/enigma-bbs
+cp ./config/config.hjson ./config/config.hjson.backup
+./node_modules/hjson/bin/hjson ./config/config.hjson.backup -j > ./config/config.hjson
+
+ +

You can always convert back to HJSON by omitting -j in the command above.

+ +

oputil

+

You can easily dump out your current configuration in a pretty-printed style using oputil: ./oputil.js config cat

+ +
+ + +
+
+
+
+ + + + diff --git a/configuration/menu-hjson.html b/configuration/menu-hjson.html new file mode 100644 index 00000000..0a491bc4 --- /dev/null +++ b/configuration/menu-hjson.html @@ -0,0 +1,2778 @@ + + + + + + + + + + + +Menu HSJON | ENiGMA½ BBS Software + + + + + + + + + + + + + + + + + +
+ +
+
+
+ + +
+

Menu HSJON

+ +

The core of a ENiGMA½ based BBS is it’s menus driven by what will be referred to as menu.hjson. Throughout ENiGMA½ documentation, when menu.hjson is referenced, we’re actually talking about config/menus/yourboardname-*.hjson. These files determine the menus (or screens) a user can see, the order they come in, how they interact with each other, ACS configuration, and so on. Like all configuration within ENiGMA½, menu configuration is done in HJSON format.

+ +

:information_source: See also HJSON General Information for more information on the HJSON file format.

+ +

:bulb: Entries in menu.hjson are often referred to as blocks or sections. Each entry defines a menu. A menu in this sense is something the user can see or visit. Examples include but are not limited to:

+ +
    +
  • Classical navigation and menus such as Main, Messages, and Files.
  • +
  • Art file display.
  • +
  • Module driven menus such as door launchers, Onelinerz, and other custom mods.
  • +
+ +

Menu entries live under the menus section of menu.hjson. The key for a menu is it’s name that can be referenced by other menus and areas of the system.

+ +

Below is a very basic menu entry called showSomeArt that displays some art then returns to the previous menu after the user hits a key:

+
showSomeArt: {
+  art: someart.ans
+  config: { pause: true }
+}
+
+

As you can see a menu can be very simple.

+ +

:information_source: Remember that the top level menu may include additional files using the includes directive. See Configuration Files for more information on this.

+ +

Common Menu Entry Members

+

Below is a table of common menu entry members. These members apply to most entries, though entries that are backed by a specialized module (ie: module: bbs_list) may differ. Menus that use their own module contain a module declaration:

+ +
module: some_fancy_module
+
+ +

See documentation for the module in question for particulars.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ItemDescription
descA friendly description that can be found in places such as “Who’s Online” or wherever the %MD MCI code is used.
artAn art file spec. See General Art Information.
nextSpecifies the menu to go to next. Can be explicit or an array of possibilities dependent on ACS. See Flow Control in the ACS Checks section below. If next is not supplied, the next menu is this menus parent. Note that special built in methods such as @systemMethod:logoff can also be utilized here.
promptSpecifies a prompt, by name, to use along with this menu. Prompts are configured in the prompts section. See Prompts for more information.
submitDefines a submit handler when using prompt.
formAn object defining one or more forms available on this menu.
moduleSets the module name to use for this menu. The system ships with many build in modules or you can build your own!
configAn object containing additional configuration. See Config Block below.
+ +

Config Block

+

The config block for a menu entry can contain common members as well as a per-module (when module is used) settings.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ItemDescription
clsIf true the screen will be cleared before showing this menu.
pauseIf true a pause will occur after showing this menu. Useful for simple menus such as displaying art or status screens.
nextTimeoutSets the number of milliseconds before the system will automatically advanced to the next menu.
baudRateSee baud rate information in General Art Information.
fontSets a SyncTERM style font to use when displaying this menus art. See font listing in General Art Information.
menuFlagsAn array of menu flag(s) controlling menu behavior. See Menu Flags below.
+ + +

The menuFlags field of a config block can change default behavior of a particular menu.

+ + + + + + + + + + + + + + + + + + + + + + +
FlagDescription
noHistoryPrevents the menu from remaining in the menu stack / history. When this flag is set, when the next menu falls back, this menu will be skipped and the previous menu again displayed instead. Example: menuA -> menuB(noHistory) -> menuC: Exiting menuC returns the user to menuA.
popParentWhen this menu is exited, fall back beyond the parent as well. Often used in combination with noHistory.
forwardArgsIf set, when the next menu is entered, forward any extraArgs arguments to this menu on to it.
+ +

Forms

+

ENiGMA½ uses a concept of forms in menus. A form is a collection of associated views. Consider a New User Application using the nua module: The default implementation utilizes a single form with multiple EditTextView views, a submit button, etc. Forms are identified by number starting with 0. A given menu may have mutiple forms (often associated with different states or screens within the menu).

+ +

Menus may also support more than one layout type by using a MCI key. A MCI key is a alpha-numerically sorted key made from 1:n MCI codes. This lets the system choose the appropriate set of form(s) based on theme or random art. An example of this may be a matrix menu: Perhaps one style of your matrix uses a vertical light bar (VM key) while another uses a horizontal (HM key). The system can discover the correct form to use by matching MCI codes found in the art to that of the available forms defined in menu.hjson.

+ +

For more information on views and associated MCI codes, see MCI Codes.

+ +

Submit Handlers

+

When a form is submitted, it’s data is matched against a submit handler. When a match is found, it’s action is performed.

+ +

Submit Actions

+

Submit actions are declared using the action member of a submit handler block. Actions can be kick off system/global or local-to-module methods, launch other menus, etc.

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
ActionDescription
@menu:menuNameTakes the user to the menuName menu
@systemMethod:methodNameExecutes the system/global method methodName. See System Methods below.
@method:methodNameExecutes methodName local to the calling module. That is, the module set by the module member of a menu entry.
@method:/path/to/some_module.js:methodNameExecutes methodName exported by the module at /path/to/some_module.js.
+ +

Advanced Action Handling

+

In addition to simple simple actions, action may also be:

+
    +
  • An array of objects containing ACS checks and a sub action if that ACS is matched. See Action Matches in the ACS documentation below for details.
  • +
  • An array of actions. In this case a random selection will be made. Example: +
    submit: [
    +  {
    +      value: { command: "FOO" }
    +      action: [
    +          // one of the following actions will be matched:
    +          "@menu:menuStyle1"
    +          "@menu:menuStyle2"
    +      ]
    +  }
    +]
    +
    +
  • +
+ +

Method Signature

+

Methods executed using @method, or @systemMethod have the following signature:

+
(callingMenu, formData, extraArgs, callback)
+
+ +

System Methods

+

Many built in global/system methods exist. Below are a few. See system_menu_method for more information.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodDescription
loginPerforms a standard login.
login2FA_OTPPerforms a 2-Factor Authentication (2FA) One-Time Password (OTP) check, if configured for the user.
logoffPerforms a standard system logoff.
prevMenuGoes to the previous menu.
nextMenuGoes to the next menu (as set by next)
prevConfSets the users message conference to the previous available.
nextConfSets the users message conference to the next available.
prevAreaSets the users message area to the previous available.
nextAreaSets the users message area to the next available.
+ +

Example

+

Let’s look a couple basic menu entries:

+ +
telnetConnected: {
+    art: CONNECT
+    next: matrix
+    config: { nextTimeout: 1500 }
+}
+
+ +

The above entry telnetConnected is set as the Telnet server’s first menu entry (set by firstMenu in the Telnet server’s config). The entry sets up a few things:

+
    +
  • A art spec of CONNECT. (See General Art Information).
  • +
  • A next entry up the next menu, by name, in the stack (matrix) that we’ll go to after telnetConnected.
  • +
  • An config block containing a single nextTimeout field telling the system to proceed to the next (matrix) entry automatically after 1500ms.
  • +
+ +

Now let’s look at matrix, the next entry from telnetConnected:

+ +
matrix: {
+    art: MATRIX
+    desc: Login Matrix
+    form: {
+        0: {
+            //
+            //  Here we have a MCI key of "VM". In this case we could
+            //  omit this level since no other keys are present.
+            //
+            VM: {
+                mci: {
+                    VM1:  {
+                        submit: true
+                        focus:  true
+                        items: [ "login", "apply", "log off" ]
+                        argName: matrixSubmit
+                    }
+                }
+                submit: {
+                    *: [
+                        {
+                            value: { matrixSubmit: 0 }
+                            action: @menu:login
+                        }
+                        {
+                            value: { matrixSubmit: 1 },
+                            action: @menu:newUserApplication
+                        }
+                        {
+                            value: { matrixSubmit: 2 },
+                            action: @menu:logoff
+                        }
+                    ]
+                }
+            }
+
+            //
+            //  If we wanted, we could declare a "HM" MCI key block here.
+            //  This would allow a horizontal matrix style when the matrix art
+            //  loaded contained a %HM code.
+            //
+        }
+    }
+}
+
+ +

In the above entry, you’ll notice form. This defines a form(s) object. In this case, a single form by ID of 0. The system is then told to use a block only when the resulting art provides a VM (VerticalMenuView) MCI entry. Some other bits about the form:

+ +
    +
  • +VM1 is then setup to submit and start focused via focus: true as well as have some menu entries (“login”, “apply”, …) defined. We provide an argName of matrixSubmit for this element view.
  • +
  • The submit object tells the system to attempt to apply provided match entries from any view ID (*).
  • +
  • Upon submit, the first match will be executed. For example, if the user selects “login”, the first entry with a value of { matrixSubmit: 0 } will match (due to 0 being the first index in the list and matrixSubmit being the arg name in question) causing action of @menu:login to be executed (go to login menu).
  • +
+ +

Prompts

+

Prompts are found in the prompts section of menu files. Prompts allow for quick user input and shorthand form requirements for menus. Additionally, prompts are often used for for multiple menus. Consider a pause prompt or menu command input for example.

+ +

TODO: additional prompt docs

+ +

ACS Checks

+

Menu modules can check user ACS in order to restrict areas and perform flow control. See ACS for available ACS syntax.

+ + +

To restrict menu access add an acs key to config. Example:

+
opOnlyMenu: {
+    desc: Ops Only!
+    config: {
+        acs: ID1
+    }
+}
+
+ +

Action Matches

+

Action blocks (action) can perform ACS checks:

+
// ...
+{
+    action: [
+        {
+            acs: SC1
+            action: @menu:secureMenu
+        }
+        {
+            action: @menu:nonSecureMenu
+        }
+    ]
+}
+
+ +

Flow Control

+

The next member of a menu may be an array of objects containing an acs check as well as the destination. Depending on the current user’s ACS, the system will pick the appropriate target. The last element in an array without an acs can be used as a catch all. Example:

+
login: {
+    desc: Logging In
+    next: [
+        {
+            //	>= 2 calls else you get the full login
+            acs: NC2
+            next: loginSequenceLoginFlavorSelect
+        }
+        {
+            next: fullLoginSequenceLoginArt
+        }
+    ]
+}
+
+ +

Art Asset Selection

+

Another area in which you can apply ACS in a menu is art asset specs.

+ +
someMenu: {
+    desc: Neato Dorito
+    art: [
+        {
+            acs: GM[couriers]
+            art: COURIERINFO
+        }
+        {
+            //  show ie: EVERYONEELSE.ANS to everyone else
+            art: EVERYONEELSE
+        }
+    ]
+}
+
+ +

Case Study: Adding a Sub Menu to Main

+

A very common task: You want to add a new menu accessible from “Main”. First, let’s create a new menu called “Snazzy Town”! Perhaps under the mainMenu entry somewhere, create a new menu:

+ +
snazzyTown: {
+    desc: Snazzy Town
+    art: snazzy
+    config: {
+        cls: true
+        pause: true
+    }
+}
+
+ +

Now let’s make it accessible by “S” from the main menu. By default the main menu entry is named mainMenu. Within the mainMenu’s submit block you will see some existing action matches to “command”. Simply add a new one pointing to snazzyTown:

+ +
{
+    value: { command: "S" }
+    action: @menu:snazzyTown
+}
+
+ +

That’s it! When users type “S” at the main menu, they’ll be sent to the Snazzy Town menu. Since we did not supply additional flow logic when they exit, they will fall back to main.

+ +

Case Study: Adding a New User Password (NUP)

+

You’ve got a super 31337 board and want to prevent lamerz! Let’s run through adding a NUP to your application flow.

+ +

Given the default menu system, two “pre” new user application menus exist due to the way Telnet vs SSH logins occur. We’ll focus only on Telnet here. This menu is newUserApplicationPre. Let’s say you want to display this preamble, but then ask for the NUP. If the user gets the password wrong, show them a LAMER.ANS and boot ‘em.

+ +

First, let’s create a new menu for the NUP:

+
newUserPassword: {
+    art: NUP.ANS
+    next: newUserApplication
+    desc: NUP!
+
+    form: {
+        0: {
+            mci: {
+                ET1: {
+                    // here we create an argument/variable of "nup"
+                    argName: nup
+                    focus: true
+                    submit: true
+                }
+            }
+            submit: {
+                *: [
+                    {
+                        // if the user submits "nup" with the correct
+                        // value of "nolamerz" action will send
+                        // them to the next menu defined above --
+                        // in our case: newUserApplication
+                        value: { nup: "nolamerz" }
+                        action: @systemMethod:nextMenu
+                    }
+                    {
+                        // anything else will result in going to the badNewUserPassword menu
+                        value: { nup: null }
+                        action: @menu:badNewUserPassword
+                    }
+                ]
+            }
+        }
+    }
+}
+
+ +

Looks like we’ll need a badNewUserPassword menu as well! Let’s create a very basic menu to show art then disconnect the user.

+ +
badNewUserPassword: {
+    art: LAMER.ANS
+    // here we use a built in system method to boot them.
+    next: @systemMethod:logoff
+    config: {
+        //  wait 2s after showing the art before kicking them
+        nextTimeout: 2000
+    }
+}
+
+ +

Great, we have a couple new menus. Now let’s just point to them. Remember the existing newUserApplicationPre menu? All that is left to do is point it’s next to our newUserPassword menu:

+ +
newUserApplicationPre: {
+    //  easy! Just tell the system where to go next
+    next: newUserPassword
+    // note that the rest of this menu is omitted for clarity
+}
+
+ +
+ + +
+
+
+
+ + + + diff --git a/configuration/security.html b/configuration/security.html new file mode 100644 index 00000000..7888fa30 --- /dev/null +++ b/configuration/security.html @@ -0,0 +1,2366 @@ + + + + + + + + + + + +Security | ENiGMA½ BBS Software + + + + + + + + + + + + + + + + + +
+ +
+
+
+ + +
+

Security

+

Security

+

Unlike in the golden era of BBSing, modern Internet-connected systems are prone to hacking attempts, eavesdropping, etc. While plain-text passwords, insecure data over Plain Old Telephone Service (POTS), and so on was good enough then, modern systems must employ protections against attacks. ENiGMA½ comes with many security features that help keep the system and your users secure — not limited to:

+ + +

Two-Factor Authentication via One-Time Password

+

Enabling Two-Factor Authentication via One-Time-Password (2FA/OTP) on an account adds an extra layer of security (“something a user has”) in addition to their password (“something a user knows”). Providing 2FA/OTP to your users has some prerequisites:

+
    +
  • +A configured email gateway such that the system can send out emails.
  • +
  • One or more secure servers enabled such as SSH or secure WebSockets (that is, WebSockets over a secure connection such as TLS).
  • +
  • The web server enabled and exposed over TLS (HTTPS).
  • +
+ +

:information_source: For WebSockets and the web server, ENiGMA½ may listen on insecure channels if behind a secure web proxy.

+ +

User Registration Flow

+

Due to the nature of 2FA/OTP, even if enabled on your system, users must opt-in and enable this feature on their account. Users must also have a valid email address such that a registration link can be sent to them. To opt-in, users must enable the option, which will cause the system to email them a registration link. Following the link provides the following:

+ +
    +
  1. A secret for manual entry into a OTP device.
  2. +
  3. If applicable, a scannable QR code for easy device entry (e.g. Google Authenticator)
  4. +
  5. A confirmation prompt in which the user must enter a OTP code. If entered correctly, this validates everything is set up properly and 2FA/OTP will be enabled for the account. Backup codes will also be provided at this time. Future logins will now prompt the user for their OTP after they enter their standard password.
  6. +
+ +

:warning: Serving 2FA/OTP registration links over insecure (HTTP) can expose secrets intended for the user and is highly discouraged!

+ +

:memo: +ops can also manually enable or disable 2FA/OTP for a user using oputil, but this is generally discouraged.

+ +

Recovery

+

In the situation that a user loses their 2FA/OTP device (such as a lost phone with Google Auth), there are some options:

+
    +
  • Utilize one of their backup codes.
  • +
  • Contact the SysOp.
  • +
+ +

:warning: There is no way for a user to disable 2FA/OTP without first fully logging in! This is by design as a security measure.

+ +

ACS Checks

+

Various places throughout the system that implement ACS can make 2FA specific checks:

+
    +
  • +AR#: Current users required authentication factor. AR2 for example means 2FA/OTP is required for this user.
  • +
  • +AF#: Current users active authentication factor. AF2 means the user is authenticated with some sort of 2FA (such as One-Time-Password).
  • +
+ +

See ACS for more information.

+ +

Example

+

The following example illustrates using an AR ACS check to require applicable users to go through an additional 2FA/OTP process during login:

+ +
login: {
+    art: USERLOG
+    next: [
+        {
+            //  users with AR2+ must first pass 2FA/OTP
+            acs: AR2
+            next: loginTwoFactorAuthOTP
+        }
+        {
+            //  everyone else skips ahead
+            next: fullLoginSequenceLoginArt
+        }
+    ]
+    // ...
+}
+
+ +
+ + +
+
+
+
+ + + + diff --git a/configuration/sysop-setup.html b/configuration/sysop-setup.html new file mode 100644 index 00000000..eeb48e23 --- /dev/null +++ b/configuration/sysop-setup.html @@ -0,0 +1,2295 @@ + + + + + + + + + + + +SysOp Setup | ENiGMA½ BBS Software + + + + + + + + + + + + + + + + + +
+ +
+
+
+ + +
+

SysOp Setup

+

SySop privileges will be granted to the first user to log into a fresh ENiGMA½ installation. +ops belong to the sysop user group by default.

+ +
+ + +
+
+
+
+ + + + diff --git a/favicon.ico b/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..6418b37500b63a4aca128ee2fb8bc454bf6647b7 GIT binary patch literal 15406 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 literal 0 HcmV?d00001 diff --git a/filebase/acs.html b/filebase/acs.html new file mode 100644 index 00000000..512c7c56 --- /dev/null +++ b/filebase/acs.html @@ -0,0 +1,2322 @@ + + + + + + + + + + + +ACS | ENiGMA½ BBS Software + + + + + + + + + + + + + + + + + +
+ +
+
+
+ + +
+

ACS

+

File Base ACS

+

ACS Codes may be used to control access to File Base areas by specifying an acs string in a file area’s definition. If no acs is supplied in a file area definition, the following defaults apply to an area:

+
    +
  • read : GM[users]: List/view the area and it’s contents.
  • +
  • write : GM[sysops]: Upload.
  • +
  • download : GM[users]: Download.
  • +
+ +

To override read and/or write ACS, supply a valid acs member.

+ +

Example File Area Config with ACS

+ +
areas: {
+	retro_pc: {
+		name: Retro PC
+		desc: Oldschool PC/DOS
+		storageTags: [ "retro_pc", "retro_pc_bbs" ]
+		acs: {
+			//	only users of the "l33t" group or those who have
+			//	uploaded 10+ files can download from here...
+			download: GM[l33t]|UP10
+		}
+	}
+}
+
+ +

See Also

+

Access Condition System (ACS)

+ +
+ + +
+
+
+
+ + + + diff --git a/filebase/first-file-area.html b/filebase/first-file-area.html new file mode 100644 index 00000000..a851cd60 --- /dev/null +++ b/filebase/first-file-area.html @@ -0,0 +1,2418 @@ + + + + + + + + + + + +Configuring a File Base | ENiGMA½ BBS Software + + + + + + + + + + + + + + + + + +
+ +
+
+
+ + +
+

Configuring a File Base

+

Configuring a File Base

+

ENiGMA½ offers a powerful and flexible file base. Configuration of file the file base and areas is handled via the fileBase section of config.hjson.

+ +

ENiGMA½ File Base Key Concepts

+

First, there are some core concepts you should understand:

+
    +
  • Storage Tags
  • +
  • Area Tags
  • +
+ +

Storage Tags

+

Storage Tags define paths to physical (filesystem) storage locations that are referenced in a file Area entry. Each entry may be either a fully qualified path or a relative path. Relative paths are relative to the value set by the fileBase.areaStoragePrefix key (defaults to /path/to/enigma-bbs/file_base).

+ +

Below is an example defining some storage tags using the relative and fully qualified forms:

+ +
storageTags: {
+	retro_pc_dos: "dos" // relative
+	retro_pc_bbs: "pc/bbs" // still relative!
+	bbs_stuff: "/path/to/bbs_stuff_storage" // fully qualified
+}
+
+ +

:memo: On their own, storage tags don’t do anything — they are simply pointers to storage locations on your system.

+ +

:warning: Remember that paths are case sensitive on most non-Windows systems!

+ +

Areas

+

File base Areas are configured using the fileBase.areas configuration block in config.hjson. Each entry’s block starts with an area tag. Valid members for an area are as follows:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ItemRequiredDescription
name:+1:Friendly area name.
desc:-1:Friendly area description.
storageTags:+1:An array of storage tags for physical storage backing of the files in this area. If uploads are enabled for this area, first storage tag location is utilized!
sort:-1:If present, provides the sort key for ordering. name is used otherwise.
hashTags:-1:Set to an array of strings or comma separated list to provide default hash tags for this area.
+ +

Example areas section:

+ +
areas: {
+	retro_pc: { // an area tag!
+		name: Retro PC
+		desc: Oldschool PC/DOS
+		storageTags: [ "retro_pc_dos", "retro_pc_bbs" ]
+		hashTags: ["retro", "pc", "dos" ]
+	}
+}
+
+

The above example defines an area called “Retro PC” which is referenced via the area tag of retro_pc. Two storage tags are used: retro_pc_dos, and retro_pc_bbs. These storage tags can be seen in the Storage Tags example above.

+ +

Example Configuration

+

This combines the two concepts described above. When viewing the file areas from ENiGMA½ a user will only see the “Retro PC” area, but the files in the area are stored in the two locations defined in the storageTags section. We also show a uploads area. Uploads are allowed due to the ACS block. See Uploads for more information.

+ +
fileBase: {
+	// override the default relative location
+	areaStoragePrefix: /enigma-bbs/file_base
+
+	storageTags: {
+		retro_pc_dos: "dos"
+		retro_pc_bbs: "pc/bbs"
+	}
+
+	areas: {
+		retro_pc: {
+			name: Retro PC
+			desc: Oldschool PC/DOS
+			storageTags: [ "retro_pc_dos", "retro_pc_bbs" ]
+		}
+
+		uploads: {
+			name: Uploads
+			desc: User uploads
+			acs: {
+				// allow any user to upload here
+				write: GM[users]
+			}
+			storageTags: [ "user_uploads" ]
+		}
+	}
+}
+
+ +

Importing Areas

+

Areas can also be imported using oputil using proper FileGate “RAID” aka FILEBONE.NA style files. After importing areas, you may wish to tweak configuration such as better desc fields, ACS, or sorting.

+ +

Importing Files (Scan For New Files)

+

A common task is to import existing files to area(s). Consider a collection of retro BBS files in the area “Retro PC” (tag: retro_pc above) under the storage tag of retro_pc_bbs. You might choose to scan for new files in this area (and thus import new entries) as follows with oputil’s fb scan:

+ +
./oputil.js fb scan --quick --tags retro,bbs,pc retro_pc@retro_pc_bbs
+
+ +

Here we have asked oputil to scan the file base area by it’s tag retro_pc and only include the storage tag of retro_pc_bbs. Note that the storage tag could be omitted, and if so, all of retro_pc would be scanned. We have also indicated to #hashtag new entries with the tags “retro”, “bbs”, and “pc”.

+ +

Please see oputil for more information.

+ + +
+ + +
+
+
+
+ + + + diff --git a/filebase/index.html b/filebase/index.html new file mode 100644 index 00000000..9c65f9d1 --- /dev/null +++ b/filebase/index.html @@ -0,0 +1,2324 @@ + + + + + + + + + + + +About File Areas | ENiGMA½ BBS Software + + + + + + + + + + + + + + + + + +
+ +
+
+
+ + +
+

About File Areas

+

About File Areas

+ +

A Different Approach

+

ENiGMA½ has strayed away from the old familiar setup here and instead takes a more modern approach:

+
    +
  • Gazelle inspired system for searching & browsing files.
  • +
  • No conferences (just areas!)
  • +
  • File areas are still around but should generally be used less. Instead, files can have one or more tags. Think things like dos.retro, pc.warez, games, etc.
  • +
+ +

Other bells and whistles

+
    +
  • Temporary web (http:// or https://) download links in additional to standard X/Y/Z protocol support. Batch downloads of many files can be downloaded as a single ZIP archive.
  • +
  • Users can rate files & search/filter by ratings.
  • +
  • Users can also create and save their own filters for later use such as “Latest Artscene Releases” or “C64 SIDs”.
  • +
  • A given area can span one to many physical storage locations.
  • +
  • Upload processor can extract and use FILE_ID.DIZ/DESC.SDI, for standard descriptions as well as README.TXT, *.NFO, and so on for longer descriptions. The processor also attempts release year estimation by scanning aforementioned description file(s).
  • +
  • Fast indexed Full Text Search (FTS) across descriptions and filenames.
  • +
  • Duplicates are checked for by cryptographically secure SHA-256 hashes.
  • +
  • Support for many archive and file formats. External utilities can easily be added to the configuration to extend for additional formats.
  • +
  • Much, much more!
  • +
+ +

Modding

+

The default ENiGMA½ approach for file areas may not be for everyone. Remember that you can mod everything your setup! Some inspirational examples:

+
    +
  • A more traditional set of areas and scrolling file listings.
  • +
  • An S/X style integration of message areas and file areas.
  • +
  • Something completely different! Some tweaks are possible without any code while others may require creating new JavaScript modules to use instead of the defaults.
  • +
+ +
+ + +
+
+
+
+ + + + diff --git a/filebase/network-mounts-and-symlinks.html b/filebase/network-mounts-and-symlinks.html new file mode 100644 index 00000000..9e687ec9 --- /dev/null +++ b/filebase/network-mounts-and-symlinks.html @@ -0,0 +1,2318 @@ + + + + + + + + + + + +Network Mounts & Symlinks | ENiGMA½ BBS Software + + + + + + + + + + + + + + + + + +
+ +
+
+
+ + +
+

Network Mounts & Symlinks

+ +

With many Bulletin Board Systems running on small headless boxes such as Raspberry Pis, it may not be practical to have all files you would like to make available in your file base. One solution to this is to utilize network mounts. Add in symbolic links to make things even easier!

+ +

A Practical Example

+

The scenario: A Windows box containing a lot of files you’d like in your systems file base. The BBS itself is running on a Raspberry Pi with very limited space.

+ +

To solve this problem, we can perform the following steps:

+
    +
  1. Create a network mount in /mnt/windows_box_share.
  2. +
  3. Next, we can create a local file base area such as /home/enigma/file_base
  4. +
  5. Within the file base directory above, create some symbolic links to areas within our share: +
      cd /home/enigma/file_base
    +  ln -s /mnt/windows_box_share/some/long/annoying/path area1
    +
    +
  6. +
+ +

What we’ve done here is make /home/enigma/file_base/area1 point to the Windows share within some nested directories. Of course we could have just pointed directly to the /mnt/windows_box_share area, but using symbolic links has some advantages:

+
    +
  • We can now set /home/enigma/file_base as our areaStoragePrefix. That is, the base path of all of our file base
  • +
  • Since we have areaStoragePrefix set, we can now make storage tags relative to that path. For example, `leet_files1: “area1/leet_files”
  • +
+ +

There are many ways one can achieve the mounts between various operating systems. See your distros documentation.

+ +
+ + +
+
+
+
+ + + + diff --git a/filebase/tic-support.html b/filebase/tic-support.html new file mode 100644 index 00000000..2e23df23 --- /dev/null +++ b/filebase/tic-support.html @@ -0,0 +1,2388 @@ + + + + + + + + + + + +TIC Support | ENiGMA½ BBS Software + + + + + + + + + + + + + + + + + +
+ +
+
+
+ + +
+

TIC Support

+

TIC Support

+

ENiGMA½ supports FidoNet-Style TIC file attachments by mapping TIC areas to local file areas.

+ +

Under a given node defined in the ftn_bso config section in config.hjson (see +BSO Import/Export), TIC configuration may be supplied:

+ +
{
+  scannerTossers: {
+    ftn_bso: {
+      nodes: {
+        "46:*": {
+          packetPassword: mypass
+          encoding: cp437
+          archiveType: zip
+          tic: {
+            password: TESTY-TEST
+            uploadBy: Agoranet TIC
+            allowReplace: true
+          }
+        }
+      }
+    }
+  }
+}
+
+ +

You then need to configure the mapping between TIC areas you want to carry, and the file base area and storage tag for them to be tossed to. Optionally you can also add hashtags to the tossed files to assist users in searching for files:

+ +
ticAreas: {
+    agn_node: {
+        areaTag: msgNetworks
+        storageTag: msg_network
+        hashTags: agoranet,nodelist
+    }
+}
+
+
+

Multiple TIC areas can be mapped to a single file base area.

+ +

Example Configuration

+

An example configuration linking file base areas, FTN BSO node configuration and TIC area configuration.

+ +
fileBase: {
+    areaStoragePrefix: /home/bbs/file_areas/
+
+    storageTags: {
+        msg_network: "msg_network"
+    }
+
+    areas: {
+        msgNetworks: {
+            name: Message Networks
+            desc: Message networks news & info
+            storageTags: [
+                "msg_network"
+            ]
+        }
+    }
+}
+
+scannerTossers: {
+    ftn_bso: {
+        nodes: {
+            "46:*": {
+                packetPassword: mypass
+                encoding: cp437
+                archiveType: zip
+                tic: {
+                    password: TESTY-TEST
+                    uploadBy: Agoranet TIC
+                    allowReplace: true
+                }
+            }
+        }
+    }
+}
+
+
+ticAreas: {
+    agn_node: {
+        areaTag: msgNetworks
+        storageTag: msg_network
+        hashTags: agoranet,nodelist
+    }
+    agn_info: {
+        areaTag: msgNetworks
+        storageTag: msg_network
+        hashTags: agoranet,infopack
+    }
+}
+
+ +

See Also

+

Message Networks

+ +
+ + +
+
+
+
+ + + + diff --git a/filebase/uploads.html b/filebase/uploads.html new file mode 100644 index 00000000..ec6206e1 --- /dev/null +++ b/filebase/uploads.html @@ -0,0 +1,2313 @@ + + + + + + + + + + + +Uploads | ENiGMA½ BBS Software + + + + + + + + + + + + + + + + + +
+ +
+
+
+ + +
+

Uploads

+

Uploads

+

The default ACS for file areas in ENiGMA½ is to allow regular users ‘read’ and sysops ‘read/write’. Read ACS includes listing and downloading while write allows for uploading. See File Base ACS for more information.

+ +

Let’s allow regular users (in the “users” group) to upload to an area:

+
uploads: {
+    name: Uploads
+    desc: User Uploads
+    storageTags: [
+        "uploads"
+    ]
+    acs: {
+        write: GM[users]
+    }
+}
+
+ +

:information_source: Remember that uploads in a particular area are stored using the first storage tag defined in that area.

+ +

:bulb: Any ACS checks are allowed. See ACS

+ +
+ + +
+
+
+
+ + + + diff --git a/filebase/web-access.html b/filebase/web-access.html new file mode 100644 index 00000000..b5b1bc19 --- /dev/null +++ b/filebase/web-access.html @@ -0,0 +1,2301 @@ + + + + + + + + + + + +Web Access | ENiGMA½ BBS Software + + + + + + + + + + + + + + + + + +
+ +
+
+
+ + +
+

Web Access

+

Temporary web HTTP(S) URLs can be used to download files using the built in web server. Temporary links +expire after fileBase::web::expireMinutes (default 24 hours). The full URL given to users is built +using contentServers::web::domain and will default to HTTPS (https://) if enabled with a fallback to +HTTP. The end result is users are given a temporary web link that may look something like this: +https://xibalba.l33t.codes:44512/f/h7JK

+ +

See Web Server for more information.

+ +
+ + +
+
+
+
+ + + + diff --git a/index.html b/index.html new file mode 100644 index 00000000..c664d9b7 --- /dev/null +++ b/index.html @@ -0,0 +1,2310 @@ + + + + + + + + + + + +Home | ENiGMA½ BBS Software + + + + + + + + + + + + + + + + Fork me on GitHub + +
+ +
+
+
+ + +

ENiGMA½ BBS

+ +

ENiGMA½ is a modern BBS software with a nostalgic flair!

+ +

Features Available Now

+
    +
  • Multi platform: Anywhere Node.js runs likely works (known to work under Linux, FreeBSD, OpenBSD, OS X and Windows)
  • +
  • Unlimited multi node support (for all those BBS “callers”!)
  • +
  • Highly customizable via HJSON based configuration, menus, and themes in addition to JavaScript based mods
  • +
  • MCI support for lightbars, toggles, input areas, and so on plus many other other bells and whistles
  • +
  • Telnet, SSH, and both secure and non-secure WebSocket access built in! Additional servers are easy to implement
  • +
  • CP437 and UTF-8 output
  • +
  • SyncTERM style font and baud emulation support. Display PC/DOS and Amiga style artwork as it’s intended! In general, ANSI-BBS / cterm.txt / bansi.txt are followed for expected BBS behavior.
  • +
  • Full SAUCE support.
  • +
  • Renegade style pipe color codes.
  • +
  • SQLite storage of users, message areas, etc.
  • +
  • Strong PBKDF2 backed password encryption.
  • +
  • Support for 2-Factor Authentication with One-Time-Passwords
  • +
  • Door support including common dropfile formats for legacy DOS doors. Built in BBSLink, DoorParty, Exodus and CombatNet support!
  • +
  • Bunyan logging!
  • +
  • Message networks with FidoNet Type Network (FTN) + BinkleyTerm Style Outbound (BSO) message import/export. Messages Bases can also be exposed via Gopher, or NNTP!
  • +
  • Gazelle inspired File Bases including fast fully indexed full text search (FTS), #tags, and HTTP(S) temporary download URLs using a built in web server. Legacy X/Y/Z modem also supported!
  • +
  • Upload processor supporting FILE_ID.DIZ and NFO extraction, year estimation, and more!
  • +
  • ANSI support in the Full Screen Editor (FSE), file descriptions, etc.
  • +
  • A built in achievement system. BBSing gamified!
  • +
+ + + + +
+
+
+
+ + + + diff --git a/installation/docker.html b/installation/docker.html new file mode 100644 index 00000000..f79c86ea --- /dev/null +++ b/installation/docker.html @@ -0,0 +1,2398 @@ + + + + + + + + + + + +Docker | ENiGMA½ BBS Software + + + + + + + + + + + + + + + + + +
+ +
+
+
+ + +
+

Docker

+

You’ll need Docker installed before going any further. How to do so are out of scope of these docs, but you can find full instructions +for every operating system on the Docker website.

+ +

Quick Start

+

prepare a folder where you are going to save your bbs files.

+
    +
  • Generate some config for your BBS:
    +you can perform this step from anywhere - but make sure to consistently run it from the same place to retain your config inside the docker guest +
    +
    docker run -it -p 8888:8888 \
    +--name "ENiGMABBS" \
    +-v "$(pwd)/config:/enigma-bbs/config" \
    +-v "$(pwd)/db:/enigma-bbs/db" \
    +-v "$(pwd)/logs:/enigma-bbs/logs" \
    +-v "$(pwd)/filebase:/enigma-bbs/filebase" \
    +-v "$(pwd)/art:/enigma-bbs/art" \
    +-v "$(pwd)/mods:/enigma-bbs/mods" \
    +-v "$(pwd)/mail:/mail" \
    +enigmabbs/enigma-bbs:latest
    +
    +
  • +
  • Run it:
    +you can use the same command as above, just daemonize and drop interactiveness (we needed it for config but most of the time docker will run in the background) +
    +
    docker run -d -p 8888:8888 \
    +--name "ENiGMABBS" \
    +-v "$(pwd)/config:/enigma-bbs/config" \
    +-v "$(pwd)/db:/enigma-bbs/db" \
    +-v "$(pwd)/logs:/enigma-bbs/logs" \
    +-v "$(pwd)/filebase:/enigma-bbs/filebase" \
    +-v "$(pwd)/art:/enigma-bbs/art" \
    +-v "$(pwd)/mods:/enigma-bbs/mods" \
    +-v "$(pwd)/mail:/mail" \
    +enigmabbs/enigma-bbs:latest
    +
    +
  • +
  • Restarting and Making changes
    +if you make any changes to your host config folder they will persist, and you can just restart ENiGMABBS container to load any changes you’ve made.
  • +
+ +

docker restart ENiGMABBS

+ +

:bulb: Configuration will be stored in $(pwd)/enigma-bbs/config.

+ +

:bulb: Windows users - you’ll need to switch out $(pwd)/enigma-bbs/config for a Windows-style path.

+ +

Volumes

+ +

Containers by their nature are ephermeral. Meaning, stuff you want to keep (config, database, mail) needs +to be stored outside of the running container. As such, the following volumes are mountable:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
VolumeUsage
/enigma-bbs/artArt, themes, etc
/enigma-bbs/configConfig such as config.hjson, menu.hjson, prompt.hjson, SSL certs etc
/enigma-bbs/dbENiGMA databases
/enigma-bbs/filebaseFilebase
/enigma-bbs/logsLogs
/enigma-bbs/modsENiGMA mods
/mailFTN mail (for use with an external mailer)
+ +

Building your own image

+ +

Customising the Docker image is easy!

+ +
    +
  1. Clone the ENiGMA-BBS source.
  2. +
  3. +

    Build the image

    + +
    +
    docker build -f ./docker/Dockerfile .
    +
    +
  4. +
+ +
+ + +
+
+
+
+ + + + diff --git a/installation/hardware/rpi.html b/installation/hardware/rpi.html new file mode 100644 index 00000000..3d553bae --- /dev/null +++ b/installation/hardware/rpi.html @@ -0,0 +1,2324 @@ + + + + + + + + + + + +Raspberry Pi | ENiGMA½ BBS Software + + + + + + + + + + + + + + + + + +
+ +
+
+
+ + +
+

Raspberry Pi

+

All Raspberry Pi models work great with ENiGMA½! Keep in mind compiling the dependencies with +npm install will take some time and may appear to hang. It’s still working - just be patient and let it +complete.

+ +

Basic Instructions

+ +
    +
  1. +

    Download Raspbian Stretch Lite. Follow the instructions +on the Raspbian site regarding how +to get it written to an SD card.

    +
  2. +
  3. Run sudo raspi-config, then: +
      +
    1. Set your timezone (option 4, option I2)
    2. +
    3. Enable SSH (option 5, option P2)
    4. +
    5. Expand the filesystem to use the entire SD card (option 7, option A1)
    6. +
    +
  4. +
  5. +

    Update & upgrade all packages: apt-get update && apt-get upgrade

    +
  6. +
  7. +

    Install required packages: sudo apt install lrzsz p7zip-full

    +
  8. +
  9. +

    Follow the installation instructions to install ENiGMA½.

    +
  10. +
  11. Profit!
  12. +
+ +
+ + +
+
+
+
+ + + + diff --git a/installation/hardware/windows.html b/installation/hardware/windows.html new file mode 100644 index 00000000..fbf9446b --- /dev/null +++ b/installation/hardware/windows.html @@ -0,0 +1,2371 @@ + + + + + + + + + + + +Installation Under Windows | ENiGMA½ BBS Software + + + + + + + + + + + + + + + + + +
+ +
+
+
+ + +
+

Installation Under Windows

+

Installation Under Windows

+ +

ENiGMA½ will run on both 32bit and 64bit Windows. If you want to run 16bit doors natively then you should use a 32bit Windows.

+ +

Basic Instructions

+ +
    +
  1. +

    Download and Install Node.JS.

    + +
      +
    1. +

      Upgrade NPM : At this time node comes with NPM 5.6 preinstalled. To upgrade to a newer version now or in the future on windows follow this method. *Run PowerShell as Administrator

      + +

      *Initial Install

      +
       Set-ExecutionPolicy Unrestricted -Scope CurrentUser -Force
      + npm install -g npm-windows-upgrade
      +
      +

      *Upgrade

      +
       npm-windows-upgrade
      +
      + +

      Note: Do not run npm i -g npm. Instead use npm-windows-upgrade to update npm going forward. + Also if you run the NodeJS installer, it will replace the node version.

      +
    2. +
    3. +

      Install windows-build-tools for npm + *This will also install python 2.7

      +
       npm install --global --production windows-build-tools
      +
      +
    4. +
    +
  2. +
  3. +

    Install 7zip.

    + +

    *Add 7zip to your path so 7z can be called from the console

    +
      +
    1. Right click This PC and Select Properties
    2. +
    3. Go to the Advanced Tab and click on Environment Variables
    4. +
    5. Select Path under System Variables and click Edit
    6. +
    7. Click New and paste the path to 7zip
    8. +
    9. Close your console window and reopen. You can type 7z to make sure it’s working.
    10. +
    +
  4. +
+ +

(Please see Archivers for additional archive utilities!)

+ +
    +
  1. +

    Install Git and optionally TortoiseGit.

    +
  2. +
  3. Clone ENiGMA½ - browse to the directory you want and run +
     git clone "https://github.com/NuSkooler/enigma-bbs.git"
    +
    +

    Optionally use the TortoiseGit by right clicking the directory and selecting Git Clone.

    +
  4. +
  5. Install ENiGMA½. +
      +
    1. In the enigma directory run +
       npm install
      +
      +
    2. +
    3. Generate your initial configuration: Follow the prompts! +
       node .\oputil.js config new
      +
      +
    4. +
    5. Edit your configuration files in enigma-bbs\config with Notepad++ or Visual Studio Code
    6. +
    7. Run ENiGMA½ +
       node .\main.js
      +
      +
    8. +
    +
  6. +
  7. Look at Production Installation for maintaining ENiGMA½ when you are ready to go live.
  8. +
+ +
+ + +
+
+
+
+ + + + diff --git a/installation/install-script.html b/installation/install-script.html new file mode 100644 index 00000000..0f209d9f --- /dev/null +++ b/installation/install-script.html @@ -0,0 +1,2313 @@ + + + + + + + + + + + +Install Script | ENiGMA½ BBS Software + + + + + + + + + + + + + + + + + +
+ +
+
+
+ + +
+

Install Script

+

Install Script

+

Under most Linux/UNIX like environments (Linux, BSD, OS X, …) new users can simply execute the install.sh script to get everything up and running. Cut + paste the following into your terminal:

+ +
curl -o- https://raw.githubusercontent.com/NuSkooler/enigma-bbs/master/misc/install.sh | bash
+
+ +

:eyes: You may wish to review the installation script +on GitHub before running it!

+ +

The script will install nvm, Node.js and grab the latest ENiGMA BBS from GitHub. It will also guide you through creating a basic configuration file, and recommend some packages to install.

+ +

:information_source: After installing:

+ + + +
+ + +
+
+
+
+ + + + diff --git a/installation/installation-methods.html b/installation/installation-methods.html new file mode 100644 index 00000000..e526c565 --- /dev/null +++ b/installation/installation-methods.html @@ -0,0 +1,2325 @@ + + + + + + + + + + + +Installation Methods | ENiGMA½ BBS Software + + + + + + + + + + + + + + + + + +
+ +
+
+
+ + +
+

Installation Methods

+

Installation Methods

+

There are multiple ways of installing ENiGMA BBS, depending on your level of experience and desire to do things manually versus have it automated for you.

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodOperating System CompatibilityNotes
Installation ScriptLinux, BSD, OSXQuick and easy installation under most Linux/UNIX like environments (Linux, BSD, OS X, …)
Docker ImagesLinux, BSD, OSX, WindowsEasy upgrades, compatible with all operating systems, no dependencies to install
ManualLinux, Windows, BSD (And others; YMMV!)If you like doing things manually, or are running Windows
+ +

Community HOWTO’s

+

:scroll: Check out this awesome video on installation and basic configuration from Al’s Geek Lab!

+ +

Keeping Up To Date

+

After installing, you’ll want to keep your system updated.

+ +
+ + +
+
+
+
+ + + + diff --git a/installation/manual.html b/installation/manual.html new file mode 100644 index 00000000..71d6432b --- /dev/null +++ b/installation/manual.html @@ -0,0 +1,2361 @@ + + + + + + + + + + + +Manual Installation | ENiGMA½ BBS Software + + + + + + + + + + + + + + + + + +
+ +
+
+
+ + +
+

Manual Installation

+

For Linux environments it’s recommended you run the install script. If you like to +do things manually, read on…

+ +

Prerequisites

+
    +
  • +Node.js version v12.x LTS or higher (Other versions may work but are not supported). +
      +
    • +:bulb: It is highly recommended to use Node Version Manager (NVM) to manage your Node.js installation if you’re on a Linux/Unix environment.
    • +
    +
  • +
  • +

    Python for compiling Node.js packages with native extensions via node-gyp.

    +
  • +
  • +

    A compiler such as Clang or GCC for Linux/UNIX systems or a recent copy of Visual Studio +(Visual Studio Express editions +are OK) for Windows users. Note that you should only need the Visual C++ component.

    +
  • +
  • +Git to check out the ENiGMA source code.
  • +
+ +

Node.js

+

With NVM

+

Node Version Manager (NVM) is an excellent way to install and manage Node.js versions on most UNIX-like environments. Get the latest version here. The nvm install may look something like this:

+ +
curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.11/install.sh | bash
+
+

:information_source: Do not cut+paste the above command! Visit the NVM page and run the latest version!

+ +

Next, install Node.js with NVM:

+
nvm install 12
+nvm use 12
+nvm alias default 12
+
+ +

If the above steps completed without errors, you should now have nvm, node, and npm installed and in your environment.

+ +

For Windows nvm-like systems exist (nvm-windows, …) or just download the installer.

+ +

ENiGMA BBS

+
git clone https://github.com/NuSkooler/enigma-bbs.git
+
+ +

Install Node Packages

+
cd enigma-bbs
+npm install # yarn also works
+
+ + +

ENiGMA BBS makes use of a few packages for archive and legacy protocol support. They’re not pre-requisites for running ENiGMA, but without them you’ll miss certain functionality. Once installed, they should be made available on your systems PATH.

+ +

:information_source: Please see External Binaries for information on setting these up.

+ +

:information_source: Additional information in Archivers and File Transfer Protocols

+ +

Config Files

+

You’ll need a basic configuration to get started. The main system configuration is handled via config/config.hjson. This is an HJSON file (compliant JSON is also OK). See Configuration for more information.

+ +

Use oputil.js to generate your initial configuration:

+ +
./oputil.js config new
+
+ +

Follow the prompts!

+ +
+ + +
+
+
+
+ + + + diff --git a/installation/network.html b/installation/network.html new file mode 100644 index 00000000..e4a31e49 --- /dev/null +++ b/installation/network.html @@ -0,0 +1,2303 @@ + + + + + + + + + + + +Network Setup | ENiGMA½ BBS Software + + + + + + + + + + + + + + + + + +
+ +
+
+
+ + +
+

Network Setup

+

Hosting an ENIGMA instance from your Home Network

+ +

If you are hosting your ENGIMA instance from inside your local network, you’ll need to open your chosen ports on your router, so people outside your local area network can access the BBS.

+ +

Each router has a different way of doing this, but this comprehensive resource explains how to port forward on most common brand routers.

+ +

Secondly, it is likely that your public facing server IP is a Dynamic Address automatically provisoned to you by your ISP. You can contact your ISP and request a static IP, but in some areas this isn’t available to consumers, only businesses.

+ +

Using a tool like Duck DNS will give you a free subdomain that automatically adjusts its records whenever your IP Address changes.

+ +
+ + +
+
+
+
+ + + + diff --git a/installation/production.html b/installation/production.html new file mode 100644 index 00000000..5ffdabe8 --- /dev/null +++ b/installation/production.html @@ -0,0 +1,2302 @@ + + + + + + + + + + + +Production Installation | ENiGMA½ BBS Software + + + + + + + + + + + + + + + + + +
+ +
+
+
+ + +
+

Production Installation

+

If you’ve become convinced you would like a “production” BBS running ENiGMA½ a more advanced installation +may be in order.

+ +

PM2 is an excellent choice for managing your running ENiGMA½ instances if +you’ve installed via the install script or manual installation method. +Additionally, it is suggested that you run as a specific more locked down user (e.g. ‘enigma’).

+ +

If you’re running ENiGMA via Docker, then process management is already handled for you!

+ +
+ + +
+
+
+
+ + + + diff --git a/installation/testing.html b/installation/testing.html new file mode 100644 index 00000000..54c174bf --- /dev/null +++ b/installation/testing.html @@ -0,0 +1,2344 @@ + + + + + + + + + + + +Testing Your Installation | ENiGMA½ BBS Software + + + + + + + + + + + + + + + + + +
+ +
+
+
+ + +
+

Testing Your Installation

+

Once you’ve completed your chosen installation method, it’s time to test!

+ +

Note that if you’ve used the Docker installation method, you’ve already done this.

+ +
./main.js
+
+ +

If everything went OK:

+ +
ENiGMA½ Copyright (c) 2014-2021, Bryan Ashby
+_____________________   _____  ____________________    __________\_   /
+\__   ____/\_ ____   \ /____/ /   _____ __         \  /   ______/ // /___jp!
+//   __|___//   |    \//   |//   |    \//  |  |    \//        \ /___   /_____
+/____       _____|      __________       ___|__|      ____|     \   /  _____  \
+---- \______\ -- |______\ ------ /______/ ---- |______\ - |______\ /__/ // ___/
+                                                                     /__   _\
+ <*>   ENiGMA½  // HTTPS://GITHUB.COM/NUSKOOLER/ENIGMA-BBS   <*>       /__/
+
+-------------------------------------------------------------------------------
+
+System started!
+
+

Grab your favourite telnet client, connect to localhost:8888 and test out your installation.

+ +

To shut down the server, press Ctrl-C.

+ +

Points of Interest

+ +
    +
  • The default port for Telnet is 8888 and 8889 for SSH. +
      +
    • Note that on *nix systems port such as telnet/23 are privileged (e.g. require root). See +this SO article for some tips on using these ports on your system if desired.
    • +
    +
  • +
  • The first user you create when logging in will be automatically be added to the sysops group.
  • +
+ +

Telnet Software

+ +

If you don’t have any telnet software, these are compatible with ENiGMA½:

+ + + +
+ + +
+
+
+
+ + + + diff --git a/messageareas/bso-import-export.html b/messageareas/bso-import-export.html new file mode 100644 index 00000000..f54160a8 --- /dev/null +++ b/messageareas/bso-import-export.html @@ -0,0 +1,2615 @@ + + + + + + + + + + + +BSO Import / Export | ENiGMA½ BBS Software + + + + + + + + + + + + + + + + + +
+ +
+
+
+ + +
+

BSO Import / Export

+

BSO Import / Export

+

The scanner/tosser module ftn_bso provides Binkley Style Outbound (BSO) import/toss and scan/export of messages EchoMail and NetMail messages. Configuration is supplied in config.hjson under scannerTossers.ftn_bso.

+ +

:information_source: ENiGMA½’s ftn_bso module is not a mailer and makes no attempts to perform packet transport! An external mailer such as Binkd is required for this task!

+ +

Configuration

+

Let’s look at some of the basic configuration:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Config ItemRequiredDescription
schedule:+1:Sets import and export schedules. Later style text parsing supported. import also can utilize a @watch:<path/to/file> syntax while export additionally supports @immediate.
packetMsgEncoding:-1:Override default utf8 encoding.
defaultNetwork:-1:Explicitly set default network (by tag found within messageNetworks.ftn.networks). If not set, the first found is used.
nodes:+1:Per-node settings. Entries (keys) here support wildcards for a portion of the FTN-style address (e.g.: 21:1/*). See Nodes below.
paths:-1:An optional configuration block that can set a additional paths or override defaults. See Paths below.
packetTargetByteSize:-1:Overrides the system target packet (.pkt) size of 512000 bytes (512k)
bundleTargetByteSize:-1:Overrides the system target ArcMail bundle size of 2048000 bytes (2M)
+ +

Nodes

+

The nodes section defines how to export messages for one or more uplinks.

+ +

A node entry starts with a FTN address (up to 5D) as a key in config.hjson. This key may contain wildcard(s) for net/zone/node/point/domain.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Config ItemRequiredDescription
packetType:-1: +2, 2.2, or 2+. Defaults to 2+ for modern mailer compatibility.
packetPassword:-1:Optional password for the packet
encoding:-1:Encoding to use for message bodies; Defaults to utf-8.
archiveType:-1:Specifies the archive type (by extension or MIME type) for ArcMail bundles. This should be zip (or application/zip) for most setups. Other valid examples include arc, arj, lhz, pak, sqz, or zoo. See Archivers for more information.
+ +

Example:

+
{
+  scannerTossers: {
+    ftn_bso: {
+      nodes: {
+        "21:*": { // wildcard address
+          packetType: 2+
+          packetPassword: D@TP4SS
+          encoding: cp437
+          archiveType: zip
+        }
+      }
+    }
+  }
+}
+
+ +

Paths

+

Paths for packet files work out of the box and are relative to your install directory. If you want to configure reject or retain to keep rejected/imported packet files respectively, set those values. You may override defaults as well.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
KeyDescriptionDefault
outbound +Base path to write outbound (exported) packet files and bundles.enigma-bbs/mail/ftn_out/
inbound +Base path to write inbound (ie: those written by an external mailer) packet files an bundles.enigma-bbs/mail/ftn_in/
secInbound +Base path to write secure inbound packet files and bundles.enigma-bbs/mail/ftn_secin/
rejectPath in which to write rejected packet files.No default
retainPath in which to write imported packet files. Useful for debugging or if you wish to archive the raw .pkt files.No default
+ +

Scheduling

+

Schedules can be defined for importing and exporting via import and export under schedule. Each entry is allowed a “free form” text and/or special indicators for immediate export or watch file triggers.

+ +
    +
  • +@immediate: A message will be immediately exported if this trigger is defined in a schedule. Only used for export.
  • +
  • +@watch:/path/to/file: This trigger watches the path specified for changes and will trigger an import or export when such events occur. Only used for import.
  • +
  • Free form Later style text — can be things like at 5:00 pm or every 2 hours.
  • +
+ +

See Later text parsing documentation for more information.

+ +

Example Schedule Configuration

+ +
{
+  scannerTossers: {
+    ftn_bso: {
+      schedule: {
+        import: every 1 hours or @watch:/path/to/watchfile.ext
+        export: every 1 hours or @immediate
+      }
+    }
+  }
+}
+
+ +

A More Complete Example

+

Below is a more complete example showing the sections described above.

+ +
scannerTossers: {
+  ftn_bso: {
+    schedule: {
+      //  Check every 30m, or whenever the "toss!.now" file is touched (ie: by Binkd)
+      import: every 30 minutes or @watch:/enigma-bbs/mail/ftn_in/toss!.now
+
+      //  Export immediately, but also check every 15m to be sure
+      export: every 15 minutes or @immediate
+    }
+
+    // optional
+    paths: {
+      reject: /path/to/store/bad/packets/
+      retain: /path/to/store/good/packets/
+    }
+
+    //  Override default FTN/BSO packet encoding. Defaults to 'utf8'
+    packetMsgEncoding: utf8
+
+    defaultNetwork: fsxnet
+
+    nodes: {
+      "21:1/100" : {            //  May also contain wildcards, ie: "21:1/*"
+        archiveType: ZIP        //  By-ext archive type: ZIP, ARJ, ..., optional.
+        encoding: utf8          //  Encoding for exported messages
+        packetPassword: MUHPA55 //  FTN .PKT password, optional
+
+        tic: {
+          //  See TIC docs
+        }
+      }
+    }
+
+    netMail: {
+      //  See NetMail docs
+    }
+
+    ticAreas: {
+      //  See TIC docs
+    }
+  }
+}
+
+ +

Binkd

+

Since Binkd is a very common mailer, a few tips on integrating it with ENiGMA½.

+ +

Example Binkd Configuration

+

Below is an example Binkd configuration file that may help serve as a reference.

+ +
# Number @ end is the root zone
+# Note that fsxNet is our *default* FTN so we use "outbound" here!
+domain fsxnet /home/enigma/enigma-bbs/mail/ftn_out/outbound 21
+domain araknet /home/enigma/enigma-bbs/mail/ftn_out/araknet 10
+
+# Our assigned addresses
+address 21:1/1234@fsxnet
+address 10:101/1234@araknet
+
+# Info about our board/op
+sysname "My BBS"
+location "Somewhere Out There"
+sysop "SysOp"
+
+nodeinfo 115200,TCP,BINKP
+try 10
+hold 600
+send-if-pwd
+
+log /var/log/binkd/binkd.log
+loglevel 4
+conlog 4
+
+percents
+printq
+backresolv
+
+inbound /home/enigma/enigma-bbs/mail/ftn_in
+temp-inbound /home/enigma/enigma-bbs/mail/ftn_in_temp
+
+minfree 2048
+minfree-nonsecure 2048
+
+kill-dup-partial-files
+kill-old-partial-files 86400
+
+prescan
+
+# fsxNet - Agency HUB
+node 21:1/100@fsxnet -md agency.bbs.nz:24556 SOMEPASS c
+
+# ArakNet
+node 10:101/0@araknet -md whq.araknet.xyz:24556 SOMEPASS c
+
+# our listening port (default=24554)
+iport 54554
+
+pid-file /var/run/binkd/binkd.pid
+
+# touch a watch file when files are received to kick of toss
+# ENiGMA can monitor this (see @watch information above)
+flag /home/enigma/enigma-bbs/mail/ftn_in/toss!.now *.su? *.mo? *.tu? *.we? *.th? *.fr? *.sa? *.pkt *.tic
+
+# nuke old .bsy/.csy files after 24 hours
+kill-old-bsy 43200
+
+ +

Scheduling Polls

+

Binkd does not have it’s own scheduler. Instead, you’ll need to set up an Event Scheduler entry or perhaps a cron job:

+ +

First, create a script that runs through all of your uplinks. For example:

+
#!/bin/bash
+UPLINKS=("21:1/100@fsxnet" "80:774/1@retronet" "10:101/0@araknet")
+for uplink in "${UPLINKS[@]}"
+do
+	/usr/local/sbin/binkd -p -P $uplink /home/enigma/xibalba/misc/binkd_xibalba.conf
+done
+
+ +

Now, create an Event Scheduler entry in your config.hjson. As an example:

+
eventScheduler: {
+  events: {
+    pollWithBink: {
+      //  execute the script above very 1 hours
+      schedule: every 1 hours
+      action: @execute:/path/to/poll_bink.sh
+    }
+  }
+}
+
+ +

Additional Resources

+ + +
+ + +
+
+
+
+ + + + diff --git a/messageareas/configuring-a-message-area.html b/messageareas/configuring-a-message-area.html new file mode 100644 index 00000000..64df3417 --- /dev/null +++ b/messageareas/configuring-a-message-area.html @@ -0,0 +1,2454 @@ + + + + + + + + + + + +Message Base | ENiGMA½ BBS Software + + + + + + + + + + + + + + + + + +
+ +
+
+
+ + +
+

Message Base

+

General Information

+

In ENiGMA½, a message base is divided into two logical grouping components: Message Conferences and Areas. Message conferences are top level containers while areas are for a specific topic. Messages are always stored internally with a area tag.

+ +

Conferences

+

Message Conferences are the top level container for 1:n Message Areas via the messageConferences block in config.hjson. A common setup may include a local conference and one or more conferences each dedicated to a particular message network such as fsxNet, ArakNet, etc.

+ +

Each conference is represented by a entry under messageConferences. Each entries top level key is it’s conference tag.

+ +

:bulb: It is highly recommended to use snake_case style message conference tags and area tags!

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Config ItemRequiredDescription
name:+1:Friendly conference name
desc:+1:Friendly conference description.
sort:-1:Set to a number to override the default alpha-numeric sort order based on the name field.
default:-1:Specify true to make this the default conference (e.g. assigned to new users)
areas:+1:Container of 1:n areas described below
acs:-1:A standard ACS block. See ACS below.
+ +

ACS

+

An optional standard ACS block can be supplied with the following rules:

+
    +
  • +read: ACS required to read (see) this conference. Defaults to GM[users].
  • +
  • +write: ACS required to write (post) to this conference. Defaults to GM[users].
  • +
+ +

Example

+ +
{
+  messageConferences: {
+    local: { // conference tag
+      name: Local
+      desc: Local discussion
+      sort: 1
+      default: true
+      acs: {
+        read: GM[users] // default
+      }
+    }
+  }
+}
+
+ +

Message Areas

+

Message Areas are topic specific containers for messages that live within a particular conference. The top level key for an area sets it’s area tag. For example, “General Discussion” may live under a Local conference while an fsxNet conference may contain “BBS Discussion”.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Config ItemRequiredDescription
name:+1:Friendly area name.
desc:+1:Friendly area description.
sort:-1:Set to a number to override the default alpha-numeric sort order based on the name field.
default:-1:Specify true to make this the default area (e.g. assigned to new users)
acs:-1:A standard ACS block. See ACS below.
autoSignatures:-1:Set to false to disable auto-signatures in this area.
realNames:-1:Set to true to use real names in this area.
+ +

ACS

+

An optional standard ACS block can be supplied with the following rules:

+
    +
  • +read: ACS required to read (see) this area. Defaults to GM[users].
  • +
  • +write: ACS required to write (post) to this area. Defaults to GM[users].
  • +
+ +

Example

+ +
messageConferences: {
+  local: {
+    // ... see above ...
+    areas: {
+      enigma_dev: { // Area tag - required elsewhere!
+        name: ENiGMA 1/2 Development
+        desc: ENiGMA 1/2 development and discussion!
+        sort: 1
+        default: true
+        acs: {
+          read: GM[users] // default
+          write: GM[l33t] // super elite ENiGMA 1/2 users!
+        }
+      }
+    }
+  }
+}
+
+ +

Importing

+

FidoNet style .na files as well as legacy AREAS.BBS files in common formats can be imported using oputil.js mb import-areas. See The oputil CLI for more information and usage.

+ +
+ + +
+
+
+
+ + + + diff --git a/messageareas/ftn.html b/messageareas/ftn.html new file mode 100644 index 00000000..5285899b --- /dev/null +++ b/messageareas/ftn.html @@ -0,0 +1,2419 @@ + + + + + + + + + + + +FidoNet-Style Networks (FTN) | ENiGMA½ BBS Software + + + + + + + + + + + + + + + + + +
+ +
+
+
+ + +
+

FidoNet-Style Networks (FTN)

+

FidoNet-Style Networks (FTN)

+

FidoNet proper and other FidoNet-Style networks are supported by ENiGMA½. A bit of configuration and you’ll be up and running in no time!

+ +

:scroll: Before proceeding you may wish to check Setting up FTN-style message networks with ENiGMA½ BBS by Alpha. An excellent guide detailing some of the setup described here!

+ +

Configuration

+

Getting a fully running FTN enabled system requires a few configuration points:

+ +
    +
  1. +messageNetworks.ftn.networks: Declares available networks. That is, networks you wish to sync up with.
  2. +
  3. +messageNetworks.ftn.areas: Establishes local area mappings (ENiGMA½ to/from FTN area tags) and per-area specific configurations.
  4. +
  5. +scannerTossers.ftn_bso: General configuration for the scanner/tosser (import/export) process. This is also where we configure per-node (uplink) settings.
  6. +
+ +

:information_source: ENiGMA½’s ftn_bso module is not a mailer and makes no attempts to perform packet transport! An external utility such as Binkd is required for this task.

+ +

Networks

+

The networks block is a per-network configuration where each entry’s ID (or “key”) may be referenced elsewhere in config.hjson. For example, consider two networks: ArakNet (araknet) and fsxNet (fsxnet):

+ +
{
+  messageNetworks: {
+    ftn: {
+      networks: {
+        // it is recommended to use lowercase network tags
+        fsxnet: {
+          defaultZone: 21
+          localAddress: "21:1/121"
+        }
+
+        araknet: {
+          defaultZone: 10
+          localAddress: "10:101/9"
+        }
+      }
+    }
+  }
+}
+
+ +

Areas

+

The areas section describes a mapping of local area tags configured in your messageConferences (see Configuring a Message Area) to a message network (described above), a FTN specific area tag, and remote uplink address(s). This section can be thought of similar to the AREAS.BBS file used by other BBS packages.

+ +

When ENiGMA½ imports messages, they will be placed in the local area that matches key under areas while exported messages will be sent to the relevant network.

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Config ItemRequiredDescription
network:+1:Associated network from the networks section above
tag:+1:FTN area tag (ie: FSX_GEN)
uplinks:+1:An array of FTN address uplink(s) for this network
+ +

Example:

+
{
+  messageNetworks: {
+    ftn: {
+      areas: {
+        // it is recommended to use lowercase area tags
+        fsx_general:        //  *local* tag found within messageConferences
+          network: fsxnet   //  that we are mapping to this network
+          tag: FSX_GEN      //  ...and this remote FTN-specific tag
+          uplinks: [ "21:1/100" ] // a single string also allowed here
+        }
+      }
+    }
+  }
+}
+
+ +

:bulb: You can import AREAS.BBS or FTN style .NA files using oputil!

+ +

A More Complete Example

+

Below is a more complete example illustrating some of the concepts above:

+ +
{
+  messageNetworks: {
+    ftn: {
+      networks: {
+        fsxnet: {
+          defaultZone: 21
+          localAddress: "21:1/121"
+        }
+      }
+
+      areas: {
+        fsx_general: {
+          network: fsxnet
+
+          //  ie as found in your info packs .NA file
+          tag: FSX_GEN
+
+          uplinks: [ "21:1/100" ]
+        }
+      }
+    }
+  }
+}
+
+ +

:information_source: Remember for a complete FTN experience, you’ll probably also want to configure FTN/BSO scanner/tosser settings.

+ +

FTN/BSO Scanner Tosser

+

Please see the FTN/BSO Scanner/Tosser documentation for information on this area.

+ +
+ + +
+
+
+
+ + + + diff --git a/messageareas/message-networks.html b/messageareas/message-networks.html new file mode 100644 index 00000000..1c33f37f --- /dev/null +++ b/messageareas/message-networks.html @@ -0,0 +1,2318 @@ + + + + + + + + + + + +Message Networks | ENiGMA½ BBS Software + + + + + + + + + + + + + + + + + +
+ +
+
+
+ + +
+

Message Networks

+

Message Networks

+

ENiGMA½ supports external networks such as FidoNet-Style (FTN) and QWK by the way of importing and exporting to/from it’s own internal format. This allows for a very flexible system that can easily be extended by creating new network modules.

+ +

All message network configuration occurs under the messageNetworks.<name> block in config.hjson (where name is something such as ftn or qwk). The most basic of external message network configurations generally comprises of two sections:

+ +
    +
  1. +messageNetworks.<name>.networks: Global/general configuration for a particular network where <name> is for example ftn or qwk.
  2. +
  3. +messageNetworks.<name>.areas: Provides mapping of ENiGMA½ area tags to their external counterparts.
  4. +
+ +

:information_source: A related section under scannerTossers.<name> may provide configuration for scanning (importing) and tossing (exporting) messages for a particular network type. As an example, FidoNet-Style networks often work with BinkleyTerm Style Outbound (BSO) and thus the FTN/BSO scanner/tosser (ftn_bso) module.

+ +

Currently Supported Networks

+

The following networks are supported out of the box. Remember that you can create modules to add others if desired!

+ +

FidoNet-Style (FTN)

+

FidoNet and FidoNet style (FTN) networks as well as a FTN/BSO scanner/tosser (ftn_bso module) are configured via the messageNetworks.ftn and scannerTossers.ftn_bso blocks in config.hjson.

+ +

See FidoNet-Style Networks for more information.

+ +

QWK

+

See QWK and QWK-Net Style Networks for more information.

+ +
+ + +
+
+
+
+ + + + diff --git a/messageareas/netmail.html b/messageareas/netmail.html new file mode 100644 index 00000000..166f7aa6 --- /dev/null +++ b/messageareas/netmail.html @@ -0,0 +1,2324 @@ + + + + + + + + + + + +Netmail | ENiGMA½ BBS Software + + + + + + + + + + + + + + + + + +
+ +
+
+
+ + +
+

Netmail

+

ENiGMA support import and export of Netmail from the Private Mail area. RiPuk @ 21:1/136 and RiPuk <21:1/136> ‘To’ address formats are supported.

+ +

Netmail Routing

+ +

A configuration block must be added to the scannerTossers::ftn_bso config.hjson section to tell the ENiGMA½ tosser where to route NetMail.

+ +

The following configuration would tell ENiGMA½ to route all netmail addressed to 21:* through 21:1/100, and all 46:* netmail through 46:1/100:

+ +

+scannerTossers: {
+    
+    /* other scannerTosser config removed for clarity */
+    
+    ftn_bso: {
+        netMail: {
+            routes: {
+                "21:*" : {
+                    address: "21:1/100"
+                    network: fsxnet
+                }
+                "46:*" : {
+                    address: "46:1/100"
+                    network: agoranet
+                }
+            }
+        }
+    }
+}
+
+

The network tag must match the networks defined in messageNetworks::ftn::networks within config.hjson.

+ +
+ + +
+
+
+
+ + + + diff --git a/messageareas/qwk.html b/messageareas/qwk.html new file mode 100644 index 00000000..f163931a --- /dev/null +++ b/messageareas/qwk.html @@ -0,0 +1,2355 @@ + + + + + + + + + + + +QWK Support | ENiGMA½ BBS Software + + + + + + + + + + + + + + + + + +
+ +
+
+
+ + +
+

QWK Support

+

QWK and QWK-Net Style Networks

+

As like all other networks such as FidoNet-Style (FTN) networks, ENiGMA½ considers QWK external to the system but can import and export the format.

+ +

Supported Standards

+

QWK must be considered a semi-standard as there are many implementations. What follows is a short & incomplete list of such standards ENiGMA½ supports:

+ + +

Configuration

+

QWK configuration occurs in the messageNetworks.qwk config block of config.hjson. As QWK wants to deal with conference numbers and ENiGMA½ uses area tags (conferences and conference tags are only used for logical grouping), a mapping can be made.

+ +

:information_source: During a regular, non QWK-Net exports, conference numbers can be auto-generated. Note that for QWK-Net style networks, you will need to create mappings however.

+ +

Example:

+
{
+    messageNetworks: {
+        qwk: {
+            areas: {
+                general: {          // local ENiGMA½ area tag
+                    conference: 1   // conference number to map to
+                }
+            }
+        }
+    }
+}
+
+ +

oputil

+

The oputil.js utility can export packet files, dump the messages of a packet to stdout, etc. See the oputil documentation for more information.

+ +

Offline Readers

+

A few of the offline readers that have been tested with QWK packet files produced by ENiGMA½:

+ + + + + + + + + + + + + + + + + + + + + +
SoftwareStatusNotes
MultiMail/Win v0.52SupportedPrivate mail seems to break even with bundles from other systems
SkyReader/W32 v1.00SupportedWorks well. No QWKE or HEADERS.DAT support. Gets confused with low conference numbers.
+ +

There are also many other readers for various systems.

+ +
+ + +
+
+
+
+ + + + diff --git a/misc/user-interrupt.html b/misc/user-interrupt.html new file mode 100644 index 00000000..4bb3bfbe --- /dev/null +++ b/misc/user-interrupt.html @@ -0,0 +1,2308 @@ + + + + + + + + + + + +User Interruptions | ENiGMA½ BBS Software + + + + + + + + + + + + + + + + + +
+ +
+
+
+ + +
+

User Interruptions

+

User Interruptions

+

ENiGMA½ provides functionality to “interrupt” a user for various purposes such as a node-to-node message. User interruptions can be queued and displayed at the next opportune time such as when switching to a new menu, or realtime if appropriate.

+ +

Standard Menu Behavior

+

Standard menus control interruption by the interrupt config block option, which may be set to one of the following values:

+
    +
  • never: Never interrupt the user when on this menu.
  • +
  • queued: Queue interrupts for the next opportune time. Any queued message(s) will then be shown. This is the default.
  • +
  • realtime: If possible, display messages in realtime. That is, show them right away. Standard menus that do not override default behavior will show the message then reload.
  • +
+ +

See Also

+

See user_interrupt_queue.js as well as usage within menu_module.js.

+ + +
+ + +
+
+
+
+ + + + diff --git a/modding/autosig-edit.html b/modding/autosig-edit.html new file mode 100644 index 00000000..6ee40f02 --- /dev/null +++ b/modding/autosig-edit.html @@ -0,0 +1,2313 @@ + + + + + + + + + + + +Auto Signature Editor | ENiGMA½ BBS Software + + + + + + + + + + + + + + + + + +
+ +
+
+
+ + +
+

Auto Signature Editor

+

The Auto Signature Editor

+

The built in autosig_edit module allows users to edit their auto signatures (AKA “autosig”).

+ +

Theming

+

The following MCI codes are available:

+
    +
  • MCI 1 (ie: MT1): Editor
  • +
  • MCI 2 (ie: BT2): Save button
  • +
+ +

Disabling Auto Signatures

+

Auto Signature support can be disabled for a particular message area by setting autoSignatures to false in the area’s configuration block.

+ +

Example:

+
my_area: {
+    name: My Area
+    autoSignatures: false
+}
+
+ +
+ + +
+
+
+
+ + + + diff --git a/modding/bbs-list.html b/modding/bbs-list.html new file mode 100644 index 00000000..ea474aa3 --- /dev/null +++ b/modding/bbs-list.html @@ -0,0 +1,2318 @@ + + + + + + + + + + + +BBS List | ENiGMA½ BBS Software + + + + + + + + + + + + + + + + + +
+ +
+
+
+ + +
+

BBS List

+

The BBS List Module

+

The built in bbs_list module provides the ability for users to manage entries to other Bulletin Board Systems.

+ +

Configuration

+

Config Block

+

Available config block entries:

+
    +
  • youSubmittedFormat: Provides a format for entries that were submitted (and therefor ediable) by the current user. Defaults to '{submitter} (You!)'. Utilizes the same itemFormat object as entries described below.
  • +
+ +

Theming

+

The following itemFormat object is provided to MCI 1 (ie: %VM1) (the BBS list):

+
    +
  • id: Row ID
  • +
  • bbsName: System name. Note that {text} also contains this value.
  • +
  • sysOp: System Operator
  • +
  • telnet: Telnet address
  • +
  • www: Web address
  • +
  • location: System location
  • +
  • software: System’s software
  • +
  • submitter: Username of entry submitter
  • +
  • submitterUserId: User ID of submitter
  • +
  • notes: Any additional notes about the system
  • +
+ +
+ + +
+
+
+
+ + + + diff --git a/modding/door-servers.html b/modding/door-servers.html new file mode 100644 index 00000000..a5486e4e --- /dev/null +++ b/modding/door-servers.html @@ -0,0 +1,2348 @@ + + + + + + + + + + + +Door Servers | ENiGMA½ BBS Software + + + + + + + + + + + + + + + + + +
+ +
+
+
+ + +
+

Door Servers

+ +

Native support for BBSLink doors is provided via the bbs_link module.

+ +

Configuration for a BBSLink door is straight forward. Take a look at the following example for launching Tradewars 2002:

+ +
doorTradeWars2002BBSLink: {
+	desc: Playing TW 2002 (BBSLink)
+	module: bbs_link
+	config: {
+		sysCode: XXXXXXXX
+		authCode: XXXXXXXX
+		schemeCode: XXXXXXXX
+		door: tw
+	}
+}
+
+
+ +

Fill in your credentials in sysCode, authCode, and schemeCode and that’s it!

+ +

The door_party Module

+

The module door_party provides native support for DoorParty! Configuration is quite easy:

+ +
doorParty: {
+    desc: Using DoorParty!
+    module: door_party
+    config: {
+        username: XXXXXXXX
+        password: XXXXXXXX
+        bbsTag: XX
+    }
+}
+
+ +

Fill in username, password, and bbsTag with credentials provided to you and you should be in business!

+ +

The CombatNet Module

+

The combatnet module provides native support for CombatNet. Add the following to your menu config:

+ +
combatNet: {
+    desc: Using CombatNet
+    module: combatnet
+    config: {
+        bbsTag: CBNxxx
+        password: XXXXXXXXX
+    }
+}
+
+

Update bbsTag (in the format CBNxxx) and password with the details provided when you register, then +you should be ready to rock!

+ +

The Exodus Module

+ +

TBC

+ +
+ + +
+
+
+
+ + + + diff --git a/modding/existing-mods.html b/modding/existing-mods.html new file mode 100644 index 00000000..95b16e09 --- /dev/null +++ b/modding/existing-mods.html @@ -0,0 +1,2324 @@ + + + + + + + + + + + +Existing Mods | ENiGMA½ BBS Software + + + + + + + + + + + + + + + + + +
+ +
+
+
+ + +
+

Existing Mods

+

Many “addon” modules exist and have been released. Below are a few:

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
NameAuthorDescription
Married Bob Fetch EventNuSkoolerAn event for fetching the latest Married Bob ANSI’s for display on you board. ACiDic release ACD-MB4E.ZIP. Can also be found on GitHub
Latest Files AnnouncementNuSkoolerAn event for posting the latest file arrivals of your board to message areas such as FTN style networks. ACiDic release ACD-LFA1.ZIP. Also found on GitHub
Message Post EventNuSkoolerAn event for posting messages/ads to networks. ACiDic release ACD-MP4E.ZIP
+ +

See also ACiDic BBS Mods by NuSkooler

+ +
+ + +
+
+
+
+ + + + diff --git a/modding/file-area-list.html b/modding/file-area-list.html new file mode 100644 index 00000000..8b036ca6 --- /dev/null +++ b/modding/file-area-list.html @@ -0,0 +1,2405 @@ + + + + + + + + + + + +File Area List | ENiGMA½ BBS Software + + + + + + + + + + + + + + + + + +
+ +
+
+
+ + +
+

File Area List

+

The File Area List Module

+

The built in file_area_list module provides a very flexible file listing UI.

+ +

Configuration

+

Config Block

+

Available config block entries:

+
    +
  • art: Sub-configuration block used to establish art files used for file browsing: +
      +
    • browse: The main browse screen.
    • +
    • details: The main file details screen.
    • +
    • detailsGeneral: The “general” tab of the details page.
    • +
    • detailsNfo: The “NFO” viewer tab of the detials page.
    • +
    • detailsFileList: The file listing tab of the details page (ie: used for listing archive contents).
    • +
    • help: The help page.
    • +
    +
  • +
  • hashTagsSep: Separator for hash entries. Defaults to “, “.
  • +
  • isQueuedIndicator: Indicator for items that are in the users download queue. Defaults to “Y”.
  • +
  • isNotQueuedIndicator: Indicator for items that are not in the users download queue. Defaults to “N”.
  • +
  • userRatingTicked: Indicator for a items current n/5 “star” rating. Defaults to “*”. userRatingTicked and userRatingUnticked are combined to build strings such as “***–” for 3/5 rating.
  • +
  • userRatingUnticked: Indicator for missing “stars” in a items n/5 rating. Defaults to “-“. userRatingTicked and userRatingUnticked are combined to build strings such as “***–” for 3/5 rating.
  • +
  • webDlExpireTimeFormat: Presents the expiration time of a web download URL. Defaults to current theme → system short date/time format.
  • +
  • webDlLinkNeedsGenerated: Text to present when no web download link is yet generated. Defaults to “Not yet generated”.
  • +
  • webDlLinkNoWebserver: Text to present when no web download is available (ie: webserver not enabled). Defaults to “Web server is not enabled”.
  • +
  • notAnArchiveFormat: Presents text for the “archive type” field for non-archives. Defaults to “Not an archive”.
  • +
  • uploadTimestampFormat: Timestamp format for xxxxxxInfoFormat##. Defaults to current theme → system short date format. See also Custom Info Formats below.
  • +
+ +

Remember that entries such as isQueuedIndicator and userRatingTicked may contain pipe color codes!

+ +

Custom Info Formats

+

Additional config block entries can set xxxxxxInfoFormat## formatting (where xxxxxx is the page name and ## is 10…99 such as browseInfoFormat10) for the various available pages:

+
    +
  • browseInfoFormat## for the browse page. See Browse Page below.
  • +
  • detailsInfoFormat## for the details page. See Details Page below.
  • +
  • detailsGeneralInfoFormat## for the detailsGeneral tab. See Details Page - General Tab below.
  • +
  • detailsNfoInfoFormat## for the detialsNfo tab. See Details Page - NFO/README Viewer Tab below.
  • +
  • detailsFileListInfoFormat## for the detailsFileList tab. See Details Page - Archive/File Listing Tab below.
  • +
+ +

Theming

+

Browse Page

+

The browse page uses the browse art described above. The following MCI codes are available:

+
    +
  • MCI 1 (ie: %MT1): File’s short description (user entered, FILE_ID.DIZ, etc.).
  • +
  • MCI 2 (ie: %HM2): Navigation menu.
  • +
  • MCI 10…99: Custom entires with the following format members: +
      +
    • {fileId}: File identifier.
    • +
    • {fileName}: File name (long).
    • +
    • {desc}: File short description (user entered, FILE_ID.DIZ, etc.).
    • +
    • {descLong}: File’s long description (README.TXT, SOMEGROUP.NFO, etc.).
    • +
    • {uploadByUserName}: User name of user that uploaded this file, or “N/A”.
    • +
    • {uploadByUserId}: User ID of user that uploaded this file, or “N/A”.
    • +
    • {userRating}: User rating of file as a number.
    • +
    • {userRatingString}: User rating of this file as a string formatted with userRatingTicked and userRatingUnticked described above.
    • +
    • {areaTag}: Area tag.
    • +
    • {areaName}: Area name or “N/A”.
    • +
    • {areaDesc}: Area description or “N/A”.
    • +
    • {fileSha256}: File’s SHA-256 value in hex.
    • +
    • {fileMd5}: File’s MD5 value in hex.
    • +
    • {fileSha1}: File’s SHA1 value in hex.
    • +
    • {fileCrc32}: File’s CRC-32 value in hex.
    • +
    • {estReleaseYear}: Estimated release year of this file.
    • +
    • {dlCount}: Number of times this file has been downloaded.
    • +
    • {byteSize}: Size of this file in bytes.
    • +
    • {archiveType}: Archive type of this file determined by system mappings, or “N/A”.
    • +
    • {archiveTypeDesc}: A more descriptive archive type based on system mappings, file extention, etc. or “N/A” if it cannot be determined.
    • +
    • {shortFileName}: Short DOS style 8.3 name available for some scenarios such as TIC import, or “N/A”.
    • +
    • {ticOrigin}: Origin from TIC imported files “Origin” field, or “N/A”.
    • +
    • {ticDesc}: Description from TIC imported files “Desc” field, or “N/A”.
    • +
    • {ticLDesc}: Long description from TIC imported files “LDesc” field joined by a line feed, or “N/A”.
    • +
    • {uploadTimestamp}: Upload timestamp formatted with browseUploadTimestampFormat.
    • +
    • {hashTags}: A string of hash tags(s) separated by hashTagsSep described above. “(none)” if there are no tags.
    • +
    • {isQueued}: Indicates if a item is currently in the user’s download queue presented as isQueuedIndicator or isNotQueuedIndicator described above.
    • +
    • {webDlLink}: Web download link if generated else webDlLinkNeedsGenerated or webDlLinkNoWebserver described above.
    • +
    • {webDlExpire}: Web download link expiration using webDlExpireTimeFormat described above.
    • +
    +
  • +
+ +

Details Page

+

The details page uses the details art described above. The following MCI codes are available:

+
    +
  • MCI 1 (ie: %HM1): Navigation menu
  • +
  • %XY2: Info area’s top X,Y position.
  • +
  • %XY3: Info area’s bottom X,Y position.
  • +
  • MCI 10…99: Custom entries with the format options described above in Browse Page via the detailsInfoFormat## config block entry.
  • +
+ +

Details Page - General Tab

+

The details page general tab uses the detailsGeneral art described above. The following MCI codes are available:

+
    +
  • MCI 10…99: Custom entries with the format options described above in Browse Page via the detailsGeneralInfoFormat## config block entry.
  • +
+ +

Details Page - NFO/README Viewer Tab

+

The details page nfo tab uses the detailsNfo art described above. The following MCI codes are available:

+
    +
  • MCI 1 (ie: %MT1): NFO/README viewer using the entries longDesc.
  • +
  • MCI 10…99: Custom entries with the format options described above in Browse Page via the detailsNfoInfoFormat## config block entry.
  • +
+ +

Details Page - Archive/File Listing Tab

+

The details page file list tab uses the detailsFileList art described above. The following MCI codes are available:

+
    +
  • MCI 1 (ie: %VM1): List of entries in archive. Entries are formatted using the standard itemFormat and focusItemFormat properties of the view and have all of the format options described above in Browse Page.
  • +
  • MCI 10…99: Custom entries with the format options described above in Browse Page via the detailsFileListInfoFormat## config block entry.
  • +
+ + +
+ + +
+
+
+
+ + + + diff --git a/modding/file-base-download-manager.html b/modding/file-base-download-manager.html new file mode 100644 index 00000000..9c083e26 --- /dev/null +++ b/modding/file-base-download-manager.html @@ -0,0 +1,2317 @@ + + + + + + + + + + + +File Base Download Manager | ENiGMA½ BBS Software + + + + + + + + + + + + + + + + + +
+ +
+
+
+ + +
+

File Base Download Manager

+

File Base Download Manager Module

+

The file_base_download_manager module provides a download queue manager for “legacy” (X/Y/Z-Modem, etc.) downloads. Web (HTTP/HTTPS) download functionality can be optionally available when the web content server is enabled.

+ +

Configuration

+

Configuration Block

+

Available config block entries:

+
    +
  • webDlExpireTimeFormat: Sets the moment.js style format for web download expiration date/time.
  • +
  • fileTransferProtocolSelection: Overrides the default fileTransferProtocolSelection target for a protocol selection menu.
  • +
  • emptyQueueMenu: Overrides the default fileBaseDownloadManagerEmptyQueue target for menu to show when the users D/L queue is empty.
  • +
+ +

Theming

+

The following itemFormat object is provided to MCI 1 (ie: %VM1) and MCI 10+ custom fields:

+
    +
  • fileId: File ID.
  • +
  • areaTag: Area tag.
  • +
  • fileName: Entry filename.
  • +
  • path: Full file path.
  • +
  • byteSize: Size in bytes of file.
  • +
  • webDlLink: Web download link including VTX style ANSI ESC sequences.
  • +
  • webDlExpire: Expiration date/time for this link. Formatted using webDlExpireTimeFormat.
  • +
+ +
+ + +
+
+
+
+ + + + diff --git a/modding/file-base-web-download-manager.html b/modding/file-base-web-download-manager.html new file mode 100644 index 00000000..3b070d83 --- /dev/null +++ b/modding/file-base-web-download-manager.html @@ -0,0 +1,2320 @@ + + + + + + + + + + + +File Base Web Download Manager | ENiGMA½ BBS Software + + + + + + + + + + + + + + + + + +
+ +
+
+
+ + +
+

File Base Web Download Manager

+

File Base Web Download Manager Module

+

The file_base_web_download_manager module provides a download queue manager for web (HTTP/HTTPS) based downloads. This module relies on having the web server enabled at a minimum.

+ +

Web downloads can be a convienent way for users to download larger (100+ MiB) files where legacy protocols often have trouble. Additionally, batch downloads can be streamed to users in a single zip archive.

+ +

Configuration

+

Configuration Block

+

Available config block entries:

+
    +
  • webDlExpireTimeFormat: Sets the moment.js style format for web download expiration date/time.
  • +
  • emptyQueueMenu: Overrides the default fileBaseDownloadManagerEmptyQueue target for menu to show when the users D/L queue is empty.
  • +
+ +

Theming

+

The following itemFormat object is provided to MCI 1 (ie: %VM1) and custom range MCI 10+ custom fields:

+
    +
  • fileId: File ID.
  • +
  • areaTag: Area tag.
  • +
  • fileName: Entry filename.
  • +
  • path: Full file path.
  • +
  • byteSize: Size in bytes of file.
  • +
  • webDlLinkRaw: Web download link.
  • +
  • webDlLink: Web download link including VTX style ANSI ESC sequences.
  • +
  • webDlExpire: Expiration date/time for this link. Formatted using webDlExpireTimeFormat.
  • +
+ + +
+ + +
+
+
+
+ + + + diff --git a/modding/file-transfer-protocol-select.html b/modding/file-transfer-protocol-select.html new file mode 100644 index 00000000..d7d489d5 --- /dev/null +++ b/modding/file-transfer-protocol-select.html @@ -0,0 +1,2305 @@ + + + + + + + + + + + +File Transfer Protocol Select | ENiGMA½ BBS Software + + + + + + + + + + + + + + + + + +
+ +
+
+
+ + +
+

File Transfer Protocol Select

+

The Rumorz Module

+

The built in file_transfer_protocol_select module provides a way to select a legacy file transfer protocol (X/Y/Z-Modem, etc.) for upload/downloads.

+ +

Configuration

+ +

Theming

+

The following itemFormat object is provided to MCI 1 (ie: %VM1) (the protocol list):

+
    +
  • name: The name of the protocol. Each entry is +op defined in config.hjson with defaults found in config_default.js. Note that the standard {text} field also contains this value.
  • +
+ + +
+ + +
+
+
+
+ + + + diff --git a/modding/last-callers.html b/modding/last-callers.html new file mode 100644 index 00000000..57000559 --- /dev/null +++ b/modding/last-callers.html @@ -0,0 +1,2342 @@ + + + + + + + + + + + +Last Callers | ENiGMA½ BBS Software + + + + + + + + + + + + + + + + + +
+ +
+
+
+ + +
+

Last Callers

+

The Last Callers Module

+

The built in last_callers module provides flexible retro last callers mod.

+ +

Configuration

+

Config Block

+

Available config block entries:

+
    +
  • dateTimeFormat: moment.js style format. Defaults to current theme → system short format.
  • +
  • user: User options: +
      +
    • collapse: Collapse or roll up entries that fall within the period specified. May be a string in the form of 30 minutes, 3 weeks, 1 hour, etc.
    • +
    +
  • +
  • sysop: Sysop options: +
      +
    • collapse: Collapse or roll up entries that fall within the period specified. May be a string in the form of 30 minutes, 3 weeks, 1 hour, etc.
    • +
    • hide: Hide all +op logins
    • +
    +
  • +
  • actionIndicators: Maps user events/actions to indicators. For example: userDownload to “D”. Available indicators: +
      +
    • newUser: User is new.
    • +
    • dlFiles: User downloaded file(s).
    • +
    • ulFiles: User uploaded file(s).
    • +
    • postMsg: User posted message(s) to the message base, EchoMail, etc.
    • +
    • sendMail: User sent private mail.
    • +
    • runDoor: User ran door(s).
    • +
    • sendNodeMsg: User sent a node message(s).
    • +
    • achievementEarned: User earned an achievement(s).
    • +
    +
  • +
  • actionIndicatorDefault: Default indicator when an action is not set. Defaults to “-“.
  • +
+ +

Remember that entries such as actionIndicators and actionIndicatorDefault may contain pipe color codes!

+ +

Theming

+

The following itemFormat object is provided to MCI 1 (ie: %VM1):

+
    +
  • userId: User ID.
  • +
  • userName: Login username.
  • +
  • realName: User’s real name.
  • +
  • ts: Timestamp in dateTimeFormat format.
  • +
  • location: User’s location.
  • +
  • affiliation or affils: Users affiliations.
  • +
  • actions: A string built by concatenating action indicators for a users logged in session. For example, given a indicator of userDownload mapped to “D”, the string may be “-D—-“. The format was made popular on Amiga style boards.
  • +
+ + +
+ + +
+
+
+
+ + + + diff --git a/modding/local-doors.html b/modding/local-doors.html new file mode 100644 index 00000000..507677c5 --- /dev/null +++ b/modding/local-doors.html @@ -0,0 +1,2642 @@ + + + + + + + + + + + +Local Doors | ENiGMA½ BBS Software + + + + + + + + + + + + + + + + + +
+ +
+
+
+ + +
+

Local Doors

+

Local Doors

+

ENiGMA½ has many ways to add doors to your system. In addition to the many built in door server modules, local doors are of course also supported using the ! The abracadabra module!

+ +

:information_source: See also Let’s add a DOS door to Enigma½ BBS by Robbie Whiting for a great writeup on adding doors!

+ +

The abracadabra Module

+

The abracadabra module provides a generic and flexible solution for many door types. Through this module you can execute native processes & scripts directly, and perform I/O through standard I/O (stdio) or a temporary TCP server.

+ +

Configuration

+

The abracadabra config block can contain the following members:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ItemRequiredDescription
name:+1:Used as a key for tracking number of clients using a particular door.
dropFileType:-1:Specifies the type of dropfile to generate (See Dropfile Types below). Can be omitted or set to none.
cmd:+1:Path to executable to launch.
args:-1:Array of argument(s) to pass to cmd. See Argument Variables below for information on variables that can be used here.
cwd:-1:Sets the Current Working Directory (CWD) for cmd. Defaults to the directory of cmd.
env:-1:Sets the environment. Supplied in the form of an map: { SOME_VAR: "value" } +
nodeMax:-1:Max number of nodes that can access this door at once. Uses name as a tracking key.
tooManyArt:-1:Art spec to display if too many instances are already in use.
io:-1:How to process input/output (I/O). Can be stdio or socket. When using stdio, I/O is handled via standard stdin/stdout. When using socket a temporary socket server is spawned that can be connected back to. The server listens on localhost on {srvPort} (See Argument Variables below for more information). Default value is stdio.
encoding:-1:Sets the door’s encoding. Defaults to cp437. Linux binaries often produce utf8.
+ +

Dropfile Types

+

Dropfile types specified by dropFileType:

+ + + + + + + + + + + + + + + + + + + + + + +
ValueDescription
DOORDOOR.SYS
DOOR32DOOR32.SYS
DORINFODORINFOx.DEF
+ +

Argument Variables

+

The following variables may be used in args entries:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
VariableDescriptionExample
{node}Current node number.1
{dropFile}Dropfile filename only.DOOR.SYS
{dropFilePath}Full path to generated dropfile. The system places dropfiles in the path set by paths.dropFiles in config.hjson.C:\enigma-bbs\drop\node1\DOOR.SYS
{userId}Current user ID.420
{userName} +Sanitized username. Safe for filenames, etc. If the full username is sanitized away, this will resolve to something like “user_1234”.izard
{userNameRaw} +Raw username. May not be safe for filenames!\/\/izard
{srvPort}Temporary server port when io is set to socket.1234
{cwd}Current Working Directory./home/enigma-bbs/doors/foo/
+ +

Example args member using some variables described above:

+
args: [
+    "-D", "{dropFilePath}",
+    "-N", "{node}"
+    "-U", "{userId}"
+]
+
+ +

DOSEMU with abracadabra

+

DOSEMU can provide a good solution for running legacy DOS doors when running on Linux systems. For this, we will create a virtual serial port (COM1) that communicates via stdio.

+ +

As an example, here are the steps for setting up Pimp Wars:

+ +

First, create a dosemu.conf file with the following contents:

+
$_cpu = "80486"
+$_cpu_emu = "vm86"
+$_external_char_set = "utf8"
+$_internal_char_set = "cp437"
+$_term_updfreq = (8)
+$_layout = "us"
+$_rawkeyboard = (0)
+$_com1 = "virtual"
+
+ +

The line $_com1 = "virtual" tells DOSEMU to use stdio as a virtual serial port on COM1.

+ +

Next, we create a virtual X drive for Pimp Wars to live such as /enigma-bbs/DOS/X/PW and map it with a custom AUTOEXEC.BAT file within DOSEMU:

+
@echo off
+path d:\bin;d:\gnu;d:\dosemu
+set TEMP=c:\tmp
+prompt $P$G
+REM http://www.pcmicro.com/bnu/
+C:\BNU\BNU.COM /L0:57600,8N1 /F
+lredir.com x: linux\fs\enigma-bbs\DOS\X
+unix -e
+
+ +

Note that we also have the BNU FOSSIL driver installed at C:\BNU\\. Another option would be to install this to X: somewhere as well.

+ +

Finally, let’s create a menu.hjson entry to launch the game:

+
doorPimpWars: {
+    desc: Playing PimpWars
+    module: abracadabra
+    config: {
+        name: PimpWars
+        dropFileType: DORINFO
+        cmd: /usr/bin/dosemu
+        args: [
+            "-quiet",
+            "-f",
+            "/path/to/dosemu.conf",
+            "X:\\PW\\START.BAT {dropFile} {node}"
+        ],
+        nodeMax: 1
+        tooManyArt: DOORMANY
+        io: stdio
+    }
+}
+
+ +

Shared Socket Descriptors

+

Due to Node.js limitations, ENiGMA½ does not directly support DOOR32.SYS style socket descriptor sharing (other DOOR32.SYS features are fully supported). However, a separate binary called bivrost! can be used. bivrost! is available for Windows and Linux x86/i686 and x86_64/AMD64. Other platforms where Rust builds are likely to work as well.

+ +

Example configuration

+

Below is an example menu.hjson entry using bivrost! to launch a door:

+ +
doorWithBivrost: {
+    desc: Bivrost Example
+    module: abracadabra
+    config: {
+        name: BivrostExample
+        dropFileType: DOOR32
+        cmd: "C:\\enigma-bbs\\utils\\bivrost.exe"
+        args: [
+            "--port", "{srvPort}",          //  bivrost! will connect this port on localhost
+            "--dropfile", "{dropFilePath}", //  ...and read this DOOR32.SYS produced by ENiGMA½
+            "--out", "C:\\doors\\jezebel",  //  ...and produce a NEW DOOR32.SYS here.
+
+            //
+            //  Note that the final <target> params bivrost! will use to
+            //  launch the door are grouped here. The {fd} variable could
+            //  also be supplied here if needed.
+            //
+            "C:\\door\\door.exe C:\\door\\door32.sys"
+        ],
+        nodeMax: 1
+        tooManyArt: DOORMANY
+        io: socket
+    }
+}
+
+ +

Please see the bivrost! documentation for more information.

+ +

Phenom Productions Releases

+

Pre-built binaries of bivrost! have been released under Phenom Productions and can be found on various boards.

+ +

Alternative Workarounds

+

Alternative workarounds include Telnet Bridge module to hook up Telnet-accessible (including local) door servers – It may also be possible bridge via NET2BBS.

+ +

QEMU with abracadabra

+

QEMU provides a robust, cross platform solution for launching doors under many platforms (likely anywhere Node.js is supported and ENiGMA½ can run). Note however that there is an important and major caveat: Multiple instances of a particular door/OS image should not be run at once! Being more flexible means being a bit more complex. Let’s look at an example for running L.O.R.D. under a UNIX like system such as Linux or FreeBSD.

+ +

Basically we’ll be creating a bootstrap shell script that generates a temporary node specific GO.BAT to launch our door. This will be called from AUTOEXEC.BAT within our QEMU FreeDOS partition.

+ +

Step 1: Create a FreeDOS image

+

FreeDOS is a free mostly MS-DOS compatible DOS package that works well for running 16bit doors. Follow the QEMU/FreeDOS guide for creating an freedos_c.img. This will contain FreeDOS itself and installed BBS doors.

+ +

After this is complete, copy LORD to C:\DOORS\LORD within FreeDOS. An easy way to tranfer files from host to DOS is to use QEMU’s vfat as a drive. For example:

+
qemu-system-i386 -localtime /home/enigma/dos/images/freedos_c.img -hdb fat:/path/to/downloads
+
+ +

With the above you can now copy files from D: to C: within FreeDOS and add the following to it’s autoexec.bat:

+
CALL E:\GO.BAT
+
+ +

Step 2: Create a bootstrap script

+

Our bootstrap script will prepare GO.BAT and launch FreeDOS. Below is an example:

+ +
#!/bin/bash
+
+NODE=$1
+DROPFILE=D:\\$2
+SRVPORT=$3
+
+mkdir -p /home/enigma/dos/go/node$NODE
+
+cat > /home/enigma/dos/go/node$NODE/GO.BAT <<EOF
+C:
+CD \FOSSIL\BNU
+BNU.COM
+CD \DOORS\LORD
+COPY /Y $DROPFILE
+CALL START.BAT $NODE
+FDAPM POWEROFF
+EOF
+
+unix2dos /home/enigma/dos/go/node$NODE/GO.BAT
+
+qemu-system-i386 -localtime /home/enigma/dos/images/freedos_c.img -chardev socket,port=$SRVPORT,nowait,host=localhost,id=s0 -device isa-serial,chardev=s0 -hdb fat:/home/enigma/xibalba/dropfiles/node$NODE -hdc fat:/home/enigma/dos/go/node$NODE -nographic
+
+ +

Note the qemu-system-i386 line. We’re telling QEMU to launch and use localtime for the clock, create a character device that connects to our temporary server port on localhost and map that to a serial device. The -hdb entry will represent the D: drive where our dropfile is generated, while -hdc is the path that GO.BAT is generated in (E:\GO.BAT). Finally we specify -nographic to run headless.

+ +

For doors that do not require a FOSSIL driver, it is recommended to not load or use one unless you are having issues.

+ +
Step 3: Create a menu entry
+

Finally we can create a menu.hjson entry using the abracadabra module:

+
doorLORD: {
+    desc: Playing L.O.R.D.
+    module: abracadabra
+    config: {
+        name: LORD
+        dropFileType: DOOR
+        cmd: /home/enigma/dos/scripts/lord.sh
+        args: [
+            "{node}",
+            "{dropFile}",
+            "{srvPort}",
+        ],
+        nodeMax: 1
+        tooManyArt: DOORMANY
+        io: socket
+    }
+}
+
+ +

See Also

+ + +

Additional Resources

+

DOS Emulation

+ + +

Door Downloads & Support Sites

+

General

+
    +
  • http://bbsfiles.com/
  • +
  • http://bbstorrents.bbses.info/
  • +
+ +

L.O.R.D.

+
    +
  • http://lord.lordlegacy.com/
  • +
+ +
+ + +
+
+
+
+ + + + diff --git a/modding/menu-modules.html b/modding/menu-modules.html new file mode 100644 index 00000000..699819d1 --- /dev/null +++ b/modding/menu-modules.html @@ -0,0 +1,2303 @@ + + + + + + + + + + + +Menu Modules | ENiGMA½ BBS Software + + + + + + + + + + + + + + + + + +
+ +
+
+
+ + +
+

Menu Modules

+ +

Menu entries found within menu.hjson are backed by menu modules.

+ +

Creating a New Module

+

TODO

+ +

Lifecycle

+

TODO

+ + +
+ + +
+
+
+
+ + + + diff --git a/modding/msg-area-list.html b/modding/msg-area-list.html new file mode 100644 index 00000000..0ddaecb8 --- /dev/null +++ b/modding/msg-area-list.html @@ -0,0 +1,2311 @@ + + + + + + + + + + + +Message Area List | ENiGMA½ BBS Software + + + + + + + + + + + + + + + + + +
+ +
+
+
+ + +
+

Message Area List

+

The Message Area List Module

+

The built in msg_area_list module provides a menu to display and change between message areas in the users current conference.

+ +

Theming

+

The following itemFormat object is provided to MCI 1 (ie: %VM1):

+
    +
  • index: 1-based index into list.
  • +
  • areaTag: Area tag.
  • +
  • name or text: Display name.
  • +
  • desc: Description.
  • +
+ +

The following additional MCIs are updated as the user changes selections in the main list:

+
    +
  • MCI 2 (ie: %TL2 or %M%2) is updated with the area description.
  • +
  • MCI 10+ (ie %TL10…) are custom ranges updated with the same information available above in itemFormat. Use areaListItemFormat##.
  • +
+ +
+ + +
+
+
+
+ + + + diff --git a/modding/msg-conf-list.html b/modding/msg-conf-list.html new file mode 100644 index 00000000..e708bf9f --- /dev/null +++ b/modding/msg-conf-list.html @@ -0,0 +1,2312 @@ + + + + + + + + + + + +Message Conference List | ENiGMA½ BBS Software + + + + + + + + + + + + + + + + + +
+ +
+
+
+ + +
+

Message Conference List

+

The Message Conference List Module

+

The built in msg_conf_list module provides a menu to display and change between message conferences.

+ +

Theming

+

The following itemFormat object is provided to MCI 1 (ie: %VM1):

+
    +
  • index: 1-based index into list.
  • +
  • confTag: Conference tag.
  • +
  • name or text: Display name.
  • +
  • desc: Description.
  • +
  • areaCount: Number of areas in this conference.
  • +
+ +

The following additional MCIs are updated as the user changes selections in the main list:

+
    +
  • MCI 2 (ie: %TL2 or %M%2) is updated with the conference description.
  • +
  • MCI 10+ (ie %TL10…) are custom ranges updated with the same information available above in itemFormat.
  • +
+ +
+ + +
+
+
+
+ + + + diff --git a/modding/node-msg.html b/modding/node-msg.html new file mode 100644 index 00000000..2b2043e6 --- /dev/null +++ b/modding/node-msg.html @@ -0,0 +1,2343 @@ + + + + + + + + + + + +Node to Node Messaging | ENiGMA½ BBS Software + + + + + + + + + + + + + + + + + +
+ +
+
+
+ + +
+

Node to Node Messaging

+

The Node to Node Messaging Module

+

The node to node messaging (node_msg) module allows users to send messages to one or more users on different nodes. Messages delivered to nodes follow standard User Interruption rules.

+ +

Configuration

+

Config Block

+

Available config block entries:

+
    +
  • dateTimeFormat: moment.js style format. Defaults to current theme → system short format.
  • +
  • messageFormat: Format string for sent messages. Defaults to Message from {fromUserName} on node {fromNodeId}:\r\n{message}. The following format object members are available: +
      +
    • fromUserName: Username who sent the message.
    • +
    • fromRealName: Real name of user who sent the message.
    • +
    • fromNodeId: Node ID where the message was sent from.
    • +
    • message: User entered message. May contain pipe color codes.
    • +
    • timestamp: A timestamp formatted using dateTimeFormat above.
    • +
    +
  • +
  • art: Block containing: +
      +
    • header: Art spec for header to display with message.
    • +
    • footer: Art spec for footer to display with message.
    • +
    +
  • +
+ +

Theming

+

MCI Codes

+
    +
  1. Node selection. Must be a View that allows lists such as SpinnerMenuView (%SM1), HorizontalMenuView (%HM1), etc.
  2. +
  3. Message entry (%ET2).
  4. +
  5. Message preview (%TL3). A rendered (that is, pipe codes resolved) preview of the text in %ET2.
  6. +
+ +

10+: Custom using itemFormat. See below.

+ +

Item Format

+

The following itemFormat object is provided for MCI 1 and 10+ for the currently selected item/node:

+
    +
  • text: Node ID or “-ALL-“ (All nodes).
  • +
  • node: Node ID or -1 in the case of all nodes.
  • +
  • userId: User ID.
  • +
  • action: User’s action.
  • +
  • userName: Username.
  • +
  • realName: Real name.
  • +
  • location: User’s location.
  • +
  • affils: Affiliations.
  • +
  • timeOn: How long the user has been online (approx).
  • +
+ + +
+ + +
+
+
+
+ + + + diff --git a/modding/onelinerz.html b/modding/onelinerz.html new file mode 100644 index 00000000..0e88075b --- /dev/null +++ b/modding/onelinerz.html @@ -0,0 +1,2313 @@ + + + + + + + + + + + +Onelinerz | ENiGMA½ BBS Software + + + + + + + + + + + + + + + + + +
+ +
+
+
+ + +
+

Onelinerz

+

The Onelinerz Module

+

The built in onelinerz module provides a retro onelinerz system.

+ +

Configuration

+

Config Block

+

Available config block entries:

+
    +
  • dateTimeFormat: moment.js style format. Defaults to current theme → system short date format.
  • +
  • dbSuffix: Provide a suffix that will be appended to the DB name to use onelinerz for more than one purpose (separate lists).
  • +
+ +

Theming

+

The following itemFormat object is provided to MCI 1 (ie: %VM1):

+
    +
  • userId: User ID of the onliner entry.
  • +
  • userName: Login username of the onliner entry.
  • +
  • oneliner: The oneliner text. Note that the standard {text} field also contains this value.
  • +
  • ts: Timestamp of the entry formatted with dateTimeFormat format described above.
  • +
+ +
+ + +
+
+
+
+ + + + diff --git a/modding/rumorz.html b/modding/rumorz.html new file mode 100644 index 00000000..86ed13bc --- /dev/null +++ b/modding/rumorz.html @@ -0,0 +1,2304 @@ + + + + + + + + + + + +Rumorz | ENiGMA½ BBS Software + + + + + + + + + + + + + + + + + +
+ +
+
+
+ + +
+

Rumorz

+

The Rumorz Module

+

The built in rumorz module provides a classic interface for users to add and view rumorz!

+ +

Configuration

+ +

Theming

+

The following itemFormat object is provided to MCI 1 (ie: %VM1) (the rumor list):

+
    +
  • rumor: The rumor text. Also available in the standard {text} field.
  • +
+ +
+ + +
+
+
+
+ + + + diff --git a/modding/set-newscan-date.html b/modding/set-newscan-date.html new file mode 100644 index 00000000..9f513e05 --- /dev/null +++ b/modding/set-newscan-date.html @@ -0,0 +1,2329 @@ + + + + + + + + + + + +Set Newscan Date Module | ENiGMA½ BBS Software + + + + + + + + + + + + + + + + + +
+ +
+
+
+ + +
+

Set Newscan Date Module

+

Set Newscan Date Module

+

The set_newscan_date module allows setting newscan dates (aka pointers) for message conferences and areas as well as within the file base. Users can select specific conferences/areas or all (where applicable).

+ +

Configuration

+

Configuration Block

+

Available config block entries are as follows:

+
    +
  • target: Choose from message for message conferences & areas, or file for file base areas.
  • +
  • scanDateFormat: Format for scan date. This format must align with the output of the MaskEditView (%ME1) MCI utilized for input. Defaults to YYYYMMDD (which matches mask of ####/##/##).
  • +
+ +

Theming

+

Message Conference & Areas

+

When target is message, the following itemFormat object is provided to MCI 2 (ie: %SM2):

+
    +
  • conf: An object containing: +
      +
    • confTag: Conference tag.
    • +
    • name: Conference name. Also available in {text}.
    • +
    • desc: Conference description.
    • +
    +
  • +
  • area: An object containing: +
      +
    • areaTag: Area tag.
    • +
    • name: Area name. Also available in {text}.
    • +
    • desc: Area description.
    • +
    +
  • +
+ +

When dealing with the file base, ENiGMA½ does not currently have the ability to set newscan dates for specific areas. No %SM2 is used in this case.

+ +

Submit Actions

+

Submit action should map to @method:scanDateSubmit and provide scanDate in form data. For message conf/areas (target of message), targetSelection should be also be provided in form data: An index to the selected conf/area.

+ +
+ + +
+
+
+
+ + + + diff --git a/modding/show-art.html b/modding/show-art.html new file mode 100644 index 00000000..5d99d1c2 --- /dev/null +++ b/modding/show-art.html @@ -0,0 +1,2358 @@ + + + + + + + + + + + +The Show Art Module | ENiGMA½ BBS Software + + + + + + + + + + + + + + + + + +
+ +
+
+
+ + +
+

The Show Art Module

+

The Show Art Module

+

The built in show_art module add some advanced ways in which you can configure your system to display art assets beyond what a standard menu entry can provide. For example, based on user selection of a file or message base area.

+ +

Configuration

+

Config Block

+

Available config block entries:

+
    +
  • method: Set the method in which to show art. See Methods below.
  • +
  • optional: Is this art required or optional? If non-optional and we cannot show art based on method, it is an error.
  • +
  • key: Used for some methods. See Methods
  • +
+ +

Methods

+

Extra Args

+

When method is extraArgs, the module selects an art spec from a value found within extraArgs that were passed to show_art by key. Consider the following:

+ +

Given an menu.hjson entry:

+
showWithExtraArgs: {
+    module: show_art
+    config: {
+        method: extraArgs
+        key: fooBaz
+    }
+}
+
+

If the showWithExtraArgs menu was entered and passed extraArgs as the following:

+
{
+    "fizzBang" : true,
+    "fooBaz" : "LOLART"
+}
+
+ +

…then the system would use the art spec of LOLART.

+ +

Area & Conferences

+

Handy for inserting into File Base, Message Conferences, or Mesage Area selections selections. When method is fileBaseArea, messageConf, or messageArea the selected conf/area’s associated art spec is utilized. Example:

+ +

Given a file base entry in config.hjson:

+
areas: {
+    all_ur_base: {
+        name: All Your Base
+        desc: chown -r us ./base
+        art: ALLBASE
+    }
+}
+
+ +

A menu entry may look like this:

+
showFileBaseAreaArt: {
+    module: show_art
+    config: {
+        method: fileBaseArea
+        cls: true
+        pause: true
+        menuFlags: [ "popParent", "noHistory" ]
+    }
+}
+
+ +

…if the user choose the “All Your Base” area, the art spec of ALLBASE would be selected and displayed.

+ +

The only difference for messageConf or messageArea methods are where the art is defined (which is always next to the conf or area declaration in config.hjson).

+ +

While key can be overridden, the system uses areaTag for message/file area selections, and confTag for conference selections by default.

+ +
+ + +
+
+
+
+ + + + diff --git a/modding/telnet-bridge.html b/modding/telnet-bridge.html new file mode 100644 index 00000000..3bed57c5 --- /dev/null +++ b/modding/telnet-bridge.html @@ -0,0 +1,2386 @@ + + + + + + + + + + + +Telnet Bridge | ENiGMA½ BBS Software + + + + + + + + + + + + + + + + + +
+ +
+
+
+ + +
+

Telnet Bridge

+

Telnet Bridge

+

The telnet_bridge module allows “bridged” Telnet connections from your board to other Telnet services (such as other BBSes!).

+ +

Configuration

+

Config Block

+

Available config entries:

+
    +
  • host: Hostname or IP address to connect to.
  • +
  • port: Port to connect to. Defaults to the standard Telnet port of 23.
  • +
  • font: A SyncTERM style font. Useful for example if you would like to connect form a “DOS” style BBS to an Amiga. See the general art documentation on SyncTERM Style Fonts.
  • +
+ +

Example

+

Below is an example menu.hjson entry that would connect to Xibalba:

+ +
{
+    telnetBridgeXibalba: {
+        desc: Xibalba BBS
+        module: telnet_bridge
+        config: {
+            host: xibalba.l33t.codes
+            port: 45510
+        }
+    }
+}
+
+ +

Using Extra Args

+

The telnet_bridge module can also accept standard extraArgs of the same configuration arguments described above. This can be illustrated with an example:

+ +
telnetBridgeMenu: {
+    desc: Telnet Bridge
+    art: telnet_bridge
+    config: {
+        font: cp437
+    }
+    form: {
+        0: {
+            mci: {
+                VM1: {
+                    argName: selection
+
+                    items: [
+                        {
+                            board: BLACK Flag
+                            soft: Mystic
+                            data: bf
+                        }
+                        {
+                            board: Xibalba
+                            soft: ENiGMA½
+                            data: xib
+                        }
+                    ]
+
+                    //  sort by 'board' fields above
+                    sort: board
+                    submit: true
+                }
+            }
+
+            submit: {
+                *: [
+                    {
+                        value: { "selection" : "bf" }
+                        action: @menu:telnetBridgeFromExtraFlags
+                        extraArgs: {
+                            host: blackflag.acid.org
+                        }
+                    }
+                    {
+                        value: { "selection" : "xib" }
+                        action: @menu:telnetBridgeFromExtraFlags
+                        extraArgs: {
+                            host: xibalba.l33t.codes
+                            port: 44510
+                        }
+                    }
+                ]
+            }
+        }
+    }
+}
+
+telnetBridgeFromExtraFlags: {
+    desc: Telnet Bridge
+    module: telnet_bridge
+}
+
+ +

Here we’ve created a lightbar menu with custom items in which we’d use itemFormat’s with in a theme. When the user selects an item, the telnetBridgeFromExtraFlags menu is instantiated using the supplied extraArgs.

+ + +
+ + +
+
+
+
+ + + + diff --git a/modding/top-x.html b/modding/top-x.html new file mode 100644 index 00000000..8d51bea8 --- /dev/null +++ b/modding/top-x.html @@ -0,0 +1,2366 @@ + + + + + + + + + + + +TopX | ENiGMA½ BBS Software + + + + + + + + + + + + + + + + + +
+ +
+
+
+ + +
+

TopX

+

The TopX Module

+

The built in top_x module allows for displaying oLDSKOOL (?!) top user stats for the week, month, etc. Ops can configure what stat(s) are displayed and how far back in days the stats are considered.

+ +

Configuration

+

Config Block

+

Available config block entries:

+
    +
  • mciMap: Supplies a mapping of MCI code to data source. See mciMap below.
  • +
+ +

MCI Map (mciMap)

+

The mciMap config block configures MCI code mapping to data sources. Currently the following data sources (determined by type) are available:

+ + + + + + + + + + + + + + + + + + +
TypeDescription
userEventLogTop counts or sum of values found in the User Event Log.
userPropTop values (aka “scores”) from user properties.
+ +
User Event Log (userEventLog)
+

When type is set to userEventLog, entries from the User Event Log can be counted (ie: individual instances of a particular log item) or summed in the case of log items that have numeric values. The default is to sum.

+ +

Some current User Event Log value examples include ul_files, dl_file_bytes, or achievement_earned. See user_log_name.js for additional information.

+ +

Example userEventLog entry:

+
mciMap: {
+    1: { //  e.g.: %VM1
+        type: userEventLog
+        value: achievement_pts_earned // top achievement points earned
+        sum: true // this is the default
+        daysBack: 7 // omit daysBack for all-of-time
+    }
+}
+
+ +

User Properties (userProp)

+

When type is set to userProp, data is collected from individual user’s properties. For example a value of minutes_online_total_count. See user_property.js for more information.

+ +

Example userProp entry:

+
mciMap: {
+    2: { // e.g.: %VM2
+        type: userProp
+        value: minutes_online_total_count // top users by minutes spent on the board
+    }
+}
+
+ +

Theming

+

Generally mciMap entries will point to a Vertical List View Menu (%VM1, %VM2, etc.). The following itemFormat object is provided:

+
    +
  • value: The value acquired from the supplied data source.
  • +
  • userName: User’s username.
  • +
  • realName: User’s real name.
  • +
  • location: User’s location.
  • +
  • affils or affiliation: Users affiliations.
  • +
  • position: Rank position (numeric).
  • +
+ +

Remember that string format rules apply, so for example, if displaying top uploaded bytes (ul_file_bytes), a itemFormat may be {userName} - {value!sizeWithAbbr} yielding something like “TopDude - 4 GB”. See MCI for additional information.

+ +
+ + +
+
+
+
+ + + + diff --git a/modding/user-2fa-otp-config.html b/modding/user-2fa-otp-config.html new file mode 100644 index 00000000..b53c1789 --- /dev/null +++ b/modding/user-2fa-otp-config.html @@ -0,0 +1,2396 @@ + + + + + + + + + + + +2FA/OTP Config | ENiGMA½ BBS Software + + + + + + + + + + + + + + + + + +
+ +
+
+
+ + +
+

2FA/OTP Config

+

The 2FA/OTP Config Module

+

The user_2fa_otp_config module provides opt-in, configuration, and viewing of Two-Factor Authentication via One-Time-Password (2FA/OTP) settings. In order to allow users access to 2FA/OTP, the system must be properly configured. See Security for more information.

+ +

:information_source: By default, the 2FA/OTP configuration menu may only be accessed by users connected securely (ACS SC). It is highly recommended to leave this default as accessing these settings over a plain-text connection could expose private secrets!

+ +

Configuration

+ +

Config Block

+

Available config block entries:

+
    +
  • +infoText: Overrides default informational text string(s). See Info Text below.
  • +
  • +statusText: Overrides default status text string(s). See Status Text below.
  • +
+ +

Example:

+
config: {
+    infoText: {
+        googleAuth: Google Authenticator available on mobile phones, etc.
+    }
+    statusText: {
+        saveError: Doh! Failed to save :(
+    }
+}
+
+ +

Info Text (infoText)

+

Overrides default informational text relative to current selections. Available keys:

+
    +
  • +disabled: Displayed when OTP switched to enabled.
  • +
  • +enabled: Displayed when OTP switched to disabled.
  • +
  • +rfc6238_TOTP: Describes TOTP.
  • +
  • +rfc4266_HOTP: Describes HOTP.
  • +
  • +googleAuth: Describes Google Authenticator OTP.
  • +
+ +

Status Text (statusText)

+

Overrides default status text for various conditions. Available keys:

+
    +
  • otpNotEnabled
  • +
  • noBackupCodes
  • +
  • saveDisabled
  • +
  • saveEmailSent
  • +
  • saveError
  • +
  • qrNotAvail
  • +
  • emailRequired
  • +
+ +

Theming

+

The following MCI codes are available:

+
    +
  • MCI 1: (ie: TM1): Toggle 2FA/OTP enabled/disabled.
  • +
  • MCI 2: (ie: SM2): 2FA/OTP type selection.
  • +
  • MCI 3: (ie: TM3): Submit/cancel toggle.
  • +
  • MCI 10…99: Custom entries with the following format members available: +
      +
    • +{infoText}: Info Text for current selection.
    • +
    +
  • +
+ +

Web and Email Templates

+

A template system is also available to customize registration emails and the landing page.

+ +

Emails

+

Multipart MIME emails are send built using template files pointed to by users.twoFactorAuth.otp.registerEmailText and users.toFactorAuth.otp.registerEmailHtml supporting the following variables:

+
    +
  • +%BOARDNAME%: BBS name.
  • +
  • +%USERNAME%: Username receiving email.
  • +
  • +%TOKEN%: Temporary registration token generally used in URL.
  • +
  • +%REGISTER_URL%: Full registration URL.
  • +
+ +

Landing Page

+

The landing page template is pointed to by users.twoFactorAuth.otp.registerPageTemplate and supports the following variables:

+
    +
  • +%BOARDNAME%: BBS name.
  • +
  • +%USERNAME%: Username receiving email.
  • +
  • +%TOKEN%: Temporary registration token generally used in URL.
  • +
  • +%OTP_TYPE%: OTP type such as googleAuth.
  • +
  • +%POST_URL%: URL to POST form to.
  • +
  • +%QR_IMG_DATA%: QR code in URL image data format. Not always available depending on OTP type and will be set to blank in these cases.
  • +
  • +%SECRET%: Secret for manual entry.
  • +
+ +
+ + +
+
+
+
+ + + + diff --git a/modding/user-list.html b/modding/user-list.html new file mode 100644 index 00000000..4f1fa460 --- /dev/null +++ b/modding/user-list.html @@ -0,0 +1,2315 @@ + + + + + + + + + + + +User List | ENiGMA½ BBS Software + + + + + + + + + + + + + + + + + +
+ +
+
+
+ + +
+

User List

+

The User List Module

+

The built in user_list module provides basic user list functionality.

+ +

Configuration

+

Config Block

+

Available config block entries:

+
    +
  • dateTimeFormat: moment.js style format. Defaults to current theme → system short format.
  • +
+ +

Theming

+

The following itemFormat object is provided to MCI 1 (ie: %VM1):

+
    +
  • userId: User ID.
  • +
  • userName: Login username.
  • +
  • realName: User’s real name.
  • +
  • lastLoginTimestamp: Full last login timestamp for formatting use.
  • +
  • lastLoginTs: Last login timestamp formatted with dateTimeFormat style.
  • +
  • location: User’s location.
  • +
  • affiliation or affils: Users affiliations.
  • +
+ +
+ + +
+
+
+
+ + + + diff --git a/modding/whos-online.html b/modding/whos-online.html new file mode 100644 index 00000000..f6e6d3d1 --- /dev/null +++ b/modding/whos-online.html @@ -0,0 +1,2310 @@ + + + + + + + + + + + +Who’s Online | ENiGMA½ BBS Software + + + + + + + + + + + + + + + + + +
+ +
+
+
+ + +
+

Who's Online

+

The Who’s Online Module

+

The built in whos_online module provides a basic who’s online mod.

+ +

Theming

+

The following itemFormat object is provided to MCI 1 (ie: %VM1):

+
    +
  • userId: User ID.
  • +
  • userName: Login username.
  • +
  • node: Node ID the user is connected to.
  • +
  • timeOn: A human friendly amount of time the user has been online.
  • +
  • realName: User’s real name.
  • +
  • location: User’s location.
  • +
  • affiliation or affils: Users affiliations.
  • +
  • action: Current action/view in the system taken from the desc field of the current MenuModule they are interacting with. For example, “Playing L.O.R.D”.
  • +
+ + +
+ + +
+
+
+
+ + + + diff --git a/robots.txt b/robots.txt new file mode 100644 index 00000000..92159487 --- /dev/null +++ b/robots.txt @@ -0,0 +1 @@ +Sitemap: /enigma-bbs/sitemap.xml diff --git a/servers/contentservers/gopher.html b/servers/contentservers/gopher.html new file mode 100644 index 00000000..71b88762 --- /dev/null +++ b/servers/contentservers/gopher.html @@ -0,0 +1,2392 @@ + + + + + + + + + + + +Gopher Server | ENiGMA½ BBS Software + + + + + + + + + + + + + + + + + +
+ +
+
+
+ + +
+

Gopher Server

+

The Gopher Content Server

+

The Gopher content server provides access to publicly exposed message conferences and areas over Gopher (gopher://) as well as any other content you wish to serve in your Gopher Hole!

+ +

Configuration

+

Gopher configuration is found in contentServers.gopher in config.hjson.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ItemRequiredDescription
enabled:+1:Set to true to enable Gopher
staticRoot:+1:Sets the path serving as the static root path for all Gopher content. Defaults to enigma-bbs/gopher.
See also Gophermap’s below
port:-1:Override the default port of 8070 +
publicHostname:+1:Set the public hostname/domain that Gopher will serve to the outside world. Example: myfancybbs.com +
publicPort:+1:Set the public port that Gopher will serve to the outside world.
messageConferences:-1:An map of conference tags to area tags that are publicly exposed via Gopher. See example below.
+ +

Notes on publicHostname and publicPort: +The Gopher protocol serves content that contains host/domain and port even when referencing it’s own documents. Due to this, these members must be set to your publicly addressable Gopher server!

+ +

Gophermap’s

+

Gophermap’s are how to build menus for your Gopher Hole. Each map is a simple text file named gophermap (all lowercase, no extension) with DOS style CRLF endings.

+ +

Within any directory nested within your staticRoot may live a gophermap. A template may be found in the enigma-bbsmisc directory.

+ +

ENiGMA will pre-process gophermap files replacing in following variables:

+
    +
  • +{publicHostname}: The public hostname from your config.
  • +
  • +{publicPort}: The public port from your config.
  • +
+ +

:information_source: See Wikipedia for more information on the gophermap format.

+ +

:information_source: See RFC 1436 for the original Gopher spec.

+ +

:bulb: Tools such as gfu may help you with gophermap’s

+ +

Example Gophermap

+

An example gophermap living in enigma-bbs/gopher:

+
iWelcome to a Gopher server!        {publicHostname}    {publicPort}
+1Public Message Area    /msgarea    {publicHostname}    {publicPort}
+.
+
+ +

Example

+

Let’s suppose you are serving Gopher for your BBS at myfancybbs.com. Your ENiGMA½ system is listening on the default Gopher port of 8070 but you’re behind a firewall and want port 70 exposed to the public. Lastly, you want to expose some fsxNet areas:

+ +
contentServers: {
+    gopher: {
+        enabled: true
+        publicHostname: myfancybbs.com
+        publicPort: 70
+
+        //  Expose some public message conferences/areas
+        messageConferences: {
+            fsxnet: { // fsxNet's conf tag
+                // Areas of fsxNet we want to expose:
+                "fsx_gen", "fsx_bbs"
+            }
+        }
+    }
+}
+
+ +
+ + +
+
+
+
+ + + + diff --git a/servers/contentservers/nntp.html b/servers/contentservers/nntp.html new file mode 100644 index 00000000..1f487380 --- /dev/null +++ b/servers/contentservers/nntp.html @@ -0,0 +1,2420 @@ + + + + + + + + + + + +NNTP Server | ENiGMA½ BBS Software + + + + + + + + + + + + + + + + + +
+ +
+
+
+ + +
+

NNTP Server

+

The NNTP Content Server

+

The NNTP content server provides access to publicly exposed message conferences and areas over either secure NNTPS (NNTP over TLS or nttps://) and/or non-secure NNTP (nntp://).

+ +

Configuration

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
ItemRequiredDescription
nntp:-1:Configuration block for non-secure NNTP. See Non-Secure NNTP Configuration below.
nntps:-1:Configuration block for secure NNTP. See Secure NNTPS Configuration below.
publicMessageConferences:+1:A map of conference tags to area tags that are publicly exposed over NNTP. Anonymous users will get read-only access to these areas.
+ +

See Non-Secure NNTP Configuration

+

Under contentServers.nntp.nntp the following configuration is allowed:

+ + + + + + + + + + + + + + + + + + + + + +
ItemRequiredDescription
enabled:+1:Set to true to enable non-secure NNTP access.
port:-1:Override the default port of 8119.
+ +

Secure NNTPS Configuration

+

Under contentServers.nntp.nntps the following configuration is allowed:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ItemRequiredDescription
enabled:+1:Set to true to enable secure NNTPS access.
port:-1:Override the default port of 8565.
certPem:-1:Override the default certificate file path of ./config/nntps_cert.pem +
keyPem:-1:Override the default certificate key file path of ./config/nntps_key.pem +
+ +

Certificates and Keys

+

In order to use secure NNTPS, a TLS certificate and key pair must be provided. You may generate your own but most clients will not trust them. A certificate and key from a trusted Certificate Authority is recommended. Let’s Encrypt provides free TLS certificates. Certificates and private keys must be in PEM format.

+ +
Generating Your Own
+

An example of generating your own cert/key pair:

+
openssl req -newkey rsa:2048 -nodes -keyout ./config/nntps_key.pem -x509 -days 3050 -out ./config/nntps_cert.pem
+
+ +

Example Configuration

+
contentServers: {
+    nntp: {
+        publicMessageConferences: {
+            fsxnet: [
+                // Expose these areas of fsxNet
+                "fsx_gen", "fsx_bbs"
+            ]
+        }
+
+        nntp: {
+            enabled: true
+        }
+
+        nntps: {
+            enabled: true
+
+            // These could point to Let's Encrypt provided pairs for example:
+            certPem: /path/to/some/tls_cert.pem
+            keyPem: /path/to/some/tls_private_key.pem
+        }
+    }
+}
+
+ +
+ + +
+
+
+
+ + + + diff --git a/servers/contentservers/web-server.html b/servers/contentservers/web-server.html new file mode 100644 index 00000000..fd11c108 --- /dev/null +++ b/servers/contentservers/web-server.html @@ -0,0 +1,2431 @@ + + + + + + + + + + + +Web Server | ENiGMA½ BBS Software + + + + + + + + + + + + + + + + + +
+ +
+
+
+ + +
+

Web Server

+

ENiGMA½ comes with a built in content server for supporting both HTTP and HTTPS. Currently the File Bases registers routes for file downloads, password reset email links are handled via the server, and static files can also be served for your BBS. Other features will likely come in the future or you can easily write your own!

+ +

Configuration

+ +

By default the web server is not enabled. To enable it, you will need to at a minimum configure two keys in the contentServers.web section of config.hjson:

+ +
contentServers: {
+    web: {
+        domain: bbs.yourdomain.com
+
+        http: {
+            enabled: true
+            port: 8080
+        }
+    }
+}
+
+ +

The following is a table of all configuration keys available under contentServers.web:

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
KeyRequiredDescription
domain:+1:Sets the domain, e.g. bbs.yourdomain.com.
http:-1:Sub configuration for HTTP (non-secure) connections. See HTTP Configuration below.
overrideUrlPrefix:-1:Instructs the system to be explicit when handing out URLs. Useful if your server is behind a transparent proxy.
+ +

HTTP Configuration

+ +

Entries available under contentServers.web.http:

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
KeyRequiredDescription
enable:+1:Set to true to enable this server.
port:-1:Override the default port of 8080.
address:-1:Sets an explicit bind address.
+ +

HTTPS Configuration

+ +

Entries available under contentServers.web.https:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
KeyRequiredDescription
enable:+1:Set to true to enable this server.
port:-1:Override the default port of 8080.
address:-1:Sets an explicit bind address.
certPem:+1:Overrides the default certificate path of /config/https_cert.pem. Certificate must be in PEM format. See Certificates below.
keyPem:+1:Overrides the default certificate key path of /config/https_cert_key.pem. Key must be in PEM format. See Certificates below.
+ +

Certificates

+ +

If you don’t have a TLS certificate for your domain, a good source for a certificate can be Let’s Encrypt who supplies free and trusted TLS certificates. A common strategy is to place another web server such as Caddy in front of ENiGMA½ acting as a transparent proxy and TLS termination point.

+ +

:information_source: Keep in mind that the SSL certificate provided by Let’s Encrypt’s Certbot is by default stored in a privileged location; if your ENIGMA instance is not running as root (which it should not be!), you’ll need to copy the SSL certificate somewhere else in order for ENIGMA to use it.

+ +

Static Routes

+ +

Static files live relative to the contentServers.web.staticRoot path which defaults to enigma-bbs/www.

+ +

index.html, favicon.ico, and any error pages like 404.html are accessible from the route path. Other static assets hosted by the web server must be referenced from /static/, for example:

+ +
<a href="/static/about.html"> Example Link
+
+ +

Custom Error Pages

+ +

Customized error pages can be created for HTTP error codes by providing a <error_code>.html file in the static routes area. For example: 404.html.

+ +
+ + +
+
+
+
+ + + + diff --git a/servers/loginservers/ssh.html b/servers/loginservers/ssh.html new file mode 100644 index 00000000..c69585c0 --- /dev/null +++ b/servers/loginservers/ssh.html @@ -0,0 +1,2385 @@ + + + + + + + + + + + +SSH Server | ENiGMA½ BBS Software + + + + + + + + + + + + + + + + + +
+ +
+
+
+ + +
+

SSH Server

+

SSH Login Server

+

The ENiGMA½ SSH login server allows secure user logins over SSH (ssh://).

+ +

Configuration

+

Entries available under config.loginServers.ssh:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ItemRequiredDescription
privateKeyPem:-1:Path to private key file. If not set, defaults to ./config/ssh_private_key.pem +
privateKeyPass:+1:Password to private key file.
firstMenu:-1:First menu an SSH connected user is presented with. Defaults to sshConnected.
firstMenuNewUser:-1:Menu presented to user when logging in with one of the usernames found within users.newUserNames in your config.hjson. Examples include new and apply.
enabled:+1:Set to true to enable the SSH server.
port:-1:Override the default port of 8443.
address:-1:Sets an explicit bind address.
algorithms:-1:Configuration block for SSH algorithms. Includes keys of kex, cipher, hmac, and compress. See the algorithms section in the ssh2-streams documentation for details. For defaults set by ENiGMA½, see core/config_default.js.
traceConnections:-1:Set to true to enable full trace-level information on SSH connections.
+ +

Example Configuration

+ +
{
+    loginServers: {
+        ssh: {
+            enabled: true
+            port: 8889
+            privateKeyPem: /path/to/ssh_private_key.pem
+            privateKeyPass: sup3rs3kr3tpa55
+        }
+    }
+}
+
+ +

Generate a SSH Private Key

+

To utilize the SSH server, an SSH Private Key (PK) will need generated. OpenSSL can be used for this task:

+ +

Modern OpenSSL

+
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -pkeyopt rsa_keygen_pubexp:65537 | openssl rsa -out ./config/ssh_private_key.pem -aes128
+
+ +

Legacy OpenSSL

+
openssl genrsa -aes128 -out ./config/ssh_private_key.pem 2048
+
+ +

Note that you may need -3des for every old implementations or SSH clients!

+ + +
+ + +
+
+
+
+ + + + diff --git a/servers/loginservers/telnet.html b/servers/loginservers/telnet.html new file mode 100644 index 00000000..8b061d42 --- /dev/null +++ b/servers/loginservers/telnet.html @@ -0,0 +1,2344 @@ + + + + + + + + + + + +Telnet Server | ENiGMA½ BBS Software + + + + + + + + + + + + + + + + + +
+ +
+
+
+ + +
+

Telnet Server

+

Telnet Login Server

+

The Telnet login server provides a standard non-secure Telnet login experience.

+ +

Configuration

+

The following configuration can be made in config.hjson under the loginServers.telnet block:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
KeyRequiredDescription
enabled +:-1: Defaults to true. Set to false to disable Telnet 
port:-1:Override the default port of 8888.
address:-1:Sets an explicit bind address.
firstMenu:-1:First menu a telnet connected user is presented with. Defaults to telnetConnected.
+ +

Example Configuration

+
{
+  loginServers: {
+    telnet: {
+      enabled: true
+      port: 8888
+    }
+  }
+}
+
+ + +
+ + +
+
+
+
+ + + + diff --git a/servers/loginservers/websocket.html b/servers/loginservers/websocket.html new file mode 100644 index 00000000..fc946547 --- /dev/null +++ b/servers/loginservers/websocket.html @@ -0,0 +1,2410 @@ + + + + + + + + + + + +Web Socket / Web Interface Server | ENiGMA½ BBS Software + + + + + + + + + + + + + + + + + +
+ +
+
+
+ + +
+

Web Socket / Web Interface Server

+

WebSocket Login Server

+

The WebSocket Login Server provides secure (wss://) as well as non-secure (ws://) WebSocket login access. This is often combined with a browser based WebSocket client such as VTX or fTelnet.

+ +

VTX Web Client

+

ENiGMA supports the VTX WebSocket client for connecting to your BBS from a web page. Example usage can be found at Xibalba and fORCE9 amongst others.

+ +

Before You Start

+

There are a few things out of scope of this document:

+ +
    +
  • +

    You’ll need a web server for hosting the files - this can be anywhere, but it obviously makes sense to host it + somewhere with a hostname relevant to your BBS!

    +
  • +
  • +

    It’s not required, but you should use SSL certificates to secure your website, and for supplying to ENiGMA to + secure the websocket connections. Let’s Encrypt provide a free well-respected service.

    +
  • +
  • +

    How you make the websocket service available on the internet is up to you, but it’ll likely by forwarding ports on + your router to the box hosting ENiGMA. Use the same method you did for forwarding the telnet port.

    +
  • +
+ +

Setup

+ +
    +
  1. Enable the websocket in ENiGMA, by adding webSocket configuration to the loginServers block in config.hjson (create it if you +don’t already have it defined).
  2. +
+ +
loginServers: {
+        webSocket : {
+                ws: {
+                    // non-secure ws://
+                    port: 8810
+                    enabled: true
+
+                    //  optional bind address
+                    address: 127.0.0.1
+                }
+                wss: {
+                    //  secure-over-tls wss://
+                    port: 8811
+                    enabled: true
+                    certPem: /path/to/https_cert.pem
+                    keyPem: /path/to/https_cert_key.pem
+                }
+                // set proxied to true to allow TLS-terminated proxied connections
+                // containing the "X-Forwarded-Proto: https" header to be treated
+                // as secure
+                proxied: true
+        }
+}
+
+ +
    +
  1. +

    Restart ENiGMA and check the logs to ensure the websocket service starts successfully, you’ll see something like the +following:

    + +
     [2017-10-29T12:13:30.668Z]  INFO: ENiGMA½ BBS/30978 on force9: Listening for connections (server="WebSocket (insecure)", port=8810)
    + [2017-10-29T12:13:30.669Z]  INFO: ENiGMA½ BBS/30978 on force9: Listening for connections (server="WebSocket (secure)", port=8811)
    +
    +
  2. +
  3. +

    Download the VTX_ClientServer to your +webserver, and unpack it to a temporary directory.

    +
  4. +
  5. +

    Download the example VTX client HTML file and save it to your webserver root.

    +
  6. +
  7. +

    Create an assets/vtx directory within your webserver root, so you have a structure like the following:

    + +
     ├── assets
    + │   └── vtx
    + └── vtx.html
    +
    +
  8. +
  9. +

    From the VTX_ClientServer package unpacked earlier, copy the contents of the www directory into assets/vtx directory.

    +
  10. +
  11. +

    Create a vtxdata.js file, and save it to assets/vtx:

    + +
     var vtxdata = {
    +     sysName: "Your Awesome BBS",
    +     wsConnect: "wss://your-hostname.here:8811",
    +     term: "ansi-bbs",
    +     codePage: "CP437",
    +     fontName: "UVGA16",
    +     fontSize: "24px",
    +     crtCols: 80,
    +     crtRows: 25,
    +     crtHistory: 500,
    +     xScale: 1,
    +     initStr: "",
    +     defPageAttr: 0x1010,
    +     defCrsrAttr: 0x0207,
    +     defCellAttr: 0x0007,
    +     telnet: 1,
    +     autoConnect: 0
    + };
    +
    +
  12. +
  13. +

    Update sysName and wsConnect accordingly. Use wss:// if you set up the websocket service with SSL, ws:// +otherwise.

    +
  14. +
  15. +

    If you navigate to http://your-hostname.here/vtx.html, you should see a splash screen like the following: + VTXClient

    +
  16. +
+ + +
+ + +
+
+
+
+ + + + diff --git a/sitemap.xml b/sitemap.xml new file mode 100644 index 00000000..94d119ba --- /dev/null +++ b/sitemap.xml @@ -0,0 +1,346 @@ + + + +/enigma-bbs/installation/installation-methods.html +2022-02-05T06:30:26+00:00 + + +/enigma-bbs/installation/install-script.html +2022-02-05T06:30:26+00:00 + + +/enigma-bbs/installation/docker.html +2022-02-05T06:30:26+00:00 + + +/enigma-bbs/installation/manual.html +2022-02-05T06:30:26+00:00 + + +/enigma-bbs/installation/hardware/rpi.html +2022-02-05T06:30:26+00:00 + + +/enigma-bbs/installation/hardware/windows.html +2022-02-05T06:30:26+00:00 + + +/enigma-bbs/installation/network.html +2022-02-05T06:30:26+00:00 + + +/enigma-bbs/installation/testing.html +2022-02-05T06:30:26+00:00 + + +/enigma-bbs/installation/production.html +2022-02-05T06:30:26+00:00 + + +/enigma-bbs/configuration/creating-config.html +2022-02-05T06:30:26+00:00 + + +/enigma-bbs/configuration/sysop-setup.html +2022-02-05T06:30:26+00:00 + + +/enigma-bbs/configuration/config-files.html +2022-02-05T06:30:26+00:00 + + +/enigma-bbs/configuration/config-hjson.html +2022-02-05T06:30:26+00:00 + + +/enigma-bbs/configuration/hjson.html +2022-02-05T06:30:26+00:00 + + +/enigma-bbs/configuration/menu-hjson.html +2022-02-05T06:30:26+00:00 + + +/enigma-bbs/configuration/directory-structure.html +2022-02-05T06:30:26+00:00 + + +/enigma-bbs/configuration/external-binaries.html +2022-02-05T06:30:26+00:00 + + +/enigma-bbs/configuration/archivers.html +2022-02-05T06:30:26+00:00 + + +/enigma-bbs/configuration/file-transfer-protocols.html +2022-02-05T06:30:26+00:00 + + +/enigma-bbs/configuration/email.html +2022-02-05T06:30:26+00:00 + + +/enigma-bbs/configuration/colour-codes.html +2022-02-05T06:30:26+00:00 + + +/enigma-bbs/configuration/event-scheduler.html +2022-02-05T06:30:26+00:00 + + +/enigma-bbs/configuration/acs.html +2022-02-05T06:30:26+00:00 + + +/enigma-bbs/configuration/security.html +2022-02-05T06:30:26+00:00 + + +/enigma-bbs/misc/user-interrupt.html +2022-02-05T06:30:26+00:00 + + +/enigma-bbs/filebase/ +2022-02-05T06:30:26+00:00 + + +/enigma-bbs/filebase/first-file-area.html +2022-02-05T06:30:26+00:00 + + +/enigma-bbs/filebase/acs.html +2022-02-05T06:30:26+00:00 + + +/enigma-bbs/filebase/uploads.html +2022-02-05T06:30:26+00:00 + + +/enigma-bbs/filebase/web-access.html +2022-02-05T06:30:26+00:00 + + +/enigma-bbs/filebase/tic-support.html +2022-02-05T06:30:26+00:00 + + +/enigma-bbs/filebase/network-mounts-and-symlinks.html +2022-02-05T06:30:26+00:00 + + +/enigma-bbs/messageareas/configuring-a-message-area.html +2022-02-05T06:30:26+00:00 + + +/enigma-bbs/messageareas/message-networks.html +2022-02-05T06:30:26+00:00 + + +/enigma-bbs/messageareas/bso-import-export.html +2022-02-05T06:30:26+00:00 + + +/enigma-bbs/messageareas/netmail.html +2022-02-05T06:30:26+00:00 + + +/enigma-bbs/messageareas/qwk.html +2022-02-05T06:30:26+00:00 + + +/enigma-bbs/messageareas/ftn.html +2022-02-05T06:30:26+00:00 + + +/enigma-bbs/art/general.html +2022-02-05T06:30:26+00:00 + + +/enigma-bbs/art/themes.html +2022-02-05T06:30:26+00:00 + + +/enigma-bbs/art/mci.html +2022-02-05T06:30:26+00:00 + + +/enigma-bbs/art/views/button_view.html +2022-02-05T06:30:26+00:00 + + +/enigma-bbs/art/views/edit_text_view.html +2022-02-05T06:30:26+00:00 + + +/enigma-bbs/art/views/full_menu_view.html +2022-02-05T06:30:26+00:00 + + +/enigma-bbs/art/views/horizontal_menu_view.html +2022-02-05T06:30:26+00:00 + + +/enigma-bbs/art/views/mask_edit_text_view.html +2022-02-05T06:30:26+00:00 + + +/enigma-bbs/art/views/multi_line_edit_text_view.html +2022-02-05T06:30:26+00:00 + + +/enigma-bbs/art/views/predefined_label_view.html +2022-02-05T06:30:26+00:00 + + +/enigma-bbs/art/views/spinner_menu_view.html +2022-02-05T06:30:26+00:00 + + +/enigma-bbs/art/views/text_view.html +2022-02-05T06:30:26+00:00 + + +/enigma-bbs/art/views/toggle_menu_view.html +2022-02-05T06:30:26+00:00 + + +/enigma-bbs/art/views/vertical_menu_view.html +2022-02-05T06:30:26+00:00 + + +/enigma-bbs/servers/loginservers/telnet.html +2022-02-05T06:30:26+00:00 + + +/enigma-bbs/servers/loginservers/ssh.html +2022-02-05T06:30:26+00:00 + + +/enigma-bbs/servers/loginservers/websocket.html +2022-02-05T06:30:26+00:00 + + +/enigma-bbs/servers/contentservers/web-server.html +2022-02-05T06:30:26+00:00 + + +/enigma-bbs/servers/contentservers/gopher.html +2022-02-05T06:30:26+00:00 + + +/enigma-bbs/servers/contentservers/nntp.html +2022-02-05T06:30:26+00:00 + + +/enigma-bbs/modding/local-doors.html +2022-02-05T06:30:26+00:00 + + +/enigma-bbs/modding/door-servers.html +2022-02-05T06:30:26+00:00 + + +/enigma-bbs/modding/telnet-bridge.html +2022-02-05T06:30:26+00:00 + + +/enigma-bbs/modding/existing-mods.html +2022-02-05T06:30:26+00:00 + + +/enigma-bbs/modding/file-area-list.html +2022-02-05T06:30:26+00:00 + + +/enigma-bbs/modding/last-callers.html +2022-02-05T06:30:26+00:00 + + +/enigma-bbs/modding/whos-online.html +2022-02-05T06:30:26+00:00 + + +/enigma-bbs/modding/user-list.html +2022-02-05T06:30:26+00:00 + + +/enigma-bbs/modding/msg-conf-list.html +2022-02-05T06:30:26+00:00 + + +/enigma-bbs/modding/msg-area-list.html +2022-02-05T06:30:26+00:00 + + +/enigma-bbs/modding/bbs-list.html +2022-02-05T06:30:26+00:00 + + +/enigma-bbs/modding/rumorz.html +2022-02-05T06:30:26+00:00 + + +/enigma-bbs/modding/file-transfer-protocol-select.html +2022-02-05T06:30:26+00:00 + + +/enigma-bbs/modding/onelinerz.html +2022-02-05T06:30:26+00:00 + + +/enigma-bbs/modding/show-art.html +2022-02-05T06:30:26+00:00 + + +/enigma-bbs/modding/file-base-download-manager.html +2022-02-05T06:30:26+00:00 + + +/enigma-bbs/modding/file-base-web-download-manager.html +2022-02-05T06:30:26+00:00 + + +/enigma-bbs/modding/set-newscan-date.html +2022-02-05T06:30:26+00:00 + + +/enigma-bbs/modding/node-msg.html +2022-02-05T06:30:26+00:00 + + +/enigma-bbs/modding/top-x.html +2022-02-05T06:30:26+00:00 + + +/enigma-bbs/modding/user-2fa-otp-config.html +2022-02-05T06:30:26+00:00 + + +/enigma-bbs/modding/autosig-edit.html +2022-02-05T06:30:26+00:00 + + +/enigma-bbs/modding/menu-modules.html +2022-02-05T06:30:26+00:00 + + +/enigma-bbs/admin/administration.html +2022-02-05T06:30:26+00:00 + + +/enigma-bbs/admin/oputil.html +2022-02-05T06:30:26+00:00 + + +/enigma-bbs/admin/updating.html +2022-02-05T06:30:26+00:00 + + +/enigma-bbs/troubleshooting/monitoring-logs.html +2022-02-05T06:30:26+00:00 + + +/enigma-bbs/ + + diff --git a/troubleshooting/monitoring-logs.html b/troubleshooting/monitoring-logs.html new file mode 100644 index 00000000..1fd413ef --- /dev/null +++ b/troubleshooting/monitoring-logs.html @@ -0,0 +1,2333 @@ + + + + + + + + + + + +Monitoring Logs | ENiGMA½ BBS Software + + + + + + + + + + + + + + + + + +
+ +
+
+
+ + +
+

Monitoring Logs

+

Monitoring Logs

+

ENiGMA½ does not produce much to stdout. Logs are produced by Bunyan which outputs each entry as a JSON object.

+ +

Start by installing bunyan and making it available on your path:

+ +
npm install bunyan -g
+
+ +

or via Yarn:

+
yarn global add bunyan
+
+ +

To tail logs in a colorized and pretty format, issue the following command:

+
tail -F /path/to/enigma-bbs/logs/enigma-bbs.log | bunyan
+
+ +

See bunyan --help for more information on what you can do!

+ +

Example

+

Logs without Bunyan:

+
tail -F /path/to/enigma-bbs/logs/enigma-bbs.log
+{"name":"ENiGMA½ BBS","hostname":"nu-dev","pid":25002,"level":30,"eventName":"updateFileAreaStats","action":{"type":"method","location":"core/file_base_area.js","what":"updateAreaStatsScheduledEvent","args":[]},"reason":"Schedule","msg":"Executing scheduled event action...","time":"2018-12-15T16:00:00.001Z","v":0}
+{"name":"ENiGMA½ BBS","hostname":"nu-dev","pid":25002,"level":30,"module":"FTN BSO","msg":"Performing scheduled message import/toss...","time":"2018-12-15T16:00:00.002Z","v":0}
+{"name":"ENiGMA½ BBS","hostname":"nu-dev","pid":25002,"level":30,"module":"FTN BSO","msg":"Performing scheduled message import/toss...","time":"2018-12-15T16:30:00.008Z","v":0}
+
+ +

Oof!

+ +

Logs with Bunyan:

+
tail -F /path/to/enigma-bbs/logs/enigma-bbs.log | bunyan
+[2018-12-15T16:00:00.001Z]  INFO: ENiGMA½ BBS/25002 on nu-dev: Executing scheduled event action... (eventName=updateFileAreaStats, reason=Schedule)
+    action: {
+      "type": "method",
+      "location": "core/file_base_area.js",
+      "what": "updateAreaStatsScheduledEvent",
+      "args": []
+    }
+[2018-12-15T16:00:00.002Z]  INFO: ENiGMA½ BBS/25002 on nu-dev: Performing scheduled message import/toss... (module="FTN BSO")
+[2018-12-15T16:30:00.008Z]  INFO: ENiGMA½ BBS/25002 on nu-dev: Performing scheduled message import/toss... (module="FTN BSO")
+
+ +

Much better!

+ + +
+ + +
+
+
+
+ + + +