Sysquake Remote Tutorial

Here are commented examples of SQR files for Sysquake Remote. You can also find them in the directory "examples".

magic.sqr

For this first example, we shall begin with a very simplified document without HTML formatting. An improved version with a nice HTML table will also be proposed.

Simplified version

magic.sqr computes and displays in a table a 5-by-5 magic square using function magic.

The beginning of the SQR file is plain HTML, without anything special, including the tag which begin raw output, <pre>.

<html>
<head>
<title>Sysquake Remote - Basic Output</title>
</head>
<body>
<h1>Sysquake Remote - Basic Output</h1>
<pre>

For computing the magic square and inserting element values in the cells of the array, we insert executable code between the special tags <?sqr and ?>. This block of code is executed on the server, and only its output (what is produced by disp and expressions which do not end with a semicolon, fprintf to stdout and similar functions, and error messages if Sysquake Remote has been configured to display them) is inserted in the HTML code and sent to the client.

Here, we simply display the magic square computed with magic.

<?sqr
disp(magic(5));
?>

The ?> tag resumes the output of plain HTML. Depending on your license, you may have to include the Sysquake Remote banner with function banner, which must be enclosed in a block of executable code to be interpreted by Sysquake Remote.

<pre>
<?sqr banner ?>
</body>
</html>

Magic square in an HTML table

The beginning of the SQR file is plain HTML, without anything special, including the tags which begin the table.

<html>
<head>
<title>Magic square with formatted output</title>
</head>
<body bgcolor="#cccccc">
<h1>Magic square with formatted output</h1>

<table border="1" bgcolor="white">

Like in the previous example, computing the magic square is performed in an SQR code fragment with the magic function. However, instead of displaying immediately its value, we store it in a variable named M.

<?sqr
M = magic(5);

Then we have a loop for formatting matrix rows.

for i = 1:size(M, 1)

Each row is delimited with <tr> and </tr> tags. Since we are in executable code, we must use one of the output functions of Sysquake Remote. Here we use fprintf.

    fprintf('<tr>');

Then we use a single fprintf statement for the whole row. The format string is reused as many times as necessary, which is its normal mode of operation.

    fprintf('<td align="center">%d</td>', M(i, :));

The remaining SQR code outputs the end tag for the row and terminates the loop.

    fprintf('</tr>\n');
end

The ?> tag resumes the output of plain HTML.

?>
</table>

The end of the SQR file is the same as in the first example.

<?sqr banner ?>
</body>
</html>

Histogram

This new example will permit us to introduce several two important features: graphics and user input. An histogram of a set of normally-distributed pseudo-random numbers generated with randn is displayed as a bar plot.

Graphics

The SQR file begins like any HTML file, until the SQR code fragment.

<html>
<head>
<title>Sysquake Remote - Image</title>
</head>
<body>
<h1>Histogram</h1>
<?sqr

In the code fragment, we set variable xs to a row vector of 1000 random numbers. Then we use function hist to get an histogram, i.e. the numbers of values in some intervals. hist is defined in library stdlib, which might be imported in all SQR files if Sysquake Remote has been configured so. But as a precaution, we import it explicitly with the use command.

use stdlib;
xs = randn(1, 20000);
(n, x) = hist(xs, -5:0.5:5);

To display the histogram, we use function bar. For simple graphics, nothing more is required.

bar(x, n);

The end of the SQR file is similar to the one of previous examples.

?>
<?sqr banner ?>
</body>
</html>

Sysquake Remote generates a temporary image file on the server hard disk and inserts the HTML code required to embed it. Every time the client reloads the SQR file, a new sequence of random numbers is generated, giving a slightly different plot.

Compound graphics

When more than a single graphical command is used to produce a single image, these commands must be enclosed between a pair of beginfigure/endfigure commands. Otherwise, a different image would be created for each command. As an example, we add a line which shows the theoretical probability density. In the previous example, the line bar(x,n) is replaced with

beginfigure;
bar(x, n);
plot(-5:0.1:5, 20000 * 0.5 * pdf('normal', -5:0.1:5), 'c');
endfigure;

User input

