this returns the http request

Whenever you need to access all variables of a page from within a local or imported user defined function, you need to pass the this http request as parameter to your function.

If you call this parameter for example "request" in your function, you will be able to access the value of the request variables such as request.localVarName or request.url['varName']; or request.post['htmlFormCpnName']; or request.session['varName']; or request.header['ip'];

Note that global variables are accessed directly from everywhere including from within functions, without having to invoke the request.

client side (file instance) >


// Import of a server side user defined method in a server side file
<IMPORT@SERVER NAME="myLib" PATH="/folderFromRoot/subFolder/file.lib"/>

<FUNCTION@SERVER myFunction(request)
{
	c = request.cookie.keys();
	p = request.post.keys();
	u = request.url.keys();
	h = request.header.keys();
	if(request.session != null)
		s = request.session.keys();
	else
	{
		request.setSession(36000,1);
		request.session['login'] = 0;
	}
	global['allUsersLoggedIn'] = 0;
	request.redirect('login.jset');
}>

// Declare a local variable:
<. name = 'Chris';>

// Output a local variable: 
<: name;>

// Declare & ouptut a local variable: 
<: name = 'Chris';>

// Declare 2 local variables: 
<. name = 'Chris'; birthDate=1969;>

// Invoke server side local user defined function
<. myFunction(this);>
// if the function returns something
<. r = myFunction(this);>
// if the function output something
<: myFunction(this);>

// Invoke server side imported user defined function
<. myLib.myFunction(this);>
// if the function returns something
<. r = myLib.myFunction(this);>
// if the function output something
<: myLib.myFunction(this);>


abort aborts processing

<. abort;>
Remember to close your queries before aborting, as if you close (<. myQuery.close();>) them after aborting this code will not be processed and they will remain unclosed.

methods & client side code >



eval(param) allows to evaluate expressions

methods & client side code >



for(i=0; i < 100; i++;) {...;} loop with for, use break & continue

<. 
	for(i = 0; i < 100; i++;) 
	{
		if (x==1) continue;
		else if (x==90) break;
		z = 3;
	}
>

methods & client side code >



getNumber(string) returns a number out of a number having a string format

<. nbr = getNumber(string);>

methods & client side code >



getType(object) returns object type

<. type = getType(param);>

methods & client side code >



if / else if and else conditions

Jset provides an easy way to code if instructions, just as it also proposes loop for server side coding with output within the instructions.
This way, you are not forced to cut strings but instead can englobe your HTML / XML or other block of output within the instructions, as follows:

<if(x > 100);>
	<table>
		<. y=0;><. z=1;>
		<tr>
			<td></td>
			<if x < 10>
				<td bgcolor="#ffff00"> </td>
			<else>
				<td bgcolor="#ff00ff"> </td>			
			</if>
		</tr>
	</table>
<else>
	<. y=1; z=2;>
</if>
or standard server side Jset syntax (no output within instruction):
// standard syntax <. if(...
<. if(x < 2) y=0; else {y=1; z=2;}>

client side if / else expressions >



param.length() returns strings and arrays length.

// use .length() (Jset syntax), not .length (javascript syntax)
<. len1 = arr.length();>
<. len2 = str.length();>
<. len3 = qry.length();>

methods & client side code >



<loop(i < 100);>.... usefull to contruct code output within the loop

Should you need to loop easily and produce server side code output, use the loop instruction instead of for.

<. i=0;>
<table>
<loop (i < 100);>
	<tr>
		<td>My html content</td>
	</tr>
	<if x==1;><. continue;></if>
	<if x==90;><. break;></if>
	<. i++>
</loop>
</table>
The loop instruction is provided as a facility to build server side coding output, including the possibility to easily use if /else statements within the loop, or other loop statements.



redirect(url) operates a server side redirection

// redirect to a full url
<. redirect('http://www.yahoo.com');>

// redirect to root
<. redirect('/');>

// redirect to a web page (path from root)
<. redirect('/folder/subFolder/page.htm');>

Attention, redirects does not process the code that follows, just like <. abort;>
So in this case too make sure you are closing your queries before operating a server side redirection.

To operate a client side redirection, use the html meta refresh:
// refresh the page every 5 seconds
<meta http-equiv="refresh" content="5">

// redirect to another page after 5 seconds
<meta http-equiv="refresh" content="5; url=http://example.com/">

// redirect to another page immediately
<meta http-equiv="refresh" content="0; url=http://example.com/">


setNoCache() is used to instruct the browser not to cache the file

<. setNoCache();>

When you use this instruction, a cached page accessed with the use of the browser back button should be resubmitted to the server, instead of diplaying a cached page. This is usefull for expample if you have logged out a user and he tries to see the previous page with the back button.



setSession(seconds, cookie) is used to start a user session

<. setSession(3600,1);>
First param is and int representing the session timeout in seconds.

Second param is a boolean (1/0, or true/false).Its defautl is 1, so the default session type is a ram cookie session. When this param is set to 0 or false, the session is maintained by a random virtual directory name. In this case, make sure your links are relative in order to maintain the session automatically.

If a session already exists for a user, the setSession() instruction will be ignored, so there is no need to test if the session exists before you create it.

To end a session, just set the seesion object to null: <. session = null;>

To set a variable value depending on the existence of a session, you could write: <. if(session != null) s=1; else s=0;>

See also session[] variables.


trace(param) is used to output the value of a variable, object, or expression in the Windows command prompt

If you have requested a Jset server license (start Jset/server/Jset.exe then jset /g), the Jset server will automatically output error messages in the command prompt console.

methods & client side code >



getString(param) converts an object representing a string into a real string

// getString() converts an object type to string
<. str = getString(File.load(path));>
<. cki = getString(cookie['name']);>
<. prm = getString(url['name']);>
<. nbr = getString(123);>

methods & client side code >



fullString.index(stringToFind) returns -1 if not found or first position of stringToFind in fullString

