====== Web Server ======

The Synchronet Web Server serves static (e.g. files) and dynamic content to HTTP clients (e.g. web browsers).

===== Introduction =====

The Synchronet Web Server is a mostly HTTP 1.1 compliant web server capable of
handing basic web servicing tasks.  It has most of the basic features of a
general-purpose web server one would come to expect, including (Fast)CGI.

It also, through Server-Side JavaScript (SSJS), allows dynamic pages to be
created which can access BBS data directly.


===== Configure =====

The Synchronet Web Server can be configured via [[util:SCFG]]:Servers->Web Server:


  ╔══════════════════════════════════════════════════════════════════╗
  ║                        Web Server Settings                       ║
  ╠══════════════════════════════════════════════════════════════════╣
  ║ │Enabled                       Yes                               ║
  ║ │Log Level                     Info                              ║
  ║ │HTTP Support...               Port 80                           ║
  ║ │HTTPS Support...              Port 443                          ║
  ║ │SSJS File Extension           .ssjs                             ║
  ║ │Index Filenames               index.html, index.ssjs, index.xjs ║
  ║ │Content Root Directory        ../webv4/root                     ║
  ║ │Error Sub-directory           error                             ║
  ║ │Virtual Host Support          No                                ║
  ║ │Access Logging                <disabled>                        ║
  ║ │Access Log Format             N/A                               ║
  ║ │Max Clients                   100                               ║
  ║ │Max Inactivity                2 minutes                         ║
  ║ │Max Concurrent Connections    10                                ║
  ║ │Rate Limiting...              <disabled>                        ║
  ║ │Authentication Methods        Basic,Digest,TLS-PSK              ║
  ║ │Output Buffer Drain Timeout   10 ms                             ║
  ║ │Lookup Client Hostname        No                                ║
  ║ │CGI Support...                <disabled>                        ║
  ║ │Filebase Support...           /files/                           ║
  ║ │Login Requirements                                              ║
  ║ │JavaScript Settings...                                          ║
  ║ │Failed Login Attempts...                                        ║
  ╚══════════════════════════════════════════════════════════════════╝

... or via [[monitor:SBBSCTRL]]:Web->Configure:

{{:server:sbbsctrl.3.20.web.config.png|}}

... or via manual edit of the ''[Web]'' section of the ''[[dir:ctrl]]/[[config:sbbs.ini]]'' file.

==== Sub-menus ====

The Web Server's main settings menu has four significant sub-menus.

=== HTTP Support / HTTPS Support ===

  ╔══════════════════════════════════════════════════════════╗
  ║                       HTTPS Support                      ║
  ╠══════════════════════════════════════════════════════════╣
  ║ │Enabled                       Yes                       ║
  ║ │Interfaces                    0.0.0.0,::                ║
  ║ │Port                          443                       ║
  ║ │Strict Transport Security     No                        ║
  ╚══════════════════════════════════════════════════════════╝

The plain HTTP variant has the same fields except for the //Strict Transport Security// toggle.

