473,396 Members | 1,738 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ


Miva Script Variables

By Ed Bradburn
Information Officer, NISS

G. Variables

Variables in Miva have the following characteristics:

The last point deserves some explanation. Miva variables have four scopes, depending on whether they are GLOBAL, SYSTEM, DATABASE or LOCAL variables. System variables are set by either a system variables file, Miva built-in variables (time & date or CGI process variables mostly) or some kinds of Miva tags (e.g. MvSMTP, the mail tag); database variables occur when a database has been opened, and last until the database is closed; local variables can be defined with the prefix 'l' inside a miva function (MvFUNCTION). Here is a short example which uses all four, and which will be used in the following pages to illustrate other Miva variables features.

<MVCOMMENT>
Database needs to be created first, ignore for now!
</MVCOMMENT>

<MVCREATE NAME="database" DATABASE="test.dbf"
FIELDS="version CHAR(10)">
<MVASSIGN NAME="database.d.version" VALUE="three">
<MVADD>
<MVCLOSE>

<P>A short Miva script demonstrating variable scope.
<P>Version is &[version].
<MVASSIGN NAME="g.version" VALUE="one">
<P>Version is now &[g.version].
<MVOPEN NAME="database" DATABASE="test.dbf">
<P>Version is now &[database.d.version].
<MVEVAL EXPR="{checkversion()}">
<MVCLOSE NAME="database">
<P>The value of system.version always called when 'version'
is prefixless: &[version].

<MVFUNCTION NAME="checkversion">
<MVASSIGN NAME="l.version" VALUE="two">
<P>Version is &[l.version].
</MVFUNCTION>

The above script will return four different values:

A short Miva script demonstrating variable scope.

Version is 3.5719. Version is now one.

Version is now three.

Version is two.

The value of system.version always called when 'version' is prefixless: 3.5719.

This is because:

This script also illustrates the order in which the scoping is checked for prefixless variables: SYSTEM,LOCAL,DATABASE,GLOBAL. This means that if a system variable 'version' exists, then no other variable assignation will apply unless the prefix is used. Equally, if there was no system variable set, and no prefixes were used,

<MVCREATE NAME="database" DATABASE="test.dbf" FIELDS="var CHAR(10)">
<MVASSIGN NAME="var" VALUE="three">
<MVADD>
<MVCLOSE>

<P>A short Miva script demonstrating variable scope.
<P>var is &[var].
<MVASSIGN NAME="var" VALUE="one">
<P>var is now &[var].
<MVOPEN NAME="database" DATABASE="test.dbf">
<P>var is now &[var].
<MVEVAL EXPR="{checkvar()}">
<MVCLOSE NAME="database">
<P>The value of system var always called when 'var' is
prefixless: &[var].

<MVFUNCTION NAME="checkvar">
<MVASSIGN NAME="var" VALUE="two">
<P>var is &[var].
</MVFUNCTION>

then the output would be as follows:

A short Miva script demonstrating variable scope.

var is .

var is now one.

var is now three.

var is two.

The value of system var always called when 'var' is prefixless: one.

Note that there is no system variable called 'var' present now, so the first value is blank. Then 'var' applies in turn to:

It can be seen from this that whilst such use of scoping can make scripts very elegant, it can be rather difficult to keep track of scope in such scripts since remembering which variables might be available in which form at any given point can be tricky. Understanding scoping is, needless to say, a key feature of using Miva variables appropriately, and 9 times out of 10 and unexpected variable result can be resolved by checking the scoping in force at that point!

H. Displaying variables

As the above example demonstrates, Miva supports a simple enough way of placing variables in the output sent to the browser: placing &[] around the variable concerned. Thus:

<MVASSIGN NAME="Ed">
<P>Hello, my name is &[name].

will send:

<P>Hello my name is Ed.

to the browser, which will in turn display:

Hello my name is Ed.

However, this is not the only way of displaying variables, and a bit of background on this explains why in certain circumstances this is not the method that must be used.

The structure '&[]' is actually an in-built Miva macro function, and is an implementation of the XML structure readers will be familiar with in uses such as & where this will display '&' in browsers which understand this code. Thus not only does '&[]' work for showing the value of 'name' but also '&[name];'. Now, since Miva is merely displaying the value, rather like a browser simply displays '&' without interpreting it (like it would a TABLE tag for example), there is the problem that if the value is in some way problematic - for example it contains HTML code itself, typed into a FORM field by an unscrupulous user - then it should not be simply displayed but evaluated.

Evaluation is carried out by using the <MVEVAL> tag, as follows:

<MVASSIGN NAME="fruit" VALUE="banana">
<MVASSIGN NAME="banana" VALUE="\"yellow, like the sun\"">
<P><MVEVAL EXPR="{'<P>' $ fruit $ ' is ' $ &[fruit]}">

Which displays:

banana is "yellow, like the sun"

Here, the EVAL tag has evaluated:

