Synchronet Web Server Documentation
===================================

$Id: websrvr.txt,v 1.17 2007/11/30 09:05:08 deuce Exp $

1. 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.

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


2. Web Server Configuration
---------------------------
Most of the web server configuration is in your startup INI file (usually
ctrl/sbbs.ini). The [Web] section contains the following unique settings:


2.1. Initialization file [Web] section keys
-------------------------------------------
RootDirectory=../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 dir.
ErrorDirectory=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=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:
    IndexFileNames=index.html,index.htm,index.ssjs
    Do not remove the index.ssjs unless you are not using the stock
    web pages at all.
Authorization=Basic,Default
    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=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=.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.
DefaultCGIContent=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=.ssjs
    Files with this extension will be considered SSJS files.  On all
    systems, this will be attempted to run with the JavaScript interpreter.
MaxInactivity=120
    If a client holds a connection open for this many seconds without a
    request, the web server will shut down the connection.
MaxCgiInactivity=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=../data/logs/http-
    The prefix of log files if HTTP_LOGGING is enabled (See next item) to
    store Common Logfile Format logs in.  The current virtual host
    (if enabled, see next item), date, and .log are appended to this.  ie:
    http-2005-03-12.log
Options=NO_HOST_LOOKUP
    The | separated list of options to enable.  In addition to the standard
    options, the web server also supports the following:
    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.
    VIRTUAL_HOSTS
        Supports name-based 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:
            <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>
    NO_CGI
        Disable CGI script execution.
    HTTP_LOGGING
        Enable logging to a Common Logfile Format log as described in
        the HttpLogFile section.  Usefull for running log analysis
        programs (like Webalizer: http://www.mrunix.net/webalizer/)
    NO_JAVASCRIPT
        Disable SSJS execution.


2.2. Other web-related configuration files
------------------------------------------
In addition to the [Web] keys in the initialization 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
        Contains 2 sections, [CGI] and [JavaScript], where a list of file
        extensions and their associated content-creation handlers are
        specified. The [CGI] section is for natively-executed CGI handlers
        (e.g. "pl = perl" indicates "perl" will be used to handle ".pl"
        files). 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.


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

AccessRequirements:
	Specifices an ARS string which all users must match to be able to access
	files in this directory.  Will force an HTTP login.
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.

For example, to require a login, but allow *any* user to access files in a
directory, but only a sysop to access *.log files, the following could be used:
AccessRequirements=level 0
[*.log]
AccessRequirements=level90


3.0 JavaScript Web Server Objects
---------------------------------
In addition to the standard JavaScript objects, the web server provides the
following:


3.1 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 usefull 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 OSs 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.


3.2 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.


3.3 Extra global methods
------------------------
The web server also adds new global methods.  These are:

set_cookie(string key, 
           string value 
		   [, time_t expires 
		   [, string domain 
		   [, string path 
		   [, bool secure ]]]])
               Requests that the specified cookie be set.


4.0 The SSJS Template System
----------------------------
The default web pages use a SSJS Template engine which also allows for Theme 
support.

[Note:  With this latest implementation of SSJS, @@ codes no longer can be
nested.]


4.1 The SSJS Template Scheme
----------------------------
Each page consists of four parts:

    The Header (../web/templates/default/header.inc)
        This file contains the basic requirements for the HTML page.
        The opening HTML, doctype, title, CSS file link, etc.  The
        header file includes the open body, System Name, and User 
        greeting plus the initial page layout table start.  The rest
        of the layout is continued in the next files.

    Top Navigation (../web/templates/default/topnav.inc & 
        ../web/lib/topnav_html.ssjs)
        The topnav.inc file contains the basic design of the "breadcrumbs"
        The links are dynamically generated by topnav_html.ssjs so both
        files need to be addressed when modifying or creating themes.
        In the case of the default layout, topnav.inc has a left and right 
        graphic and a middle section that the dynamic content goes.  The
        background image is handled by CSS.  You can change this to anything
        you like.
        The topnav_html.ssjs file may seem daunting at first, but it is 
        pretty straight forward.  It has a series of if statements that
        check the current page location and sets up the breadcrumbs based
        on what you want it to say.
        For example:
            You want to add a Links page called links.html in the main 
            directory.  You would add a check for the path to links.html
            as:  
                if(http_request.virtual_path=="/links.html")
                    template.topnav.push({html: '<span class="tlink">
                        Some Links</span>'});

    Left Side Navigation (../web/templates/default/leftnav.inc &
        ../web/lib/leftnav_nodelist.ssjs & ../web/lib/leftnav_html.ssjs)
        This starts the main table layout in the default layout and also
        provides two other things -- the main navigation links and a brief
        nodelisting that displays when users are online via telnet.
        The links are dynamically created as in the Top Navigation example
        above with the exception of the two static links.

    Main Content (various files)
        This is where the layout of the main content is created.  It is best
        to look at the various files in ../web/templates/default & 
        ../web/templates/default/msgs to see how the code is dispayed for the
        various functions of the Web side of Synchronet.  Some details on what
        each of the special codes contained in those files do will follow.

    Footer (../web/templates/default/footer.inc)
        This file contains the closing HTML and whatever bottom information
        you would like. In the case of the default layout, the
        Web Server/Synchronet versions and the XHTML 1.0 logo.  Links to
        privacy statements or anything else can be placed here and they will 
        be displayed at the bottom of each page.


4.2 SSJS Theme Support
----------------------
Theme Layouts can be added to Synchronet by creating them and placing the
*.inc files in their own directory under ../web/templates/

Themes are activated by editing the ../web/templates/html_themes.ssjs file.
This file contains:

    /* Set default theme name */
    var DefaultTheme="Default";

    /* Edit this bit to add/remove/modify theme descriptions and dirs */
    Themes["Default"]=new Object;
    Themes["Default"].desc="Default Synchronet Theme";
    Themes["Default"].dir="default";
    Themes["Default"].css="/synchronet.css"; 

Themes are added by editing below the Default Theme such as:

    Themes["CoolTheme"]=new Object;
    Themes["CoolTheme"].desc="My Cool Theme";
    Themes["CoolTheme"].dir="cooltheme";
    Themes["CoolTheme"].css="/cooltheme.css";

To change the Default Theme, change:

    var DefaultTheme="Default";

to:

    var DefaultTheme="CoolTheme";


4.3 Special Codes Used in the SSJS Template System
--------------------------------------------------
By looking at at the message related files located in templates/default/msgs,
it can be seen that some special codes are used to display dynamically created
content. It is very important to maintain the information EXACTLY as seen in
each file or else the messaging system will fail.  While how it is displayed
can be changed, the correct information will only be dispayed by following the
format in the *.inc files.

For example the groups.inc:

<!-- Main Content -->  
    
    <td class="main" valign="top"><br />

<table class="grouplist" border="0" cellpadding="2" cellspacing="2">
<tr>
<th class="grouplist">Message Group</th><th class="grouplist">Subs</th>
</tr>
<<REPEAT groups>>
<tr>
    <td class="grouplist">
        <a class="grouplist" href="subs.ssjs?msg_grp=^^groups:name^^">
            %%groups:description%%</a></td>
    <td class="grouplist" align="right">
        @@JS:msg_area.grp_list[RepeatObj.index].sub_list.length@@</td>
</tr>
<<END REPEAT groups>>
</table>
<br />

<!-- end Main Content -->

While the table layout can be changed or even eliminated, the information
within the <<REPEAT groups>> and <<END REPEAT groups>> must remain intact.
To remove the table yet keep the correct infomation, the resulting groups.inc
would be changed to (while maintaining the main table layout in this case) to:

<!-- Main Content -->  
    
    <td class="main" valign="top"><br />

<<REPEAT groups>>
    <a class="grouplist" href="subs.ssjs?msg_grp=^^groups:name^^">
        %%groups:description%%</a>
    @@JS:msg_area.grp_list[RepeatObj.index].sub_list.length@@<br />
<<END REPEAT groups>>

<br />

<!-- end Main Content -->

This principle applies to all the .inc files in msgs respectively.


4.4 The SSJS Template Library
-------------------------------

%%name%% is replaced with the HTML encoded value of template.name

i.e.; Spaces are replaced with: this&nbsp;is&nbsp;html

^^name^^ is replaced with the URI encoded value of template.name

i.e.; Spaces are replaced with:  this%20is%20URI
          
@@name@@ is replaced with the value if template.name

No changes or encoding is performed.

@@name:sname@@ is replaced with the value of template.name.sname
(^^ and %% are also supported)

@@JS:js_expression@@ is replaced with the return value of js_expression   
(^^ and %% are also supported)

<<REPEAT name>>
    @@name:sname@@
<<END REPEAT name>>

Iterates over the array/object template.name and replaces name:sname with 
the value of template.name.sname.
(^^ and %% are also supported)


4.5 SSJS Message Configuration
------------------------------
Configuration settings for the SSJS Messaging system is located in the
../web/lib/msgsconfig.ssjs file:

max_messages=20;
max_pages=30;
next_msg_html="Next Message";
prev_msg_html="Previous Message";
next_page_html="NEXT";
prev_page_html="PREV";
showall_subs_enable_html="Show all subs";
showall_subs_disable_html="Show subs in new scan only";
show_messages_all_html="Show all messages";
show_messages_yours_html="Show messages to you only";
show_messages_your_unread_html="Show unread messages to you only";
show_messages_spacer_html="&nbsp;<b>|</b>&nbsp;";
anon_only_message="Message will be posted anonymously";
anon_allowed_message='<input type="checkbox" name="anonymous" value="Yes" /> \
Post message anonymously';
anon_reply_message='<input type="checkbox" name="anonymous" value="Yes" checked /> \
Post message anonymously';
private_only_message="Message will be marked private";
private_allowed_message='<input type="checkbox" name="private" value="Yes" /> \
Mark message as private';
private_reply_message='<input type="checkbox" name="private" value="Yes" checked /> \
Mark message as private';

Each of these are configurable.  NOTE:  Lines ending in "\" indicate the line
below is part of the line above.  The "\" is not part of the configuration as
it too be removed.

See the actual file for the defaults currently in use.

4.6 Embedded Javascript
-----------------------

The *.inc files can (and do in the default layout) have embedded JavaScript
which is parsed by the JavaScript engine.  Care should be taken as a large
number of embedded JavaScript in the *.inc files slow down overall processing
of pages.

Anything contained within @@JS: @@ is processed by the Server-side JavaScript
engine.

For example, it can check if the user is Guest or an actual user with this line:

@@JS:if(user.number==0 || user.security.restrictions&UFLAG_G) \
'<html code for Guest>'; else '<html code for registered user>';@@
        
What this does is display links specific for Registered Users only to them
and not Guest.  There are many things that can be done with @@JS: @@ code.
Note, it also can be used to display HTML based on location as in the
node listing stuff. In this case, it checks for whether or not a user is
online, or if the user is anywhere but the Who's Online page before displaying
the Left side node listing.

IMPORTANT!  Anything contained within @@JS: @@ MUST be on one line or there
will be errors in parsing.


4.7 global_defs.ssjs
--------------------

This version of the Web Layout now includes a new file called
global_defs.ssjs.  It is located in the ../web/lib directory.  This file can
be used for creating global definitions that span all pages of a site.
For example:

template.user_alias=user.alias;

Now @@user_alias@@ can be in any *.inc template files and it will display the
user's alias.

Care should be excersied when using this file as loading it up with hundreds
of predefined definitions may slow down overall page rendering as the file is
loaded on every page.  It would be better to just put a few popular 
definitions that are truly global rather many definitions.  It would be
inefficient to have thirty of forty message definitions being loaded when a
user is looking at the statistics page.


5.0 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.


5.1 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:

<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>

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

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.
<html><head><title>Counter</title></head>
<body>
<?xjs
var i;
for(i=1; i<=10; i++) {
?>
<?xjs write(i) ?><br>
<?xjs } ?>
</body>
</html>


5.2 XJS-specific global methods and properties
----------------------------------------------
The following JS commands 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.

/* End of file */