// use index() (Jset syntax), not indexOf() (javascript syntax)
<. fullString = 'This is the full string in which we search';>
<. pos = fullString.index('which');>

methods & client side code >



string.lower() converts a string into a lower case string

// at the end, str will be = to 'chris'
<. str = 'Chris';>
<. str = str.lower();>
<. trace(str);>

methods & client side code >



fullString.replace(stringToFind, stringToUse) replaces all occurrences of a stringToFind by stringToUse

// example
<. fullString.replace('find this string','replace by this string');>

methods & client side code >



string.split(sep) converts an separated string (param is delimeter) into an array.

// set a string with items separator (,)
<. str = 'Chris,Pierre';>

// this str length will be equal to 12
<. strLen = str.length();>

// convert the string into an array with split()
<. arr = str.split(',');>

// the array length will be equal to 2
<. arrLen = arr.length();>

// each array position represents an array item
<. item_1 = arr[0];>
<. item_2 = arr[1];>

You can now loop the array with for() or loop.

methods & client side code >



fullString.subString(startInt, endInt) returns the subString of the fullString

methods & client side code >



getService(dbClientName) returns a database object on which you can apply SQL statements

Use the database client (dynamic/static) name defined in your host configuration file a getService() parameter. <. db = getService('client_name');> You can now apply other database instructions on the db object, such as runQuery() and runUpdate().


db.getTables() returns the database table names

<. tables = getService(dbClientName).getTables();> returns a new Array() of database table names.
In this example, if db represents the getService: <. tables = db.getTables();> will return return the same.

methods & client side code >



getDescription(db, tableName) to retrieve a table fields

// example
<. fields = getDescription(db,table_name);>
<. len = fields.length(); f=0;>
<loop f < len>
	<. field=fields[f];>
	// create a bag of field informations for each field
	<. fieldInfos=new Bag();>
	// bag variable names
	<. fieldInfos['name']=field.getName();>
	<. fieldInfos['pos'] = field.getPos();>
	<. fieldInfos['readOnly'] = field.isReadOnly();>
	<. fieldInfos['auto'] = field.isAuto();>
	<. fieldInfos['text'] = field.isText();>
	<. fieldInfos['double'] = field.isDouble();>
	<. fieldInfos['precision'] = field.getPrecision();>
	<. fieldInfos['sqlType'] = field.getSQLType();>
	<. fieldInfos.primary=field.isPrimary();>
	// isPrimary() only returns XML declared keys.
	<. f++;>
</loop>



db.runQuery(sql) to perform SQL SELECT operations

Execute SELECT SQL statements on your database.
When used on a dynamic client, the SQL SELECT statement has to be very basic, but supports WHERE and ORDER BY clauses.
In this case, result sets with their updates are automatically updated in the server ram.

// set the database service object
<. db = getService('Jset');>
// create your SQL statement
<. sql = 'SELECT * FROM CTR WHERE eu = 1 ORDER BY ctrEN;';>
// execute the query under a local variable name called query
<. query = db.runQuery(sql);>

// you can do the same in one line of code like this:
<. query = getService('Jset').runQuery('SELECT * FROM CTR WHERE eu = 1 ORDER BY ctrEN;');>

methods & client side code >



db.runQuery(sql) HTML demo looping an HTML result set

// loop the query result set in an html table
<. r=0;>
<table>
<tr>
	<td>uid</td>
	<td>Country name</td>
</tr>
<loop r < query.length();>
	<. record = query[r];>
	<tr>
		<td><: record['uid'];></td>
		<td><: record['ctrEN'];></td>
	</tr>
	<. r++;>
</loop>
</table>

// loop the query result set in an html combo
<. r=0;>
<select name="ctr">
	<loop r < global['COUNTRIES'].length();>
		<. record = global['COUNTRIES'][r];>
		<option value="<: record['uid'];>"><: record['ctrEN'];></option>
		<. r++;>
	</loop>
</select>

// close the query
<. query.close();>

/*
You must be sure the query exists before you close it.
If the query is within an <if>...</if>, you must test if it does exists before you try to close it:
*/
<. if(query != null) query.close();>
// or
<if query != null><. query.close();></if>


db.runQuery(sql) XML demo looping an XML result set

// loop the query result set in XML format, to populate a client side component data (but no real-time/true push in this case).
<. r=0;>
<loop r < query.length();>
	<. record = query[r];>
	<RECORD UID="<: record['uid'];>" NAME="<: record['ctrEN'];>"/>
	<. r++;>
</loop>

// close the query
<. query.close();>

/*
You must be sure the query exists before you close it.
If the query is within an <if>...</if>, you must test if it does exists before you try to close it:
*/
<. if(query != null) query.close();>
// or
<if query != null><. query.close();></if>


db.runQuery(sql) as a global object result set accessible by all users on all host pages

// test if the global variable holding the result set array already exists
<if global['COUNTRIES'] == null;> 
	<. db = getService('Jset');>
	<. sql = 'SELECT * FROM CTR WHERE eu = 1 ORDER BY ctrEN;';>
	<. global['COUNTRIES'] = db.runQuery(sql);>
</if>

// loop the query result set in an html table
<. r=0;>
<table>
<tr>
	<td>uid</td>
	<td>Country name</td>
</tr>
<loop r < global['COUNTRIES'].length();>
	<. record = global['COUNTRIES'][r];>
	<tr>
		<td><: record['uid'];></td>
		<td><: record['ctrEN'];></td>
	</tr>
	<. r++;>
</loop>
</table>

// loop the query result set in an html combo
<. r=0;>
<select name="ctr">
	<loop r < global['COUNTRIES'].length();>
		<. record = global['COUNTRIES'][r];>
		<option value="<: record['uid'];>"><: record['ctrEN'];></option>
		<. r++;>
	</loop>
</select>


db.runQuery(sql) as a session object result set accessible by a specific user on all host pages

// start a one hour session timeout
<. startSession(3600,1);>

