Cross-platform means that the same source code is compiled for different platforms into different executable files, but with the same functionality. We will refer to any executable version as 'xwrc'.
Currently we support:
Windows : xwrc.exe Linux on x86 CPU's : xwrc.x86 Linux on ARM CPU's : xwrc.arm Linux on MIPS CPU's : xwrc.mips
The server's basic functionality is to serve a collection of webpages that make up a website. The layout of the website and the page content is fully customizable, all you need is basic knowledge of HTML or a good HTML editor (i.e. FrontPage) and an idea how your site should look like. As an alternative the xWizard tool can be used.
The server supports a structured command URL to extend it's functionality beyond serving files. Part of the supported commands will be handled by xWRC itself, and some will be passed along to to xiControl which is an extension to the server.
xiControl is an integrated part of software that handles communication with a PEHA (c) PHC domotic system, allowing to control it from a webpage and report it's status. For more details refer to the xiControl help files.
Files that are served by xWRC can contain tags, these are placeholders for variable data that are replaced on-the-fly when the file is sent back to the client.
The used syntax is as follows: xwrc *[ - <option> ]To get a list of the available options, start xWRC as follows:
./xwrc -help e.g. ./xwrc.mips -help
xwrc -inifile <ini-file> e.g. ./xwrc.mips -inifile ./xwrc.iniNote that an option in the ini-file overrides any previous occurrence of that option, and similar any option specified on the command line after the ini-file will override the previous value of an option.
e.g. ./xwrc.mips -inifile ./xwrc.ini -httpport 8080Above sample will use 8080 as the HTTP port to listen on, even if another value was present in the ini-file.
The layout of the ini-file follows the standard Windows ini-file format:
ini-file = empty-line | comment-line | section-line | item-line empty-line = '' comment-line = ';' <comment...> section-line = '[' <section-name> ']' item-line = <key> '=' <value>
[wrc] ; license file to use, default is './license.bin' ;licfile=./license.bin ; HTTP listening port, default is 80 ;httpport=8080 ; xWRC hostname override ;hostname=abcd ; web page root directory relative to wrc/bin, default is '..' ;httproot=.. ; server theme, default is 'default' ; default page to return when accessing the server root or directory is derived as '<theme>.html' ;theme=default ; fontsize to use for the the fontsize tag, default is 8 ;fontsize=8 ; user management db file, default is './umdb.ini' ;umdbfile=./umdb.ini ; authentication method, default is 0 (none) ; 0=none : no authentication, everybody can access all content ; 1=basic : basic authentication, user/ugrp/rule logic will be applied to restrict access ; 2=session : session based authentication, allows login/logout, user/ugrp/rule logic will be applied to restrict access authmeth=0 ; allow authentication by means of peer ip-address, default is 0 (no) ; 0=no : peer ip-address is not used ; 1=yes : peer ip-address is checked against user db to grant unauthenticated access authaddr=0 ; loglevel, decimal or hex 32bit value, default is 0 ; only set to non-zero value as per instruction of support engineer ;loglevel=0xFFFFFFFF ; logfile prefix, default is '../log/xWRC' ; will generate logging to ../log/xWRC_YYYYMMDD_hhmmss.log ;logpfx=../log/xWRC ; syslogd settings to report logging to remote syslog deamon, default is disabled ;logaddr=192.168.0.127 ;logport=514
[icontrol.0] ; address of STM module connected to (0-7), default is 0 ;stmaddr=0 ; remote ip-addres to connect over TCP to STM module, default is 127.0.0.1 ;remaddr=192.168.0.127 ; remote ip-port to connect over TCP to STM module, default is 10000 ;remport=10000
The basic access restriction model used by xWRC is this:
+------+ 1 1-16 +------------+ 1 N +------+ | USER |--------->| USER-GROUP |--------->| RULE | +------+ +------------+ +------+This means that each user can belong to 1 upto 16 user-groups, and each user-group can have an undefined number of rules linked to it.
All the information of users, user-groups and rules are placed in a separate ini-file, by default this is 'umdb.ini', this ini-file has sections for each part of information as follows:
; ; List of user-groups ; ; When <ugrp-name> or <description> contains a space, it has to be placed between double quotes ; ; Syntax: <ugrp-name> '=' <flags> ',' <def-access> ',' {<description>} ; ; ugrp-name := mandatory, maximum 16 characters, starting with a letter ; flags := bitwise OR of following values, default is 0 ; 1 group is enabled ; def-access := default access to apply when no matching rule is found, default is 0 ; 0 none ; 1 read ; 2 exec ; 3 full ; description := optional, maximum 64 characters ; [ugrps] grpAdmin=1,3,"Administrator user-group" grpGuest=1,1,"Guest user-group"
; ; List of users ; ; When <usr-name>, <pswd>, <description> or <ugrp-name> contains a space, it has to be placed between double quotes ; ; Syntax: <usr-name> '=' <flags> ',' <pswd> ',' {<description>} 1-16(',' <ugrp-name>) ; ; usr-name := mandatory, maximum 16 characters, starting with a letter ; flags := bitwise OR of following values, default is 0 ; 1: user is enabled ; 2: user is allowed to change password ; 4: user is admininstrator ; 8: user is IP-address ; pswd := plain text or hashed password, maximum 15 characters ; description := optional, maximum 64 characters ; ugrp-name := 1 upto 16 user-groups the user belongs to ; [users] admin=5,"admin","Administrator",grpAdmin guest=3,"guest","Guest",grpGuest
; ; This section lists all rules applicable to webpages served ; ; Wildcards that apply: '?' can occur multiple times at any place ; '*' can occur once at any place ; ; Syntax: <url> '=' <access> 1-*(',' <ugrp-name>) ; ; url := '"' *(<ascii> | '*' | '?') '"' ; ; access := 0 none ; 1 read ; 2 exec ; 3 full ; ; ugrp-name := 1 upto 16 user-groups the user belongs to ; [wrc] "*"=1,grpAdmin "/icontrol/util*"=0,grpGuest "*"=1,grpGuest
; ; This section lists all rules applicable to xiControl objects ; ; Wildcards that apply: '?' can occur multiple times at any place except in a range ; '*' can occur once at any place except in a range ; '[' and ']' indicate a numerical range [from to] ; ; Syntax: { {<inst-range>} ':'} <obj-range> , <access> 1-16(',' <grp-name>) ; ; inst-range := '[' <inst> {'-' <inst>} *{',' <inst> {'-' <inst>} } ']' ; inst := 0..7 ; ; obj-range := (<stm-obj>|<mod-range>) *{';' (<stm-obj>|<mod-range>) } ; ; stm-obj := 'stm.' <stm-method> ) ; stm-method := 'ping' | 'inquiry' | 'read' | ... ; ; mod-range := <mod> '.' '[' <addr> {'-' <addr>} *{',' <addr> {'-' <addr>}} ']' {'.' <chn-range> } ; mod := 'imd' | 'imw' | 'tab' | 'omd' | 'jrm' | 'amd' | 'fui' | 'fu2' | 'ebs' | 'ebr' | 'ebd' | 'dim' ; addr := 0..31 ; ; chn-range := <chn> '.' '[' <nr> {'-' <nr>} *{',' <nr> {'-' <nr>}} ']' ; chn := 'in' | 'ir' | 'im' | 'il' | 'out' | 'fb' ; nr := 0..31 ; ; access := 0 none ; 1 read ; 2 exec ; 3 full ; ; ugrp-name := 1 upto 16 user-groups the user belongs to ; [icontrol] "stm.version;stm.date;stm.time;stm.read;stm.clkread"=1,grpAdmin "omd.[0-3,16]*;dim*"=3,grpAdmin "omd.[0-3,16]*;dim*"=1,grpGuest
There are 2 xWRC options that will limit this, and apply user authentication and access rules.
; authmeth specifies the authentication method to use, values supported are: ; 0 = no authentication (default) ; 1 = basic authtentication, this will let the browser popup a window to prompt for a user/password combination, ; this method does not allow you to logout that user, unless your browser supports clearing 'authenticated sessions' ; 2 = session authentication, this will let a user login using a webpage, and also allows the user to logout authmeth=0 ; authaddr specifies whether a browser can login without any password, by using the IP-address of the machine it runs on, ; note that this is considered insecure and can only be applied for local networks ; 0 = do not support IP-address based login (default) ; 1 = support IP-address based login authaddr=0
For ease of reference we will use below notational conventions:
'string' : literal string as it shall appear [ ] : everything between the brackets is optional * : the following definition can occur zero or more times #value : numerical value, either decimal (123) or hexadecimal (0x1B3C) $value : string value, i.e. abc ( ) : groups multiple options | : denotes 'or' in case of multiple options (# | $ | *) // : the rest of the line is comment
url = 'http://' [user [':' pswd] '@'] server [':' port] '/' [req-file-spec] ['?' query] user = username in case basic authentication is enabled pswd = password in case basic authentication is enabled server = name or IP address of xWRC server, i.e. 'myserver', '192.168.0.99' port = optional port on which xWRC server is listening, default is 80 req-file-spec = ( *[dir-name '/'] [file-name] | 'icontrol.dll' ) dir-name = optional directory containing file to be served, i.e. /dir1/dir2/dir3/ file-name = optional filename including extension, i.e. abc.html, if omitted then 'default.html' will be used query = [ command ] *['&' command ] command = wait-directive | output-directive | compound-cmd wait-directive = 'wait=' #delay #delay = 0...60000 (milliseconds) output-directive = verbose-directive | terse-directive | xml-directive | file-directive | ipfile-directive verbose-directive = 'verbose' terse-directive = 'terse' xml-directive = 'xml' file-directive = 'file=' file-spec ipfile-directive = 'ipfile=' file-spec file-spec = ['/'] *[dir-name '/'] [file-name] compound-cmd = 'ccmd=' ... is passed on to xiControl, refer xiControl help files for syntax and meaning
Example:
http://myserver/default.html http://myserver/?file=/abc.html
xWRC will parse the command URL and execute any commands present, during which a $verbose-result, $terse-result and $xml-result will be composed with the outcome of each command.
If req-file-spec equals '/icontrol.dll' then the default file to return will be '/icontrol/.html', if req-file-spec is missing then '/.html' will be returned.
After execution of all commands, xWRC will send a response based on the req-file-spec overridden with optional output-directives.
The $verbose-result is a more textual description of the command outcome, it is structured as follows:
verbose-result = cmd-line CRLF *[result-line CRLF] CRLF = carriage-return + line-feed cmd-line = marker cmd ':' (error-result | success-result) result-line = marker $result-data marker = last-line | detail-line last-line = '-' detail-line = '+' cmd = command that was executed (without parameters) error-result = "err=" #error-code success-result = "ok" [$result-data]
Example:
- stm.inquiry: ok 2.18,05/07/10,12:26:46 - omd.0: err=87 - omd.0.status: ok 8 + stm.read: ok + 4000 : 0B60EEC3-40404B60-FFFFFFFF-FFFF4380 .`..@@K`......C. - 4010 : 44804580-FFFFFF D.E....
The $terse-result is a string concatinating either the error-code of a failing command, or the decimal formatted result-data of each command. A command that returns a string will add "0" to the terse result.
The separating character is the same as the character separating the commands, either a semicolon (;) or a colon (:) is allowed.
The use of these separating characters and their meaning is determined by the command sending application.
Syntax:
terse-result = (error-result | success-result) *[ (';' | ':') (error-result | success-result) ] error-result = 'err=' #err-code success-result = #result-data
Example:
0;1;0;err=1460
The $xml-result is an XML formatted string with an encapsulating <main> tag and one or more <obj> tags representing the outcome of each command, syntax:
xml-result = xml-header main-tag xml-header = <?xml version="1.0" encoding="ISO-8859-1"?> main-tag = <main> *[obj-tag] </main> obj-tag = <obj> id-tag err-tag value-tag </obj> id-tag = <id> cmd without params </id> err-tag = <err> #error-code </err> value-tag = <value> $result-data </value>
Example:
<?xml version="1.0" encoding="ISO-8859-1"?> <main> <obj> <id>omd.0.out0</id> <err>0</err> <value>0</value> </obj> </main>
The file-directive provides a way to return another file than req-file-spec, each subsequent file-directive overrides the previous one.
The ipfile-directive is similar to the file-directive, the only difference is that xWRC will lookup the peer IP-address (this is the IP-address of the browser sending the request) and insert it between $dir-name and $file-name.
Example: ipfile="/abc/main.html" is requested from a browser at IP-address 192.168.0.22, then xWRC will in effect return a file "/abc/192.168.0.22.main.html" as response.
This section explains how xWRC handles a command URL.
if (verbose-directive) { response = $verbose-result; } else if (terse-directive) { response = $terse-result; } else if (xml-directive) { response = $xml-result; // refer to section 6) AJAX Support } else if (ipfile-directive) { response = ['/'] *[ $dir-name '/' ] $peer-ip-address '.' $file-name; } else if (file-directive) { response = ['/'] *[ $dir-name '/' ] $file-name; } else if (req-file-spec == '/icontrol.dll') { response = '/icontrol/<?server theme?>.html'; } else if (req-file-spec == '') { response = '/<?server theme?>.html'; } else { response = req-file-spec; }
When a client requests a page, the server will load the file representing the page and look for tags, replacing them with their actual value on-the-fly.
If the server does not know a certain tag, it will call xiControl in an attempt to let it replace the tag with actual data.
tag = ssi | format-1 | format-2 ssi = '<!--#include file="' $template-file '" -->' format-1 = '<#' branch node [predef=value ...] '#>' format-2 = '<?' branch node [predef=value ...] '?>'Where 'ssi' stands for Server Side Include, it just includes the file referenced by file="...".
Where 'format-1' was the original tag format and is still supported for backward compatibility.
Where 'format-2' was added because it is better suited for maintaining the HTML pages in a website authoring tool like Dreamweaver. Both formats will give the same result.
Per branch dedicated nodes are defined, some nodes have pre-defined states (i.e. no, yes), for these cases it is possible to insert an optional [arg=value] specification to replace this value with a customisable output. An example can be:
<?cookie abcd empty="use this string"?> <?request loggedin no="loggedout" yes="loggedin"?>Below table lists all branches and nodes supported by the xWRC server, with a detailed description:
Branch | Node | Predef | Description |
include | [path="pathmask"] file="file" |
Generic form of include, all tags in the included file(s) will be translated. | |
path="pathmask" | Optional, enumerates "pathmask" directories to include "file", if omitted then xWRC root path will be used.
Example: <#include path="/icontrol/*.prj"#> |
||
file="file" | Specifies which file to include from the director(y)(ies) selected by 'path'.
Example: <#include file="menu.html"#> |
||
cookie | $name | empty | Inserts the value of the cookie $name, if the cookie is not set
or empty and the 'empty' argument is specified, then this value will be used instead.
Examples: |
server | alias | xWRC short product name, will be all lowercase. Example: <#server alias#> will be replaced with '<#server alias#>'. |
|
author | xWRC author + copyright statement. Example: <#server author#> will be replaced with '<#server author#>'. |
||
connections | The current number of network connections handled by the server. Example: <#server connections#> will be replaced with '<#server connections#>'. |
||
created | xWRC creation date of this version. Example: <#server created#> will be replaced with '<#server created#>'. |
||
date | The current server UTC date in format 'yyyy/mm/dd'. Example: <#server date#> will be replaced with '<#server date#>'. |
||
description | xWRC product description. Example: <#server description#> will be replaced with '<#server description#>'. |
||
fontsize | The fontsize in pt to use in all server pages. Example: <#server fontsize#> will be replaced with '<#server fontsize#>'. |
||
hits | The number of hits (client requests) handled by xWRC. Example: <#server hits#> will be replaced with '<#server hits#>'. |
||
hostname | Name of the machine on which xWRC is running. Example: <#server hostname#> will be replaced with '<#server hostname#>'. |
||
httpport | The port on which the xWRC HTTP server is listening. Example: <#server httpport#> will be replaced with '<#server httpport#>'. |
||
name | xWRC full product name. Example: <#server name#> will be replaced with '<#server name#>'. |
||
platform | The HW platform on which xWRC is running, either 'Win32/x86', 'Linux/MIPS', 'Linux/ARM' or 'Linux/x86'. Example: <#server platform#> will be replaced with '<#server platform#>'. |
||
plugcount | The number of plugins found by xWRC server. Example: <#server plugcount#> will be replaced with '<#server plugcount#>'. |
||
plugins="file" | Enumerates the available plugins using template "file", supported for backward compatibility. Example: <#server plugins="xwrc.menu.plugin.html"#> |
||
theme | The current server theme, used to determine server root page as /<theme>.html. Example: <#server theme#> will be replaced with '<#server theme#>'. |
||
time | The current server UTC time in format 'hh:mm:ss'. Example: <#server time#> will be replaced with '<#server time#>'. |
||
uptime | The time during which xWRC has been running so far. Example: <#server uptime#> will be replaced with '<#server uptime#>'. |
||
version | xWRC version using format 'x.y.z.t'. Example: <#server version#> will be replaced with '<#server version#>'. |
||
request | loggedin | no yes |
Indicates whether this request was made by a logged in user, 0=no, 1=yes.
Example: <?request loggedin no="No" yes="Yes"?> |
loggedinas | Returns the name of the logged in user.
Example: <?request loggedinas?> |
||
sessionid | The sessionid allocated for a logged in user.
Example: <?request sessionid?> |
||
authmeth | none basic session ipaddr |
Authentication method used for this request, 0=none, 1=basic, 2=session, 3=ipaddr.
Example: <?request authmeth none="None" basic="Basic" session="Session" ipaddr="IpAddr"?> |
|
file | The last file-directive or ipfile-directive of a request.
Example: <#request file#> returns '<#request file#>' |
||
terse | no yes |
Indicates the presence of the terse-directive in the request, there are
2 predefined values: no, yes.
Example: <#request terse#> |
|
verbose | no yes |
Indicates the presence of the verbose-directive in the request, there are
2 predefined values: no, yes.
Example: <#request verbose#> |
|
xml | no yes |
Indicates the presence of the xml-directive in the request, there are
2 predefined values: no, yes.
Example: <#request xml#> |
|
response | verbose | The $verbose-result after handling the request.
Example: <#response verbose#> |
|
terse | The $terse-result after handling the request.
Example: <#response terse#> |
||
xml | The $xml-result after handling the request.
Example: <#response xml#> |
||
xml | file="xml-file" node="xml-node" |
Generic form to include data from an xml formatted file. | |
file="xml-file" |
Specifies which xml formatted file to use, contents can be like this:
<!-- this is comment --> <?xml optional header ?> <node1> <!-- this is comment --> <subnode1>value1</subnode1> <subnode2> <!-- this is comment --> <subnode21>value21</subnode21> </subnode2> </node1>
|
||
node="xml-node" | Specifies which xml-node value to include from 'file', the format is:
xml-node ::= node-name *[ '.' node-name ]
Example: <#xml file="/icontrol/test.xml" node="node1.subnode2.subnode21"#> |
Opposed to the standard HTTP request/response behaviour where a client sends a request and reloads the complete page as returned by xWRC, it is also possible to send commands to xWRC over a separate communication channel that does not require complete reloading of the page.
For this we use JavaScript to initiate a separate connection with the server, send a command and handle the response data. The response data can be XML encoded or plain text depending on the output-directives specified.
Refer to the wikipedia page on AJAX for a more complete technical explanation.
Upto now we prepared a static HTML page, with command links and tags to represent the actual state of your PHC system, but it was always xWRC that made sure to compose the final HTML code sent to your browser.
With AJAX we can move part of that intelligence to your browser by using JavaScript code, as a result your webpage will become more responsive and less data is transferred from xWRC to your browser.
xWRC implements 3 modes of AJAX support:
Selected by adding the terse-directive to the request sent to xWRC.
Terse mode causes the $terse-result to be returned, it is upto the JavaScript to map these results onto the existing page.
Example:
http://myserver/icontrol.dll?ccmd=omd.0.toggle&terse
Selected by adding the xml-directive to the request sent to xWRC.
Mode 0 causes the $xml-result to be returned, it is upto the receiving JavaScript to map results onto the existing page.
Example:
http://myserver/icontrol.dll?ccmd=omd.0.toggle&xml
This mode is selected by only adding a file-directive or ipfile-directive specifying an XML file (*.xml).
Example:
http://myserver/icontrol.dll?ccmd=omd.0.toggle&ipfile="/icontrol/myproject.xml"
Mode 2 causes the complete XML file to be returned, thereby replacing tags when present, it is upto the receiving JavaScript to map results onto the existing page.
Last modified: 15-apr-2013 |