^ SCFG label                 ^ ini key (in [[#sbbs.ini|''[Web]'']])  ^
| //Enabled//                 | option ''ALLOW_TLS'' (HTTPS) / ''NO_HTTP'' (HTTP) |
| //Interfaces//              | ''TLSInterface'' / ''Interface'' |
| //Port//                    | ''TLSPort'' / ''Port'' |
| //Strict Transport Security//   | option ''HSTS_SAFE'' — on enable, redirect plain-HTTP clients to HTTPS and emit ''Strict-Transport-Security'' headers. Use only when **all** content is also served over HTTPS. |

=== CGI Support ===

  ╔══════════════════════════════════════════════════════════╗
  ║                  Web Server CGI Support                  ║
  ╠══════════════════════════════════════════════════════════╣
  ║ │Enabled                  Yes                            ║
  ║ │Directory                cgi-bin                        ║
  ║ │File Extensions          .cgi                           ║
  ║ │Default Content-Type     text/plain                     ║
  ║ │Max Inactivity           Default                        ║
  ╚══════════════════════════════════════════════════════════╝

^ SCFG label                ^ ini key  ^
| //Enabled//                | option ''NO_CGI'' (off when set) |
| //Directory//              | ''CGIDirectory'' |
| //File Extensions//        | ''CGIExtensions'' |
| //Default Content-Type//   | ''DefaultCGIContent'' — the MIME type sent if a CGI script doesn't emit a ''Content-Type:'' header itself. |
| //Max Inactivity//         | ''MaxCgiInactivity'' |

=== Filebase Support ===

  ╔══════════════════════════════════════════════════════════╗
  ║               Web Server Filebase Support                ║
  ╠══════════════════════════════════════════════════════════╣
  ║ │Enabled            Yes                                  ║
  ║ │Index Script       webfileindex.ssjs                    ║
  ║ │VPath Prefix       /files/                              ║
  ║ │VPath for VHosts   No                                   ║
  ╚══════════════════════════════════════════════════════════╝

^ SCFG label                ^ ini key  ^
| //Enabled//                | option ''NO_FILEBASE'' (off when set) |
| //Index Script//           | ''FileIndexScript'' — server-side JavaScript that renders library/directory listings under the virtual file path (typically [[module:webfileindex|webfileindex.ssjs]]). |
| //VPath Prefix//           | ''FileVPathPrefix'' — URL path prefix at which the file base is exposed (e.g. ''/files/''). |
| //VPath for VHosts//       | ''FileVPathForVHosts'' — when virtual hosts are enabled, also serve the file base from each virtual host. //N/A// when virtual hosts are off. |

=== Rate Limiting ===

Limit the rate of incoming connections and/or requests from a client, optionally counting all clients within a subnet together, and optionally auto-filtering (blocking) repeat abusers.  The connection limiter is enforced at //accept// (before a session thread or TLS handshake is created), making it the cheapest place to shed a flood; the request limiter is enforced after each request is parsed.  See [[howto:block-hackers]] and [[config:ip.can]] for the filtering side.

  ╔══════════════════════════════════════════════════════════════════╗
  ║                     Web Server Rate Limiting                     ║
  ╠══════════════════════════════════════════════════════════════════╣
  ║ │Limit Rate of Connections     <disabled>                        ║
  ║ │Limit Rate of Requests        <disabled>                        ║
  ║ │Count IPv4 Clients By         Per-host IP address               ║
  ║ │Count IPv6 Clients By         Per-host IP address               ║
  ║ │Auto-Filter Threshold         <disabled>                        ║
  ║ │Auto-Filter Duration          Infinite                          ║
  ║ │Auto-Filter Silently          No                                ║
  ╚══════════════════════════════════════════════════════════════════╝

^ SCFG label                    ^ ini key  ^
| //Limit Rate of Connections//   | ''MaxConnectsPerPeriod'' / ''ConnectRateLimitPeriod'' — maximum connections allowed from a client per period, enforced at //accept//. |
| //Limit Rate of Requests//      | ''MaxRequestsPerPeriod'' / ''RequestRateLimitPeriod'' — maximum HTTP[S] requests allowed from a client per period. |
| //Count IPv4 Clients By//       | ''RateLimitSubnetPrefix4'' — IPv4 subnet prefix bits (e.g. ''24'') for aggregating clients, so abuse spread thinly across a provider's range is counted and filtered as one CIDR block.  ''0'' counts each host IP separately. |
| //Count IPv6 Clients By//       | ''RateLimitSubnetPrefix6'' — as above for IPv6 (e.g. ''64''). |
| //Auto-Filter Threshold//       | ''RateLimitFilterThreshold'' — number of rate-limit violations before the offending IP or subnet is automatically added to the IP filter.  ''0'' disables auto-filtering. |
| //Auto-Filter Duration//        | ''RateLimitFilterDuration'' — lifetime of an auto-filter entry, in seconds.  ''0'' filters indefinitely. |
| //Auto-Filter Silently//        | ''RateLimitFilterSilent'' — when enabled, abusers are added to ''ip-silent.can'' (dropped at //accept//, no log notice) instead of [[config:ip.can]]. |

==== sbbs.ini ====

The ''[Web]'' section of your [[config:sbbs.ini]] file supports the following configuration settings (keys):

^ Key                      ^ Default          ^ Description ^
| AutoStart                | ''true''         | Automatically start-up the server when Synchronet is started |
| HostName	           | //none//         | Override system hostname |
| LogLevel	           | Informational    | Default minimum severity of log messages to view or log-to-disk |
| TLSErrorLevel	           | Emergency	      | Maximum severity of TLS-related log messages |
| Interface                | ''0.0.0.0,::''   | Comma-separated list of IPv4 and IPv6 addresses of network interfaces and optional port numbers to listen for incoming HTTP/TCP connections |
| TLSInterface             | //Interface//    | ... for incoming HTTPS/TLS connections |
| Port                     | ''80''           | Default TCP port to listen for incoming HTTP connections |
| TLSPort                  | ''443''          | Default TCP port to listen for incoming HTTPS/TLS connections |
| BindRetryCount	   | 2	              | Default number of network interface/port bind retry attempts |
| BindRetryDelay	   | 15	              | Default number of seconds to wait between bind attempts |
| MaxClients               | 100              | Maximum number of simultaneous connections supported (0 = unlimited) |
| MaxConcurrentConnections | 10               | Maximum number of simultaneous connections allowed from a single client IP address |
| MaxInactivity            | ''2m''           | Maximum duration of client inactivity before disconnection |
| MaxCgiInactivity         | ''2m''           | Maximum duration of CGI application inactivity |
| MaxConnectsPerPeriod     | 0                | Maximum number of connections from a single client over //ConnectRateLimitPeriod//, enforced at connection accept (0 = disabled) |
| ConnectRateLimitPeriod   | 3600             | Time period (in seconds) over which client connections are rate-calculated and limited |
| MaxRequestsPerPeriod     | 0                | Maximum number of requests from a single IP address over the specified time period |
| RequestRateLimitPeriod   | 0                | Time period (in seconds) over which client requests are to be rate calculated and limited |
| RateLimitSubnetPrefix4   | 0                | IPv4 subnet prefix bits used to aggregate clients for rate-counting and filtering, e.g. ''24'' (0 = count each host IP separately) |
| RateLimitSubnetPrefix6   | 64               | IPv6 subnet prefix bits used to aggregate clients (0 = per-host IP).  The /64 default reflects that a single IPv6 host owns its entire /64 (the SLAAC subnet) and can rotate source addresses within it for free, making per-host (/128) counting and filtering rarely meaningful. |
| RateLimitFilterThreshold | 0                | Number of rate-limit violations before a client/subnet is auto-added to the IP filter (0 = disabled) |
| RateLimitFilterDuration  | 0                | Lifetime (in seconds) of an auto-filter entry (0 = forever) |
| RateLimitFilterSilent    | false            | When //true//, auto-filter to ''ip-silent.can'' (dropped at accept) instead of [[config:ip.can]] |
| SemFileCheckFrequency    | //global// (2)   | Seconds between semaphore file checks |
| IndexFileNames           | ''index.html,index.ssjs''    | Index filenames to search for and serve up (when no file name was requested) |
| RootDirectory            | ''../web/root''  | Files are served out of this directory tree |
| ErrorDirectory           | ''error''        | Sub-directory of //RootDirectory// where error files are served from |
| CGIDirectory             | ''cgi-bin''      | Sub-directory of //RootDirectory// where CGI applications are served from |
| DefaultCGIContent        | ''text/plain''   | Default MIME-type of CGI content |
| CGIExtensions            | ''.cgi''         | Comma-separate list of file extensions (suffixes) used to recognize CGI application files |
| JavaScriptExtension      | ''.ssjs''        | File extension used to recognize Server-side JavaScript content files |
| Authentication           | ''Basic,Digest,TLS-PSK ''    | Authentication methods supported |
| HttpLogFile              | ''[[dir:data]]/logs/http-''  | Path prefix for HTTP access log files |
| CustomLogFormat          | ""               | [[https://httpd.apache.org/docs/current/mod/mod_log_config.html|Apache-style]] custom HTTP access log line format |
| FileIndexScript          | ""               | Server-side JavaScript to execute to provide HTML/CSS library and directory listings of virtual file paths (e.g. ''[[module:webfileindex|webfileindex.ssjs]]'') |
| FileVPathPrefix          | ""               | Virtual path for HTTP file base access, suggested value: ''/files/'' |
| FileVPathForVHosts       | ''false''        | If you'd like your virtual hosts to provide HTTP access to your file bases (using virtual file paths), set this to ''true'' |
| OutbufDrainTimeout       | ''10''           | Number of milliseconds to wait for output buffer to drain |
| TempDirectory	           | ''../temp/''     | Override default temporary file directory |
| LoginRequirements        | [global]         | [[:Access:]] [[:access:requirements]] (in ARS format) for users to be allowed login |
| LoginAttempt*            | [global]         | Failed login attempt throttling / filtering / banning |
| LoginInfoSave            |                  | An optional [[access:requirements|ARS]] that can be used to limit which users will have their login details saved to the userbase |
| RemoteIPHeader           | ""               | Name of an HTTP header that contains the real IP address of the proxied client |
| Options                  |                  | See below for details |

=== Options ===

The ''Options'' key is set to a ''|'' separated list of options to enable.  

Default value: **''NO_HOST_LOOKUP | HTTP_LOGGING | NO_CGI''**

In addition to the [[config:sbbs.ini|standard options]], the web server also supports the following:

^ Option        ^ Description ^
| VIRTUAL_HOSTS | Supports name-based virtual hosts. |
| NO_JAVASCRIPT | Disable SSJS execution. |
| NO_CGI        | Disable CGI/FastCGI script execution. |
| NO_HTTP       | Disable plain-text HTTP support |
| NO_FILEBASE   | Disable FileBase support |
| HTTP_LOGGING  | Enable logging to a Combined Log Format or Custom Log Format http access log.  Useful for running log analysis programs (like Webalizer: http://web.archive.org/web/20120424203622/http://www.mrunix.net:80/webalizer/). |
| ONE_HTTP_LOG  | When enabled along with VIRTUAL_HOSTS, client requests will be logged to a single file instead of a separate file per requested virtual host or IP address. |
| ALLOW_TLS     | Enable TLS/SSL support (required for HTTPS) |
| HSTS_SAFE     | Indicates that all URLs available via http are also available via https and redirects clients who want a TLS session to the https location. |
| HAPROXY_PROTO | Indicate that incoming requests are via HAproxy |
| DEBUG_RX      | Log all received data to the console log, as well as various extra bits related to receiving data. |
| DEBUG_TX      | Log all transmitted data except the reply body itself, as well as various extra bits of information related to transmitted data. |
| DEBUG_SSJS    | Log server-side JavaScript execution details. |

==== Reference ====

Web Server configuration settings reference:
 
=== Virtual Hosts ===

If your system has multiple
host names, you can have each host name return unique content depending on which hostname is used.  ie: if ''freebsd.synchro.net'' and ''nix.synchro.net'' both resolved to your system, you could have FreeBSD-specific pages on one, and general *nix stuff on the other.

A virtual host is added by simply putting the desired content into a sub-directory of [[#RootDirectory]] with the desired hostname ie: ''web/root/freebsd.synchro.net/'' if the browser doesn't send
the request host name (very old browsers, or some automated tools) they will be served out of document root. It is therefore a good idea to put links to your various virtual hosts in an ''index.html'' page in [[#RootDirectory]] something like this:

<code html>
<html>
  <head>
    <title>Old Browser</title>
  </head>
  <body>
    Your browser is either too old to support
    name-based virtual hosts, or you have visited a
    virtual hosts that is not yet configured.  The
    following are hosted here:<br>
    <a href="freebsd.synchro.net">freebsd.synchro.net</a><br>
    <a href="nix.synchro.net">nix.synchro.net</a><br>
  </body>
</html>
</code>

=== RootDirectory ===

Default value: ''../web/root''

This is the root directory of your web server... a request to
''http://yourbbs.synchro.net/index.html'' will be served out of this directory.

**NOTE**: Older versions of Synchronet had this value default to ''../web/html''

**NOTE**: If you change the root directory and use letsyncrypt for your certificate management, you will want to update the Domains section of letsyncrypt.ini in the ctrl directory. You will also need to do that if you have a virtual host so Let's Encrypt can find the correct document root.


=== ErrorDirectory ===
Default value: ''error''

The directory relative to [[#RootDirectory]] where the various error
message files are located.  The error message files are named by the
numeric HTTP error code they will represent and may be either ''.html''
or ''.ssjs'' files (''.ssjs'' files take precedence over ''.html'' files for the
same error).

=== IndexFileNames ===

Default value: ''index.html,index.ssjs''

A comma-separated list of filenames in order of preference to serve as
the default document in a directory.  Many Sysops change this to:
''index.html,index.htm,index.ssjs''.
Do not remove the ''index.ssjs'' unless you are not using the stock
web pages at all.

=== Authorization ===

Default value: ''Basic,Digest''

A comma-separated list of authentication mechanisms in order of preference.
The standards say that Basic must come first, but no browser currently
appears to use Digest if Basic is listed first.  Supported values are Basic
and Digest.  Digest is more secure as the users password is not sent in the
clear over the wire.

=== CGIDirectory ===
Default value: ''cgi-bin''

A directory relative to [[#RootDirectory]] where any files found will be
considered CGI-executable. Be careful what files you put in this
directory.

=== CGIExtensions ===
Default value: ''.cgi''

A comma-separated list of file extensions/suffixes. Files with these
extensions will be considered CGI-executable and the web server will
attempt to execute them as such.

Other probably values include: ''.pl,.php,.exe''

=== DefaultCGIContent ===

Default value: ''text/plain''

If the CGI program does not generate a content-type header, this value
will be used for the MIME content-type specified in the HTTP response.

=== JavaScriptExtension ===

Default value: ''.ssjs''

Files with this extension will be considered SSJS files.  On all
systems, this will be attempted to run with the JavaScript interpreter.

=== MaxInactivity ===

Default value: ''120''

If a client holds a connection open for this many seconds without a
request, the web server will shut down the connection.

=== MaxCgiInactivity ===

Defalut value: ''120''

If a CGI script runs for more than this many seconds without any
output, it will be terminated and the connection will be shut down.

=== HttpLogFile ===

Default value: ''../data/logs/http-''

The prefix of HTTP access log filenames, used when HTTP_LOGGING is enabled.  By default (when the ''ONE_HTTP_LOG'' option is **not** enabled), the current virtual host, date, and ''.log'' are appended to this string (e.g.''http-2005-03-12.log'').

=== CustomLogFormat ===

When the ''CustomLogFormat'' setting is not used, the default format is the Apache "Combined Log Format".

When the ''CustomLogFormat'' setting is used, the supported [[https://httpd.apache.org/docs/current/mod/mod_log_config.html|Apache Custom Log Format directives]] are:

| %% | The percent sign | 
| %a | Client IP address of the request | 
| %B | Size of response in bytes, excluding HTTP headers. | 
| %b | Size of response in bytes, excluding HTTP headers. In CLF format |  
| %h | Remote hostname or IP address | 
| %H | The request protocol | 
| %l | Remote logname (from identd, if supplied) | 
| %p | Server TCP port number |
| %r | First line of request | 
| %s | Status | 
| %t | Time the request was received, in the format [18/Sep/2011:19:18:28 -0400] | 
| %u | Remote user if the request was authenticated | 
| %v | The canonical ServerName of the server serving the request. (the vhost) | 
| %{remote}p | the client's actual port | 
| %{Referer}i | the HTTP Referer [sic] header line | 
| %{User-agent}i | the HTTP User-agent header line |

Note: Double-quote characters used in the format string do **not** need to be escaped (i.e. with a backslash)

Example:

This is the equivalent of Apache's combined log format which is used by default.

    CustomLogFormat = %h %l %u %t "%r" %s - "%{Referer}i" "%{User-agent}i"

This is the equivalent of Apache's vhost_combined log format.
    
    CustomLogFormat = %v:%p %h %l %u %t "%r" %s - "%{Referer}i" "%{User-agent}i"


=== FileVPathPrefix ===
Default value: ""

Suggested value: ''/files/''

A virtual sub-directory of your web root to provide direct HTTP[S] access to your file bases. HTTP-AUTH is used for conditional access/restrictions, when necessary. The trailing slash is important.

=== FileVPathForVHosts ===
Default value: ''false''

By default, virtual hosts will not have the virtual file path (if enabled). Set this to ''true'' if you would like your virtual hosts to support the virtual file paths as well.

=== FileIndexScript ===
Default value: ""

Suggested value: ''[[module:webfileindex|webfileindex.ssjs]]''

A Server-side JavaScript (SSJS) file to execute and provide HTML/CSS indexes to file libraries and directories accessed via virtual file paths.

==== Other configuration files ====

In addition to the ''[Web]'' keys in the [[config:sbbs.ini]] file, the web server
also uses some other configuration files:

=== ctrl/mime_types.ini ===
Contains the file extension to mime-type mapping.  Each line
is in the format "extension = mime-type" ie: "html = text/html"
The extensions are case-insensitive and do not include the '.'.

=== ctrl/webicons.ini ===
Contains the URLs to the icons used by the default 404.ssjs
script for each file type/extension.  Format is "extension = URL".
Example: "html=/icons/layout.gif".  Two "magical" extensions exist:
DIRECTORY which is used for directories and DefaultIcon which
is used for extensions which don't exist in the list.

=== ctrl/web_handler.ini ===

This file contains 2 sections where a list of file
extensions and their associated content-creation handlers are
specified:

== [CGI] ==

The [CGI] section is for natively-executed CGI handlers
(e.g. "pl = perl" indicates "perl" will be used to handle ".pl" files).  

== [JavaScript] ==

The [JavaScript] section is used for JS-executed content
handlers (e.g. "xjs = xjs_handler.js").

=== ctrl/cgi_env.ini ===
Contains a list of system environment variables to pass to CGI
processes.  Each variable can have an optionally specified default
value, over-ridden value, and prepended or appended text.


==== webctrl.ini ====

Each directory under the [[#RootDirectory]] may have a ''webctrl.ini'' file which overrides certain settings for
the directory it's in and all child directories.  Configuration keys may be set
either globally, in a per-filename group, or, in version 3.17 or greater, a per-directory-name group.
Using the * and ? wildcards as the group name such as ''[*.html]'' or ''[dirname/]''.  The following keys may be used in these files:

=== AccessRequirements ===
Specifies an ARS string which all users must match to be able to access
files in this directory.  Will force an HTTP login.

For example, to require a login, but allow **any** user to access files in a
directory, but only a sysop to access ''*.log'' files and .git directories, the following could be used:
<file webctrl.ini>
AccessRequirements=level 0
[*.log]
AccessRequirements=level 90
[*.git]
AccessRequirements=level 90
</file>

=== Realm ===
Sets the realm that is displayed to the user for the HTTP login.
Default is the BBS name.

=== DigestRealm ===
Sets the realm that is displayed to the user for the HTTP login when
Digest authentication is being used.  Default is the [[#Realm]] value.

=== Authorization ===
A comma-separated list of authentication mechanisms in order of
preference.  The standards say that Basic must come first, but no
browser currently appears to use Digest if Basic is listed first.
Supported values are ''Basic'' and ''Digest''.  Digest is more secure as the
users password is never sent over the wire.

=== ErrorDirectory ===
Specifies a different directory to check for error pages.  If the error
page is not found, will still check the global error directory.

=== CGIDirectory ===
Specify an alternate CGI directory to check for CGI files.

=== PathInfoIndex ===
Specifies that the index files can be ran for unlocated pages in the
current directory.  This effecively works like a custom 404 page.

=== FastCGISocket ===
Specifies the socket address of a FastCGI listener in either <Address>:<Port> format (e.g. ''127.0.0.1:9000'') or ''unix:/path/to/unix/socket'' format.  Should be used with wildcard sections like this:
<file webctrl.ini>
[*.php]
FastCGISocket=127.0.0.1:9000
</file>

See [[howto:php]] for details on using with PHP.

=== Rewrite* ===
Specifies a Javascript snippet which can modify the http_request.request_string.  This allows internal redirects like the RewriteRule feature in Apache .htaccess files.  The key must *begin* with the string "Rewrite" which may be followed by any legal INI key characters.  The order of execution is not guaranteed.

<file webctrl.ini>
RewriteDetail=var n=http_request.request_string.replace(/_detail\/(.*)/,"lib/exe/detail.php?media=$1"); if(n != http_request.request_string) { http_request.request_string=n; true }
</file>

If the expression returns "true", reparses http_request.request_string as
an internal redirect.

Added on November 3rd, 2015 to CVS (in 3.17a). ([[https://gitlab.synchro.net/main/sbbs/-/commit/370cb673ce644a77bb94f9375cbe3463390e485a|Commit]])

=== JSPreExec ===
A JavaScript snippet which is executed in the same context as Rewrite* lines, but before any Rewrites are executed.  This allows load()ing some common code before execution... ie: ''JSPreExec=load(js.startup_dir+'/rewrite_lib.js');''.

Added on November 3rd, 2015 to CVS (in 3.17a).

===== JavaScript Objects =====
In addition to the standard JavaScript objects, the web server provides the
following:

==== http_request object ====

The http_request object contains information from the client that was included
during this request.  This objects properties are as follows:

=== path_info ===
Contains extra path information that was included with the
request AFTER the URI which identified this script.  For 
example, if the request was for
''http://www.synchro.net/script.ssjs/test/this'' then path_info
would contain the string "/test/this"

=== method ===
Contains the HTTP method used to run the script.  As of this
writing, the available methods are "HEAD", "GET", "POST", and
"OPTIONS"

=== virtual_path ===
The virtual path that this URI was reached by.  This is the
portion of the URI from the end of the host to the end of the
filename.

=== query ===
This object contains the values of any form data which was
submitted with the request.  This is an associative "array" of
name/value pairs.  THE VALUES ARE ARRAYS OF STRINGS.  The reason
for this is that it is legal and often useful to have multiple
form fields with the same name.

=== query_string ===
If a query string was included, this is the raw, unparsed query
string.

=== post_data ===
As with query_string but for data which was POSTed.

=== header ===
An associative array of header name/value pairs.

=== cookie ===
Much like the query object, this object contains key/value pairs
of set cookies.  Once again, this is an array of strings since
multiple values for the same key can be set for cookies.

=== real_path ===
The real OS's complete path to this script.

=== ars ===
The ARS string which applies to this request.

=== request_string ===

The raw request string sent by the client.

=== host ===
The value of the host header for this request.
=== vhost ===
The virtual host serving this request.
=== http_ver ===
The HTTP version used for this request as a string.

=== remote_ip ===
The IP address of the client.

=== remote_host ===

If the web server does host lookups (disabled by default), this
is the remote hostname.

=== scheme ===

"https" if TLS is in use, "http" otherwise.
==== http_reply object ====


The http_reply object is used to pass information about the reply back to the
Synchronet web server.  The properties are as follows:

=== status ===

HTTP status string.  The default is generally "200 Ok"

=== header ===
An associative array of headers to include with the reply.  The
only pre-defined one is "Content-Type" which defaults to "text/html".

=== fast ===
This optional property can be set to "true" to make write()s go
directly to the client for HTTP/1.0 connections.  This prevents
keep-alives from working but generally appears faster to the
client.  Since HTTP/1.1 requests use chunked mode, this isn't
required for HTTP/1.1.


==== Extra global methods ====

The web server also adds a new global JavaScript method that requests that the specified cookie be set:

  set_cookie(string key, 
           string value 
		   [, time_t expires 
		   [, string domain 
		   [, string path 
		   [, bool secure ]]]])


==== Extra global variables ====

=== web_root_dir ===
The path to the web server's document root directory.

See also: the RootDirectory key under [Web] in [[config:sbbs.ini]].

===== XJS files =====

XJS files, handled by ''exec/xjs_handler.js'' are what many people consider to be
an easier method of generating SSJS files.  XJS files are HTML files with JS
commands embedded in them using special tags much like PHP.  XJS files are
translated on-the-fly to .ssjs files using the same name with ''.ssjs'' appended.
For example, a file named test.xjs will, when ran, generate a ''test.xjs.ssjs''
file.


==== XJS syntax ====

In an XJS file, everything not within a special xjs tag is send to the remote
host unmodified, and everything inside the xjs tag is interpreted as JS
statements to be executed at that point in the file.  The xjs tag begins with
either "<?xjs" or "<?" and ends with "?>".  A simple example would be:

<code html>
<html><head><title><?xjs write(system.name) ?></title></head>
<body>
Your SysOp "<?xjs write(system.operator) ?>" welcomes you to
<?xjs write(system.name) ?>
</body>
</html>
</code>

This would send the following web page to the remote system:
<code html>
<html><head><title>My Brand New BBS</title></head>
<body>
Your SysOp "Sysop" welcomes you to
My Brand New BBS
</body>
</html>
</code>

Looping constructs are permitted, however, not using brackets can result in
unexpected effects.  Because of this, it is reccomended to *always* use
brackets with looping and flow control items.

The following example displays the numbers from one to 10.
<code html>
<html><head><title>Counter</title></head>
<body>
<?xjs
var i;
for(i=1; i<=10; i++) {
?>
<?xjs write(i) ?><br>
<?xjs } ?>
</body>
</html>
</code>

==== XJS-specific global methods and properties ====

The following JavaScript methods and properties are available to XJS files only.

=== xjs_load(filename) ===
Runs the specified xjs file at the current position.  Local variables
are NOT visible to ''xjs_load()''ed pages.  The filename is assumed to be
relative to the including file (or absolute.)

=== cwd ===
Contains the path that the current xjs script was loaded from and which
parameters to ''xjs_load()'' are assumed to be relative to.  If you change
the value of ''cwd'', it will change the location where ''xjs_load()'' will
check for files.

{{indexmenu_n>4}}