User input can be provided in two different ways: in form controls (text fields, menus, check boxes, radio buttons or plain buttons), or as mouse clicks in images. We will first consider the first case, by adding two text fields to specify the number of random numbers (samples) and the number of intervals for the histogram and a check box to enbale or disable the display of the probability density function.

Rather than writing manually the code of the HTML form and using low-level Sysquake Remote functions to access data sent by the user, we will the high-level functions defined in library sqr. There are two functions which both use descriptions of the form, of the data, and of the relationship between both: displayhtmlform to produce the HTML code, and processhtmlform to obtain the user input. These two functions permit to decide exactly where in the SQR file these actions are performed, or even to split them into two different SQR files.

In our case, we will use them in the same SQR file: form elements are placed below the histogram, and submitting new data retrieves the same page again with an updated histogram and the form elements filled with the new values. In order to have these values before the histogram is created, processhtmlform must be placed at the beginning. If the page is displayed for the first time, just by entering its URL or following a link from another page, default values are used. displayhtmlform will be placed below the figure.

The first argument of processhtmlform and displayhtmlform is a format string, similar to fprintf's. We want two numbers and a checkbox with some labels on the same line, followed by a line with a Reset and a Submit buttons. The string, which we store in a variable because we use it in two functions, is

format = ['Number of samples: %n\n', ...
          'Number of intervals: %n\n', ...
          '%c Probability density function\n', ...
          '%R %S'];

We use brackets to split the declaration into several lines, but the result is a plain string. (The SQR code fragment we begin here will replace the one of the previous example; see below for the complete SQR file.)

Each variable element corresponds to a field in a structure. The structure is used as input to provide default values, and as output to retrieve values. Since elements of structures are orderless, we need an explicit mapping, provided as a list of field names:

fnames = {'nsamples', 'nintervals', 'pdfdisplay'};

The last argument is a structure which contains the default values:

val.nsamples = 20000;
val.nintervals = 20;
val.pdfdisplay = true;

processhtmlform uses these default values if no data has been posted from the client (typically the first time the page is displayed), or if some field weren't found in the posted data (in case the client forges data). It returns a new structure with the same fields; the contents of fields found in the posted data are updated. Since we do not need the initial default values, we reuse the same variable as input and output.

val = processhtmlform(format, fnames, val);

Then we can use the fields of val in the computation of the histogram (we use linspace to generate the intervals):

xs = randn(1, val.nsamples);
intervals = linspace(-5, 5, val.nintervals);
width = intervals(2) - intervals(1);
(n, x) = hist(xs, intervals);
beginfigure;
bar(x, n);
if val.pdfdisplay
  plot(-5:0.1:5, val.nsamples * width * pdf('normal', -5:0.1:5), 'c');
end
endfigure;

Below the figure, we display the form with the last values submitted by the user, which correspond to what is displayed in the figure.

displayhtmlform(format, fnames, val);

The whole SQR file is

<html>
<head>
<title>Histogram</title>
</head>
<body>
<h1>Histogram</h1>
<?sqr
use stdlib, sqr;
format = ['Number of samples: %n\n', ...
          'Number of intervals: %n\n', ...
          '%c Probability density function\n', ...
          '%R %S'];
fnames = {'nsamples', 'nintervals', 'pdfdisplay'};
val.nsamples = 20000;
val.nintervals = 20;
val.pdfdisplay = true;
val = processhtmlform(format, fnames, val);
xs = randn(1, val.nsamples);
intervals = linspace(-5, 5, val.nintervals);
width = intervals(2) - intervals(1);
(n, x) = hist(xs, intervals);
beginfigure;
bar(x, n);
if val.pdfdisplay
  plot(-5:0.1:5, val.nsamples * width * pdf('normal', -5:0.1:5), 'c');
end
endfigure;
displayhtmlform(format, fnames, val);
banner;
?>
</body>
</html>

Clickable image

By adding option 'kind' with value 'interactive' to beginfigure, the same page is requested again when the user clicks it and the position of the click can be retrieved with getclick. getclick gives a structure whose fields x and y contain the position of the click, in figure coordinates (pixel coordinates provided by the client are converted automatically by Sysquake Remote). If the user has not clicked the image, these fields are not defined, which can be tested with function isfield.