Although one cannot 'nest' it further (i.e. &[&[fruit]] returns an error), this is a powerful construct for displaying variables and creating self-generating code. One last point is that variables which may contain double quotes are safely evaluated by MVEVAL, whereas &[] would return an error. (Note however that " marks do need to be escaped (using the \ mark, as conventionally) when assigned literally, as above.)

I. Program inputs & outputs

Miva has a number of input paths which can be used to make data available to the script. They are:

Equally, Miva can output to all these inputs, returning data to:

Moreover, whilst Miva has no execute command (see the Install notes for how Miva is sandboxed with respect to the rest of the system), it can include a script within another script and then run all, or parts, of it, and likewise can include HTML pages in scripts and display them before continuing. This makes it the perfect tool for websites built around templates, a simple example being:

<MVDO FILE="welcome_&[language].html">

where 'language' has been chosen (perhaps in a drop-down form) by a user before loading this page.

With respect to the other inputs/outputs listed above, it is worth noting that not only are databases handled easily - as will be explained in Section M - but flat text files are also handled well, as an example using the full syntax shows:

<MVIMPORT FILE="myfile.txt" FIELDS="age,height,sex" DELIMITER="|" FILTER="{age GT 20}">
<MVASSIGN NAME="recordsfound" VALUE="{recordsfound + 1}">
<MVIF EXPR="{recordsfound GT 10}">
<MVIMPORTSTOP>
<MVELSE>
<P>Age is &[age].
</MVIF>
</MVIMPORT>

Note that:

The equivalent 'opposite' tag, MVEXPORT, has the same syntax, and writes sequential lines to a file. (Note that to overwrite the file each time would require deleting the old one first, since MVEXPORT appends lines to the end of the existing file.)

Whilst databases are the best way to keep data in Miva, the use of simple text files for, e.g, logging (even conditional logging) is made very easy by these two tags.

The last input method to note is the MVCALL tag, which obtains data by emulating an HTTP 1.0 browser. Although this does not allow the acquiring of Javascript-returned values from a web page containing Javascript, it is perfect for obtaining whole pages or parts thereof, and manipulating them for various purposes. Here, for example, is an MVCALL script which grabs a system-generated web stats page and only returns a certain part of it:

<MVCALL ACTION="http://www.server.com/webstats/index.html" METHOD="GET">
<MVIF EXPR="{callobjectelement EQ 'img'}">
<MVIF EXPR="{terminate}">
&[on]
</td></tr></table>
&[off]
<MVCALLSTOP>
</MVIF>
<MVASSIGN NAME="callvalue" VALUE="{glosub(callvalue,
callobjectvalue1, ('/webstats/' $ callobjectvalue1))}">
<MVASSIGN NAME="terminate" VALUE="1">
</MVIF>
<MVIF EXPR="{display OR (callobjectelement EQ 'p')}">
&[on]
<MVEVAL EXPR="{callvalue}">
<MVASSIGN NAME="display" VALUE="1">
&[off]
<MVELSE>
</MVIF>
</MVCALL>

Although some of the syntax used here is beyond the scope of this introduction to Miva, the basic idea is easy enough to see. MVCALL mimics an HTTP 1.0 browser, and successively 'calls' the HTML page in question, breaking it up into discrete tags which can be dealt with separately (each tag is one iteration of the MVCALL loop) - in this case the HTML page is treated so that only a portion of the original more complex stats page is sent to the browser by this script.

J. Control structures

Miva has three main control structures: the LOOP, the ability to DO (i.e. include), and the FUNCTION.

Looping is basic but utilitarian, giving the scriptor an IF/ELSE construction, a WHILE construction, loops for MVCALLing as we have already seen, and loops are also provided for MVIMPORT and MVEXPORT, which read or write lines to text files. Nesting is supported to a level that can set by the user, although the default is 23 - more than enough for most eventualities.

Including files couldn't be easier - if they are plain HTML then one can simply issue a command such as: <MVDO FILE="my.html"> and the file will be inserted at the current point in the script 'as is'. Alternatively, the file can be a Miva script itself, in which case it is run from the current point in the script, and can make full use of the current stock of variables in the scope in which it is being run. This powerful facility allows Miva to be modularised, and it is common to have library scripts which might index databases, or set up conditional variables, query web pages, or any one of a hundred other repetitive actions.

Miva's most powerful feature, and one that is required for the MVDO to work in the first place, is the function, which sets aside a piece of code from the main script in order for it to be called as necessary. Common to almost all scripting languages, the function in Miva can be called either internally or externally (via an MVDO command, which can be 'pointed' to just one function in the while external script), and, like most languages, can have variables that are local to it, whilst making use of any global, system or database variables that are available depending on the particular scope at the point at which it is run. It is even possible to have conditional functions. Here is an example of a brief piece of code which might be used on a bilingual site, where the same script is run, but from different URLs. This code will then run an appropriate function to set up variables for the next part of the script to use:

<MVASSIGN NAME="country" VALUE="{gettoken(documenturl,'.',3)}">
<MVEVAL EXPR="{&[country]()}">

<MVFUNCTION NAME="fr">
<P>Bienvenue!</P>
</MVFUNCTION>

<MVFUNCTION NAME="de">
<P>Wilkommen!</P>
</MVFUNCTION>

Here, the URL has been analysed to see what is the last element, and this is then run as a function, i.e. the second line of the code translates to:

<MVEVAL EXPR="{de()}">
or
<MVEVAL EXPR="{fr()}">

depending on what URL the script is being accessed from.

K. Built-in functions

Note also above the function I used which was not declared: gettoken().

Miva has a host of useful built-in functions, giving the user quick ways to access date and time data (e.g. timezone() to return the current timezone), manipulate strings (e.g. tolower() to perform basic lowercase conversion), produce random numbers (especially the useful makesessionid() which generates a unique 128-bit string), and a whole host of other useful tasks.

« Miva Script Part 1 Miva Script Part 3 »

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.