CommuniGate Pro
Version 6.3
 

CommuniGate Programming Language (CG/PL)

The CommuniGate Programming Language (CG/PL) is a powerful, yet simple procedural language. It can be used with various components of the CommuniGate Pro Server software, including:

The language structure and the language features are the same for all applications, but different applications use different sets of built-in functions and procedures.

The following is a simple CG/PL program (using the "basic" and "alternative" syntax):

//	
// A simple CG/PL application
//
entry Main is
  myName = "Jim" + " " + "Smith";
  if length(myName) > 10 then
    myName = Substring(myName,0,8) + "..";
  end if;
end;
 
/*
 * A simple CG/PL application
 */
entry Main {
  myName = "Jim" + " " + "Smith";
  if(myName.length() > 10) {
    myName = myName.substring(0,8) + "..";
  }
}

Data Model

Information is presented as objects. An object can be a string, a number, a datablock, a timestamp, an ip-address, an array, a dictionary, or an XML object. See the Data section for more details.

An object can also be a Mailbox handle, a Task handle, or any other special object defined within a particular environment.

A special type of object is the null-value (null value or "no object" value).

When processing logical (boolean) values, the null-value is used as a false-value, and a string "YES" is used as a true-value.


Lexemes

The program source code is a plain text encoded using the UTF-8 character set.

The language lexemes are:
  • keywords - and, by, elif, else, entry, exitif, external, false, for, forward, function, if, is, not, loop, null, or, procedure, return, spawn, stop, then, true, var, xor, while.
    All keywords are case-insensitive.
  • names - sequences starting with alpha-symbols and optionally followed by alpha-symbols, digits, and/or underscore symbols.
    All names are case-insensitive.
    The keywords cannot be used as names.
  • signs - +, -, *, //, /, %, +=, -=, *=, /=, %=, =, ==, !=, <, <=, >, >=, !, &, &&, &=, |, ||, |=, ?, ;, ,, :, (, ), [, ], {, }
  • numbers - sequences of digits.
  • strings - quoted strings as specified in the Data section.