// test if the session variable holding the result set array already exists
<if session['COUNTRIES'] == null;> 
	<. db = getService('Jset');>
	<. sql = 'SELECT * FROM CTR WHERE eu = 1 ORDER BY ctrEN;';>
	<. session['COUNTRIES'] = db.runQuery(sql);>
</if>

// loop the query result set in an html table
<. r=0;>
<table>
<tr>
	<td>uid</td>
	<td>Country name</td>
</tr>
<loop r < session['COUNTRIES'].length();>
	<. record = global['COUNTRIES'][r];>
	<tr>
		<td><: record['uid'];></td>
		<td><: record['ctrEN'];></td>
	</tr>
	<. r++;>
</loop>
</table>

// loop the query result set in an html combo
<. r=0;>
<select name="ctr">
	<loop r < session['COUNTRIES'].length();>
		<. record = session['COUNTRIES'][r];>
		<option value="<: record['uid'];>"><: record['ctrEN'];></option>
		<. r++;>
	</loop>
</select>


db.runQuery(sql) at host startup easy way to execute queries at host startup

Should you need to reuse the same result set many times on different pages, the easiest way is to create the global query in the host config file in the INIT code, just like this:

<INIT>
	"
	global['db'] = getService('Jset');
	sql = 'SELECT * FROM CTR WHERE eu = 1 ORDER BY ctrEN;'
	global['COUNTRIES'] = global['db'].runQuery(sql);
	"
</INIT>

This INIT code is processed at host startup, in fact on the first time a host page is called.

If you need to reuse a database result set in different pages on your host (website), you can save the result set into a global variable, and loop the query result set array wherever you need to output it, without having to requery everytime.

If the Jset client declared in the host config file is dynamic, looping your result set will show updates and newly inserted values everytime you loop the query.



db.runUpdate(sql) to perform SQL INSERT, UPDATE, & DELETE operations

The runUpdate() instruction can only be used with a database configured as a dynamic client in the host configuration file.

Use getService() get the database object, before you apply an SQL instruction to it.

// use runUpdate() only on a dynamic Jset client, and only with INSERT, UPDATE, OR DELETE
<. result = getService('dbClientName').runUpdate('INSERT ...;');>
// or
<. db = getService('dbClientName');>
<. sql = 'INSERT INTO...;';>
<. uid = db.runUpdate(sql);>
// uid will be the newly created record value (value of auto number field).

methods & client side code >



setContentType(mimeType) is used to set the content type of a returned file

The mime types are defined in your server or host config file.
When you need to set the mime type of a file dynamically, you can use this setContentType() to do it.
If the file extention associated with the mime type you need is defined in the server or host config file, you can use the File.getMimeType() as a parameter to return the mime type of a file extention, just like this: <. setContentType(File.getMimeType('xls'));>



setDownload(fileName) is used to set the file name of a downloaded file

This instruction will instruct the browser that the file should be dowbloaded, and sets its download name.



stream(physicalPath[, process, process remote header]) is used to stream a file

// stream takes a full physical path as parameter
// process (true/false) to process the file or not (default is true);
// process remote header (true/false) to process the header ot the streamed file (default is false)

<: stream('C:/.../file.ext');>

