================================================================================ Bauk HTTP Server GromJS Server-Side JavaScript interpreter ================================================================================ Version 1.7.14 Server-Side JavaScript Reference This manual includes prototypes of built-in classes, objects and functions available with GromJS Server-Side JavaScript interpreter. In addition to this manual see sample Server-Side JavaScript Web scripts provided in package. The definitions of classes, objects and function prototypes in this manual are given in pseudo-code ie. close resembling C/C++ programming lanugages with precise definitions of data type, function arguments, return values, etc. Note that this manual does not cover JavaScript basics, ie. it is assumed that reader already has minimum previous knowledge of JS. -------------------------------------------------------------------------------- CONTENTS -------------------------------------------------------------------------------- - Top level functions - Cgi object (handles client-sent data in GET/POST request, HTTP uploaded files, cookies, etc., and provides methods for manipulation of these values; ie. var myval = Cgi.any("myvar"); see examples below) - Server object (includes various functions related to JS interpreter process ie. getpid, timeout, etc., utility functions ie. getenv, time, rand, FS manipulation ie. mkdir, rmdir, unlink, link, symlink, chmod etc.) - Session object (disk-based session variables for data persistence between script executions) - File class (manipulation of files on server, ie. open, close, read, write, lock, seek, truncate, etc.; efficient, unlimited file size support, easy and intuitive JS API) - BDB class (BDB database JS API) - MySQL class (MySQL database JS API) - PostgreSQL class (PostgreSQL database JS API) - SQLite class (SQLite3 database JS API) - Pipe class (executing external programs and communicating through Unix pipe) - Dictionary class (hash array, unlimited number of entries, configurable efficiency/speed) -------------------------------------------------------------------------------- TOP LEVEL FUNCTIONS -------------------------------------------------------------------------------- void load(string SCRIPTPATH [,string SCRIPTPATH2 ...]); //Load script(s) on SCRIPTPATH void include(string SCRIPTPATH [,string SCRIPTPATH2 ...]); //Same as "load()" uint print(string DATA [,string DATA2 ...]); //Print arguments uint printf(string DATA [,string DATA2 ...]); //Same as "print()" -------------------------------------------------------------------------------- CGI OBJECT -------------------------------------------------------------------------------- GromJS built-in "Cgi" object provides access to client-sent data ie. query string, POST data, uploaded files, cookies etc. GromJS interpreter by default automatically outputs response headers and Cgi.header() function is available for setting arbitrary response headers. //object prototype: object Cgi { //methods: string query([string VARNAME [, string DEFAULT]]); string querystring([string VARNAME [, string DEFAULT]]); /*Used with no argument, returns whole querystring; with argument VARNAME returns it's value; if var not found returns null; if second arg DEFAULT supplied it is returned if var not found.*/ string post([string VARNAME] [, string DEFAULT]); string postdata([string VARNAME] [, string DEFAULT]); /*Values searched in POST data.*/ string any(string VARNAME [, string DEFAULT]); /*Fetch variable from any available, querystring or POST data, searched in that order. Note: methods Cgi.query(), Cgi.post(), Cgi.any() by default return null if requested var not found. Optional 2nd arg DEFAULT can be supplied which is returned when requested var is not found, ie.: var myval = Cgi.any("myvar", ""); returns empty string if myvar not found.*/ array varnames(); /*Returns array of strings with all var names from querystring and postdata ie. script with URL "script.js?a=a&b=b" returns array containing "a", "b". */ void varurldecode(uint DECODE); /*Sets on/off decoding of vars from query/POST data. By default decoding is enabled, ie. Cgi.any("abc") etc. return URL-decoded values. Setting Cgi.varurldecode(0) will return values 'as is' as they are supplied in HTTP request.*/ void separators(string SEPARATORS); /*Use alternative separator (delimiter) chars for querystring/postdata; default are "=" and "&" Example: Cgi.separators("=;") to use "=" and ";" as delimiters.*/ string getcookie(string COOKIENAM [, string DEFAULT]); /*Get value of COOKIENAM (available in "HTTP_COOKIE" environment variable), if var not found returns null; second argument DEFAULT if supplied is returned if requested var not found.*/ bool setcookie(string COOKIESTR); /*Set cookie.*/ bool header(string HEADER); /*Add arbitrary response header ie. Cgi.header("Content-Type: image/gif"); */ void freepost(); /*Optional; POST data automatically released on end of script execution.*/ //properties: array Files; /*Array of "Uploadedfile" objects; see "Uploadedfile" prototype below.*/ }; //example: //Hello world JS Web script: //BEGIN SCRIPT--> print(""); print("

Hello, world!!