A comment is a double-slash (//) symbol and all following symbols up to and including the next EOL (end-of-line) symbol.

A comment is a pair of the slash and star (/*) symbols and all following symbols up to and including the first pair of the star and slash (*/) symbols.

white-space is a sequence of 1 or more space symbols, tabulation symbols, EOL symbols, and/or comments. At least one white space is required between a name and a keyword, other lexemes can be separated with zero or more white spaces.


Literals

Literals are constant values representing themselves. A literal is one of the following:
  • a number lexem
  • a string lexem
  • the null keyword (the null-value)
  • the false keyword (the false-value, same as the null-value)
  • the true keyword (the true-value)

Code Sections

A program code is a set of code sections:
  • Entries are code sections executed when the program is activated.
  • Procedures and functions are code sections that can be used in (called from) entry code sections, and other procedures and/or functions.

The procedures and functions can be called recursively: a procedure or a function can call itself - directly or via calling some other procedures or functions.

All code sections are reenterable: the same code section can be used by several program activations or Tasks at the same time.

Code sections must be declared before they can be used. Declarations include forward-declarations, external-declarations, and definitions.

A program code may contain not more than one forward-declaration of a code section, specified before its definition.
Forward-definitions are used in programs containing two or more code sections calling each other, so it is not possible to define each section before it is used in the other code section.

Modules

External-declarations allow code sections to call code sections defined in separate program code modules.
External-declarations are allowed only in the environments that support them, such as the Real-Time Application and Web Applications environments. See the environment description for more details.
If the external-declaration specifies the code section name as a regular name, when this code section is used, the module with the same name as the code section name is loaded: if the external declaration is
function myName(param) external;
and the myName function is called, then the separate program code module "myName" is loaded, and its code section "myName" is called.
The external-declaration may contain a qualified name, explicitly specifying the module name: if the external declaration is
function myModule::myName(param) external;
and the myModule::myName function is called, then the separate program code module "myModule" is loaded, and its code section "myName" is called.
The code section name and its parameter names specified in an external-declaration must match the code section name and its parameter names specified in the code section definition given in an external program code module.
The code section definition can specify more parameters than an external-declaration. The missing parameters are assigned null-values when such an external-declaration is used.

A program code should contain exactly one external-declaration or exactly one definition (but not both) of each code section used.

Entries

An entry declaration consists of the entry keyword, the entry name, followed by one of the following:
for a forward-declaration:
the forward keyword followed by the semicolon (;) symbol
for an entry definition:
the is keyword followed by an operator sequence, followed by the end keyword (optionally followed by the entry keyword), and followed by the semicolon (;) symbol
for an alternative entry definition:
the left brace ({) symbol followed by an operator sequence, followed by the right brace (}) symbol

If a running program reaches the end of an entry section operator sequence, an implicit stop operator is executed.

The following example shows an entry for a Real-Time Application. It tries to accept an incoming call, and if succeeds, it plays a sound. The entry code ends, quitting the program and thus finishing the call:
entry main is
  if acceptCall() == null then
    playFile("greeting.wav");
  end if;
end entry;

Or, in the alternative form, and using the alternative form of the conditional operator:

entry main {
  if (acceptCall() == null) {
    playFile("greeting.wav");
  }
}

Procedures

A procedure declaration consists of the procedure keyword, the procedure name, the left parenthesis, an optional list of parameter names, the right parenthesis, followed by one of the following:
for a forward-declaration:
the forward keyword followed by the semicolon (;) symbol
for a procedure definition:
the is keyword followed by an operator sequence, followed by the end keyword (optionally followed by the procedure keyword), and followed by the semicolon (;) symbol
for an alternative procedure definition:
the left brace ({) symbol followed by an operator sequence, followed by the right brace (}) symbol
for an external-declaration:
the external keyword followed by the semicolon (;) symbol

If a running program reaches the end of a procedure operator sequence, an implicit return operator is executed.

The following example shows a Real-Time Application procedure that speaks the specified number:
procedure sayNumber(x) is
  x = x % 100;
  if x >= 10 then
    PlayFile(String(x/10*10)+".wav");
  end if;
  if x != 0 then
    PlayFile(String(x%10)+".wav");
  end if;
end procedure;

If a forward-declaration is used, the procedure definition must have exactly the same parameters as its forward-declaration.

Example:
procedure sayMoney(x,units) forward;
procedure sayNumber(x) forward;
procedure sayMoney(x,units) is
  sayNumber(x);
  PlayFile(units+".wav");
end procedure;

Functions

A function declaration is the same as a procedure declaration, but the function keyword is used instead of the procedure keyword.

All program control paths in a function code section must end with a return or a stop operator.

The following example defines a function calculating the factorial of its argument:
function Factorial(x) is
  if x <= 1 then return 1; end if;
  return Factorial(x-1)*x;
end function;

Below is the same function definition in the alternative form, using the ternary operator:

function Factorial(x) {
  return x <= 1 ? 1 : Factorial(x-1)*x;
}

All code section (entry, procedure, and function) names used within the same program code must be unique.


Variables

Variables are containers. Any object (including a null-value) can be assigned to a variable, and that object becomes the variable value. Initially, the variable value is a null-value.

Local variables are local to the code section (function/procedure/entry) instance (invocation) where they were created. All their values are destroyed when the code section exits (returns).

To declare variables, use the var keyword and the list of variable names:

var var1,var2,var3;

It is possible to declare a local variable and immediately assign it some value, using an initial value expression:

var var1=expr1,var2,var3=expr3;

Each code section can contain several var declarations. Variables should be used after they are declared (later in the code section code).

var myCount;           // the myCount variable is created
myCount = 3;           // the numeric value 3 is assigned to it
myCount = myCount + 2; // myCount variable value changed to 5
myCount = "Service";   // myCount variable value changed to a string

Alternatively, if the code section contains no explicit var declaration, any name used in any code section operator which is not declared as a procedure or function name, and which is not matching a built-in procedure or function name declares a variable with this name.

myCount = 3;           // the myCount variable is created and
                       // the numeric value 3 is assigned to it
myCount = myCount + 2; // myCount variable value changed to 5
myCount = "Service";   // myCount variable value changed to a string

Note: declaring a variable inside some "block operator" (such as the if or loop operator) declares this variable only inside this "block operator".

"Task variables" are stored in a dictionary unique for each Task ("invocation") created, and they can be used in all code sections, after being declared as Task variables. The Task variables dictionary is destroyed when the Task completes.

The Task variables are declared using the same var keyword and the variable name list, but these declarations should be placed outside any code section, and they should not contain any initial value expressions.

The alternative way to use the "task variables" is to access the Task variable dictionary directly, using the Vars() built-in function.


Constants

Constants are names associated with literal values.

To declare constants, use the const keyword and the list of constant names and their values:

const c1=1234,c2="test",cFlag=true;

When the constant name is used, the value associated with it is substituted.


Expressions

The language implements unary operations. Unary operations are specified as

operation operand

The following unary operations are supported:

-
unary minus. If the operand value is a number, operation value is the number with the opposite sign, otherwise the operation value is the number 0.
The following expressions have the value of -5:
-5
-(3+2)
+
unary plus. If the operand value is a number, operation value is that number, otherwise the operation value is the number 0.
The following expressions have the value of 5:
+5
+(10/2)
not
Negation. If the operand value is a null-value, the operation value is a true-value, otherwise the operation value is a null-value.
The ! symbol can be used instead of the not keyword.
The following expressions have the value of "YES":
not null
!(2 == 3)

The unary operations have a higher priority than binary and ternary operations.

The following expression has the value of -1, not -3:
-2 + 1

The language implements binary operations. Binary operations are specified as

left-operand operation right-operand
Unless explicitly specified otherwise, both operands are computed first (in a non-specified order), and the operation is applied to the operand values.

The following binary operations are supported, listed in the descending priority order:

*, /, %
These arithmetic operations can be applied to numeric operand values only.
If one of the operands is not a Number, or if the right operand of the / or % operations is number 0, the operation value is a null-value.
The following expressions have the value of 10:
5 * 2
-20 / -2
30 % 20
+, -
These arithmetic operations can be applied to numeric operand values.
The + operation can be applied to a pair of string operand values, producing a string value with their catenation.
The + operation can be applied to a pair of datablock operand values, producing a datablock value with their catenation.
The + operation can be applied to a datablock and a string value operands, producing a datablock copy with the string bytes added to the datablock end.
The + operation can be applied to a datablock and a numeric value operands, where the numeric value should be in the 0..255 range, producing a datablock copy with an additional byte (containing the numeric operand value) added to the datablock end.
The + operation can be applied to a timestamp and a numeric value operands, producing a timestamp value that is the numeric value seconds later than the timestamp operand value.
The - operation can be applied to a left operand with a timestamp value and a right operand with a numeric value, producing a timestamp value that is the numeric value seconds earlier than the timestamp operand value.
The - operation can be applied to a pair or operands with timestamp values, producing a numeric value - the number of seconds between the left and the right operand values.
In other cases the operation value is a null-value.
The following expressions have the value of 5:
3 + 2
-2 - -7
The following expression has the value of "John Doe":
"Joh" + "n Doe"
<, <=, ==, !=, >=, >
These comparison operations can be applied to a pair of numeric operands, to produce a true-value when the arithmetic comparison condition is met.
These comparison operations can be applied to a pair of timestamp operands, to produce a true-value when the arithmetic comparison condition is met.
These comparison operations can be applied to a pair of string operands, to produce a true-value when the arithmetic comparison condition is met. Strings are interpreted as sequences of UTF-8 encoded 16-bit Unicode symbols, compared symbol by symbol.
These comparison operations can be applied to a pair of datablock operands, to produce a true-value when the arithmetic comparison condition is met. Datablocks are interpreted as sequences on bytes (with values in the 0..255 range), compared byte by byte.
The ==, != comparison operations can also be applied to any pair of objects, checking if they are "equal":
  • A null-value is equal to and only to a null-value.
  • Numbers are equal if their numeric values are equal.
  • Strings are equal if they have the same length and have the same symbol in each string position.
  • Datablocks are equal if they have the same length and have the same data byte in each datablock position.
  • Arrays are equal if they have the same number of elements and elements in each position are equal.
  • Dictionaries are equal if they have the same number of key-value pairs, the key strings are equal, and the values for each key are equal in both dictionaries.
  • For all other object types any object is equal to itself only (no two different objects are considered equal).

In other cases the comparison operation value is a null-value.
The following expressions have the value of "YES":
1+2 == 3
2+2 != 3
2+2 >= 3
"Joe" == "Joe"
null == (2 == 3)
and, or, xor, and then, or else
these logical operations compare their operands with null-values.
The and operation value is a true-value if both operand values are not null-values, and a null-value otherwise.
The & symbol can be used instead of the and keyword.
The or operation value is a true-value if at least of the operand values is not a null-value, and a null-value otherwise.
The | symbol can be used instead of the or keyword.
The xor operation value is a null-value if none or both operand values are null-values. Otherwise, the operation value is the operand value that is not a null-value.
The ^ symbol can be used instead of the xor keyword.
The and then operation computes the left operand value first. If that value is a null-value, the right operand is not computed, and the operation value is a null-value. Otherwise the right operand is computed and its value becomes the operation value.
The && symbols can be used instead of the and then keywords.
The or else operation computes the left operand value first. If that value is not a null-value, the right operand is not computed, and the left operand value becomes the operation value. Otherwise the right operand is computed and its value becomes the operation value.
The || symbols can be used instead of the or else keywords.
The following expressions have the value of "YES":
1+2 == 3 & 2+2 == 4
2+2 == 3 or else 7-5 == 2
false ^ true

The binary operations of the same priority group left-to-right: X op Y op Z is the same as ( X op Y ) op Z

The binary operations have a higher priority than the ternary operations.

The language implements one ternary operation:
cond ? expr1 : expr2
  • the cond operand is computed.
  • If the computed value is not a null-value, the expr1 operand is computed and its value becomes the operation value.
  • Otherwise the expr2 operand is computed and its value becomes the operation value.
The following expressions have the value of "Good":
3 == 3 ? "Good" : "Bad"
null ? 77777 : "Good"

The ternary operation groups right-to-left: A ? B : C ? D : E is the same as A ? B : (C ? D : E)

The language implements the indexing operation:

object[index]
where
the object expression should have an array, a dictionary value, a string value, or a datablock (otherwise the operation results in a program exception), and
the index expression should have a numeric value smaller than the number of object elements, or the length of the object string or datablock.

If the object expression value is an array, the operation references the array element number index (the first element has the number 0).
Retrieving an element that does not exist results in a null-value.
Assigning a new value to the first array element that does not exist adds the value to the array as a new element.
An attempt to assign a new value to any other non-existing array element results in a program exception.
If SquareArray value is (1,4,9,16,25), the following expression has the value of 9:
SquareArray[2]
while the following operator:
SquareArray[5] = "Blue";
changes the SquareArray value to (1,4,9,16,25,"Blue"),

If the object expression value is a dictionary, the operation references the dictionary key number index (the first key has the number 0).
Retrieving a key that does not exist results in a null-value.
An attempt to assign a new value to a referenced key results in a program exception.

If SquareDictionary value is {"one" = 1; "two" = "four"; "three"=9;}, the following expression has the value of "three":
SquareDictionary[2]

If the object expression value is a string, the operation returns a 1-byte string containing the string symbol number index (the first string symbol has the number 0).
Retrieving a symbol that does not exist results in a null-value.
An attempt to assign a new value to any string symbol results in a program exception.
If SquareString value is "grass", the following expression has the value of "r":
SquareString[1]

If the object expression value is a datablock, the operation returns a number representing the datablock byte number index (the first datablock byte has the number 0).
Datablock bytes have unsigned numeric values in the 0..255 range.
Retrieving a byte that does not exist results in a null-value.
An attempt to assign a new value to any datablock byte results in a program exception.

The language implements the key, or dictionary-element operation:

dictionary.keyName
where
the dictionary expression should have a dictionary value (otherwise the operation results in a program exception), and
the keyName is a name.

The operation references the dictionary element with the key keyName.
Retrieving an element for a key that does not exist results in a null-value.
Assigning a null-value to a key results in the key-value pair being removed from the dictionary.
Assigning a non-null-value to a key that does not exist results in a new key-value pair being added to the dictionary.
If SquareDictionary value is {"one" = 1; "two" = "four"; "three"=9;},
the following expression has the value of 9:
SquareDictionary.three

and the following expression has the value of null:
SquareDictionary.four
The language implements the computed key, or dictionary-element operation:
dictionary.(keyExpr)
where
the dictionary expression should have a dictionary value, and
the keyExpr expression should have a string value (otherwise the operation results in a program exception).

The operation references the dictionary element for the keyExpr key.
If SquareDictionary value is {"one" = 1; "two" = "four"; "three"=9;}, the following expression has the value of 9:
SquareDictionary.("th" + "ree")

The language implements function calls. A function call is specified as a name followed by parentheses optionally containing a list of expressions (parameter-expressions):

functionName()
functionName(arg1)
functionName(arg1,arg2,...)

The functionName should be a name of a built-in function or an already defined function.
Parameter expressions (if any) are computed, and the function code is executed using the parameter expression values.
A function result is an object, and the indexing and dictionary-element operations can be applied to a function result.

If MyFunction function has 2 parameters and its returned value is an array (1,"four",9), the following expression has the value of "four":

MyFunction(myData,"zzz")[1]

A function with one or more parameters can be called as a method:

arg1.functionName()
arg1.functionName(arg2)
arg1.functionName(arg2,arg3,...)

The MyFunction function call (see above) can be expressed as a method:

myData.MyFunction("zzz")[1]

Operators

An operator sequence contains zero or more operators, followed by the semicolon (';') symbol.

An empty operator performs no action:

;

A null operator consists of the keyword null. It performs no action:

null;

An assignment operator consists of a data container reference (a variable, an array element, or a dictionary element), the assignment operation, and an expression. The expression and the data container reference are computed (in an unspecified order), and the expression value is used to modify the data container.
The = operation assigns the expression value to the data container.

myVar = 123 + 111;
myVar = "string";
Other assignment operations consist of a binary operation symbol and the = symbol. They apply the corresponding binary operation to the current data container value and the expression value, and store the result in the data container.
myVar[123] += 123; myVar.message += ", program stopped";

If a data container reference is an array element, that element must exist or it must be the first non-existent array element, i.e. if an array has 3 elements, you can assign values to elements number 0,1,2, and 3. In the last case, a new element is added to the array.

If a data container reference is a dictionary element, assigning a null-value effectively removes the element from the dictionary.

A procedure call operator is specified in the same way as a function call expression. The name used should be a name of a built-in procedure or an already defined procedure.

If MyProc procedure has 2 parameters, the following operator is a correct procedure call:
MyProc(myData,"zzz");

For procedure with one or more parameters, a call operator can be specified as a method:

arg1.procedureName()
arg1.procedureName(arg2)
arg1.procedureName(arg2,arg3,...)
The MyProc call (see above) can be specified as a method:
myData.MyProc("zzz");

A stop operator terminates the Task execution. It consists of the stop keyword:

stop;

A return operator finishes function or procedure execution.
A return operator within a function consists of the return keyword and an expression. This expression is computed and its value becomes the value of the function call.

return 12*year+month;

A return operator within a procedure consists of the return keyword.
return;

A conditional operator consists of the if keyword followed by an expression (if-expression), the end keyword, an operator sequence (if-sequence), and the end keyword optionally followed by the if keyword.
The if-expression is computed, and if its value is not a null-value, the if-sequence is executed, and the conditional operation execution ends.

The following example increases the myCount variable value by 2 if its value is less than 10:
if myCount < 10 then
  myCount = myCount + 2;
end if;

A conditional operator can optionally contain one or more elif-portions after the if-sequence. Each elif-portion consists of the elif keyword, an expression (elif-expression), the then keyword, and an operator sequence (elif-sequence).
If the if-expression value is a null-value, the first elif-expression is computed, and if its value is not a null-value, its elif-sequence is executed and the conditional operation execution ends. If the elif-expression value is a null-value, the next elif-portion is processed.
In the following example the myCount variable value is checked. If the value is less than 10, the variable value is increased by 2. Otherwise (i.e. if the variable value is not less than 10), if the value is less than 20, it is decreased by 3:
if myCount < 10 then
  myCount = myCount + 2;
elif myCount < 20 then
  myCount = myCount - 3;
end if;

A conditional operator can optionally contain an else-portion. It is specified after the if-sequence and after all optional elif-portions. The else-portion consists of the else keyword and an operator sequence (else-sequence).
If the if-expression value is a null-value, and all optional elif-expression values are null-values, the else-sequence is executed and the conditional operator execution ends.
The following example increases the myCount variable value by 2 if the value is less than 10, it decreases the variable value by 3 if the value is not less than 10, but it is less than 20, and the variable value is multiplied by 4 in all other cases:
if myCount < 10 then
  myCount = myCount + 2;
elif myCount < 20 then
  myCount = myCount - 3;
else
  myCount = myCount * 4;
end if;

The loop operator consists of an optional preamble, the loop keyword, an operator sequence (initial sequence), and the end keyword optionally followed by the loop keyword.
Operators in the sequence are executed repeatedly.
A preamble for a while-loop is the while keyword and an expression (while-expression).
The while-expression is computed every time before the operator sequence is executed. If the while-expression result is a null-value, the loop operator ends.
A preamble for a for-loop is the for keyword optionally followed by an initializer operator, optionally followed by the while keyword and an expression (while-expression), optionally followed by the by keyword and an assignment operator (the iterator operator).
The initializer operator is either an assignment operator, or the var keyword followed by variable declarations. In the later case, these variables can be used only in the while-expression, iterator operator, and inside the loop operator sequence.
If the initializer operator is specified, it is executed once, when the loop operator starts.
If the while-expression is specified, it is computed every time before the loop operator sequence is executed. If the while-expression result is a null-value, the loop operator ends.
If the iterator operator is specified, it is executed every time after the loop operator sequence is executed.

The following example checks the myCount variable value and keeps increasing it by 2 while that value is less than 10:
while myCount < 10 loop
  myCount = myCount + 2;
end loop;

The following example calls the myProc procedure in an unconditional loop:

loop
  myProc(2,"test.wav");
end loop;

The following example calls the myProc procedure 3 times, with parameter values 5,7,9:

for i = 5 while i < 10 by i += 2 loop
  myProc(i);
end loop;

The loop operator can optionally contain one or more exitif-portions between the initial sequence and the end keyword. Each exitif-portion consists of the exitif keyword, followed by an expression (exitif-expression), the semicolon (';') symbol, and an operator sequence. After the initial sequence is executed, the first exitif-expression is computed. If its value is not null, the loop operator execution ends. Otherwise the exitif operator sequence is executed, and the next exitif expression is computed. After the last exitif operator sequence is executed, the loop operator execution repeats.

The following example appends the "aaa" string to the myWord variable, checks the variable lengths, and if the length is less than 20, appends the "bbb" string to the myWord variable, and repeats the process:
loop
  myWord += "aaa";
exitif length(myWord) >= 20;
  myWord += "bbb";
end loop;

Alternative Forms

Some operators in a sequence may be presented in an alternative form. Operators in an alternative form are not followed by the semicolon symbol.

The alternative form of a conditional operator consists of the if keyword followed by an expression (if-expression), and an operator sequence (if-sequence) enclosed in left ({) and right (}) brace symbols.
The alternative form of a conditional operator can optionally contain one or more elif-portions after the enclosed if-sequence. Each elif-portion consists of the elif keyword, an expression (elif-expression), and an operator sequence (elif-sequence), enclosed into braces.
The alternative form of a conditional operator can optionally contain an else-portion. It is specified after the enclosed if-sequence and after all optional elif-portions. The else-portion consists of the else keyword and an operator sequence (else-sequence) enclosed in braces.

The following example increases the myCount variable value by 2 if the value is less than 10, it decreases the variable value by 3 if the value is not less than 10, but it is less than 20, and the variable value is multiplied by 4 in all other cases:
if (myCount < 10) {
  myCount = myCount + 2;
} elif (myCount < 20) {
  myCount = myCount - 3;
} else {
  myCount = myCount * 4;
}
Note: it is not required to use parentheses to enclose if-expressions or elif-expressions.

The alternative form of a while-loop operator consists of the while keyword, an expression (while-expression), the left brace ('{') symbol, an operator sequence (initial sequence), zero or more exitif-portions and a right brace ('}') symbol.
The alternative form of a for-loop operator consists of the for keyword, the left parenthesis ('(') symbol, an optional initializer operator, the semicolon (';') symbol, an optional while-expression, the semicolon (';') symbol, an optional iterator operator, the right parenthesis (')') symbol, the left brace ('{') symbol, an operator sequence (initial sequence), zero or more exitif-portions and a right brace ('}') symbol.
Each optional exitif-portion consists of the exitif keyword, followed by an expression (exitif-expression), the semicolon (';') symbol, and an operator sequence.

The following example appends the "aaa" string to the myWord variable, checks the variable lengths, and if the length is less than 20, appends the "bbb" string to the myWord variable, and repeats the process:

while ( true ) {
  myWord = myWord + "aaa";
exitif (length(myWord) >= 20);
  myWord = myWord + "bbb";
}
Note: it is not required to use parentheses to enclose while-expressions or exitif-expressions.

The following example assigns the factorial of the variable X value to the myFactor variable.

myFactor = 1; for(i = 0; i <= X; i += 1) {
  myFactor *= i;
}


Built-in Procedures and Functions

The following procedures and functions are built into the language, and they are available to all applications. You should not use their names for user-defined procedures or functions.

Same(arg1,arg2)
This function returns a true-value if the values of arg1 and arg2 are the same object or if both values are null-values or both values are true-values. In other cases the function returns a null-value.
The value of Same("J" + "ack","Jack") is a null-value.
In the following example:
x = "my string";
y = "my string";
z = x;
test1 = Same(x,y);
test2 = Same(x,x);
test3 = Same(x,z);
the resulting value of test1 is a null-value, while the values of test2 and test3 are true-values.
Copy(arg)
If the arg value is a null-value, this function returns a null-value.
Otherwise, the function returns the copy of the arg value.
For complex objects (such as arrays, dictionaries, XML objects), this function copies all complex object elements, too.
Length(arg)
If arg is a string, this function returns the string size (in bytes);
If arg is a datablock, this function returns the datablock size (in bytes);
If arg is an array, this function returns the number of array elements;
If arg is a dictionary, this function returns the number of dictionary keys;
If arg is a Mailbox handle, this function returns the number of messages in the Mailbox;
In all other cases, this function returns the number 0.
Min(arg1,arg2)
If the arg1 value < the arg2 value, then the function returns the arg1 value, otherwise it returns the arg2 value.
See above for the < operation definition.
Max(arg1,arg2)
If the arg1 value > the arg2 value, then the function returns the arg1 value, otherwise it returns the arg2 value.
See above for the > operation definition.
Void(arg1)
This procedure does nothing, it just discards the arg1 value. Use this procedure when you need to call a function, but you do not want to use the function result.
ProcCall(name)
ProcCall(name,arg1)
ProcCall(name,arg1,arg2)
ProcCall(name,arg1,....)
This procedure has 1 or more parameters. The name value should be a string, it specifies a simple or a qualified external procedure name.
This external procedure is called, using the remaining parameters as its parameters.
There is no need to use external-declarations for procedures called this way.
ProcCall("myModule::myProc",123,"2222");
is the same as
procedure myModule::myProc(x,y) external;
myModule::myProc(123,"2222");
FuncCall(name)
FuncCall(name,arg1)
FuncCall(name,arg1,arg2)
FuncCall(name,arg1,....)
This function has 1 or more parameters. The name value should be a string, it specifies a simple or a qualified external function name.
This external function is called, using the remaining parameters as its parameters.
There is no need to use external-declarations for functions called this way.
x = FuncCall("myModule::myFunc",123,"2222");
is the same as
function myModule::myFunc(x,y) external;
x = myModule::myFunc(123,"2222");
objectClass(arg)
the function returns a string with the name of the class the arg value belongs to ("SharedString" for strings, "SharedNumber" for numbers, "SharedDate" for timestamps, "SharedData" for datablocks, etc.)

Strings

IsString(arg)
This function returns a true-value if the arg value is a string, otherwise the function returns a null-value.
String(arg)
If the arg value is a string, this function returns this string.
If the arg value is a number, this function returns a string with the decimal representation of that number.
If the arg value is a datablock, this function returns a string with the datablock content (interpreted as textual data).
If the arg value is a timestamp, this function returns a string with the system-standard timestamp text representation.
If the arg value is an ip-address, this function returns a string with the canonical representation of that network address.
If the arg value is an XML Object, this function returns the XML object text body ("text node").
If the arg value is a null-value, this function returns a null-value.
In all other cases, this function returns a string with a textual representation of the arg value.
Substring(str,from,len)
If the str value is a string, and the from value is a number, and the len value is a non-negative number, this function returns a string that is a substring of the str value, with the len length.
If from has a non-negative value, the substring starts at the from position (the first symbol of the string has the position 0).
If from is a negative value, then the substring ends at the -1-from position from the string end (to include the last str symbol(s), from should be -1).
If the from value (or -1-from value) is equal to or greater than the str value length, the result is an empty string.
If the from + len (or -1-from + len) value is greater than the str value length, the resulting string is shorter than len.
In all other cases this function returns a null-value.
Note: this function interprets a string as a sequence of bytes, and thus it can break non-ASCII symbols which are stored as a multi-byte sequence.
FindSubstring(str,substr)
FindSubstring(str,substr,offset)
The str and substr values should be strings, while the offset should be a number. The function checks if the substr value is a substring of the str value.
If the offset parameter is specified and its value is greater than zero, then the search ignores the first offset bytes of the str string value, and the position of the first found substring in the str value is returned.
If the offset parameter is specified and its value is less than zero, then the search ignores the last -1-offset bytes of the str string value, and the position of the last found substring in the str value is returned.
All positions start with 0.
If no substring is found, this function returns the number -1.
Example 1. The value of FindSubstring("forest","for") is 0.
Example 2. The value of FindSubstring("A forest","for") is 2.
Example 3. The value of FindSubstring("A forest for all","for",1) is 2.
Example 4. The value of FindSubstring("A forest for all","for",4) is 9.
Example 5. The value of FindSubstring("A forest for all","for",-3) is 9.
Example 6. The value of FindSubstring("A forest for all","for",-5) is 2.
Range(str,from,len)
This function works in the same way as the Substring function, but if the str value is a string, it is interpreted as a sequence of "glyphs" - single and multi-byte sequences representing ASCII and non-ASCII symbols. The from and len values specify the substring position and length in terms of symbols, rather than bytes.
If the str value is a datablock, the function returns a datablock containing a portion of the str value, cut using the same rules, while the from and len values specify the position position and length in bytes.
EOL()
This function returns a string containing the EOL (end-of-line) symbol(s) used on the Server OS platform.
CRLF()
This function returns a string with the Internet EOL (<carriage-return><line-feed>) symbols.
ToUpperCase(str)
If the str value is a string, the function result is this string with all its letters converted to the upper case.
ToLowerCase(str)
If the str value is a string, the function result is this string with all its letters converted to the lower case.
IsDigit(str)
This function returns a true-value if the str value is a 1-symbol string and that symbol is a decimal digit (0..9), otherwise the function returns a null-value.
IsWhiteSpaces(str)
This function returns a true-value if the str value is a string containing only space, <tab>, <carriage-return> or <line-feed> symbols, otherwise the function returns a null-value.
FindRegEx(str,picture)
The function compares the str string with the picture string containing a regular expression.
If str is not a string, or picture is not a string, or the picture string cannot be interpreted as a regular expression, or the str string does not match the regular expression, the function returns a null-value.
Otherwise, the function returns an array of strings. Its zero element contains a copy of the str string, while additional elements (if any) contain the str substrings matching the regular expression groups.
The picture string should specify a regular expression using the extended POSIX syntax.
EmailDomainPart(address)
If the address value is a string, and the string contains the @ symbol, this function returns a string containing the address string part after its first the @ symbol.
Otherwise, the function returns a null-value.
EmailUserPart(address)
If the address value is not string, this function returns a null-value.
If the address value is a string not containing the @ symbol, this function returns the same string.
Otherwise (the address value is a string containing the @ symbol), this function returns the address string part before the first @ symbol.

Numbers

IsNumber(arg)
This function returns a true-value if the arg value is a number, otherwise the function returns a null-value.
Number(arg)
If the arg value is a number, this function returns this number.
If the arg value is a string, this function returns the numeric value of that string, till the first non-numeric symbol.
For example, the value of Number("123#") is 123.
In all other cases, this function returns the number 0.
RandomNumber()
This function returns a random integer number in the [0..9223372036854775807] ([0..2*63-1]) range.

TimeStamps

IsDate(arg)
This function returns a true-value if the arg value is a timestamp, otherwise the function returns a null-value.
Date(arg)
If the arg value is a timestamp, this function returns this timestamp.
If the arg value is the number 0, this function returns the "remote past" timestamp.
If the arg value is a negative number, this function returns the "remote future" timestamp.
If the arg value is a positive number N, this function returns the timestamp corresponding to the start of the Nth day, where the 1st day is 2nd of January, 1970.
If the arg value is a string, if should be a textual representation of some timestamp, and this function returns that timestamp.
In all other cases, this function returns a null-value.
GMTTime()
This function returns a timestamp object with the current GMT time.
LocalTime()
This function returns a timestamp object with the current local time.
GMTToLocal(arg)
If the arg value is a timestamp object, this function returns a timestamp object containing the arg value converted from the GMT to the local time.
In all other cases, this function returns a null-value.
LocalToGMT(arg)
If the arg value is a timestamp object, this function returns a timestamp object containing the arg value converted from the local time to the GMT.
In all other cases, this function returns a null-value.
Year(arg)
If the arg value is a timestamp object, this function returns a number containing the arg value year.
If the the timestamp value is the "remote past" timestamp, the function returns the number 0.
If the the timestamp value is the "remote future" timestamp, the function returns the number 9999.
In all other cases, this function returns a null-value.
Month(arg)
If the arg value is a timestamp object, this function returns a string containing the arg value month name (Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec).
If the arg value is a number in the 1..12 range, this function returns a string containing the name of month number arg (Month(1) returns Jan).
In all other cases, this function returns a null-value.
MonthNum(arg)
If the arg value is a timestamp object, this function returns the arg value month number (1 for January).
In all other cases, this function returns a null-value.
MonthDay(arg)
If the arg value is a timestamp object, this function returns a number containing the day of month for the arg value date (1 is returned for the first day of month).
In all other cases, this function returns a null-value.
Hour(arg)
If the arg value is a timestamp object, this function returns a number containing the arg value hour.
If the the timestamp value is the "remote past" timestamp, the function returns the number 0.
If the the timestamp value is the "remote future" timestamp, the function returns the number 9999.
In all other cases, this function returns a null-value.
Minute(arg)
If the arg value is a timestamp object, this function returns a number containing the arg value minute.
If the the timestamp value is the "remote past" timestamp, the function returns the number 0.
If the the timestamp value is the "remote future" timestamp, the function returns the number 9999.
In all other cases, this function returns a null-value.
Second(arg)
If the arg value is a timestamp object, this function returns a number containing the arg value second.
If the the timestamp value is the "remote past" timestamp, the function returns the number 0.
If the the timestamp value is the "remote future" timestamp, the function returns the number 9999.
In all other cases, this function returns a null-value.
WeekDay(arg)
If the arg value is a timestamp object, this function returns a string containing the name of week day of the arg value date (Mon, Tue, Wed, Thu, Fri, Sat, Sun).
In all other cases, this function returns a null-value.
YearDay(arg)
If the arg value is a timestamp object, this function returns a number containing the day of year for the arg value date (the number 1 is returned for the 1st of January).
In all other cases, this function returns a null-value.
TimeOfDay(arg)
If the arg value is a timestamp object, this function returns the number of seconds between the date arg value and the start of its day.
In all other cases, this function returns a null-value.
DateNumber(arg)
If the arg value is a timestamp object, this function returns the number of full days between the arg value date and 01-Jan-1970.
In all other cases, this function returns a null-value.
DateByMonthDay(year,monthNum,monthDay)
The year, monthNum, monthDay values should be positive numbers. If any of these values is incorrect, this function returns a null-value. Otherwise, the function returns a timestamp object presenting midnight of the specified date.
The following expression timestamp value is midnight, 05-Nov-2008:
DateByMonthDay(2008,11,5)
DateByYearDay(year,yearDay)
The year, yearDay values should be positive numbers. If any of these values is incorrect, this function returns a null-value. Otherwise, the function returns a timestamp object presenting midnight of the specified date.
The following expression timestamp value is midnight, 01-Feb-2006:
DateByYearDay(2006,32)

IP Addresses

IsIPAddress(arg)
This function returns a true-value if the arg value is an ip-address, otherwise the function returns a null-value.
IPAddress(arg)
If the arg value is an ip-address, this function returns this ip-address.
If the arg value is a string with a correct presentation of an IP address (with an optional port number), the function returns that ip-address.
In all other cases, this function returns a null-value.

Datablocks

IsData(arg)
This function returns a true-value if the arg value is a datablock, otherwise the function returns a null-value.
RandomData(length)
The length value should be a positive numbers not larger than 4096.
This function returns a datablock of the specified length, filled with random data.
EmptyData()
This function returns an empty datablock.

Arrays

IsArray(arg)
This function returns a true-value if the arg value is an array, otherwise the function returns a null-value.
NewArray()
This function returns a newly created empty array.
Invert(arg)
The arg value should be an array, otherwise this function call results in a program exception.
This function returns an array containing the same elements as the arg value, but in the reversed order.
Find(source,object)
If the source value is an array, this function returns a number - the index in the array for the first element equal to the object value. If the source array does not contain such an object, a negative numeric value is returned.
If the source value is a Calendar handle, calendar items are returned (see below).
If the source value is anything else, a negative numeric value is returned.
AddElement(target,element)
If the target value is an array, this procedure adds element value as the new last element of that array.
If the myArray value is (1,4,9,16,25), the AddElement(myArray,"test") call changes the myArray value to (1,4,9,16,25,"test").
If the target value is an XML Object, this procedure adds element value as its new sub-element (the element value should be a string or an XML Object).
In all other cases this procedure call results in a program exception.
RemoveElement(target,what)
This procedure removes an element from an array.
If target value is an array, the what value should be a number or a string containing a decimal number, specifying the array element to remove.
If the myArray value is (1,4,9,16,25), the RemoveElement(myArray,2) call changes the myArray value to (1,4,16,25).
In all other cases this procedure call results in a program exception.
InsertElement(target,index,element)
This procedure inserts an element into an array.
The target value should be an array, otherwise this procedure call results in a program exception.
The index value should be a number or a string containing a decimal number, specifying where to insert the element value. All existing array elements with index number of index and bigger increase their index number by one.
If the myArray value is (1,4,9,16,25), the InsertElement(myArray,2,"Jack") call changes the myArray value to (1,4,"Jack",9,16,25).
SortStrings(arg)
This procedure sorts array elements.
The arg value should be an array, and all array elements must be strings, otherwise this procedure call results in a program exception.
The array elements are compared as case-insensitive UTF-8 strings.

Dictionaries

IsDictionary(arg)
This function returns a true-value if the arg value is a dictionary, otherwise the function returns a null-value.
NewDictionary()
This function returns a newly created empty dictionary.
SetCaseSensitive(target,flag)
This procedure specifies if dictionary keys should be processes as case-sensitive.
The target value should be a dictionary, otherwise this procedure call results in a program exception.
If flag value is a null-value, the target dictionary becomes case-insensitive, otherwise it becomes case-sensitive.
New dictionaries are created as case-sensitive.

XML Objects

IsXML(arg)
This function returns a true-value if the arg value is an XML object, otherwise the function returns a null-value.
NewXML(type)
NewXML(type,prefix)
NewXML(type,prefix,namespace)
This function returns a newly created XML Object of type type. The type value should be a string containing a valid XML tag.
The prefix value (if specified) can be a null-value or a string containing a valid XML prefix. This prefix is used to qualify the XML object name, if not specified or if its value is a null-value, then an empty string value is used.
If the namespace value is specified and its value is not a null-value, it should be a string containing the namespace to be associated with the prefix value.
SetNamespace(data,namespace)
SetNamespace(data,namespace,prefix)
This procedure associates an XML prefix with some namespace.
The data value should be an XML Object, otherwise this procedure call results in a program exception.
If the prefix is not specified, or its value is a null-value, then an empty string value is used. Otherwise, its value should be a string containing a valid XML prefix.
If the namespace value is a null-value, the namespaces associated with the prefix value is removed. Otherwise the namespace value should be a string, containing the namespace to be associated with the prefix value.
GetNamespace(data)
GetNamespace(data,prefix)
This function returns a string with the namespace associated with the specified XML prefix, or a null-value if there is no associated namespace.
The data value should be an XML Object, otherwise this function call results in a program exception.
If the prefix is not specified, or its value is a null-value, then an empty string value is used. Otherwise, its value should be a string containing a valid XML prefix.
GetPrefix(data,namespace)
This function returns a string with the prefix assigned to the specified namespace, or a null-value if the namespace is not included into the XML object.
The data value should be an XML Object, otherwise this function call results in a program exception.
The prefix value should be a string containing a valid XML prefix.
SetAttribute(data,value,name)
SetAttribute(data,value,name,prefix )
This procedure sets an XML Object attribute for the specified name and prefix.
The data value should be an XML Object, otherwise this procedure call results in a program exception.
The name value should be a string containing a valid XML attribute name.
If the prefix parameter is specified, its value should be a null-value or a string containing a valid XML prefix.
If the value value is a null-value, the attribute with the specified name and prefix is removed. Otherwise the value value should be a string containing the new attribute value.
GetAttribute(data,name)
GetAttribute(data,name,prefix)

The data value should be an XML Object, otherwise this function call results in a program exception.
If the prefix parameter is specified, its value value should be a null-value or a string containing a valid XML prefix.
If the name value is a string, it should contain a valid XML attribute name. In this case this function returns a string value of the attribute with the specified name and prefix, or a null-value if there is no such attribute.
If the name value is a number, it should specify the attribute index (starting from 0). If an attribute with this index does not exist, this function returns a null-value. Otherwise, this function returns an array. The first array element is the attribute name, the second array element is the attribute prefix.
If the name value is not a string and it is not a number, this function call results in a program exception.
XMLBody(data,type)
XMLBody(data,type,namespace)
XMLBody(data,type,namespace,index)
This function returns an XML sub-element with the specified type, namespace, and position, or a null-value if there is no such sub-element.
The data value should be an XML Object, otherwise this function call results in a program exception.
The type value should be a null-value or a string containing a valid XML tag name. If the type value is a null-value, the function retrieves sub-elements of any type.
If the namespace parameter is specified, its value should be a null-value or a string containing a namespace. If the namespace is not specified, or its value is a null-value, the function looks for sub-elements ignoring their namespaces.
If the index parameter is specified, its value should be a non-negative number. To retrieve the first sub-element with the specified type and namespace, the index value (if specified) should be 0.
XMLType(data)
This function returns a string with the XML Object type.
The data value should be an XML Object, otherwise this function call results in a program exception.
XMLPrefix(data)
This function returns a string with the XML Object type prefix.
The data value should be an XML Object, otherwise this function call results in a program exception.

Data Conversion

ObjectToString(arg)
This function returns a string with a textual representation of the arg value.
If the arg value is a null-value, the function returns the "#null#" string.
ObjectToXML(arg)
This function returns an XML representation of the arg value, as specified in XML Objects section.
ToObject(arg)
If the arg value is a string or a datablock, this function returns an object textually represented with the arg value.
If the arg value is an XML object, this function returns an object this XML represents (as specified in XML Objects section).
Otherwise this function call results in a program exception.
If conversion fails or if the arg value is the "#null#" string, the function returns a null-value.
Base32Encode(arg)
The arg value should be a string or a datablock, otherwise this function call results in a program exception.
This function returns a string containing the base32-encoded arg data.
Base32Decode(arg)
The arg value should be a string, otherwise this function call results in a program exception.
This function returns a datablock containing the base32-decoded arg data.
Base64Encode(arg)
The arg value should be a string or a datablock, otherwise this function call results in a program exception.
This function returns a string containing the base64-encoded arg data.
Base64Decode(arg)
The arg value should be a string, otherwise this function call results in a program exception.
This function returns a datablock containing the base64-decoded arg data.
Base64UrlEncode(arg)
The arg value should be a string or a datablock, otherwise this function call results in a program exception.
This function returns a string containing the base64url-encoded arg data.
Base64UrlDecode(arg)
The arg value should be a string, otherwise this function call results in a program exception.
This function returns a datablock containing the base64url-decoded arg data.
AppToXML(data,format)
This function converts application data into its XML representation.
The data value should be a string or a datablock containing the application data text.
The format value should be a string specifying the application data format. The following formats are supported:
  • vCard - vCard format, the function returns either a vCard XML object, or an array of vCard XML objects.
  • vCardGroup - vCardGroup format, the function returns a vCardGroup XML object.
  • iCalendar - iCalendar format, the function returns an iCalendar XML object.
  • sdp - SDP format, the function returns an SDP XML object.

If the function fails to parse the application data, or the specified format is not supported, the function returns an error code string.
XMLToApp(data)
This function converts an XML representation into application data (see above).
The data value should be an XML object.
The function returns the application data string.
If the XML object is not a representation of some supported application data format, the resulting string is a generic textual representation of the data value XML object.
If the function fails to convert the XML representation into application data, the resulting string contains the error code.
ObjectToJSON(arg)
This function returns a string with a JSON (JavaScript Object Notation) representation of the arg value.
Null-values are represented as null tokens.
Timestamp objects are represented as RFC822-formatted date strings.
Binary data blocks are represented as base64-encoded strings.
JSONToObject(arg)
If the arg value is a string or a datablock, this function returns an object textually represented with the arg value, using the JSON format.
Otherwise this function call results in a program exception.
If conversion fails or if the arg value is the null string, the function returns a null-value.
Convert(data,format)
This function converts the data value into the format specified with the format value, which should be a string.
The following format values are supported (case-insensitive, unless explicitly specified):
"base32"
If the data value is a string, the function returns a datablock with its base32-decoded data.
If the data value is a datablock, the function returns a string with its base32-encoded data.
"base64"
If the data value is a string, the function returns a datablock with its base64-decoded data.
If the data value is a datablock, the function returns a string with its base64-encoded data.
"hex"
If the data value is a string, it should contain hexadecimal symbols, and the function returns a datablock with its decoded data.
If the data value is a datablock, the function returns a string with its hexadecimal encoding. The "HEX" format produces upper-case encodings, the "hex" format produces lower-case encodings.
"toURI"
The data should be a string, the function returns that string URI-encoded.
"fromURI"
The data should be an URI-encoded string, the function returns the decoded string.
"ucs-2[+][le|be]"
If the data value is a string, the function returns a datablock with its ucs-2 encoded data.
If the data value is a datablock, the function returns a string with its ucs-2 decoded data.
The le or be suffix specifies the ucs-2 encoding byte order (little-endian or big-endian, respectively). The big-endian byte order is used by default.
If the datablock to be decoded contains a BOM (byte order mark), the byte order suffix is ignored.
The + symbol causes the BOM (byte order mark) to be placed into the encoded data. This symbol is ignored when decoding.
"charsetName" (any character set name known to the CommuniGate Pro Server)
If the data value is a string, the function returns a datablock with its data encoded using the specified character set.
If the data value is a datablock, the function returns a string with its data decoded from the specified character set.
"utfcode"
If the data value is a string, the function returns a number - the Unicode code of the first string symbol.
If the data value is a number, it is interpreted as a Unicode code, and the function returns a string consisting of this symbol.
"words"
If the data value is a string, the function splits it into words - non-empty substrings separated with sequences of "white space" and "end of line" symbols, and returns an array containing all "word" strings.
"asn.1"
If the data value is an array, it should represent some ASN.1 data structure. The function returns a datablock with ASN.1 BER encoding of this structure.
If encoding fails, the function returns an error code string.
If the data value is a datablock, the function returns an array representing this ASN.1 data structure.
If decoding fails, the function returns an error code string.
"dns-a"
If the data value is a string, the function peforms a DNS A-record search for this domain name.
The function returns either an array of IP Addresses from the found records, or an error code string.
"dns-aaaa"
Same as "dns-a", but for the DNS AAAA-record.
"dns-ptr"
If the data value is a string, the function peforms a DNS PTR-record search for this domain name.
If the data value is an IP Address, the function peforms a DNS "IN-Addr" PTR-record search for that address.
The function returns either an array with one string element - the found domain name, or an error code string.
"dns-txt"
If the data value is a string, the function peforms a DNS TXT-record search for this domain name.
The function returns either an array containing the found record strings, or an error code string.
"gennonce"
The function returns a datablock with a "nonce" data. The data value should be a number, it specifies the "nonce" size in bytes. If this value is outside the supported nonce size range, the function returns a null-value.
"checknonce"
If the data value is a datablock, the function returns a true-value if this datablock is a valid "nonce", otherwise the function returns a null-value.
SystemInfo(what)
This function retrieves platform-specific data specified with the what value, which should be a string.
The following what values are supported (case-insensitive, unless explicitly specified):
"serverVersion"
The function returns a string with this CommuniGate Pro Server version.
"serverOS"
The function returns a string with the name of the Operating System controlling the computer this CommuniGate Pro Server is running on.
"serverCPU"
The function returns a string with the type of processor(s) this CommuniGate Pro Server is running on.
"mainDomainName"
The function returns a string with the CommuniGate Pro Server Main Domain Name.
"licenseDomainName"
The function returns a string with the Cluster Domain Name for a Cluster system, the Main Domain Name or a non-clustered system.
"startTime"
The function returns a timestamp value specifying the time when this CommuniGate Pro Server instance started.
"serverInstance"
The function returns a string which is unique for each running instance of the CommuniGate Pro Server.
"clusterInstance"
The function returns a string which is unique for each running instance of the CommuniGate Pro Cluster, and it has the same value for all cluster members.
"knownCharsets"
The function returns an array with the list of character sets names known to the server.
QRCode(str)
This function returns a data block that contains image/png data for QR representation of the str string value.
TOTPCode(str)
This function returns a numeric sequence containing the time-based one-time password (TOTP) for the secret, encoded in base32 format and passed as a string value str.

Cryptography

CryDigest(algName,data)
CryDigest(algName,data,salt)
This function computes the cryptographic digest of the data datablock.
The algName value should be a string specifying the digest algorithm name (MD5, SHA1, etc).
If the third parameter salt is specified, the digest is calculated using the HMAC algorithm with this third parameter used as the key and algName used for both HMAC stages.
If the algorithm with the specified name is unknown, the function returns a null-value, otherwise the function returns a datablock with the calculated digest.
CryEncrypt(algName,key,data)
This function encrypts the data datablock using the key datablock as the encryption key. For the ciphers with fixed block size the last data block should contain the initialization vector.
The algName value should be a string specifying the cipher algorithm name (RC4, DES3, AES, etc).
If the algorithm with the specified name is unknown, the function returns a null-value, otherwise the function returns a datablock with the encrypted data.
CryDecrypt(algName,key,data)
This function decrypts the data datablock using the key datablock as the decryption key. For the ciphers with fixed block size the last data block should contain the initialization vector.
The algName value should be a string specifying the cipher algorithm name.
If the algorithm with the specified name is unknown, the function returns a null-value, otherwise the function returns a datablock with the decrypted data.

Environments

Vars()
This function returns a dictionary unique for this Task (a program invocation). This dictionary can be used to store "task variables" visible in all procedures and functions executed in this Task.
When a Task is started with parameters (for example, when a Real-Time Application is started to process a Signal directed with the Router), the parameter array is placed into the startParameter element of the Vars() dictionary.
The following example retrieves the first two Task parameters:
  firstParam  = Vars().startParameter[0];
  secondParam = Vars().startParameter[1];

Addresses and URIs

SIPURIToEmail(uri)
This function converts the uri value from a SIP URI into an E-mail string.
If the uri value is not a string, or if it cannot be parsed as a SIP URI, the function returns a null-value.
EmailToSIPURI(email)
This function converts the email value from an E-mail address into a SIP URI string.
If the email value is not a string, or if it cannot be parsed as an E-mail, the function returns a null-value.
PhoneNumberToSIPURI(phoneNumber)
This function converts the phoneNumber value into a SIP URI string.
If the email value is not a string, or if it cannot be parsed as a telephone number, the function returns a null-value.
The function removes all formatting symbols from the phoneNumber value, leaving only the digits and the leading plus (+) symbol (if it exists).
The function adds the current Domain name to the converted number.
RouteAddress(email,type)
This function uses the Router to process the email address.
The type value specifies the address type: it should be the mail, signal, or access string.
If address routing fails, the function returns an error code string. Otherwise, the function result is a dictionary with the following elements:
module
the name of the CommuniGate Pro module that will process this address.
host
a string with the name of the host (a local Account, a remote domain, etc.) the address is routed to.
object
a string with the name of the host object the address is routed to.
canRelay
this optional element exists and contains a true-value if information can be relayed to this address.
RouteENUM(service,phoneNumber,domain)
This function uses the Domain Name Resolver to convert the phoneNumber telephone number (a string with any sequence of digits with an optional leading + symbol) into a URL.
The service value should be a string. It specifies the ENUM "service" (such as "E2U+SIP" or "E2U+MAIL").
The domain value should be a string. It specifies the ENUM domain name (such as "e164.arpa").
If the telephone number has been converted successfully, this function returns an array. Its first element contains a string - the resulting URL.
Otherwise, this function returns an error code string.

Account Data

The following functions and procedures are available when the program (a Task) has a "current Account" set.
MyDomain()
This function returns a string with the current Domain name, if there is one. If there is no Account or Domain associated with the current Task, this function returns a null-value.
MyEmail()
This function returns a string with the current Account E-mail, if there is one. If there is no Account associated with the current Task, this function returns a null-value.
GetAccountPreferences(keyName)
This function returns Preference data for the current Account.
If the keyName is a non-empty string, the Account Preference object for that key is returned. Otherwise a dictionary with all effective Account Preferences is returned.
If the keyName string starts with a ~username/ prefix, the prefix is removed. The username string specifies the name of the Account to use. If this Account is not the same as the current Account, the operation succeeds only if the current Account has a Domain Administrator right for the specified Account Domain.
SetAccountPreferences(keyValue,keyName)
This function updates Preference data for the current Account.
If the keyName is a non-empty string, the keyValue value specifies the new object for that key. If the keyValue is a null-value, the object is removed from the Account Preference data, enabling the default value for the specified key.
If the keyName string starts with a ~username/ prefix, the prefix is removed. The username string specifies the name of the Account to update. If this Account is not the same as the current Account, the operation succeeds only if the current Account has a Domain Administrator right for the specified Account Domain.
If the keyName is a ~username/ string, or an empty string, or if it is not a string, the keyValue value must be a dictionary. It is used to update the Account Preference Data.
This function returns a null-value if Preference data is successfully updated, otherwise it returns a string with an error code.
Impersonate(email)
This function Routes the email address and sets the result as the current Account.
If the routed address is not local, the current Account is cleared.
If the routed address is local and it is not the same as the current Account, the current Account must have the CanImpersonate access right for the routed address Domain.
When the current Account is changed, the preferences, the selected language, and the selected time zone are changed, too.
This function returns a null-value if the operation has succeeded, otherwise it returns a string with an error code.
ReadGroupMembers(groupName)
This function reads a Group.
The groupName value should be a string. It specifies the name of the Group to read. If this name does not contain a Domain name, the current Domain is used.
This function returns an array of strings containing Group member E-mail addresses. This function returns a null-value if there is no Group with the specified name.
The current Account should have the Domain Administrator right for the Group Domain.
ReadTelnums()
ReadTelnums(accountName)
This function reads Phone Numbers assigned to the accountName Account or to the current Account, if the accountName parameter is not specified or if its value is a null-value.
This function returns an array of strings. This function returns a null-value if there is no Account with the specified name.
To retrieve the Phone Numbers assigned to a different Account, the current Account should have the Domain Administrator right for the accountName Account Domain.
UpdateAccountMailRule(ruleData)
UpdateAccountMailRule(ruleData,accountName)
UpdateAccountSignalRule(ruleData)
UpdateAccountSignalRule(ruleData,accountName)
These functions modify Account Queue or Signal Rules.
The ruleData parameter is a string or an array. It has the same meaning as the newRule parameter of the UpdateAccountMailRule and UpdateAccountSignalRule CLI commands.
These functions update the Rules of the the accountName Account, or the current Account if the accountName parameter is not specified or its value is a null-value.
To update Queue Rules of a different Account, the current Account should have the RulesAllowed Domain Administrator right for the accountName Account Domain.
To update Signal Rules of a different Account, the current Account should have the SignalRulesAllowed Domain Administrator right for the accountName Account Domain.
This function returns a null-value if the operation has succeeded, otherwise it returns a string with an error code.

Mailboxes

ListMailboxes(filter)
This function lists all Mailboxes in the current Account.
The filter value should be a string - it specifies the search pattern. If the value is a null-value, the search pattern * (all Account Mailboxes) is used.
To search Mailboxes in a different Account, the search pattern should be specified as a "~accountName/pattern" string.
If the operation is successful, this function returns a dictionary. Each dictionary key is a string with the found Mailbox name.
The dictionary element value is:
  • a dictionary with the Mailbox attributes - if the found Mailbox is an "item container" only.
  • an empty array - if the found Mailbox is a "mailbox folder" only.
  • an array with one dictionary element- if the found Mailbox is both a "mailbox folder" and an "item container".

If the Mailbox Access rights allow the current Account to see that Mailbox, but do not allow the current Account to open it, the Mailbox Attribute dictionary is replaced with a string containing the Mailbox Access Rights for the current Account.
If this function fails, it returns a string with an error code.
CreateMailbox(mailboxName,class)
This function creates the mailboxName Mailbox.
If the class is not a null-value, it specified the Mailbox Class for the newly created Mailbox.
This function returns a null-value if the Mailbox is successfully created, otherwise it returns a string with an error code.
RenameMailbox(oldMailboxName,newMailboxName,renameSub)
This function renames the oldMailboxName Mailbox into newMailboxName. Both parameters must have string values.
If the renameSub value is not a null-value, all oldMailboxName sub-Mailboxes are renamed, too.
This function returns a null-value if the Mailbox is successfully renamed, otherwise it returns a string with an error code.
DeleteMailbox(mailboxName,deleteSub)
This function deletes the mailboxName Mailbox.
If the deleteSub value is not a null-value, all mailboxName sub-Mailboxes are deleted, too.
This function returns a null-value if the Mailbox is successfully deleted, otherwise it returns a string with an error code.
GetMailboxACLs(mailboxName)
This function reads the Access Control List for the mailboxName Mailbox.
If the function successfully retrieves the ACL data, it returns a dictionary containing ACL identifiers as keys, and access rights as value strings.
Otherwise the function returns a string with an error code.
SetMailboxACLs(mailboxName,newACLs)
This function updates the Access Control List for the mailboxName Mailbox.
The newACL value should be a dictionary, containing ACL identifiers as keys, and access rights as value strings.
To remove an identifier from the ACL, specify an empty array as its value.
This function returns a null-value if the Mailbox ACL is successfully modified, otherwise it returns a string with an error code.
Note: To access Mailboxes in other Accounts, specify a Mailbox name as a "~accountName[@domainName]/mailboxName" string.
GetMailboxAliases(accountName)
This function reads Mailbox Aliases created in the accountName Account or to the current Account, if the accountName value is a null-value.
If the function successfully retrieves the Mailbox Aliases data, it returns a dictionary. Each dictionary key is the Mailbox Alias name, and its value is a string with the Mailbox name this Mailbox Alias points to.
Otherwise the function returns a string with an error code.
SetMailboxAliases(newAliases,accountName)
This function sets the Mailbox Aliases for the accountName Account or for the current Account, if the accountName value is a null-value. The old Mailbox Aliases are removed.
The newAliases value should be a dictionary. Each dictionary key is the Mailbox Alias name, and its value is a string with the Mailbox name this Mailbox Alias points to.
This function returns a null-value if the Mailbox Aliases are successfully modified, otherwise it returns a string with an error code.
GetMailboxSubscription(accountName)
This function reads Mailbox Subscription created in the accountName Account or to the current Account, if the accountName value is a null-value.
If the function successfully retrieves the Mailbox Subscription data, it returns an array. Each array element is a string containing a Mailbox name.
Otherwise the function returns a string with an error code.
SetMailboxSubscription(newSubscription,accountName)
This function sets the Mailbox Subscription for the accountName Account or to the current Account, if the accountName value is a null-value. The old Mailbox Subscription elements are removed.
The newSubscription value should be an array. Each array element is a string containing a Mailbox name.
This function returns a null-value if the Mailbox Subscription is successfully modified, otherwise it returns a string with an error code.

Mailbox Handles

Mailbox handles are internal objects representing Mailboxes. Mailbox Messages can be addressed either using their UID (unique IDs) numeric values, or their current index values.

Some operations use a "message set" as a parameter. A message set specifies a set of numbers, which is interpreted either as a set of message UIDs or a set of message indeces.
If a "message set" parameter value is a number, the resulting set includes this number only.
If a "message set" parameter value is an array, containing numeric elements. All these numbers are included into the resulting set. The array can also contain "ranges", where a "range" is an array containing two numbers ("range ends"). The resulting set includes the "range end" numbers, and all numbers between them.
Examples:

if a "message set" value is the 123 number, the resulting set includes the number 123 only
if a "message set" value is the (123, 125, 130) array, the resulting set includes the numbers 123,125,130
if a "message set" value is the (123, (125,128), 130) array, the resulting set includes the numbers 123,125,126,127,128,130
OpenMailbox(mailboxName)
This function opens a Mailbox. The mailboxName value should be a string. It specifies the Mailbox name.
If the name does not start with the ~ symbol, the Mailbox is opened in the current Account, if any.
The current Account (if any) must have the Read/Select access right for the specified Mailbox.
The function returns a Mailbox handle if the Mailbox has been opened successfully, otherwise it returns an error code string.
OpenMailboxView(params)
This function opens a Mailbox and creates a Mailbox handle.
The params value should be a dictionary containing a mailbox and sortField string elements, and optional mailboxClass, sortOrder, filter, filterField string elements, and UIDValidity, UIDMin numeric elements.
See the XIMSS section for more details on these parameter values.
The function returns a Mailbox handle if the Mailbox has been opened successfully, otherwise it returns an error code string.
MailboxUIDs(boxRef,flags)
This function returns an array of numbers - Mailbox message UIDs.
The boxRef value should be a Mailbox handle.
If the flags value is a string, it should contain a comma-separated list of message flag Names and/or Negative Names. Only UIDs of messages that have flags specified with the flag Names and do not have flags specified with the Negative Names are included into the resulting array.
The following example retrieves UIDs of all messages that have the Seen flag and do not have the Deleted flag:
myMailbox = OpenMailbox("INBOX");
seen = MailboxUIDs(myMailbox,"Seen,Undeleted");
SubscribeEvents(object,refData)
This function enables or disables object object event generation.
If the refData value is a null-value, the object stops to generate events.
Otherwise, the refData value should be a "basic" object. When the object generates events and send them to this Task, the event parameter element contains the refData value.
If the object value is a Mailbox handle, it should be created with the OpenMailboxView function. A Mailbox notification Event is sent to this Task when the Mailbox messages are removed, added, or modified. The "mailbox view" is not actually modified (i.e. the MailboxUIDs function returns the same set of message UIDs) until the Sync operation is applied to that Mailbox handle.
IsMailboxNotifyEvent(data)
This function returns a true-value if the data value is a Mailbox notification Event, otherwise it returns a null-value.
Sync(boxRef)
This function checks for Mailbox modifications.
The boxRef value should be a Mailbox Handle.
This function takes the first pending Mailbox modification and "commits" it by modifying the message UIDs (adding added messages, removing removed messages). It returns a dictionary with the following elements:
mode
a "removed", "added", "updated", or "attrsUpdated" string specifying this Mailbox modification type.
UID
a number - the UID of the removed, added, or modified message
index
for an updated message - its position in the message UIDs array.
for a removed message - its position in the message UIDs array before it was removed from that array.
for an added message - its position in the message UIDs array after it was added to that array.

If there is no pending modification in the Mailbox, this function returns a null-value.
MailboxInternalTimeByUID(boxRef,uid)
This function returns a timestamp object containing the message Internal Date.
The boxRef value should be a Mailbox handle, the uid value should be a number - the message UID.
If a message with the specified UID does not exist in the Mailbox, the function returns a null-value.
MailboxFlagsByUID(boxRef,uid)
This function returns a string containing a comma-separated list of Mailbox message flags Names.
The boxRef value should be a Mailbox handle, the uid value should be a number - the message UID.
If a message with the specified UID does not exist in the Mailbox, the function returns a null-value.
MailboxOrigUIDByUID(boxRef,uid)
This function returns a number containing the message "original" (permanent) UID.
The boxRef value should be a Mailbox handle, the uid value should be a number - the message UID.
If a message with the specified UID does not exist in the Mailbox, the function returns a null-value.
MailboxUIDByOrigUID(boxRef,origUID)
This function returns a number containing the real UID of the message with the specified "original" (permanent) UID.
The boxRef value should be a Mailbox handle, the origUID value should be a number - the message original UID.
If a message with the specified original UID does not exist in the Mailbox, the function returns a null-value.
MailboxSetFlags(boxRef,idData,params)
This function modifies Mailbox Message flags.
The boxRef value should be a Mailbox handle, and the idData value is a "message set" (see above).
If the params value is a string, it should be "flag values": a comma-separated list of message flag Names and/or Negative Names.
If the params value is a dictionary, it should include the following elements:
flags
the "flag values" string
useIndex
if this optional element is present, the "message set" specified with the idData value is interpreted as a set of message index values in the boxRef "mailbox view", if this element is absent, it is interpreted as the UID value set.
This element can be present only if the boxRef handle was open using the OpenMailboxView function. Otherwise this function call results in a program exception.

The function sets the flags specified with their Names and resets the flags specified with their Negative Names.
The function returns a null-value if the current Account (if any) has sufficient Mailbox Access Rights to modify the flags, and flags have been successfully modified, otherwise the function returns an error code string.
MailboxExpunge(boxRef)
This function removes all Mailbox messages marked as "purgable" or "deleted".
The boxRef value should be a Mailbox handle.
This function returns a null-value if the operation has succeeded, otherwise it returns a string with an error code.
MailboxAudioByUID(boxRef,uid)
This function returns a datablock containing an audio section of the message.
The boxRef value should be a Mailbox handle, the uid value should be a number - the message UID.
If a message with the specified UID does not exist in the Mailbox, or the message does not contain an audio part, the function returns a null-value.
MailboxRedirectByUID(boxRef,uid,addresses)
MailboxForwardByUID(boxRef,uid,addresses)
These function redirect or forward the specified message to the specified E-mail addresses.
The boxRef value should be a Mailbox handle, the uid value should be a number - the message UID, the addresses should be a string containing one E-mail address or several E-mail addresses separated with the comma (,) symbols.
These functions return a null-value if the operation has succeeded, otherwise they return a string with an error code.
MailboxAppend(boxRef,headers,content)
These function composes an E-mail message and appends it to the Mailbox.
The boxRef value should be a Mailbox handle.
The headers and content values are processed in the same way they are processed with the SubmitEMail function.
The headers dictionary may contain the following additional elements:
flags
a string that specifies the message flags the newly created message will have in the Mailbox. Several flags can be specified, separated with the comma symbol. See the Mailbox section for more details.
internalDate
a timestamp value with the "internal timestamp" for the newly created message. If absent, the current time is used.
replacesUID, replaceMode
an UID value for the previous version of this message. The meaning is the same as the meaning of these attributes in the XIMSS messageAppend operation.
report
if this element is specified, it should have the "uid" value.

If the content value is a vCard or vCardGroup XML object, a Contacts item is composed (regular headers elements are ignored), and this item is added to the Mailbox.
If the operation has failed, this function returns a string with an error code.
If the operation has succeeded, this function returns a null-value, or, if the report element was specified in the headers dictionary, the function returns a number - the UID value of the newly created Mailbox message.
MailboxCopy(boxRef,uidData,parameters)
These function copies or moves messages from one Mailbox to some other Mailbox.
The boxRef value should be a Mailbox handle.
The uidData value should be either a number or an array of numbers or "ranges", where a "range" is an array with 2 numbers as its elements. The "range" includes its "start" and "end" numbers, and all the numbers in between.
All these numbers specify the set of UIDs or Mailbox indeces of the message(s) to be copied.
If the uidData value is the 123 number, the message with UID 123 is copied. If the uidData value is the (123, 125, 130) array, the messages with UIDs 123,125,130 are copied. If the uidData value is the (123, (125,128), 130) array, the messages with UIDs 123,125,126,127,128,130 are copied.
If the parameters value is a string, it specifies the target Mailbox name.
Otherwise, the parameters value should be a dictionary with the following elements:
targetMailbox
the target Mailbox name string.
doMove
if this element is present, the original messages are removed after they have been successfully copied.
mailboxClass
if this element value is a string, and the targetMailbox Mailbox does not exist, that Mailbox is created.
If the element value is a non-empty string, that value is assigned as the Mailbox Class to the newly created Mailbox.
useIndex
if this element is present, the set specified with the uidData value is interpreted as a set of message index values in the boxRef "mailbox view". This element can be present only if the boxRef handle was open using the OpenMailboxView function. Otherwise this function call results in a program exception.
report
if this element is present, the function returns an array of numbers - the UIDs of copied messages created in the target Mailbox.

This function returns a null-value or an array if the operation has succeeded, otherwise it returns a string with an error code.
GetMessageAttr(boxRef,uid)
This function retrieves Message attributes.
The boxRef value should be a Mailbox handle, the uid value should be a number - the message UID.
If the function succeeds, it returns a dictionary with the message attribute values, otherwise it returns a string with an error code.
UpdateMessageAttr(boxRef,uid,newData)
This function modifies Message attributes.
The boxRef value should be a Mailbox handle, the uid value should be a number - the message UID.
The newData value should be a dictionary with new attribute values. To remove an attribute, set its value to the "default" string.
If the function succeeds, it returns a null-value, otherwise it returns a string with an error code.

Message Handles

Message Handles are internal objects representing individual messages stored in Mailboxes.

OpenMessage(boxRef,uid)
This function opens a Message Handle.
The boxRef value should be a Mailbox handle, the uid value should be a number - the message UID.
The function returns a Message Handle if the message has been opened successfully, otherwise it returns a null-value.
MessagePart(msgRef,type)
The msgRef value should be a Message Handle.
If the type value is a null-value, this function returns a dictionary containing the message MIME structure.
Otherwise, the type value should be a string. It specifies the message subpart to search for:
audio
a subpart with audio/* Content-Type.
plain
a subpart with text/plain Content-Type.
text
a subpart with text/* Content-Type. If several alternative subtypes are available, the text/plain part has the lowest priority, followed by text/html part.
If a subpart is found, this function returns a dictionary with this subpart MIME structure.
If no subpart is not found, the function returns a null-value.
If the message cannot be read or parsed, the function returns an error code string.
The dictionary elements are:
estimatedSize
estimated size of the message (or message part) decoded body.
filename
optional - the decoded message part file name.
Content-Type
the message (or message part) content type string (such as "text", "image", etc.)
Content-Subtype
the message (or message part) content subtype string (such as "plain", "jpeg", etc.)
DispositionParams
a dictionary with Content-Disposition field parameters
ContentTypeParams
a dictionary with Content-Type field parameters
MIMEPartID
This element is an empty string for the message itself. For message subparts, this element is a string with the message part ID.
MIMEParts
an array of MIME subparts. Each array element is a dictionary with subpart MIME structure.
contentFieldName
a string with Content-contentFieldName field value
MessageHeader(msgRef,partID,fieldName)
This function returns an array of the specified message header fields, or a dictionary with all message header fields. If the message cannot be read or parsed, the function returns an error code string.
The msgRef value should be a Message Handle.
If the partID is a null-value, then the message header fields are returned.
If the partID is a string, it should be a message part ID, and that message part should be of the text/rfc822headers type, or it should be the (only) subpart of the message/rfc822 part. The header fields of the specified message part are returned.
If the fieldName value is a string, it specifies the message header field name, and the function value is an array of the specified field values.
Otherwise, the fieldName value should be a null-value. In this case the function value is a dictionary: the dictionary keys are the names of all message header fields, and their values are arrays with the corresponding field values.
If the field name specifies an Email-type field ("From", "To", "Sender", etc.) then the field value is a dictionary. The dictionary element with an empty ("") key is the parsed E-mail address. An optional realName element contains the address "comment" string.
If the field name is a "E-emailField" string, where emailField is an Email-type field name, then the field value is a string with the parsed E-mail address.
If the field name is a date-type field ("Date","Resent-Date"), then the field value is a timestamp.
In all other cases, the field value is a string containing the field data, MIME-decoded and converted into the UTF-8 character set.

Example: the msgRef Message Handle references a message with the following header:

From: "Sender Name" <fromName@domain>
Subject: I'll be there!
To: "Recipient Name" <toName@domain>, <toName1@domain1>,
To: <toName2@domain2>
Cc: "Cc Name" <toName3@domain3>
MIME-Version: 1.0
X-Mailer: SuperClient v7.77
Date: Fri, 24 Oct 2008 02:51:24 -0800
Message-ID: <ximss-38150012@this.server.dom>
Content-Type: text/plain; charset="utf-8"
Then the MessageHeader(msgRef,null,"To") returns
({""="toName@domain",realName="Sender Name"},{""="toName1@domain1"},{""="toName2@domain2"})
the MessageHeader(msgRef,null,"E-Cc") returns
("toName3@domain3")
and the MessageHeader(msgRef,null,null) returns
{
 Cc = ({""="toName3@domain3",realName="Cc Name"});
 Date = (#T24-10-2008_10:51:24);
 From = ({""="fromName@domain",realName="Sender Name"});
 Message-ID = ("<ximss-38150012@this.server.dom>");
 Subject = ("I'll be there!");
 To=({""="toName@domain",realName="Recipient Name"},{""="toName1@domain1"},{""="toName2@domain2"});
 X-Mailer = ("SuperClient v7.77");
}
MessageBody(msgRef,partID)
This function returns the message or message part body.
The msgRef value should be a Message Handle.
If the partID is a null-value, then the entire message body is returned.
If the partID is a string, it should be a message part ID. The message part body is returned.
If the message cannot be read, or if the specified message part is not found, this function returns an error code string.
If the message or message part Content-Type is text/*, the function reencodes the result using the UTF-8 character set.
If the message or message part Content-Type is text/xml, the function returns a parsed XML object.
For all other Content-Types, the function returns a datablock with the message body data.

Calendars

Calendar handles are internal objects representing Calendars. When a Calendar handle is created, it can be used to retrieve its events within the specified time intervals, to publish new events, to accept, decline, and cancel events, etc.

OpenCalendar(mailboxName)
This function opens the specified Mailbox as a Calendar. The mailboxName value should be a string. It specifies the Mailbox name.
If the name does not start with the ~ symbol, the Mailbox is opened in the current Account, if any.
The current Account (if any) must have the Read/Select access right for the specified Mailbox.
The function returns a Calendar handle if the Mailbox has been opened successfully and the Calendar is built using its content, otherwise the function returns an error code string.
Find(calendarRef,params)
the calendarRef value should be a Calendar handle, and the params value should be a dictionary.
This function retrieves all calendar events falling into the specified time interval.
The params dictionary should contain the required timeFrom and timeTill elements with the timestamp values, and optional limit and skip number elements, and an optional byAlarm element. These elements have the same meanings as the attributes of the findEvents XIMSS operation.
If the function fails, it returns an error code string. Otherwise, it returns an array of dictionaries for each 24-hour day (in the selected time zone) included into the specified time interval.
Each dictionary has the following elements:
timeFrom, timeTill, skip, items
these elements have the same meanings as the attributes of the events XIMSS data message
events
An array of found Events, represented as dictionaries with the following elements:
UID, timeFrom, dateFrom, duration, alarmTime
these elements have the same meanings as the attributes of the event sub-elements of the events XIMSS data message
data
the XML presentation of the found Event
parent
this element is present if the found Event is an exception of some other Event. The element value is the XML presentation of that parent Event.
The value of the data element is included into the parent element value as a sub-element of its exceptions sub-element.
ProcessCalendar(calendarRef,params)
the calendarRef value should be a Calendar handle, and the params value should be a dictionary.
The function applies an operation specified with the params to the specified Calendar.
If the operation succeeds, this function returns a null-value. Otherwise it returns an error code string.
The operation performed is specified with the opCode string element of the params dictionary:
"PUBLISH"
The function publishes an Event or a ToDo element in the Calendar. Other params elements:
data
an iCalendar element to place into the Calendar.
attachments
(optional) array containing the item attachments, each array element specified as an EMail part content.
If this element is not specified, and a calendaring item with the same UID already exists in the Calendar, then all attachments are copied from the existing item. To remove all attachments, specify an empty array.
sendRequests
this optional string element has the same meaning as the attribute of the XIMSS calendarPublish operation.
"CANCEL"
The function removes an Event or a ToDo element from the Calendar. Other params elements:
data
an iCalendar element to remove from the Calendar.
UID
this optional numeric element has the same meaning as the attribute of the XIMSS calendarCancel operation.
itemUID, sendRequests
these optional string elements have the same meanings as the attributes of the XIMSS calendarCancel operation.
recurrenceId
this optional timestamp element has the same meaning as the attribute of the XIMSS calendarCancel operation.
requestComment
this optional string element has the same meaning as the body element of the XIMSS calendarCancel operation.
"DECLINE"
The function rejects a calendaring item and sends a negative reply the item organizer. Other params elements:
data
an iCalendar element to decline.
sendReply
this optional string element has the same meaning as the attribute of the XIMSS calendarDecline operation.
replyComment
this optional string element has the same meaning as the body element of the XIMSS calendarDecline operation.

The calendarRef value can be a null-value. In this case, only a negative reply is generated.
"ACCEPT"
The function places a calendaring item into a Calendar and sends a positive reply the item organizer. The existing items(s) with the same UID are replaced. Other params elements:
data
an iCalendar element to accept.
attachments
this optional element has the same meaning here as for the PUBLISH operation code.
PARTSTAT, sendReply
these string elements have the same meaning as the attributes of the XIMSS calendarAccept operation.
replyComment
this optional string element has the same meaning as the body element of the XIMSS calendarAccept operation.
"UPDATE"
The function updates a calendaring item in a Calendar using a reply-type iCalendar object. This item specifies if a particular attendee has accepted or rejected the invitation. Other params elements:
data
an iCalendar "reply" element to use for updating.

File Storage

The following functions manage files and file directories in the current Account File Storage.
To access other Accounts File Storage, specify a file or folder name as a ~account[@domainName]/fileName string.

ReadStorageFile(fileDescr)
This function reads a File Storage file.
If the fileDescr value is a string, it specifies the name of the File Storage file to read. The entire file is read - and only files not larger than 1MB in size can be read this way.
If the fileDescr value is a dictionary, the following dictionary elements are used:
fileName
a string - the name of the file to read
position
an optional element. Its value should be a non-negative number, it specifies the file position (in bytes) from which reading should start.
limit
an optional element. Its value should be a non-negative number, it specifies the maximum data length to read (in bytes). If the file is shorter than starting position plus the read limit, a shorter datablock is read. This value should not exceed 1MB.

This function returns a datablock value with the file content, or a null-value if the specified file could not be read.
WriteStorageFile(fileDescr,data)
This function stores the data value (which should be either a datablock or a string) into the specified File Storage file.
If the fileDescr value is a string, it specifies the name of the file to write to. The entire file is rewritten.
If the fileDescr value is a dictionary, the following dictionary elements are used:
fileName
a string - the name of the file to write
position
an optional element. If present, the file is not completely rewritten.
If this element value is a non-negative number, it specifies the file position (in bytes) from which writing should start.
If this element value is the "end" or "append" string, the writing operation starts from the current file end.
If this element value is the "new" string, the writing operation checks that the file does not already exist.

This function returns a null-value if the file is successfully written, otherwise it returns a string with an error code.
AppendStorageFile(fileName,data)
This function appends the data datablock or string to the end of the fileName File Storage file.
If fileName is not a string or data is not a datablock nor it is a string, this function call results in a program exception.
This function returns a null-value if the file is successfully written, otherwise it returns a string with an error code.
DeleteStorageFile(fileName)
This function deletes the fileName File Storage file.
This function returns a null-value if the file is successfully deleted, otherwise it returns a string with an error code.
RenameStorageFile(oldFileName,newFileName)
This function renames the oldFileName File Storage file into newFileName. Both parameters must have string values.
This function returns a null-value if the file is successfully renamed, otherwise it returns a string with an error code.
CreateStorageDirectory(directoryName)
This function creates the directoryName File Storage directory.
This function returns a null-value if the directory is successfully created, otherwise it returns a string with an error code.
RenameStorageDirectory(oldDirectoryName,newDirectoryName)
This function renames the oldDirectoryName File Storage directory into newDirectoryName. Both parameters must have string values.
This function returns a null-value if the directory is successfully renamed, otherwise it returns a string with an error code.
DeleteStorageDirectory(directoryName)
This function deletes the directoryName File Storage directory. The directory should be empty.
This function returns a null-value if the directory is successfully deleted, otherwise it returns a string with an error code.
ListStorageFiles(folderName)
This function returns information about all files in the specified File Storage subdirectory.
If folderName is not a string, information about the top-level directory in the current Account File Storage is returned.
This function returns a null-value if an error occurred. Otherwise, the function returns a dictionary. Each dictionary key is a file or a subdirectory name, and the dictionary value is a dictionary with the following elements:
STFileSize
a numeric value with the file size in bytes. This element is present for files and absent for subdirectories.
STCreated
(optional) a timestamp value with the file creation date.
STModified
a timestamp value with the file modification date.
MetaModified
(optional) a timestamp value with the file or subdirectory attribute set modification date.
ReadStorageFileAttr(fileName,attributes)
This function reads attributes of the fileName File Storage file or file directory.
If fileName is not a string or attributes is neither an array nor a null-value, this function call results in a program exception.
The attributes value should be either a null-value (then all file attributes are retrieved), or an array of strings - then only the attributes with names included into the array are retrieved.
If attributes are successfully retrieved, this function returns an array of file attributes (each attribute is an XML object). Otherwise the function returns a string with an error code.
WriteStorageFileAttr(fileName,attributes)
This function modifies attributes of the fileName File Storage file or file directory.
If fileName is not a string or attributes is not an array, this function call results in a program exception.
The attributes value should be an array of XML objects. See the XIMSS section for more details.
This function returns a null-value if the attributes have been successfully updated, otherwise it returns a string with an error code.
LockStorageFile(fileName,params)
This function manages "locks" of the fileName File Storage file or file directory.
If fileName is not a string or params is not a dictionary, this function call results in a program exception.
The params value should be a dictionary with lock request parameters. See the XIMSS section for more details.
This function returns a dictionary if the operation has been completed successfully, otherwise it returns a string with an error code.

Roster

The following built-in functions implement an interface to the Account Roster.

ReadRoster()
ReadRoster(accountName)
This function retrieves Roster items.
If the the accountName parameter is not specified, or if its value is a null-value, the current Account Roster is read, otherwise the accountName value should be a string specifying the name of the Account to read Roster items from.
This function returns a dictionary with Roster items, where dictionary keys are contact E-mail addresses, and dictionary values are dictionaries with the following elements:
Inp
the "incoming" subscription mode: it controls if the contact can watch the user presence. Possible values: null-value, true-value, "Pending", "Blocked".
Out
the "outgoing" subscription mode: it controls if the user can watch the contact presence. Possible values: null-value, true-value, "Pending".
RealName
the contact real name string (optional).
If the function fails to retrieve Roster items, it returns an error code string.
SetRoster(params)
SetRoster(params,accountName)
This function updates a Roster item.
If the the accountName parameter is not specified, or it value is a null-value, the current Account Roster is updated, otherwise the accountName value should be a string specifying the name of the Account to update.
The params should be a dictionary with the following elements:
peer
The contact E-mail address string ("accountName@domainName").
what
The operation type string:
  • "update": update the contact information.
  • "remove": remove the contact from the Roster.
  • "subscribed": confirm the contact request to monitor the user's presence information.
  • "unsubscribed": reject the contact request to monitor the user's presence information, or revoke the already granted right to monitor.
  • "subscribe": send a request to monitor the contact's presence information.
  • "subBoth": confirm the contact request to monitor the user's presence information, and send a request to monitor the contact's presence information.
  • "unsubscribe": stop monitoring the contact's presence information.
data
optional - a dictionary containing new contact info.

Datasets

The following built-in functions implement an interface to the Account Datasets. To access Datasets in other Accounts, the dataset name should be specified as a "~accountName[@domainName]/datasetName" string.

DatasetList(datasetName,filterField,filterValue)
This function retrieves data entries from an Account dataset.
The datasetName value should be a string with the dataset name.
The filterField, filterValue values should be null-values or strings. If the values are strings, they specify an entry attribute name and value. Only the entries that have the specified attribute with the specified value are included into the resulting value.
This function returns a dictionary with dataset entries. The dictionary keys are entry names, the dictionary elements are data entries. Each data entry is a dictionary containing the data entry attributes.
If the dataset entries could not be retrieved, the function returns an error code string.
DatasetCreate(datasetName)
This function creates an Account dataset.
The datasetName value should be a string; it specifies the dataset name.
If the dataset is created successfully, the function returns a null-value. Otherwise the function returns an error code string.
DatasetRemove(datasetName,ifExists)
This function removes an Account dataset.
The datasetName value should be a string; it specifies the dataset name.
If the ifExists value is not a null-value, and the dataset to be removed already does not exist, the function does not return an error code.
If the dataset is removed successfully, the function returns a null-value. Otherwise the function returns an error code string.
DatasetSet(datasetName,entryName,entryData,ifExists)
This function modifies data entries in an Account dataset.
The datasetName value should be a string; it specifies the dataset name.
The entryName value should be a string; it specifies the entry name.
The entryData value should be a dictionary; it specifies the entry data (attributes).
If the ifExists value is a null-value, then the dataset is created if it does not exist, and the entry with the specified name is created if it does not exist.
If the dataset is updated successfully, the function returns a null-value. Otherwise the function returns an error code string.
DatasetDelete(datasetName,entryName,ifExists)
This function deletes a data entry from an Account dataset.
The datasetName value should be a string; it specifies the dataset name.
The entryName value should be a string; it specifies the entry name.
If the ifExists value is not a null-value, and the entry to be deleted already does not exist, the function does not return an error code.
If the dataset is removed successfully, the function returns a null-value. Otherwise the function returns an error code string.

Directory

The following built-in functions implement an interface to the Directory Manager.

DirectorySearch(baseDN,filter,parameters)
This function performs a directory search, returning a dictionary with found records.
The baseDN value should be a string with the search base DN. If this value is "$", the Directory Integration settings are used to compose the base DN for the current Domain.
The filter value should be a null-value, or a string with a search filter, in the RFC2254 format.
The parameters value should be a null-value or a dictionary containing search options:
limit
If this option value is a positive number, it specifies the maximum number of records to return. Otherwise, the record limit is set to 100.
keys
If this option value is "DN", the resulting dictionary keys are full record DNs. Otherwise, the record RDNs are used as resulting dictionary keys.
scope
If this option value is "sub", a subtree search is performed. Otherwise, only the direct children of the base DN record are searched.
attributes
If this option value is an array of strings, only the attributes listed in the array are included into resulting records.
Otherwise, all record attributes are included into resulting records.

If the directory search operation fails (no base DN record, insufficient access rights, etc.), this function returns an error code string.
DirectoryModify(theDN,newRDN,record)
This function performs a directory search, returning a dictionary with found records.
The theDN value should be a string with the record DN. If this value is "$", the Directory Integration settings are used to compose the base DN for the current Domain.
The newRDN value should be a null-value, or a string with a new relative DN for the record, where the record should be relocated.
The record value should be a null-value (then the record specified with theDN parameter is deleted) or a dictionary containing attributes for the record to be created.
If the directory modification operation fails (no base DN record, insufficient access rights, etc.), this function returns an error code string.

Services

GetLanguage()
This function value is a string with the currently "selected language".
SetLanguage(lang)
This procedure sets the "selected language". The lang value should be a string with the language name, or a null-value to select the default language.
GetTimeZoneName()
This function value is a string with the currently selected time zone name. If no time zone is selected (the Server time offset is used), the function returns a null-value.
SetTimeZone(zoneName)
This procedure sets the current time zone. The zoneName value should be a string with a known time zone name. If an unknown zone name is specified, or if the zoneName value is not a string, the no zone fictitious value is set, and the Server current time offset is used.
ReadEnvirFile(fileName)
This function retrieves the specified file from the current "environment" - such as the Real-Time Application environment.
This function value is a datablock with the file content or a null-value if the specified file does not exist.
ReadSkinObject(tagName)
ReadSkinObject(tagName,index)
ReadSkinObject(tagName,index,skinName)
This function retrieves the specified object from the specified WebUser skin's Text Dataset (or the Basic skin, if skinName is not specified). Object is specified by its tagName and index, where index can be either of:
null
the entire object is returned;
a string
used as the key when the object is a dictionary;
a number
used as the index when the object is an array or a dictionary;
an array
elements are sequentially used as keys or indices through the object hierarchy.
This function value is the object defined by the combination of tagName and index or a null-value if the specified object does not exist in the skin's Text Dataset.
SysLog(arg)
This procedure places the textual representation of the arg value into the Server Log.
SysProfile(arg)
If the arg value is a null-value, the procedure decreases an internal integer profile level counter by 1, otherwise it increases it by 1.
The profile level counter is set to zero when the program starts.
When the profile level counter is positive, profiling records are placed into the Server Log when every user-defined and some built-in functions and procedures are entered and exited.
ExecuteCLI(arg)
This function executes the Command Line Interface (CLI) command.
The arg value should be a string containing one CLI command.
If the CLI command has been executed successfully, this function returns a null-value. Otherwise this function returns an error code string.
If the CLI command has produced an output, it is placed into the Task variable executeCLIResult (it can be accessed as Vars().executeCLIResult.
If the CLI command has failed, or it has not produced any output, this Task variable is assigned a null-value.
SetApplicationStatus(arg)
This procedure copies its argument and stores is in the current Task descriptor.
External modules and entities can retrieve this information from the Task descriptor.
StoreCDR(arg)
This procedure sends the arg value (which should be a string) to the External CDR Processor program.
The "APP" prefix is added to the arg value, and the application is supposed to provide its name and the version number as the first part of the arg value to allow the External CDR Processor program to differentiate records generated with different applications:
APP arg
DoBalance(parameters,accountName)
This function performs a Billing operation.
If the accountName is null, the operation is applied to the current Account. Otherwise, the accountName value must be a string specifying the target Account name. In any case, the operation is subject to the Access Rights restrictions.
The parameters value must be a dictionary. It specifies the operation parameters, see the Billing section for the details. The operation name should be specified as the value of the dictionary key "op".
The function returns an error code string if the operation has failed.
Otherwise the function returns a dictionary with the operation results (as specified in the Billing section).
Statistics(elementName,opCode,setValue)
This function reads and updates the Server Statistics Element value.
The elementName value should be a string specifying either a Statistics Element OID, or a Custom Statistics Element name.
The setValue value should be a numeric value.
The opCode value should be a null-value or a string. If the string value is "inc", then the Element value is increased by the setValue value. If the string value is "set", then the Element value is set to the setValue value. If the value is a null-value, then the Element value is not modified.
Only the Custom Statistics Elements can be modified.
The function returns either a number - the current Statistics Element value, or an error code string.
CallHelper(name,parameters)
CallHelper(name,parameters,mode)
This function sends a request to an External Application Helper.
The name value should be a string specifying the Application Helper name.
The parameters value (application-specific) is passed to the Application Helper program.
The optional mode string is used to specify the cluster member that is used to run Application Helper program.
The function returns the data object from the External Application Helper response (it may return a null-value).
BannerRead(type,parameters)
This function sends a request to the External Banner System.
The type value should be a string specifying the banner type (application-specific, such as "prontoEmailTop", "myClientLeftBanner").
The parameters value is passed to the External Banner System.
The function returns the banner data object from the External Banner System response (it may return a null-value).
syncDelay(milliseconds)
This function blocks the execution of the script for the specified number of milliseconds.

Communications

HTTPCall(URL,parameters)
This function performs an HTTP transaction.
The current Account must have the HTTP Service enabled.
The URL value should be a string. It specifies the request URL.
The parameters value should be a dictionary. It specifies the request parameters and, optionally, the request body.
These values, along with the maximum time-out time of 30 seconds are passed to the HTTP Client module for processing.
This function returns either a result dictionary the HTTP module produced, or an error code string.
SubmitEMail(headers,content)
This function composes and sends an E-mail message.
The headers value should be a null-value or a dictionary. This dictionary specifies the header field values for the composed E-mail message. The following elements are processed (all of them are optional):
From
the element value should be an E-mail address string. It specifies the message From: address
To
the element value should be an E-mail address string or an array of E-mail address strings. It specifies the message To: address(es)
Cc
the element value should be an E-mail address string or an array of E-mail address strings. It specifies the message Cc: address(es)
Bcc
the element value should be an E-mail address string or an array of E-mail address strings. It specifies the message Bcc: address(es)
Subject
the element value should be a string. It specifies the message Subject: field.
Date
the element value should be a timestamp. It specifies the message Date: field. If this element is absent, the current time is used.
sourceType
the element value should be a string. It specifies the message source. If this element is absent, the "CGPL" string value is used.
sourceAddress
the element value should be a string. It specifies the address of the message source (network address, remote system name, etc.)
Message-ID
the element value should be a string. It specifies the message Message-ID: field. If this element is absent, an automatically generated string is used.
protocol
the element value should be a string. It specifies the name of the protocol used to submit this message.
Content-Class
the element value should be a string. It specifies the E-mail header Content-Class: field value.
X-Priority
the element value should be a string. It specifies the E-mail header X-Priority: field value.
X-Mailer
the element value should be a string. It specifies the message X-Mailer: field. If this element is absent, an automatically generated string is used.
The content value specifies the E-mail message body. If the value is a dictionary, then the dictionary body element is the actual content, and other dictionary elements specify various body parameters (content header fields). Otherwise the content itself is the actual content and the content body parameters set is an empty one.
The following content body parameters (dictionary elements) are processed (all of them are optional):
Content-Type
the element value should be a string. It specifies the content body Content-Type. If this element is not specified, the Content-Type is set to "text" if the actual content is a string, otherwise it the Content-Type is set to "application"
Content-Subtype
the element value should be a string. It specifies the content body Content-Type subtype. If this element is absent, and the Content-Type is set to "text", the Content-Subtype is set to "plain"
filename
the element value should be a string. It specifies the content body file name.
Content-Disposition
the element value should be a string. It specifies the content body Content-Disposition. If this element is absent, and the fileName element is present, the Content-Disposition value is set to "attachment"

If the actual content is a string, it is stored "as is", using the 8bit Content-Transfer-Encoding.
If the actual content is a datablock, it is stored using the base64 Content-Transfer-Encoding.
If the actual content is an array, the content is a multi-part one. Only the Content-Subtype parameter element is used, if it is absent, the "mixed" value is used.
Each array element is stored in the same way as the content value itself.
If the actual content is not an array, a string, or a datablock, an empty content body is stored.
This function returns a null-value if an E-mail message has been composed and sent (submitted to the Queue). Otherwise, this function returns an error code string.

In the following example, a simple text message is sent.

  headers = NewDictionary();
  headers.From    = "from@sender.dom";
  headers.Subject = "Test Message";
  headers.To      = "To@recipient.dom";
  result  = SubmitEmail(headers,"Test Message Body\eEnd Of Message\e");

In the following example, a multipart/mixed message is sent. It contains an HTML text and a binary attachment.

  content = NewArray();

  textPart = NewDictionary();
  textPart.("Content-Type") = "text";
  textPart.("Content-Subtype") = "html";
  textPart.body = "<HTML><BODY>This is an <B>HTML</B> text</BODY></HTML>";
  content[0] = textPart;

  dataPart = NewDictionary();
  dataPart.("Content-Type")    = "image";
  dataPart.("Content-Subtype") = "gif";
  dataPart.fileName = "file.gif";
  dataPart.body     = ReadStorageFile(dataPart.fileName);
  content[1] = dataPart;

  headers = NewDictionary();
  headers.From    = "from@sender.dom";
  headers.Subject = "Test Attachment";
  headers.To      = "To@recipient.dom";
  headers.("Content-Class") = "message";

  result = SubmitEMail(headers,content);

It is possible to include parts of other E-mail messages into a newly composed one. If there is a content body parameter MIMEPartID with a string value, then there must be a content body parameter source with a Message Handle value.
If the MIMEPartID parameter value is "message", the entire source Message is copied (as a message/rfc822 MIME part body).
If the MIMEPartID parameter value is any other string, it specifies the MIME part of the source Message to be copied into the new message; when copying the part headers, only the MIME (Content-xxxxxx) fields are copied.

  content = NewArray();

  textPart = NewDictionary();
  textPart.("Content-Type")    = "text";
  textPart.("Content-Subtype") = "plain";
  textPart.body = "Please see the attached letter.\e";
  content[0] = textPart;

  attachPart = NewDictionary();
  attachPart.("source")    = MyOldMessage;
  attachPart.("MIMEPartID") = "message";
  content[1] = dataPart;

  headers = NewDictionary();
  headers.From    = "from@sender.dom";
  headers.Subject = "Test Forwarded message";
  headers.To      = "To@recipient.dom";
  headers.("Content-Class") = "message";

  result = SubmitEMail(headers,content);
SendEMail(fromAddress,subject,to,headers,content)
This function composes and sends an E-mail message. A call to this function does the same as the SubmitEMail(headers,content) function call, where the fromAddress, subject, and to value (if they are not null-values) are used instead of the headers dictionary From,Subject, and To elements.

In the following example, a simple text message is sent.

  result = SendEmail("from@sender.dom","Test Message","To@recipient.dom",
                      null,"Test Message\eEnd Of Message\e");
SendInstantMessage(fromAddress,toAddress,content)
This function sends an Instant Message.
The fromAddress value should be a string or a null-value. It specifies the message From (sender) address.
If this value is a null-value, then the sender address is the current Account address.
If this value is a string, but it does not contain a @ symbol, the sender address is the current Account address, and this value is used as the sender "instance" name.
If this value contains a @ symbol, it can also specify the sender "instance" name, as in "user@domain/instance" string.
The toAddress value should be a string. It specifies the message To (recipient) address.
It must contain the @ symbol and it can specify the recipient "instance" name, as in "user@domain/instance" string.
The content value should be a string or a dictionary. If the value is a string, it specifies the message content. If the value is a dictionary, it can contain the following elements:
"" (empty string)
this optional element should be a string - the instant message body.
type
this optional element should be a string - the instant message XMPP-style type - "chat", "groupchat", etc.
id
this optional element should be an string - it specifies the IM request "id" attribute.
suppl
this optional element should be an array of XML objects to be sent inside the instant message.
IMSubject
this optional element should be a string - the instant message subject.
IMState
if this optional element is present, the "" (body), IMSubject and suppl elements should not be used. This element should be one of the strings "gone", "composing", "paused", "active", and informs the recipient about the sender intentions.

The function only initiates an Instant Message signaling operation, it does not wait for the message delivery operation to complete.
This function returns a null-value if an Instant Message has been composed and sent (submitted to the Signal component). Otherwise, this function returns an error code string.
SendXMPPIQ(fromAddress,toAddress,content)
This function sends an XMPP-style IQ request or a presence request.
The fromAddress and toAddress values have the same meaning as for the SendInstantMessage function.
The content value should be a dictionary with the following elements:
type
this element should be a string - "get", "set", "result", etc. To send a presence request, this element should be "cgp_presence".
suppl
this element should be an array of XML objects to be sent inside the IQ request.
id
this element should be an string - it specifies the IQ request "id" attribute. This element is not used for presence requests.
opcode
this element should be an string, it is used for presence requests only. It specifies the presence request "type" attribute value, such as "unavailable".
status
this element should be an string, it is used for presence requests only. It specifies the presence state, such as "online", "busy", etc.

The function only initiates an signaling operation, it does not wait for the operation to complete.
This function returns a null-value if a request has been composed and sent (submitted to the Signal component). Otherwise, this function returns an error code string.
RADIUSCall(address,parameters)
This function composes and sends a RADIUS request.
The address value should be an ip-address. It specifies the address and the port of the RADIUS server to send the request to.
The parameters value should be a dictionary with the following elements:
Type
this element should be a string. It specifies the type of RADIUS request to send:
"authenticate", "accountingStart", "accountingUpdate", "accountingStop".
Secret
this element should be a string. It specifies the "shared secret" of the RADIUS server.
Username
this element should be a string. It is used to compose the userName (1) request attribute.
Password
this element should exist in the authenticate requests, and it should be a string. It contains the clear text password to use in the authentication operation.
nn (where nn is a decimal number)
these elements specify additional request attributes (by their attribute numbers).
These element values should be strings, or (for the integer-type parameters) - numbers, or (for Internet-type parameters) ip-addresses.
If an element value is a datablock, then the content of the datablock is sent without any encoding.
If an element value is an array, then the request attribute is added to the request zero or more times, once for each array value.
-nnnnn (where nnnnn is a decimal number)
these elements specify additional vendor-specific attributes (where nnnnn is the VendorID). See the RADIUS section to see more on the vendor-specific attribute presentation.
Error
if this optional element value is "data", and a denied-response is received for an authentication request, the function returns a response attribute dictionary (see below) with an additional Error element.
If this optional element value is not "data", and a denied-response is received for an authentication request, the function returns an error string.
Retries
this optional element should be a number or a numeric string in the [1..20] range. It overrides the default limit of request resends. Set this element to 1 if you want the RADIUS request to be sent only once.
Timeout
this optional element should be a number or a numeric string in the [0..30] range. It overrides the default timeout value (in seconds). When a response is not received within the specified time, the request is resent or an error message is produced.

If the RADIUS operation succeeds, this function returns a dictionary. This dictionary contains attributes the RADIUS server sent in its response. If the RADIUS fails, this function returns a string with an error code.
Note: requests are sent using the UDP socket of the RADIUS module, so this module should be enabled (it should be configured to use some non-zero port number).

In the following example, a RADIUS authentication request is sent. The request contains the nasIdentifier (32) text attribute.

callParam = newDictionary();
callParam.Type     = "authenticate";
callParam.Secret   = "sys2";
callParam.Username = "user4567";
callParam.Password = "drum$1245";
callParam.("32")   = "my NAS";
result = RADIUSCall(IPAddress("[10.0.1.77]:1812"),callParam);

In the following example, a RADIUS accounting request is sent. The request contains the nasIdentifier (32) text attribute and the acctSessionTime (46) numeric attribute.

callParam = newDictionary();
callParam.Type     = "accountingStart";
callParam.Secret   = "sys2";
callParam.Username = "user4567";
callParam.("32")   = "my NAS";
callParam.("46")   = SessionTimeInMinites*60;
result = RADIUSCall(IPAddress("[10.0.1.77]:1812"),callParam);

Synchronous Scripts

CG/PL code sections can be used for immediate synchronous operation and their code can be shared between different environments. Such a code should be stored in files with the extension .scgp, its external modules should be store in files with the extension .scgi in the Basic Skin environment.

A synchronous script takes an object as a parameter, which is accessible through the startParameter key in the Vars() dictionary, and returns an object as a result. The execution time-out is 5 minutes. CG/PL programs that implement both Real-Time Applications and Web Applications can use the same shared synchronous scripts code.

RunScript(scriptName)
RunScript(scriptName,paramObj)
RunScript(scriptName,paramObj,entryName)
This function is used to run a script synchronously.
The scriptName value should be a string with the script name with the optional .scgp suffix.
The paramObj is the optional parameter with any CG/PL object.
The entryName is the optional parameter with the name of the entry point. The entry point main is used if this parameter is omitted.
This function returns an object constructed by the synchronous script.
If there is a problem with running the specified script the function returns null.
SetResult(object)
This procedure is used to set result of synchronous script execution.
The object parameter will be passed as the result of the RunScript function.

Multitasking

Certain environments (such as Real-Time Application environments) provide multitasking functionality. In these environments, program invocations (Tasks) can locate each other and exchange data. This section defines the additional language features available in these multitasking environments.

Task handles are internal objects representing a Task. In a Cluster environment, a Task handler includes a reference to the cluster member running the Task.

Spawning

A program (a running Task) can create a new Task by using the spawning expression. It is specified using the spawn keyword followed by a name of an entry code section. A new Task is created and it starts to run concurrently with the Task that used the spawning expression, executing the specified entry code section.
The entry code section name can be followed with an expression enclosed in parentheses. If specified, the copy of the expression value is assigned to the startParameter element of the Vars() dictionary (global variables) in the new Task.
The current Task handle is assigned to the parent element of the Vars() dictionary in the new Task.
The spawning expression value is a Task handle for the newly created Task, or null if the system failed to create a new Task.

In the following example, a program executing the Main entry code section creates a new task that starts to execute the DoBackup entry code section, which copies files "file1","file2",...."file100" into "backup1","backup2",..., files.

entry DoBackup is
  nameIndex = 1;
  while nameIndex <= 100 loop
    fileData = ReadStorageFile("file" + String(nameIndex));
    if fileData != null then
      resultCode = WriteStorageFile("backup" + String(nameIndex),fileData);
      if resultCode != null then
        Log("failed to backup file" + String(nameIndex) +
            ". Error Code=" + resultCode);
      end if;
    end if;
  end loop;
end entry;
 
entry Main is
  backuper = spawn DoBackup;
  if backuper == null then
    Log("Failed to start a Backup Task");
  end if;
end entry;

Tasks do not share any variables, even when a Task directly creates a new Task using the spawning expression.

ThisTask()
This function returns the Task handle of the current Task.
This function returns a null value if the current environment is not a Task.
IsTask(arg)
This function returns a true-value if the arg value is a Task Handle, otherwise the function returns a null-value.

Events

The Actor Model is used: Tasks exchange data by sending each other Events.

SendEvent(taskRef,eventName)
SendEvent(taskRef,eventName,eventParam)
This function sends an Event to a Task. It returns a null value if an Event was sent successfully, or a string with an error code otherwise (for example, when the specified Task does not exist).
The taskRef value should be a Task handle.
The eventName value should be a string starting with a Latin letter.
The optional eventParam parameter value should be a null-value, or a Task handle, or a "basic" object.
This function only sends an Event to the specified (target) Task. It does not wait till that Task receives an event, nor does it wait for any response from the target Task.
ReadInput(secsToWait)
Events sent to a task are enqueued, and the task can read the first Event in queue using this function. The function value is a dictionary containing the event data.
The secsToWait value should be a non-negative number.
If the Task Event queue is empty and the Task does not receive a new Event within the specified number of seconds, the function returns a null-value.
If this function returns a dictionary value, the dictionary contains the following elements:
what
the Event name string. If the Event was sent using the SendEvent operation, this string is the eventName parameter value used in the SendEvent call in the sender Task.
sender
the Task handle of the sender Task (the Task that has sent this event). In a Cluster environment, this Task and the current Task may be running on different Cluster member computers.
If the Event is sent by the platform itself, or if the sender was not a Task, the sender element does not exist.
parameter
the event parameter. If the event was sent using the SendEvent operation in the sender Task, this element contains the eventParam parameter value of the SendEvent call.
Note: depending on the environment, the ReadInput function can return various other objects. For example, if the function is used in a Real-Time Application environment, it can return a string containing the first enqueued DTMF symbol.
Note: the ReadInput function may have "false wakeups", i.e. it can return the null-object even before the specified time period has elapsed.

Meetings

The Meeting mechanism allows a Task to make itself known to other Tasks associated with the same Account.

Each Account can have several named Meeting Sets and an unnamed Default Meeting Set. Several named Meetings can be created in any Meeting Set. Each Meeting is a dictionary object that can contain zero or one Task handle.

The set name can be specified as a "~accountName[@domainName]/setName" string to access Meetings Sets in other Accounts.
To access Meeting Sets in other Accounts, the current Account should have the canImpersonate Domain Access Right for the target Account Domain.

CreateMeeting(setName,key)
CreateMeeting(setName,key,parameter)
This function creates a Meeting object in some Meeting Set within the current Account.
The setName parameter specifies the Meeting set name. If its value is a null-value or an empty string, the Default Meeting Set is used.
The key parameter must be a string. It specifies a unique ID or name for the new Meeting. For example, an application implementing real-time conferencing can generate a random numeric string to be used as the conference password, and it can create a Meeting using that string. Other Tasks associated with the same Account can find that Meeting (and a Task handle for the Task associated with it) if they know the key and the setName parameter values used with the CreateMeeting operation.
If the parameter parameter is specified and its value is not a null-value, that value is stored with the Meeting. Note that the value is stored using its textual representation, so only the standard objects can be used as the parameter values or the parameter value sub-elements. For example, you cannot store Mailbox or Task handles.
This function returns a null-value if a Meeting has been created. Otherwise, this function returns an error code string.
ActivateMeeting(setName,key)
ActivateMeeting(setName,key,parameter)
This function adds the Task handle for the current Task to a Meeting in the current Account.
The setName and key parameter values specify an already created Meeting.
There should be no other Task handle stored in this Meeting.
The current Task becomes the Meeting Active Task.
The optional parameter parameter value is stored with the Meeting.
This function returns a null-value if the Task handle has been successfully added. Otherwise, this function returns an error code string.
DeactivateMeeting(setName,key)
DeactivateMeeting(setName,key,parameter)
This function removes Task handle for the current Task from a Meeting in the current Account.
The setName and key parameter values specify an already created Meeting, and that Meeting should contain a Task handle for the current Task.
The optional parameter parameter value is stored with the Meeting.
When this operation completes successfully, the Meeting has no Active Task.
This function returns a null-value if the Task handle has been successfully removed. Otherwise, this function returns an error code string.
RemoveMeeting(setName,key)
This function removes a Meeting from a current Account Meeting Set.
The setName and key parameter values specify the Meeting to remove.
This function returns a null-value if the Meeting has been successfully removed or if the specified Meeting has not been found. Otherwise, this function returns an error code string.
FindMeeting(setName,key)
This function retrieves Meeting information from a current Account Meeting Set.
The setName and key parameter values specify the Meeting to look for.
If the Account does not have the specified Meeting, the function returns null.
Otherwise, the function returns the Meeting information dictionary containing the following elements:
parameter
the value of the parameter parameter used with the CreateMeeting operation.
id
a Task handle for the Active Task, if any.
In a Cluster environment, the Active Task and the current Task may be running on different Cluster member computers.
ClearMeeting(setName,key)
This function removes a Task handle from a Meeting (if any).
The setName and key parameter values specify the Meeting to clear.
This function can be used to clear a reference set by a Task that has died.
This function returns a null-value if the Meeting has been successfully cleared. Otherwise, this function returns an error code string.

Queues

The Queue mechanism allows a Task to make itself known to other Tasks associated with the same Account. When a Task registered in a Queue is found by some other Task, the found Task is removed from the Queue.

The queue name can be specified as a "~accountName[@domainName]/queueName" string to access Queues in other Accounts.
To access Queues in other Accounts, the current Account should have the canImpersonate Domain Access Right for the target Account Domain.

Enqueue(queueName)
Enqueue(queueName,parameter)
Enqueue(queueName,parameter,pty)
This function registers the current Task with the Account associated with it.
An Account may have several Queues with Task registrations.
The queueName parameter specifies the Queue name. If this parameter value is a null-value or an empty string, the default Queue of the associated Account is used.
The optional parameter parameter value is stored with the Task registration. Note that the value is stored using its textual representation, so only the standard objects can be used as the parameter values or the parameter value sub-elements. For example, you cannot store Mailbox or Task handles.
The optional pty parameter value should be a string containing a decimal number with one digit, the dot (.) symbol and any number of digits. The Task is placed in the Queue before all other Tasks with a smaller pty parameter value, but after all tasks with the same or larger pty parameter value.
If the pty parameter is not specified, or if its value is a null-string, the default "1.0" value is assumed.
A Task may register itself several times in different Queues, but it can be registered only once with any given Queue. If the Enqueue function is used by a Task that has been already enqueued into the same Queue, the function does not create a second registration. Instead, the function updates the parameter value enqueued with the Task and may change the Task position in the Queue according to the new pty parameter value.
The function returns a null-value if registration has failed. If registration was successful, the function returns a dictionary containing the following elements:
length
a number - the total number of Tasks in the Queue
position
a number - the current position of the current Tasks in the Queue.
The position of the first Task in the Queue is 0
CheckQueue(queueName)
This function checks the current Task position in an Account Queue.
The queueName parameter specifies the Queue name.
The function returns a null-value if it has failed to access the specified Queue. Otherwise, it returns the same dictionary as the Enqueue function.
Note: the position element exists in the returned dictionary only if the current Task is currently enqueued into the specified Queue. If current Task was not enqueued, or if it has been already removed from the Queue by some other task, this elements will be absent.
Dequeue(queueName)
This procedure removes the current Task from the Account Queue.
The queueName parameter specifies the Queue name.
ReadQueue(queueName)
This function retrieves the first Task from the Account Queue.
The queueName parameter specifies the Queue name.
The function returns a null-value if there is no Tasks in the specified Queue.
Otherwise, the function returns a dictionary containing the following elements:
id
the Task handle for the retrieved Task. In a Cluster environment, this Task and the current Task may be running on different Cluster member computers
parameter
the value of the parameter parameter used when the Task was enqueued
Note: this function removes the first Task from the Queue. Unless the retrieved Task re-enqueues itself into the same Queue, no other Task will find it in that Queue.

Formal Syntax

string::="string-data"
number::=digits
name ::=alpha-numeric-and-underscore-starting-with-alpha
variable::=name
codeName::=name | name :: name
varDeclaration::=var name 0*(, name)
varValueDeclaration::=var name [= expr] 0*(, name [= expr] )
dataRef::=variable | expr [ expr ] | expr . name | expr . ( expr )
constDeclaration::=const name = constExpr 0*(, name = constExpr)
constExpr::=string | number | null | false | true
spawnExpr::=spawn name [ ( expr ) ]
basicExpr::=constExpr | dataRef | expr . name ( [argList] ) | spawnExpr
unaryOp::=! | not | - | +
unary::=basicExpr | unaryOp unary | ( expr )
multOp::=* | / | %
multBinary::=unary | multBinary multOp unary
addOp::=+ | -
addBinary::=multBinary | addBinary addOp multBinary
cmpOp::=< | <= | == | != | >= | >
cmpBinary::=addBinary | cmpBinary cmpOp addBinary
logicOp::=& | and | | | or | && | and then | || | or else
logicBinary::=cmpBinary | logicBinary logOp cmpBinary
ternary::=logicBinary | logicBinary ? logicBinary : ternary
expr::=ternary
argList::=expr 0*(, expr)
funcCall::=codeName ( [argList] )
procCall::=codeName ( [argList] ) | expr . name ( [argList] )
letOp::== | += | -= | *= | /= | %= | |= | &=
letOper::=dataRef letOp expr
nullOper::=| null
stopOper::=stop
returnOper::=return [ expr ]
ifOper::=if expr then opSequence 0*( elif expr then opSequence ) [ else opSequence ] end [ if ]
altIfOper::=if expr { opSequence } 0*( elif expr { opSequence } ) [ else { opSequence } ]
loopInitOp::=letOp | varValueDeclaration
loopPreamble::=while expr | for [ loopInitOp ] [while expr ] [ by letOp ]
altLoopPreamble::=while expr | for ( [ loopInitOp ] ; [ expr ] ; [ letOp ] )
loopOper::=[ loopPreamble ]loop opSequence 0*( exitif expr ; opSequence) end [ loop ]
altLoopOper::=altLoopPreamble { opSequence 0*( exitif expr ; opSequence) }
oper::=nullOper | procCall | letOper | returnOper | stopOper | ifOper | loopOper | varValueDeclaration
altOper::=altIfOper | altLoopOper
seqOper::=oper ; | altOper
opSequence::=0*( seqOper )
entryBody::=forward ; | is opSequence end [ entry ] ; | { opSequence }
procBody::=forward ; | external ; | is opSequence end [ procedure ] ; | { opSequence }
funcBody::=forward ; | external ; | is opSequence end [ function ] ; | { opSequence }
parmList::=name 0*(, name)
entry::=entry name entryBody
procedure::=procedure codeName ( [ paramlist] ) procBody
function::=function codeName ( [ paramlist] ) funcBody
program::=1*(entry | procedure | function | varDeclaration | constDeclaration)

CommuniGate Pro Guide. Copyright © 2024, AO SBK