// use File.getMapping() to return the file full physical path
<: stream(File.getMapping('/http_path_from_root/folder/file.ext');>

// stream a UTF8 encoded file content
<: stream(Format.fromUTF8(File.getMapping('/http_path_from_root/folder/file.ext')));>
global, session, and url variables can be accessed from and set into streamed files, as long as the streamed file is processed.

Unlike File.load(), you must not append url variables to the path, as streamed file will access all url variables of the request page (the page doing the stream()).

If you need to change or add an url variable before you stream, you can do it in code just as if it was another variable type:
<. url['firstName']='Chris'; url['lastName']=null;>

Unlike the File.load(), stream() output cannot be saved as a variable, so instruct it like this:
<: stream();> and not like this <. stream();>

See also, File.getMapping() to return a physical path out of a web path.


// @SERVER in order not to return function source code on client side

<FUNCTION@SERVER myFunction(request)
{
	// get a the web page prm variable value
	prm = request.prm;
	// resolve the param type
	type=getString(getType(prm)).lower();
	// trace the type in the MS Windows command prompt.
	trace(type);
	// trace more info in the MS Windows command prompt.	
	if(param.index('array') != -1) trace('prm is an array of '+prm.length()+' positions.');
	else if(prm.index('bag') != -1) trace('prm is an array of '+prm.length()+' positions.');
	else if(prm.index('int') != -1) trace('prm is a int and equals to '+prm+'.');
	else if(prm.index('string') != -1) trace('prm is a string ('+prm+') of '+prm.length()+' characters.');
	trace('----------------');
	// optionally return a result.
	return type;
}>

// output the result
<: myFunction(this);>

// save the result into a variable
<.  type = myFunction(this);>

// output & save the result into a variable
<:  type = myFunction(this);>

client side libraries >


client side libraries imports >

Some libraries must be imported at the top of a file to have the possibility to use them from within the file, and some others are implicitely imported for you so that you can use them without having to declare them.

Note that you can import them in a header file to have them accessible from all files in that folder, and in files in sub-folders as well, as long as your sub-folders do not have their own headers without the import.

Import Jset native & external APIs libraries with NAME / CLASS
<IMPORT@SERVER NAME="Exports" CLASS="jset.util.lib.Exports"/>
<IMPORT@SERVER NAME="FTP" CLASS="jset.server.http.lib.FtpLibrary"/>
<IMPORT@SERVER NAME="Mail" CLASS="jset.server.mail.client.MailLibrary"/>
<IMPORT@SERVER NAME="SrvJoin" CLASS="jset.server.http.data.sql.SQLJoinLibrary">

<IMPORT@SERVER NAME="Fedex" CLASS="jset.server.lib.fedex.FedexWebService"/>
<IMPORT@SERVER NAME="SocGen" CLASS="jset.server.lib.sips.Sips"/>

Import your own (user defined) libraries with NAME / PATH
<IMPORT NAME="pth" PATH="/addOn/file/lib/pth.lib"/>
// IMPORT will import a library on both client & server sides

<IMPORT@SERVER NAME="cpn" PATH="/addOn/cpn/lib/cpn.lib"/>
<IMPORT@SERVER NAME="html" PATH="/addOn/html/lib/html.lib"/>
<IMPORT@SERVER NAME="lib" PATH="/addOn/lib/lib.lib"/>
// IMPORT@SERVER or IMPORT@SRV will import a library server side only


To use for a method, it must either be imported or defined at the top of the page calling it.

Jset methods can be imported to your projects When using a method You can import existing and your own libraries into your projects.



Importing your own methods instead of pl When located in the imported library file, this method must be called like this:
returnedValue = libName.functionName([param1,param2,...]);

if not returning any value:
libName.functionName([param1,param2,...]);


Functions return only one value.

If you need to return more than one value, return a new Array(size) or a new Bag().

If you wish to update variables/objects located in the file instance calling the method without having to return them, simply pass theit names as parameters preceeded by the & character. This way, when you update them in the method, they are automatically updated in the file instance as well.

Also, functions do not necessarily need parameters.

If you do not wish to return the method code on the client side, you can import it like this: You can also use @SRV instead of @SERVER.

Server side methods have access to global variables without having to pass any parameter.

dteTme = new Date(); Creates a date object with the now value.
dateObject = Date.parse(dateString,format); Creates a date object out of a string, format is the date format of the string.
dateObject = Date.format(dateObject, format); Formats a date object, format is the format you wish to use.
moveBy(param, int) dateObject.moveBy(param, int);
Moves dateObject to another date, param must be one of the following:
Date.DAY_IN_MONTH or 0x0020000
Date.DAY_IN_WEEK or 0x0040000
Date.DAY_IN_YEAR or 0x0010000
Date.HALF or 0x0000100
Date.HOURS or 0x2000000
Date.MINUTES or 0x4000000
Date.MONTH or 0x0000400
Date.QUARTER or 0x0000200
Date.SECONDS or 0x8000000
Date.WEEK or 0x0001000
Date.WORK_DAY or 0x0080000
Date.YEAR or 0x0000010
Date formats:

yy -> Year, 2 digits
yyyy-> Year, 4 digits
M -> Month (1-2 digits)
MM -> Month(2 digits)
MMM -> Month, short text
MMMM-> Month, text
d -> day of month (1-2 digits)
dd -> day of month (2 digits)
ddd -> day of week, short text
dddd-> day of week, text
h -> AMPM hour (1-2 digits)
hh -> AMPM hour (2 digits)
H -> 24 hour (1-2 digits)
HH -> 24 hour (2 digits)
m -> minutes (1-2 digits)
mm -> minutes (2 digits)
s -> seconds (1-2 digits)
ss -> seconds (2 digits)
Q -> Quarter (1 digit)
S -> Half/Semester (1 digit)
w -> week of year (1-2 digits)
ww -> Week of year (2 digits)
t -> AMPM, short text
tt -> AMPM, long text
D -> Day of week (1 digit)
DD -> Day of year (1-3 digits)
DDD -> Day of year (3 digits)
Formats in bold are the recommended formats to use.

If you are going to save dates/times in a database text field, it is advised to use this format :

Date only > yyyy/MM/dd
Time only > HH:mm
Date & time > yyyy/MM/dd HH:mm

Using the reverse recommended format will allow you to perform SQL ORDER BY clause and preserve date time consitency, as in this case alphanumeric sort will perform a logical date/time sort.

methods & client side code >


<IMPORT@SERVER NAME="Exports" CLASS="jset.util.lib.Exports"/>

client side exports >


Export to HTML and save file on server:

<IMPORT@SERVER NAME="Exports" CLASS="jset.util.lib.Exports"/>
// Export of Jset Editor (XML file) document to HTML
<. content = Format.fromUTF8(File.load('C:/.../JsetEditorXmlFile.jsd'));>
<. export = new Exports.Html(content,'http://www.domain.com/',1);>
<. code = export.getOutput();> 
<. File.save('C:/.../JsetEditorHtmlFile.htm',Format.toUTF8(code));>


Export to PDF and download file in browser:

Make sure you have declared the second processor (named txt here) in your host config file.

<PROCESSOR NAME="txt" CLASS="jset.server.http.report.text.JsTextReportEngine"/>


Define a mime type extention that will be processed by this second processor (in the Jset/server/config.xml file or in your host config file if mime tyes have been redefined for the host).
<TYPE EXT="exp" NAME="text/html" PROCESSOR_NAME="txt"/>

Code your PDF template and save this code in a file having the extention that depends on the second processor (here fileName.exp):
<doc page="A4L">
<body>
Hello my dear
How are you ?
<: Format.fromUTF8('You can have accents here since Format.fromUTF8 will preserve them...');>
<. db = getService('/Jset');>
<. query = db.runQuery('select * from cpn;'); i=0;>
<table>
<col size=30/>
<col size=300/>
<tr>
	<td bg_color="0xC0C0C0">uid</td>
	<td bg_color="0xC0C0C0">cpn name</td>
</tr>
<loop (i < query.length())>
	<tr>
		<td><: query[i]['uid'];></td>
		<td><: query[i]['cpn'];></td>
	</tr>
	<. i = i+1;>
</loop>
</table>
boum boum boum....
<font size=14/>
Bombo 14....
<font/>
Brutal 14....
</body>
</doc>

Ceate a file with an extention processed by the default processor.
Set the instructions and the path to the dynamic PDF template and set the download intruction:
<IMPORT@SERVER name="Exports" class="jset.util.lib.Exports"/>
<. 
	setDownload('myFileName.pdf');
	content = File.load(File.getMapping('/code/lib/Exports/pdfCode.exp'));
	export = new Exports.Pdf(content,null);
>
<: export.getOutput();>


Jset/server/config.xml must include the Fedex jars in the CLASS_PATH to be able to use the Fedex API
<JAVA 
	START_MEMORY="512" 
	LICENSE="..." 
	ACTIVATION_KEY="..." 
	CLASS_PATH=".;
		fedex/axis.jar;fedex/axis-ant.jar;
		fedex/commons-discovery-0.2.jar;
		fedex/commons-logging-1.0.4.jar;
		fedex/jaxrpc.jar;fedex/log4j-1.2.8.jar;
		fedex/saaj.jar;fedex/wsdl4j-1.5.1.jar;
		fedex/fedex.jar" 
/>


Fedex library import add this import on top of your server page

<IMPORT@SERVER NAME="Fedex" CLASS="jset.server.lib.fedex.FedexWebService"/>


new Fedex.Request() to instantiate a new fedex shipment

new Fedex.Request(
	String key, 
	String password, 
	String account, 
	String meter, 
	True/false true = international priority and false = next day, default is true
)

<. shipment = new Fedex.Request(
	'MkuUEGYC3Uqb85i9', 
	'q2gmVnZetW9TCnwSvz2sz2Yyb',
	'510087488','100099874', 
	'https://wsbeta.fedex.com:443/web-services/ship',
	false
);>


shipment.setShipper() to set shipper location

setShipper(
	String countryCode, 
	String postalCode, 
	String stateOrProvinceCode, 
	String city, 
	String streetLine1
)

More street lines can be added: ..., streetLine1, streetLine2, streetLine3)