"); print(""); //<--END SCRIPT //example: //fetching client-supplied values: //ie. /script.js?somevar=someval&myvar=myval //print value of "myvar" print(Cgi.any("myvar"), "
"); //ie. /script.js?somevar=someval&myvar=myval //test if "myvar" is supplied in request: var smyval = Cgi.any("myvar"); if ( smyval!=null ) { //yes, "myvar" found } //print cookie //test if cookie "myid" is supplied in request: var myid = Cgi.getcookie("myid"); if ( myid!=null ) { //yes, "myid" cookie fond print(myid, "
"); } //set cookie Cgi.setcookie("myid=myval;"); //set dynamically generated cookie, expires 7 days from now Cgi.setcookie("myid=myval; path=/; expires=" +Server.gmtdate(Server.time()+(7*24*60*60)) +";"); -------------------------------------------------------------------------------- UPLOADEDFILE OBJECT -------------------------------------------------------------------------------- GromJS built-in "Uploadedfile" object is an element of "Cgi.Files" array and provides information about (by a HTTP client) newly uploaded file on server, ie. size, file location/path, original filename, encoding, etc. //Uploadedfile object //object prototype: object Uploadedfile { //properties string name; /*Name of HTML form input field ie. "myphoto1".*/ string filename; /*Filename on client's disk ie. "c:\files\myfile.gif" or "/files/myfile.gif".*/ string tmpfile; /*Location of newly created uploaded file on server ie. /tmp/upload23457742463624355325.dat.*/ string type; /*File type ie. image/gif.*/ string encoding; /*Encoding.*/ uint size; /*Size of uploaded file in bytes.*/ }; //example: //array length indicates the number of uploaded files if ( Cgi.Files.length>0 ) { var Uplfile = Cgi.Files[0]; //0'th Uploadedfile object print(Uplfile.name,"
"); //print the name of HTML form input field print(Uplfile.filename,"
"); //print filename of uploaded file print(Uplfile.tmpfile,"
"); //uploaded tmp file location print(Uplfile.size,"
"); //size of uploaded file } //example: //BEGIN SCRIPT--> print(""); print("

File upload example