We make now the histogram example display the numerical value of the probability distribution function for the x value clicked by the user.

The line beginfigure; is replaced with

beginfigure('kind', 'interactive');

Below the line endfigure; (but like processhtmlform, we could place it anywhere in the SQR file), we add the following code:

click = getclick;
if isfield(click, 'x')
  fprintf('<p>Probability density function at x=%g: %g</p>', ...
          click.x, pdf('normal', click.x));
end

command.sqr

Sysquake Remote can be used to execute arbitrary commands which are submitted by the client. While this could be insecure if all functions were available, function sandbox executes commands in an environment where potentially dangerous commands are disabled. These commands include those which access files (such as fopen), the network, the shell, and the debugger.

The beginning of the SQR file needs no explanations.

<html>
<head>
<title>Sysquake Remote - Remote Commands</title>
</head>
<body>
<h1> Sysquake Remote - Remote Commands </h1>

Code evaluated by sandbox can import functions from libraries with the use command, but it may be more convenient to do it in the SQR file.

<?sqr
use stdlib, stat, constants, classes, lti;

We have seen how forms can be managed with the high-level functions displayhtmlform and processhtmlform. Here, to demonstrate an alternative, we shall use the lower-level httpvars function, which gives the contents of all form elements in a structure. Fields of the structure have the same name as those specified in the HTML form. Commands are written in a form element of type textarea, whose name is cmd. The first time the SQR page is loaded, no data have been submitted by the user; httpvars gives an empty structure. In the statements below, we try to get field cmd anyway; if this fails, we catch the error in a try/catch block and set variable cmd to a default value, the empty string.

try
  cmd = deblank(httpvars.cmd);
catch
  cmd = '';
end
?>

The form with the textarea element which permits the user to enter commands is made of standard HTML tags. The initial contents of the textarea element is the value of variable cmd, i.e. either empty the first time the page is loaded, or the previous commands which the user can edit and submit again. fprintf is used to insert the value of cmd, whose character which have a special meaning in HTML (<>&") are converted with htmlspecialchars.

<form method="post">
  <table>
    <tr><td>
      <textarea rows="8" cols="70" name="cmd">
        <?sqr fprintf('%s',htmlspecialchars(cmd)); ?>
      </textarea>
    </td></tr>
    <tr><td align="right">
      <input type="reset" value="Revert">
      <input type="submit" value="Execute">
    </td></tr>
  </table>
</form>

The evaluation of commands is done directly at the place where we want the results to appear. We enclose the results in a <pre> tag, so that formatting is preserved. Graphics, if any, will also be displayed.

<h2>Result</h2>

<pre>
<?sqr
sandbox(cmd)
?>
</pre>

The end of the SQR file is similar to what we have already seen.

<hr>
<?sqr banner ?>
</body>
</html>

Variables as input and output

To predefine variables which could be used by the commands submitted by the client, you can prepend code to define them in front of them. We shall modify the SQR file to request from a student to enter the code which computes the mean of a vector a. First, we create a column vector with 5 random values between 0 and 10, and we display it.

<?sqr
x = 10 * rand(5, 1);
dumpvar('x', x);
?>

Instead of evaluating only what the client has entered, we prepend the variable definition, and we retrieve all the variables which are defined in structure var.

<pre>
<?sqr
var = sandbox([dumpvar('x', x), cmd]);
?>
</pre>

Fields of var correspond to variables, so we can expect a field var.m and compare it to the mean of x. If the command is empty, we do not display anything. The following code does it.

<?sqr
if cmd ~== ''
  try
    m = var.m;
    if m === mean(x)
      ?>
      <p>The mean is correct.</p>
      <?sqr
    else
      ?>
      <p>Variable <samp>m</samp> is not equal
        to the mean of <samp>x</samp>.</p>
      <?sqr
    end
  catch
    ?>
    <p>Variable <samp>m</samp> is not defined.</p>
    <?sqr
  end
end
?>

An interesting thing to note is the mixing of LME and HTML code: programming structures such as if and try can span several fragments of LME code.


Copyright 2002-2008, Calerga.
All rights reserved.