<. shipment.setShipper('FR','75007','PA','Paris','200 boulevard Saint Germain');>


shipment.setRecipient() to set recipient location

setRecipient(
	String countryCode, 
	String postalCode, 
	String stateOrProvinceCode, 
	String city, 
	String streetLine1
) 

More street lines can be added: ..., streetLine1, streetLine2, streetLine3)

<. shipment.setRecipient('FR','75016','PA','Paris','57 avenue Paul Doumer');>


shipment.addPackage() to add a package to the shipment

addPackage(
	double weightInKgs, 
	double insuredValue, 
	String insuredValueCurrencyCode, 
	int lengthInCms, 
	int widthInCms, 
	int heightInCms
)

You can add more addPackage() instructions.

<. shipment.addPackage(1,0,'',60,46,8);>


shipment.getQuote() to get a quote from Fedex

// RATED is the sender, PAYOR is the final client

<. if (shipment.getQuote()) res = shipment.getAmount('RATED'); else res = shipment.getError();>

// same with currency output
<. if (shipment.getQuote()) 
	res = shipment.getAmount('RATED')+' '+shipment.getCurrency('RATED'); 
else 
	res = shipment.getError();
>

// following example adds 5% to fedex cost
<. if (shipment.getQuote()) 
{
	cost = shipment.getAmount('RATED');
	cost=Math.round(cost*1.05,100);
	res = cost+' '+shipment.getCurrency('RATED');
} 
else res = shipment.getError();
>

File.createFolder(full physical path) Creates a new folder on the server. Path is a string representing the full physical folder path/name to be created.
Use File.save() to create a new file on the server.
File.delete(full physical path) Deletes a folder on the server. Path is a string representing the full physical file path/name of file or folder to be deleted. When deleting a folder, you must first delete its sub folders and files before.
File.dir(full physical path[,mode][,filter]) Retrieve server directories and files. Path is the full physical folder path.

Mode values can be -1 (default) to list folders and files 1 to list folders only 2 to list files only

Filter allows you to specify which folder/files should be returned, the others will be skipped (ex: '*.htm,*.srv,*.clt').

The File.dir will return an array, so it is possible to use the sort like this sort(File.dir(C:/Jset/));>.
File.exists(full physical path) Path is a string representing the full physical server file path to look for.
The path can be a directory or file path.
It will return true (or 1) if the file exists.
You cannot test if a file or folder exists if its parent folder does not exist.
Test if the parent folder exists instead, before eventually testing if your file or folder exists.
File.getMapping(http path from root) This method is very usefull and used by almost all other File methods.
It takes a relative path and will return a full physical path.
It also works with virtual directories.
So whenever you need to specify a relative path to a methid requiring a full physical server path, you can use it to resolve your path.
File.getMimeType(extention) Param is the file extention (without the dot).
Returns the mime type associated with the file extention param, as defined in the server/config.xml file (default mime types for all hosts), or in the host configuration file.
For use only within the setContentType(), as in following ex :
<. setContentType(File.getMimeType('pdf'));>
File.load(full physical path[, bol][, bol]) First param is the full physical server file path to load.
Second param is 1/0 to process loaded file or not (default = 1).
Third param is 1/0 to process loaded file header (in case file it is located in another folder, default = 0).

See also, stream()
File.move(full physical path, new path) Moves a folder or a file.
File.save(full physical path, content) Param is the full physical file path to create or update on the server.
Allows you to create or update a file on the server. Use File.createFolder() to create a new folder on the server.

How to save a posted file:
// form.jset: HTML file input to submit
<form action="formAction.jset" method="post">
	<input name="myFile" type="file">
</form>

// formAction.jset: submitted file
<. name = post['myFile'].value;>
<. content = post['myFile'].content;>
<. File.save('C:/folder/'+name,content);>


<IMPORT@SERVER NAME="FTP" CLASS="jset.server.http.lib.FtpLibrary"/>
// Sample code to get csv delimited file data from an FTP server

<. now = Date.format(new Date(),'d/MM/yyyy H:mm.ss');>
<. ftpCon = new FTP.FtpConnection(1);>
<. ftpCon.connect(host name OR ip);>
<. ftpCon.login(login,password);>
<. ftpCon.changeDirectory('/folder');>
<. myFile = ftpCon.download('SG_stock.csv');>
<. records = getString(myFile).split('\n');>
<. rows = records.length()-2; r=0;>
<loop r < rows;>
	<. row = records[r].split(';')>
	...
	<. r++;>
</loop>
<. ftpCon.delete('/SG_stock.csv');>
<. ftpCon.logout();>
<. ftpCon.disconnect();>