"); var cFile = 0; //move multiple uploaded files to their destination while ( cFileMoving uploaded file into upload dir... "); //move tmp file to destination if ( Server.move(Upfl.tmpfile, "/path/to/uploaddir/newfile_"+cFile+".jpg")==true ) { print("[OK] file moved"); } //error else { print("[error] ", Server.errnstr()); } print(""); cFile++; } print(""); //<--END SCRIPT -------------------------------------------------------------------------------- SERVER OBJECT -------------------------------------------------------------------------------- GromJS built-in "Server" object includes a set of functions (methods) related to JavaScript interpreter process such as process PID, errno, exit etc., various utility functions such as current time, rand etc., file-system interaction functions ie. mkdir, chmod, stat, file copy, unlink, etc. //object prototype: object Server { //methods: void timeout(uint SECONDS); /*Script timeout; set max SECONDS allowed for script execution after which process exits, ie. abort script in infinite loop.*/ uint sleep(uint SECONDS); /*Put process to sleep for SECONDS seconds.*/ void gc(); /*Run garbage-collector; Ie. after many vars used, large arrays, database reads/writes etc.*/ void buffer(uint BUFFER); /*Output buffer; 0==no buffer, output is sent immediately; non-zero==output is buffered and sent in blocks of that size default is buffered to 64kb (max).*/ void verbose(uint VERBOSE); /*Overrides default GromJS verbosity, ie. Server.verbose(1) displays script path on error, 0 keeps path descrete.*/ void fflush(); void flush(); /*Force output from buffer (flush output buffer)*/ void exit([string MSG]); /*Abort script execution and exit process; before exit print MSG if provided.*/ void quit([string MSG]); void abort([string MSG]); /*Abort script execution but without terminating JS interpreter's persistent process.*/ string version([uint ELEM]); /*GromJS JavaScript Host Environment version string, ie. GromJS 1.7.11 JavaScript-C 1.7.0; Optional arg ELEM if supplied causes return only the specific element 0-3 of complete version string.*/ uint uptime(); /*Number of seconds persistent process is active.*/ uint requests(); /*Number of requests (scripts) GromJS persistent process has executed ie. 1, 2, 50, 5000 etc.*/ uint rss(); /*Process resident set size (memory footprint), in kilobytes.*/ uint wsimode(); /*Returns 1 if GromJS is operating in WSI mode, 0 otherwise.*/ uint random(); uint rand(); /*Random 52bit unsigned integer number.*/ uint time(); /*Current time, in seconds; number of seconds since epoch time.*/ uint microtime(); uint utime(); /*Current time in microseconds.*/ string timestamp([uint TIME]); /*Return date and time string in format yyyymmddhhmmss, for example 20081124182144. If used without argument, returns timestamp for current time. */ string localdate([uint SECONDS]); /*Local date string, if no args date is for current time, identical to calling Server.localdate(Server.time()).*/ string gmtdate([uint SECONDS]); /*GMT date.*/ string date([uint SECONDS [, uint LOCALDATE]]); /*Date format "dd-mmm-yyyy hh:mm:ss", with no args date for current GMT time; If SECONDS is null date also for current time; if LOCALDATE supplied and non-zero, date is local, otherwise GMT; ie. localdate for current time: Server.date(null,1);*/ uint getpid(); /*Process PID number.*/ string getcwd(); /*Get current working dir.*/ //system error functions uint errno([uint ERRNO]); /*System errno. With no argument, get system error number. If argument is provided and value 0, sets errno to zero.*/ string errstr([uint ERRNO]); /*System error string. If ERRNO supplied, string for that specific ERRNO.*/ string errnstr([uint ERRNO]); /*Returns string with joined errno() and errstr(). If ERRNO supplied, string for that specific ERRNO.*/ array dirlist(string DIRPATH); /*List filenames in dir DIRPATH and return as array of strings, without "." and ".." entries; null returned on error, ie. unable to read directory, no permission etc. Server.errno() provides more info.*/ string filemodestring(uint MODE); /*Ie. for mode 0755 return string -rwxr-xr-x*/ string pathcompile(string ARG [,string ARG2, ...]); /*Assemble path string from optional number of arguments; converts backslashes to slashes and removes double slashes: ie. Server.pathcompile("aaa","\\bbb/","/ccc") returns path "aaa/bbb/ccc"; to create absolute path simply begin by "/".*/ string includepathget(void); string getincludepath(void); /*Returns path of include directories, with multiple paths separated by colon ':', ie. "/usr/lib:/usr/local/lib".*/ void includepathset(string PATH); void setincludepath(string PATH); /*Sets path of include directories, with multiple paths separated by colon ':' ie. "/usr/lib:/usr/local/lib". Example: Server.includepathset(Server.includepathget()+":"+"/path/to/xyz"); */ //environment variables string getenv(string VARNAME [,string DEFAULT]); /*Returns value of VARNAME, null if not found; optional second arg can be supplied which is returned if var is non-existing, ie. Server.getenv("myvar","") returns empty string if var not found.*/ string setenv(string VARNAME, string VALUE); /*Sets env vars passed to Server.execve() or Pipe() program. Calling with parameter null ie. Server.setenv(null) clears all vars set by Server.setenv(). It also allows over-writing present vars if required ie. to hide them from executed script, ie. Server.setenv("PATH_TRANSLATED",""); causes empty path to be passed to executed script/program.*/ array envvarnames(); array varnames(); /*Array of all environment variables names.*/ array argv(); /*Returns array of command line arguments*/ //All functions below return true if operation succeeded, false //otherwise; If operation failed, Server.errno() provides the system //error number: bool chdir(string DIRPATH); /*Change working dir to DIRPATH*/ bool mkdir(string DIRPATH, uint MODE); /*Make new dir under filemode MODE*/ bool rmdir(string DIRPATH); /*Remove empty dir*/ bool chmod(string PATH, uint MODE); /*Change mode of PATH to MODE ie. 0644*/ bool rename(string OLDPATH, string NEWPATH); bool move(string OLDPATH, string NEWPATH); /*Rename/move OLDPATH to NEWPATH; if NEWPATH is a directory, moves to destdir.*/ bool symlink(string EXISTINGPATH, string NEWLINKPATH); /*Create a symlink.*/ bool link(string EXISTINGPATH, string NEWLINKPATH); /*Create a hard link.*/ bool unlink(string PATH); /*Remove a file.*/ bool copy(string FILEPATH, string NEWPATH [, uint APPEND]); /*Copy regular file on FILEPATH to NEWPATH, if third arg APPEND present and non-zero then append to destination if NEWPATH is directory, copies under original filename to destdir.*/ bool utimes(string PATH [, uint ASEC [, uint AUSEC [, uint MSEC [, uint MUSEC]]]]); /*Change file access and modification time only with PATH arg supplied, Server.utimes() changes file access and modification time to current time optional arguments are access seconds/microseconds, and modification seconds/microseconds. Example: Server.utimes("/path/to/myfile.txt", Server.time()- 10) sets both acc/mod times to 10 seconds prior current time.*/ int cat(string FILEPATH [, uint OFFSET [, uint LEN]]); /*Read file contents and output to stdout; if no arguments OFFSET and LEN, offset is 0 and length is untill end-of-file; returns number of bytes output, -1 on error.*/ string readlink(string PATH); /*Read the contents of the symbolic link path in PATH and return as string. On error returns null.*/ //retrieving file status object Stat stat(string PATH [, bool INFOABOUTSYMLINK]); /*get file status information returned as Stat object (see prototype below); on error function returns null and Server.errno() provides system error number. */ //utility uint hash(string TEXT); /*Create unique uint for string TEXT*/ string hashx(string TEXT); /*For string TEXT calculate 128bit hash number returned as string; ie. Server.hashx("abcxyz") returns string ie. 83417c95fa27a5ed5c68dc4df3ccca3a.*/ string sha1(string TEXT); /*For given string TEXT, calculate sha1 and return as string (hex representation of 160bit sha1 number).*/ string execve(string PROGPATH [,string ARG1 [,string ARG2 ...]]); /*Run executable on location PROGPATH and return it's output as a string; on error Server.execvestatus() is non-zero ie. execve failed/process unclean exit.*/ int execvestatus(void); /*Returns execve'd program exit status; non-zero on error or process unclean exit.*/ uint ip2n(string IPADR); /*IPv4, for string "123.45.67.8" return numeric value 23478899*/ string n2ip(uint IPNUM); /*IPv4, for numeric value 23478899 return string "123.45.67.8"*/ object Hostent gethostby(string NAMEORADR); /*IPv4, get hostentry by name or IP address. Argument NAMEORADR represents an IP ie. 123.4.5.78 or hostname ie. www.domain.com etc. See object Hostent prototype below. */ string read([uint LEN]); /*GromJS CLI mode only, in WSI mode returns null; read up to LEN bytes from stdin and return as string, with no argument reads untill end of input (closed write end).*/ string readline(void); /*GromJS CLI mode only, in WSI mode returns null; read a single line from stdin, or untill end of input (closed write end)*/ //String chars manipulation functions: int charbfind(string DATA, string CHAR2FIND); int charlastindexof(string DATA, string CHAR2FIND); /*Find last index of specific char var cindex = Server.charbfind("xyxyz", "y"); returns 3 as index for 'y' char first found backwards. Returns -1 if char not found. */ string chartrim(string DATA [, string CHARS2TRIM [, uint WHICHEND]]); /*Trim chars CHARS2TRIM, WHICHEND 1=leading, 2=trailing, 3=trim both ends. Used only with argument DATA, by default trims both ends chars TAB CR LF and SPACE ("\t\r\n "). var trimmed = Server.chartrim(" abc ", "\t\r\n ", 3); returns string "abc". */ string charkeep(string DATA, string CHARS2KEEP); /*Keep chars CHARS2KEEP remove all other var cleared = Server.charkeep(" abc ", "ac"); returns string "ac", all other chars removed. */ string charremove(string DATA, string CHARSREMOV); /*Remove chars CHARSREMOV var cleared = Server.charremove(" abc ", " c"); returns string "ab", spaces and c removed. */ string charreplace(string DATA, string CHARSFROM, string CHARSTO); /*Char by char replace, CHARSFROM change to CHARSTO var changed = Server.charreplace(" abc ", " b", "_"); returns string "_a_c_", spaces and b changed to _. */ string charcutto1(string DATA, string WHICH); /*Cut repetitive successive chars to 1 count var ccut = Server.charcutto1(" aaa bbbb ccc ", " a"); returns string " a bbbb ccc ", with a and spaces reduced to 1 count. */ }; //Example: //Simple script printing environment variables: //BEGIN SCRIPT--> print(""); //get a single env variable: var contlen = Server.getenv("CONTENT_LENGTH"); //print all environment variables var ENVNAMES = Server.envvarnames(); //array of all env var names var cVarnam = 0; //Ie. //REQUEST_METHOD = POST //CONTENT_LENGTH = 123 //QUERY_STRING = abc=234 //etc. etc. for ( cVarnam=0; cVarnam"); //<--END SCRIPT //Utility functions examples: //print localdate print(Server.localdate(), "
"); //file copy example: if ( Server.copy("myfile.txt", "myfile2.txt")==true ) { //operation succeded } -------------------------------------------------------------------------------- STAT OBJECT -------------------------------------------------------------------------------- GromJS "Stat" object is returned by Server.stat() function and provides file status information such as file type, size, modification and access time, mode, etc. //object prototype: object Stat { //properties: uint size; //size of file in bytes uint ta; //time of last access, in seconds uint tm; //time of last modified uint tc; //time of last file status change uint mode; //file mode, ie. 0644 //bools indicating file type bool isreg; //true if regular file bool isdir; //true if file is a directory bool islink; //true if symlink bool ischar; //true if char special bool isblock; //true if block special bool isfifo; //true if named pipe (fifo) bool issock; //true if socket }; //example: var statobj = Server.stat(string PATH [, bool SYMLINKINFO]); //prototype var statobj = Server.stat("/path/to/myfile.txt"); /*get file status information*/ var statobj = Server.stat("/path/to/myfile.txt", 1); /*same, 2nd argument indicates that if file is symlink get information about link itself not file it points to*/ //file stat ok if ( statobj!=null ) { print("The size of myfile.txt is ", statobj.size, "
"); if ( statobj.isreg ) { //regular file } if ( statobj.isdir ) { //directory } } //error else { print("ERROR: Getting information about myfile.txt failed"); //ie. [errno 2] No such file or directory print(Server.errnstr(),""); } -------------------------------------------------------------------------------- HOSTENT OBJECT -------------------------------------------------------------------------------- The "Hostent" object is returned by Server.gethostby() function and provides information about host by IP address/hostname. //object prototype: object Hostent { string name; //Official name of host array aliases ; //String array alias list array addresses; //String array list of addresses from name server uint herrno; //herrno (host errno) number; 0 on success }; //example: var Hstent = Server.gethostby("123.34.67.89"); var Hstent = Server.gethostby("www.domain.net"); if ( Hstent.error==0 ) { //operation succeded print(Hstent.name, "
"); //print official name of host print(Hstent.aliases.join(", "), "
"); //print joined array of aliases print(Hstent.addresses.join(", "), "
"); //print joined array of adresses } -------------------------------------------------------------------------------- SESSION OBJECT -------------------------------------------------------------------------------- GromJS built-in "Session" object provides methods for efficiently reading/storing variables between script executions. Session variables are disk based (stored on disk) and have no direct memory limitation ie. it is ok using a 20mb data in session variable if required. Variables are stored in form of text, meaning that numbers (or objects) must first be converted to string and then stored in session. When reading a numeric (or object) value from session variable, it is a reverse process, value is retrieved as text, then converted to it's original type. Each session is unique and defined by identifier sent to HTTP client/browser as session-id cookie, for example, SESSIONID=56827836d5b2f627597894b24793788c. On reading (fetching) a session var which is not present in session (ie. has not been set, or has expired) ie. Session.get("varnam") returns null. Optionally if second arg is supplied ie. Session.get("varnam", "") and var not found, returns the second arg, ie. empty string. Storing null as value effectively deletes variable from session, ie. Session.set("varnam", null) deletes "varnam" from session. Setting time 0 deletes all variables in session ie. calling Session.time(0); makes all variables expire immediately and effectively deletes them. Session object and methods are fully automated and do not require any type of initialization or special management. Ie. user calls "get()", "set()" etc. at any desired order/sequence to fetch/store variables, and session management is done automatically by interpreter (ie. it's automatically initialized on start and automatically stored to disk at end of script execution). //object prototype: object Session { //methods: uint time([uint DURATION]); /*Get or set duration of variables in seconds; used with no argument returns the duration of session variables, otherwise argument sets session duration; setting time to 0 has effect of deleting all variables ie. all vars expire immediately. */ string get(string VARNAM [, string DEFAULT]); /*Get value of variable VARNAM; if variable is not present in session (not set or has expired) null is returned; optional second arg DEFAULT can be supplied to be returned if VARNAM not found in session. */ void set(string VARNAM, string VALUE); /*For variable VARNAM set value to VALUE; supplying null as value has effect of deleting a var from session. */ array varnames(); /*Returns array (of strings) of all var names in session*/ void todisk(); /*Optional, store session to disk (if omitted it is done automatically by session itself at end of script execution). */ }; //Example: var sessdurat = Session.time(); //get current duration of session Session.time(7*24*60*60); //set session duration to 7 days var sessvar1 = Session.get("sessvar1"); //get value of sessvar1 Session.set("sessvar2", "abc"); //set session var Session.todisk(); //optional force storing to disk var sessvar3 = Session.get("sessvar3"); //ok to call again after storing on disk Session.time(10*60); //change duration to 10min Session.set("sessvar4", "def"); //set another session var Session.todisk(); //again, to disk //..etc etc... //Example: //BEGIN SCRIPT--> //Page visit counter: //Demonstrate usage of session object var sSessVarName = "visitcount"; var nVisits = parseInt(Session.get(sSessVarName,"")); //if not set or zero if ( isNaN(nVisits) || nVisits==0 ) { nVisits = 1; } //print HTML page print(""); print("