<. abort>
ftpCon.changeDirectory(new directory) returns true if ok
ftpCon.download(filename) returns an array that contains the file to download.
ftpCon.delete(filename) returns true if ok

Format.decode(string) Returns a decoded string out of an URL encoded string.
Format.encode(string) Returns an URL encoded string out of string.
Format.fromUTF8(string) Use with load, not stream.
Returns a string out of an UTF8 string.
Format.sqlString(string) Appends a single quote at the beginning and end of a string, and preserves single quotes in the string.
Used to construct sql statements.
Format.toCString(string) Use with File.load(), not stream.
Returns the formatted representation of the string.
' will be \'
carriage return will be \r\n
tab will be \t
Format.toHtmlString(string) Returns the string in html encoded format.
Usefull for accents and other weird characters.
Format.toUTF8(string) Use with load, not stream.
Returns the UTF8 representation of the parameter.


new Mail.reader() to read mails

Initates a connection to an IMAP mail server.


new Mail.sender(smtpAuth, smtpHostPort, secured, smtpLogin, smtpPassword) to send mails

// Import the Mail library, attachment is a bytes array param
<IMPORT@SERVER NAME="Mail" CLASS="jset.server.mail.client.MailLibrary"/>

<. smtpSession = new Mail.sender(
	Str smtpHost, 
	Int smtpHostPort, 
	True/false secured
	[, Str smtpLogin, Str smtpPassword]
);>

<. from = new Mail.address('SenderFirstName SenderLastName <SenderEmail>');>
<. message = new Mail.message(from, 'This is the mail subject');>

<. message.setText('This is the mail body');>
<. message.setHtml('<html>This is the HTML body</html>');>

<. attachment = Format.toUTF8('<html>...</html>');>
<. message.addFile(attachment,File.getMimeType('htm'), 'myHTMLfileName.htm');>

<. attachment = File.load('C:/JsetProject/Jset.com/web/pdf/test.pdf');>
<. message.addFile(attachment,File.getMimeType('pdf'), 'myPDFfileName.pdf');>

<. message.addRecipient('email@domain.com');>
<. message.addRecipient('email2@domain.com');>
<. message.addCC('email3@domain.com');>
<. message.addCC('email4@domain.com');>
<. message.addBCC('email4@domain.com');>
<. message.addBCC('email5@domain.com');>

<. smtpSession.send(message);>
<. smtpSession.close();>


Math.abs(number) Returns positive value.
So even if your number is negative, you will get a positive value.
Math.fromBase(number, base) Returns an integer out of a number in the specified base.
Math.int(number) Returns an integer (no decimals) out of a number.
Note that this does not round the number, so 1.9 will return 1.
Math.log(number) Returns natural logarithm value of number.
Math.random() Returns a random number between 0 and 1.
Math.round(number, precision) Returns a rounded number.
Use 10 to round to 1 digit after the comma (0.1) to take into consideration the 2rd number after the comma.
Use 100 to round to 2 digits after the comma (0.01) by taking into consideration the 3rd number after the comma...
Use 20 to round to closest 0.05...
Math.toBase(int, base) Returns a string in this base.
Used to get representation of a number in another base.
Math.toHex(int) Treats the number like a not signed number.
Usefull to get hex color codes (Jset XML colors (0x......) and html color codes).
Returns an hex string.


Math operators reference

&& Logical AND operator, you can also type "AND".
|| Logical OR operator, you can also type "OR"
== Checks if two items are equal.
!= Checks it two items are unequal (equivalent to NOT (A = B), but faster).
< Checks if A is less than B (2 < 3 is true, 3 < 3 is false).
<= Checks if A is less than or equal to B (2 < 3 is true, 3 < 3 is true).
> Checks if A is greater than B (2 > 3 is false, 3 > 2 is true).
>= Checks if A is greater than or equal to B (2 >= 2 is true, 3 > 2 is true).
+ Adds two items, meaning is following:
If A or B is an array, the result is an array containing all items of A and all items of B.
Or, if A or B is a string, the result is a string containting the concatenation of A and B.
Or if A and B are integers, the result is an integer.
Or if A and B are numbers, the result is a number.
Or if A or B is a number, the result is a number.
- Substracts two numbers, the result is an integer if both items are integers, a number otherwise.
* Multiplies two numbers, the result is an integer if both items are integers, a number otherwise.
% Remainder of the division of two integers, always an integer value.
^ Mathematical power (a^b).

Jset/server/config.xml must include the SocGen jar to be able to use the SocGen API
<JAVA 
	START_MEMORY="512" 
	LICENSE="..." 
	ACTIVATION_KEY="..." 
	CLASS_PATH=".;socgen/apipayment.jar" 
/>
Create a folder in a safe path (in this example C:/JsetProject/myProject/socgen) that cannot be accessed from the internet, and place the files provided by SocGen in here (certif.fr.xxx, parmcom.xxx, parmcom.sogenactif, and pathfile.


Société Générale parmcom.xxx file to set URLs of your called pages

###############################################################################
#
#	Fichier des parametres du commercant
#
#	Remarque :	Ce fichier param?e est sous la responsabilit?u
#				commercant
#
###############################################################################

# Logo du commercant (il apparait en haut a gauche des pages de paiement)

LOGO!merchant.gif!

# URL de retour automatique de la reponse du paiement

AUTO_RESPONSE_URL!http://www.domain.com/socgen/auto.jset!

# URL de retour suite a paiement refuse

CANCEL_URL!http://www.domain.com/socgen/socgen/cancel.jset!

# URL de retour suite a paiement accepte

RETURN_URL!http://www.domain.com/socgen/return.jset!


# END OF FILE


Société Générale pathfile file sets the safe folder files location

#########################################################################
#
#	Pathfile 
#
#	Liste fichiers parametres utilises par le module de paiement
#
#########################################################################
#
#
#-------------------------------------------------------------------------
# Activation (YES) / Dsactivation (NO) du mode DEBUG
#-------------------------------------------------------------------------
#
DEBUG!NO!
#
# ------------------------------------------------------------------------
# Chemin vers le rpertoire des logos depuis le web alias  
# Exemple pour le rpertoire www.merchant.com/sogenactif/payment/logo/
# indiquer:
# ------------------------------------------------------------------------
#
D_LOGO!/socgen/logo/!
#
# --------------------------------------------------------------------------
#  Fichiers paramtres lis a l'api sogenactif paiement	
# --------------------------------------------------------------------------
#
# certificat du commercant
#
F_CERTIFICATE!C:/JsetProject/myProject/socgen/certif!
#
# type du certificat
#
F_CTYPE!!
#
# fichier paramtre commercant
#
F_PARAM!C:/JsetProject/myProject/socgen/parmcom!
#
# fichier des paramtres sogenactif
#
F_DEFAULT!C:/JsetProject/myProject/socgen/parmcom.sogenactif!
#
#########################################################################
# End of file
#########################################################################



SocGen Request see also SocGen documentation

// Import the library
<IMPORT@SERVER NAME="SocGen" class="jset.server.lib.sips.Sips"/>

// Instantiate the payment
<. payment = new SocGen.Request('C:/JsetProject/myProject/socgen/pathfile');>

// add the payment parameters
<. payment.setValue('merchant_id','your_merchant_id_here');>
<. payment.setValue('merchant_country','fr');>
<. payment.setValue('currency_code','978');>
<. payment.setValue('language','en');>
<. payment.setValue('header_flag','yes');>
<. payment.setValue('cancel_return_url','http://www.domain.com/page.jset');>
<. payment.setValue('transaction_id',1234);>
<. payment.setValue('logo_id','logo.jpg');>
<. payment.setValue('cancel_return_logo','logo.jpg');>
<. payment.setValue('amount',10000));>
<: payment.call();>


SocGen Response see also SocGen documentation

// Sample code for the AUTO_RESPONSE_URL page

<if post['DATA'] != null>
	<. response = new SocGen.Response('C:/JsetProject/myProject/socgen/pathfile', post['DATA']);>
	<. params='
		amount,
		transaction_id,
		transmission_date,
		payment_means,
		payment_time,
		payment_date,
		response_code,
		payment_certificate,
		authorisation_id,
		currency_code,
		card_number,
		cvv_flag,
		cvv_response_code,
		bank_response_code,
		complementary_code,
		complementary_info,
		return_context,
		caddie,
		receipt_complement,
		merchant_language,
		language,
		customer_id,
		order_id,
		customer_email,
		customer_ip_address,
		capture_day,
		capture_mode,
		data,
		order_validity,
		transaction_condition,
		statement_reference,
		card_validity,
		score_color,
		score_info,
		score_value,
		score_threshold
	';>
	<. params = params.split(','); p=0;>
	<. htmlStr = ''>
	<loop p < params.length();>
		<. param = params[p];>
		<. value = response.getValue(param);>
		<. htmlStr = htmlStr + param + '=' + value + '<br>';>
		<. p++;>
	</loop>
	<. orderUid = getNumber(response.getValue('transaction_id'));>
	<. paymentAmt = getNumber(response.getValue('amount'))/100.0;>
	<. status = response.getValue('response_code');>

	<. dte = response.getValue('payment_date');>
	<. time = response.getValue('payment_time');>
	<. paymentDte = 
		dte.subString(0,4)+'/'+dte.subString(4,6)+'/'+dte.subString(6,8)+' '+
		time.subString(0,2)+':'+time.subString(2,4)+'.'+time.subString(4,6)
	;>
</if>

Use it with database clients declared as dynamic in the host configuration file.
This way, if you store your query as a global or session variable, looping this result set will reflect the database changes automatically. Also, this will allow you to perform database joins on databases located in different database engines.

<IMPORT@SERVER NAME="SrvJoin" CLASS="jset.server.http.data.sql.SQLJoinLibrary">
Example:
<FUNCTION@SERVER getMailAccounts()
{
	jd = new SrvJoin.joinDefinition('USRMAILACC','usrUid='+session['usrUid'],'USRMAILACC.ord');
	j =jd.addJoin('USRMAILACC.mailAccUid','MAILACC.uid', null, 'SELECT * FROM MAILACC');
	j2= j.addJoin('MAILACC.mailProviderUid','MAILPROVIDER.uid', null, 'SELECT * FROM MAILPROVIDER');
	session['USRMAILACC'] = jd.getDataSet(getService(DynamicClientName));
}>


new SrvJoin.joinDefinition(table, clause, sortOrder)

The table param is the main table from which the lookups will start.
The clause param allows you to filter the main table result set.
The sortOrder param allows you to sort the main table reuslt set.

Note that we are not sepcifying the database service here, as it will use the one specified in the getDataSet().


new Array(size) variables list, accessed by position

Array objects are used to save a list of variables. Each variable within the array does not have an name but is accessed by its position.
// Server side array syntax
<. a = new Array(2);>
<. a[0] = 'Chris';>
<. a[1] = 1969;>
My array length is equal to <: len = a.length();>
<. a[2] = 'Third array item';>
<. a[3] = 'Fourth array item';>

methods & client side code >



new Bag() variables list, accessed by name

Bag objects are used to save a list of variables. Each variable within the bag has a name.
// Server side bag syntax
<. b['name'] = 'Chris';>
<. b['birthDate'] = 1969;>
My bag length is equal to <: len = b.length();>
<. b['friend'] = 'Pierre';>
<. b['friendBirthDate'] = 1973;>

methods & client side code >



new XmlParser().doParse(data) retrieves XML attributes names and values out of an XML string

node = new XmlParser().doParse(data to parse);

/*
Returns a node.
On the node, you do a [ ] to get attributes. Otherwise, 
*/

getName();
getValue();
getAttributes();
getNode();
getNodes();

// getAttributes(); returns attributes list