Page visited: ", nVisits, " times.

"); //set duration of variables Session.time(7*24*60*60); //increment value and store to session Session.set(sSessVarName, (nVisits+1)+""); print(""); //Session is stored to disk automatically at and of script execution. //<--END SCRIPT -------------------------------------------------------------------------------- FILE CLASS -------------------------------------------------------------------------------- GromJS built-in "File" class provides access to files for read/write, and additional functions for manipulating file data such as lock, truncate, seek, etc. File data I/O by functions read()/write() is in chunk mode and "textual" (data is first converted to string then stored), ie. calling function myfile.read(20) reads 20 bytes from current file position, myfile.write("abcd") writes string "abcd" to file's current position. Numeric values (numbers) are read/written in their string (textual) representation. Functions nread()/nwrite() provide binary file I/O for numeric values, ie. each nwrite() call stores JavaScript Number type binary value to file, and nread() retrives it from file in same way. Additional information about file itself ie. file type (regular, dir, symlink etc.), permissions, etc. can be obtained using Server.stat() function. //example var fileobj = new File(string FILEPATH); var fileobj = new File("/path/to/myfile.txt"); //class prototype: class File { //methods bool open(string OPENMODE [,uint CREATEMODE]); /*Open file by specified mode OPENMODE; see below.*/ bool close(); /*Close; also removes any lock file has set.*/ int write(string DATA [, string DATA2, ...]); /*Write to file; multiple arguments; returns number of bytes written; on error returns -1. */ string read([uint LEN]); /*Read LEN bytes and return as JavaScript string; if no argument read all available bytes from current file position onward; on failure null returned. */ int cat([uint LEN]); /*Cat LEN bytes to stdout, if no argument, cat all available bytes from current file position onward; returns number of bytes done; -1 returned on error. */ uint tell(); /*Returns current file position index.*/ bool seek([uint ABSPOSITION]); /*Seek to new absolute position within file, if no argument seek to end of file. */ string path(); /*Returns file path used in "new File(PATH)" call.*/ bool lock(string LOCKTYPE); /*Lock using LOCKTYPE; see below.*/ bool unlock(); /*Release lock.*/ bool truncate([uint LEN]); /*Truncate opened file to new length; if no argument truncate to current file position. */ }; File open modes: ---------------- r = Open for reading w = Open for writing and set file position to beggining of file c = Create file by mode CREATEMODE if not existing t = Truncate file a = Open for write/append and set position to end of file, excludes truncate flag File lock modes: ---------------- s = Set shared lock x = Set exclusive lock n = Non-blocking, attempt to set lock but if locked by another process and would block, return error EWOULDBLOCK u = Unlock //example var fileobj = new File("/path/to/myfile.txt"); //set errno 0 Server.errno(0); //open for RW, truncate and if not existing create mode 0644 if ( fileobj.open("rwtc", 0644)==true ) { //set exclusive lock, blocking if ( fileobj.lock("x")==true ) { //locked fileobj.unlock(); } //set non-blocking exclusive lock if ( fileobj.lock("xn")==true ) { //locked fileobj.unlock(); } //set shared lock; process blocked untill capable of setting lock if ( fileobj.lock("s")==true ) { //locked fileobj.unlock(); } fileobj.close(); } //error else { //ie. [errno 13] Permission denied print(Server.errnstr(),""); } //open and read complete file if ( fileobj.open("r")==true ) { var fdata = fileobj.read(); //read all if ( fdata!=null ) { //ok } fileobj.close(); } -------------------------------------------------------------------------------- BDBCLIENT CLASS -------------------------------------------------------------------------------- GromJS built-in "Bdbclient" class provides JS API for manipulating BDB database. BDB client is part of native GromJS code and requires no linking. //constructor var Bdbc = new Bdbclient(); //class prototype: class Bdbclient { //methods bool connect(string HOST, uint PORT, string USERNAME, string PASSWORD); /*Connect to BDB database server.*/ void close(); /*Close connection.*/ bool dbcreate(string DATABASE); bool createdb(string DATABASE); /*Create new database.*/ bool dbdrop(string DATABASE); bool dropdb(string DATABASE); /*Remove an existing database.*/ bool dbselect(string DATABASE); bool selectdb(string DATABASE); /*Select database.*/ bool exec(string COMMAND); /*Execute single or multiple BDB commands separated by semicolon in COMMAND text. Returs true if all commands executed with no error. If executed with error, function "error()" provides additional info.*/ bool rowhas(); bool rowavailable(); /*Returns true if there is a row available in result list and positiones the cursor on it.*/ uint rowcount(); /*Returns number of rows in result list.*/ array rowget(); array rowfetch(); array fetchrow(); /*Returns next row from result list as array of strings. Returns null if no row available.*/ object rowobjectget(); object getrowobject(); /*Returns next row from result list as JS object with each column name as property prepended by '_'. Ie. rowid column as "rowobj._rowid". If no row available returns null.*/ array object rowobjectlist(); /*Returns array of row objects from result list. On error returns null.*/ uint rowsaffected(); /*Returns number of rows affected by DELETE or UPDATE command.*/ uint lastinsertrowid(); /*Returns the last rowid generated by INSERT command.*/ uint colcount(); /*Returns number of columns in result list.*/ string colname(uint COL); /*Returns column name for index COL in result list. Returns null if no row available.*/ string colget(uint COL); /*Returns column value for index COL in result list. Returns null if no row available.*/ string random(); string rand(); /*Returns 64bit uint random number as string, for example 2349843454689430854.*/ string hash64(string TEXT); /*Returns 64bit uint hash number as string for given TEXT. Ie. db.hash("abc") returns string such as 8458874259895733280.*/ string composite64(uint32 HI, uint32 LO); /*Returns 64bit uint number as string composed of two 32bit numbers. Usable for creating large 64bit identifiers from smaller 32bit values.*/ bool fdump([string FILEPATH]); /*Output complete contents of database in form of BDB commands to a file.*/ bool fexec(string FILEPATH); /*Load and execute BDB commands from a file.*/ bool reorganize(); /*Notifies server to reorganize database data. Results in optimized data alignment and eliminating any unused space. Database must be dbselect()'ed first.*/ string stringescape(string DATA); /*Returns BDB escaped string.*/ string stringescapeenclose(string DATA); string see(string DATA); /*Returns BDB escaped and enclosed by single quotes string.*/ string error(); /*Database error string and information.*/ }; //Example: //BEGIN SCRIPT--> //A simple bulletin board script with BDB database print(""); print("