For getNode() and getNodes(), you can either use 1 or 3 params.
One param: node name.
Three params: node name, attribute name, attribute value.

Jset XML parser to get MNC (SMS payment gateway) response

<if (post.length() > 0)>
	<. xml=Format.decode(post); node= new XmlParser().doParse(xml);>
	<if xml.index('<Notification>') != -1;>
		<. notification = node.getNode('Notification');>
		<. text = notification.getNode('parameters').getNode('text').getValue().trim().lower();>
		<if text == 'adi ad';>
			<. sender = Format.sqlString(notification.getNode('sender').getValue().trim());>
			<. startDate = Format.sqlString(notification.getNode('receptionDate').getValue().trim().subString(0,10));>
			<. startDateObj = Date.parse(startDate,'yyyy-MM-dd');>
			<. password = getString(Math.random());>
			<. passwordStr = password.subString(password.length()-6,password.length());>
			<. password = Format.sqlString(passwordStr);>
			<. sql = 'INSERT INTO SUB (mob,startDate,password) VALUES ('+sender+','+startDate+','+password+');';>
			<. global['dyn'].runUpdate(sql);>
			<: Format.toUTF8(
				'<?xml version="1.0" encoding="UTF-8" ?><NotificationReply><message><text>Votre mot de passe sur le site www.adimante.ch est '+passwordStr+'</text><cost>1500</cost></message></NotificationReply>');><else><: Format.toUTF8('<?xml version="1.0" encoding="UTF-8" ?><NotificationReply><message><text>Votre message SMS ne contient pas le bon code.</text><cost>20</cost></message></NotificationReply>'
			);>
		</if>
	</if>
</if>

The production mode version of this file in has the spaces and carriage returns located outside server tags removed (deleted).


VARIABLES server side variables types

For each of these variable types, you can use the keys() method to return an array of all variable names of this type
<. c = cookie.keys(); g = global.keys(); h = header.keys(); p = post.keys(); s = session.keys(); u = url.keys();>

client side variables >



name local variables, these variables are only accessible from within the pages in which tey have been set.

Use local variables to set a variable you do not need in other web pages.

Any query (runQuery()) for which you do not need to need to preload the result set nor need to loop the result set in another page of your host sould be executed as a local or session variable.

client side local variables >



cookie[name] ram and regular cookies, with expiration period.

// Cookie variables can only represent string values
<. cookie['name'] = 'Chris';>

// You can set the expiration of a cookie like this (value in seconds)
<. cookie['name'].expires = 360000;>');>

// To delete a cookie, use -1
<. cookie['name'].expires = -1;>



global[name] global variables, these variables are accessible on all pages of a host.

Use global variables to set a variable value for all users on all pages of a host (website).

It is a good idea to set these variables in the host config file.
This way, they will be set just before the first http request will be sent to any of the host pages (host startup).

<INIT>
	"
	global['name'] = 'Chris';
	global['nbr'] = 123;
	global['db'] = getService('Jset');
	sql = 'SELECT * FROM CTR WHERE eu = 1 ORDER BY ctrEN;'
	global['COUNTRIES'] = global['db'].runQuery(sql);
	"
</INIT>
They are often used to define host variables default values in the host configuration file, in order to be able to update them in one place for all users accessing the same host.

Code in the INIT host config file uses the same syntax than methods & client side coding.
The server side coding syntax is:
<. global['name'] = 'Chris';>
<. global['nbr'] = 123;>
<. global['db'] = getService('Jset');>
<. sql = 'SELECT * FROM CTR WHERE eu = 1 ORDER BY ctrEN;'>
<. global['COUNTRIES'] = global['db'].runQuery(sql);>
The following piece of code will output all global variables names and values:
<. list=global.keys(); i=0;>
<table>
<tr>
	<td>Name</td>
	<td>Value</td>
</tr>
<loop i < list.length();>
	<tr>
		<td><: list[i];></td>
		<td><: global[list[i]];></td>
	</tr>
	<. i++;>
</loop>
</table>

client side application variables >



header[name] you can only read header variables, and cannot set variables of this type

<. list = header.keys(); i=0;>
<div class="table-responsive">
	<table class="table">
	<loop i < list.length();>
		<tr>
			<td><: list[i];></td>
			<td><: header[list[i]];></td>
		</tr>
		<. i++;>
	</loop>
	</table>
</div>
header variables output:
User-Agent
Accept
Accept-Encoding
Host
Accept-Language
Connection


post[name] param must be and html posted component name

When you post an HTML form using the POST method (GET method will send url parameters), you get the values of the form components using the post['htmlComponentName'] variable type.

remember to add the the ENYTYPE if you will post a file in the form:
<html><head><title>My form</title></head><body>

<form action="file.ext" method="post" ENCTYPE="multipart/form-data">
	<input name="myFile" type="file">
	<input type="submit" value="submit">
</form>

</body></html>
posted files have additionnal attributes:
// use the value and content attributes
<. fileName = post['myFile'].value;>
<. fileContent = post['myFile'].content;>

See also File.save() to learn how to save an HTML form posted file.


session[name] use session variables after you have started a session for a user.

Some session variables are available after you start a session:
session['id']
session['expired']
session['createStamp']
session['accessStamp']
session['ttl']

See also setSession()


url[name] param must be and url param name, or an html component name submitted ith the GET method.

When you post an HTML form using the GET method, you get the values of the form components using the url['htmlComponentName'] variable type.

You also set / change the value of an url['name'] variable in code: <: url['name'] = 'Chris'>
This can be usefull before you stream() a file (streamed file has access to url and session variables).
In case of File.load(), you will need to append the url params to the path of the loaded file.
Sample code:
<. list = url.keys(); i=0;>
<div class="table-responsive">
	<table class="table">
	<if (url.length() > 0);>
		<loop i < list.length();>
			<tr>
				<td><: list[i];></td>
				<td><: url[list[i]];></td>
			</tr>
			<. i++;>
		</loop>
	</if>
	</table>
</div>

url variables output:
side srv