BDB Bulletin Board

"); print("
"); //Wrapper method for handling rows and columns in objective style Bdbclient.prototype.rowxobjectlist2 = function(sCmnd) { //Local class function ObjectListClass(aRowObjs) { var Lst = this; //List Lst.aROL = aRowObjs; //Row object list Lst.nRows = aRowObjs.length; Lst.cRow = 0; //methods Lst.count = function() //Number of rows in list { return Lst.nRows; } Lst.next = function() //Fetch next row { if ( Lst.cRow",HTMLENCODE(Thrd._stitle),""); print("

Thread by: ",HTMLENCODE(Thrd._suser),"

"); if ( Msglst!=null ) { var Msg; //One message //Print messages in a loop while ( (Msg=Msglst.next())!=null ) { //Print messages print("

By: ", HTMLENCODE(Msg._suser), "
", HTMLENCODE(Msg._smessage), "

" ); } } } } //Close connection Bdbc.close(); } //Error else { print("

[error] ",Bdbc.error(),"

"); } print(""); //<--END SCRIPT -------------------------------------------------------------------------------- MYSQL CLASS -------------------------------------------------------------------------------- GromJS "Mysql" class provides JavaScript API for manipulating MySQL database. //class prototype: class Mysql { //methods bool connect(string HOSTNAM, string USER, string PSWRD [, uint PORT, string FIFOSOCK]); /*Connect to MySQL database server, returns true on success*/ bool close(); /*Close connection to Mysql database*/ bool query(string STMT); /*Execute SQL statement STMT and create result set; returns true on success */ bool exec(string STMT); /*Same as "query()"*/ bool ping(); /*Check if connection active, reconnect if required, returns true on success */ bool selectdb(string DBNAME); /*Select database*/ array colnames(); /*Returns array of column names in result set*/ uint colnum(); /*Number of columns in result set*/ uint colcount(); /*Same as "colnum()"*/ array rowfetch(); /*Return a single row from result, as JavaScript array of strings; null returned if no row is available */ array fetchrow(); /*Same as "rowfetch()"*/ array array rowsallfetch(); /*Return all rows from result as JavaScript two- dimensional array of strings */ array array fetchallrows(); /*Same as "rowsallfetch()"*/ uint insertid(); /*Returns id created by database last insert operation*/ uint affectedrows(); /*Number of rows affected by INSERT, DELETE etc. operations*/ string error(); /*MySQL db error string*/ uint errno(); /*MySQL db error number*/ string realescapestring(string DATA); /*Escapes special characters according to character set of the connection */ string escapestring(string DATA); /*Escape string*/ void freeresult(); /*Results are free'd automatically; if required freeresult() can be used */ }; //BEGIN CODE--> //Mysql class; //Create new database and table, insert values, and then select and print //values from table print(""); var Mdb = new Mysql(); //Mysql class //set errno 0 Server.errno(0); //Connect to MySQL server if ( Mdb.connect("domain.com","usernam345","pswrd345",3306,"/tmp/mysql.sock")==true ) { //create database, table, insert values... //Mdb.query("CREATE DATABASE testdb"); //Mdb.selectdb("testdb"); //Mdb.query("CREATE TABLE testtbl ..."); //Mdb.query("INSERT INTO testtbl ..."); //query values: if ( Mdb.selectdb("testdb")==true ) { //now query if ( Mdb.query("SELECT id FROM testtbl")==true ) { var onerow; //get row as JS Array object from result set while ( (onerow=Mdb.rowfetch())!=null ) { //print column: //1
//2
print(onerow[0], "
"); } //optional; results free'd automatically Mdb.freeresult(); } } //error else { //ie. cannot select database etc. print("Error in exec, error [" ,Mdb.error(), "]
"); } //close connection Mdb.close(); } //error else { //ie. can not connect to database server etc. print("Error connecting to database, error [" ,Mdb.error(), "]
"); //ie. no permission etc. print("System errno: " , Server.errnstr(), "
"); } print(""); // <--END CODE -------------------------------------------------------------------------------- POSTGRESQL CLASS -------------------------------------------------------------------------------- GromJS "Postgresql" class provides JavaScript API for manipulating PostgreSQL database. //class prototype: class Postgresql { //methods bool connect(string CONNARGS); /*Connect to PostgreSQL database server, returns true on success */ bool close(); /*Close connection to Postgresql database*/ bool query(string STMT); /*Execute SQL statement STMT and create result set, returns true on success */ bool exec(string STMT); /*Same as "query()"*/ bool ping(); /*Check if connection active, reconnect if required, returns true on success */ array colnames(); /*Returns array of column names in result set*/ uint colnum(); /*Number of columns in result set*/ uint colcount(); /*Same as "colnum()"*/ array rowfetch(); /*Return a single row from result, as JavaScript array of strings; null returned if no row is available */ array fetchrow(); /*Same as "rowfetch()"*/ array array rowsallfetch(); /*Return all rows from result as JavaScript two- dimensional array of strings */ array array fetchallrows(); /*Same as "rowsallfetch()"*/ uint lastoid(); /*Returns object id created by database last insert operation*/ uint insertid(); /*Same as "lastoid()"*/ uint affectedrows(); /*Number of rows affected by INSERT, DELETE, UPDATE etc. operations */ string error(); /*PostgreSQL db error string*/ string escapestring(string DATA); /*Escape string*/ void freeresult(); /*Results are free'd automatically; if required freeresult() can be used */ }; //Example: /* After PostgreSQL server is started, create user "luka" and database "testdb", from command line: % /usr/local/pgsql/bin/createuser -P -e -d luka % /usr/local/pgsql/bin/createdb testdb */ //example Server-Side JavaScript Web script //BEGIN CODE--> //create Postgresql object var Pgdb = new Postgresql(); print(""); print("

PostgreSQL database


"); //Connect to PostgreSQL server if ( Pgdb.connect("dbname=testdb user=luka password=lukaspswrd567")==true ) { print("

Ok, connected to PostgreSQL server

"); //SQL statement var sSqlstmt = "CREATE TABLE ttesttbl( " +" rowid integer PRIMARY KEY, " +" smpl2 varchar(255), " +" smpl3 varchar(255) " +" ); "; //execute SQL statement if ( Pgdb.exec(sSqlstmt)==true ) { print("

Ok, created table

"); } else { print("

Error exec

"); print("

[",Pgdb.error(),"]

"); } //insert values to database //Pgdb.exec("INSERT INTO ttesttbl ... "); //Pgdb.exec("INSERT INTO ttesttbl ... "); //etc etc.. //execute SQL statement if ( Pgdb.query("SELECT rowid,smpl2,smpl3 FROM ttesttbl")==true ) { while ( (onerow=Pgdb.fetchrow())!=null ) { //123 -- xyz -- abc
print(onerow[0], " -- ", onerow[1], " -- ", onerow[2], ""); } } else { print("

Error query

"); print("

[",Pgdb.error(),"]

"); } Pgdb.close(); } else { print("

Error connect

"); print("

[",Pgdb.error(),"]

"); } print(""); // <--END CODE -------------------------------------------------------------------------------- SQLITE CLASS -------------------------------------------------------------------------------- GromJS "Sqlite" class provides JavaScript API for manipulating Sqlite3 database. //constructor var databaseobj = new Sqlite(string DBPATH); var databaseobj = new Sqlite("/path/to/mydatabase.db"); //class prototype: class Sqlite { //methods bool open(); /*Open database, returns true on success.*/ bool close(); /*Close database.*/ bool exec(string STATEMENT); /*Execute a result-less SQL statement; returns true on success.*/ bool query(string SQLQUERY); /*Execute SQL query SQLQUERY and create result set; returns true on success */ string colname(uint INDX); /*For column at INDX return column name used in CREATE table statement */ array colnames(); /*Array of column names in result set*/ string coltype(uint INDX); /*For column at INDX return column data type used in CREATE statement ie. INTEGER, CHAR, FLOAT */ uint colcount(); /*Number of columns in result set*/ uint colnum(); /*Same as "colcount()"*/ uint rowcount(); /*Number of rows in result set*/ bool rowhas(); /*Returns true if there is row under cursor available*/ array rowfetch(); /*From result set get single row, returned as JavaScript array of strings; null returned if no row available */ array fetchrow(); /*Same as "rowfetch()"*/ array array rowsallfetch(); /*From result set get all rows, returned as JavaScript two-dimensional array of strings */ array array fetchallrows(); /*Same as "rowsallfetch()"*/ uint rowlastinsertid(); /*Returns id created by database last insert operation*/ uint lastinsertrowid(); /*Alias for rowlastinsertid*/ bool rewind(); /*Move to first row of result set*/ string error(); /*Returns Sqlite3 error string*/ void freeresult(); /*Results are free'd automatically; if required freeresult() can be used */ }; //Example: //BEGIN SCRIPT--> //demonstrate using Sqlite3 database and JavaScript interface print(""); var dbfilepath = "mydatabase.db"; var Sqdb = new Sqlite(dbfilepath); print("Opening database.
"); if ( Sqdb.open()==true ) { print("Executing CREATE and INSERT statement.
"); //statement var ssqlstmt = "" +"CREATE TABLE ttesttable (i INTEGER PRIMARY KEY, cname CHAR(255), cweight INTEGER); " +"INSERT INTO ttesttable (cname,cweight) VALUES ('firstuser',95); " +"INSERT INTO ttesttable (cname,cweight) VALUES ('anotheruser',263); " ; //if statements executed ok... if ( Sqdb.exec(ssqlstmt)==true ) { print("Using SELECT query to fetch inserted values.
"); //query if ( Sqdb.query("SELECT * FROM ttesttable")==true ) { //printing selected values in tabular form ie. //colname (TYPE) colname (TYPE) colname (TYPE) //-------------------------------------------------- //value value value //value value value //etc etc... print("Printing selected values in tabular form.

"); print(""); //print header row with column names and types print(""); for ( var ccol=0; ccol!=Sqdb.colcount(); ccol++ ) { print(""); } print(""); //print rows var nrows = 0; var onerow; while ( (onerow=Sqdb.rowfetch())!=null ) { print(""); for ( var indx in onerow ) { print(""); } print(""); nrows++; } print("
"); print(Sqdb.colname(ccol)); print(" ("); print(Sqdb.coltype(ccol)); print(")
"); print(onerow[indx]); print("
"); print("
"); print("number of rows in select statement [",nrows,"]
"); } } //error else { //ie. table already exist etc print("Error in exec, error [" ,Sqdb.error(), "]
"); } print("Closing database.
"); Sqdb.close(); print("Database closed.
"); } //error else { //ie. invalid path, no permission etc print("Error opening database, error [" ,Sqdb.error(), "]
"); } print("Deleting database file.
"); //delete database file if ( Server.unlink(dbfilepath)==true ) { print("Database file deleted.
"); } else { //ie. invalid path, no permission etc print("Error deleting file ",dbfilepath,", system errno [" ,Server.errno(), "]
"); } print(""); //<--END SCRIPT -------------------------------------------------------------------------------- PIPE CLASS -------------------------------------------------------------------------------- GromJS built-in "Pipe" class provides interface for using inter-process communication through Unix pipe, a new process is launched from specified path and bidirectional pipe is opened for reading/writing to new process. //constructor var pipeobj = new Pipe(string PROGPATH [,string ARG1 [,string ARG2 ...]]); var pipeobj = new Pipe("/path/to/executable"); //path to executable var pipeobj = new Pipe("/path/to/executable","arg0","arg1","arg2"); //executable with command line arguments //class prototype: class Pipe { //methods bool open(); /*Open bidirectional pipe, returns true if succedded*/ uint close([uint WHICHEND]); /*Close pipe; if argument is supplied, it's either 0=read end close, or 1=write end close; with no argument, closes any open (both) end(s) and returns status 0 for success; status nonzero indicates error or process unclean exit */ string read([uint LEN]); /*Read from pipe; with argument read LEN bytes from pipe and return as string; Returns empty string on reading EOF, null on error. With no argument, read all from pipe in single action and return as string; returns null on error. */ int write(string ARG0 [, string ARG1 , ...]); /*Write to pipe; returns no of bytes written, -1 on error*/ }; //Example: //BEGIN SCRIPT--> //sending email using Pipe class and sendmail: print(""); var pipeobj = new Pipe("/usr/sbin/sendmail","otheruser@domain.com"); //set errno 0 Server.errno(0); if ( pipeobj.open()==true ) { var smsg = "" +"From: myusernam@domain.com\n" +"To: otheruser@domain.com\n" +"Subject: Webscript test email\n" +"\n" +"Text text text\n" +"more text some more text etc.\n" +"\n" ; //writing ok if ( pipeobj.write(smsg)!=(-1) ) { pipeobj.close(1); //close write end print("
");
		print(pipeobj.read()); //read and print output, if any
		print("
"); } //error else { print("Failed writing to pipe [errno " , Server.errno() ,"]"); } //close() with no arg performs final close (closes any open end) and returns program exit status var xstatus = pipeobj.close(); //final close //if non-zero there was an error or process unclean exit if ( xstatus!=0 ) { print("Closing pipe indicate failure [exit status " , xstatus ,"]"); print("System status: " , Server.errnstr() ,""); } } else { print("Opening pipe failed, system status: " , Server.errnstr() ,""); } print(""); //<--END SCRIPT -------------------------------------------------------------------------------- DICTIONARY CLASS -------------------------------------------------------------------------------- GromJS built-in "Dictionary" class is a hash array of unlimited length. Values are objects of any type and in Dictionary are stored by reference, not copy. Optional argument SPEEDLEVEL (0-20) is used to increase the speed of array read/write by setting the size of Dictionary's hash table. //constructor var dictobj = new Dictionary([uint SPEEDLEVEL]); //optional argument SPEEDLEVEL 0-20 is used to increase the //size of hash table //class prototype: class Dictionary { //methods uint set(string NAME, object VALUE); /*Set the value in dictionary; setting new value over-writes previously set value; if VALUE is null effectively deletes previously set value from dictionary; returns number of entries in dictionary */ object get(string NAME [, object DEFAULT]); /*Get value from dictionary; null returned if value not in dictionary; optional second arg DEFAULT can be supplied to be returned if NAME not found in dictionary */ array varnames(); /*Returns unsorted JS Array of strings containing list of all names in dictionary */ uint length(); /*Number of entries in dictionary*/ uint len(); /*Same as "length()"*/ }; //Example: //BEGIN SCRIPT--> var dictobj = new Dictionary(5); //create new dictionary var exmplobj = new Object(); //create new object to store in dictionary dictobj.set("name123",exmplobj); //write/set value in dictionary //now read/get value from dictionary var rdobj = dictobj.get("name123"); if ( rdobj!=null ) { //item found.. } //storing null deletes value from dictionary dictobj.set("name123",null); //delete value from dictionary //set multiple values dictobj.set("name1","val"); //set value dictobj.set("name2","val"); //set value dictobj.set("name3","val"); //set value dictobj.set("name4","val"); //set value //print all names in dictionary, ie.: //[name1, name4, name3, name2] print("[", dictobj.varnames().join(", "), "]"); //<--END SCRIPT [end of readme] -------------------------------------------------------------------------------- --