The Inferno Internet Explorer Plug-in
John Bates, Vita Nuova.
December 2000.
Introduction
This document provides an overview of the first (preliminary) release
of Vita Nuova's Internet Explorer plug-in.
The plug-in is designed to allow the controlled execution of
compiled Limbo programs (Dis modules) within Microsoft
Internet Explorer using a secure Inferno sandbox.
Dis modules may be referenced from within a web page
and are automatically fetched and executed from the Internet.
A module interacts with a user through the web page.
Unsigned (untrusted) modules are run in a namespace that
provides them with no access to the network (local or remote),
or access to any of the local devices. A richer namespace may
be composed for signed (trusted) modules.
The plug-in enables a web page to utilise the full range of
Inferno authentication and security mechanisms to provide
mutual authentication, message authentication and message encryption
when connecting to any kind of service on the Internet, not just to
other web pages.
A network conversation can be secured against modification alone
or against both modification and snooping.
To secure against modification, a secure MD5 hash or SHA hash
can be appended to each message.
To secure against snooping, encryption of the complete conversation
can be performed using RC4, IDEA or DES
with either DES chain block coding (DESCBC)
or electronic code book (DESECB).
If you are not already familiar with Inferno and Limbo you can use the online
manual pages
at Vita Nuova's web site to
provide some of the background. Printed and bound manuals
which describe all of the function and system calls available
to Dis modules and a collection of papers, including Dennis Ritchie's
"Limbo Reference Manual", are also available from the same site.
The Inferno Internet Explorer plug-in allows a Limbo program
to run inside a web page when displayed by Microsoft Internet
Explorer 4 or 5.
The plug-in executes Dis within a sandbox in the
Inferno Dis virtual machine which provides the execution
environment for all programs running under the Inferno
Operating System. In this preliminary release, only unsigned
modules are handled and so an
application has no access to the network and
no access to devices on the local machine.
The filespace visible to a program run by the plugin is the
contents of a read-only KFS filesystem combined with a writeable
RAM filesystem for temporary storage.
We are currently working on a the security issues and the
consequent relaxation of these restrictions. The second release
of the plug-in will allow network connections and controlled
access to other devices with the introduction of signed Dis modules.
Plug-in applications are compiled into Dis bytecode and can
either be interpreted by the Dis virtual machine or compiled on-the-fly into
native machine code. The application can be developed and debugged
on any system that currently runs Inferno (including Linux,
Solaris, Plan 9, Windows or native Inferno systems and,
now, also including Internet Explorer itself).
A web page references the Dis executable which is fetched
on demand from the Internet and stored in Internet Explorer's
cache. The next time the page is viewed, unless it has been purged,
the file will be retrieved from the local cache.
The plug-in contains several builtin modules, which provide a variety
of functionality including: file access, basic I/O, namespace manipulation,
formatted output, exception handling, basic character and string manipulation,
basic graphics facilities, image and font handling, rectangular geometric
operations, a complete Tk implementation based on Ousterhout's Tcl/Tk,
elementary functions of applied mathematics, a floating point environment
and authentication and security related operations.
The entire plug-in
including a minimal filesystem and the complete Inferno Dis virtual
machine is contained in a download which occupies 719 Kbytes.
Examples
Click here to see an example of
an Inferno plug-in running in an Internet Explorer web page.
The example shows a ticker-tape display which is the output
of the Limbo program ticker.b.
The compiled program, ticker.dis (1462 bytes in size), is
automatically downloaded from the web page and run in the Inferno sandbox.
The next time you visit the web page, unless files in the browser cache have been
deleted, the page and the Dis module will be picked up locally and so no downloading
will occur.
Click here to see a more interactive module.
This is a port to Limbo of the Eliza and psychotherapist classic.
The module runs an interactive session with the user in a text window
on the web page.
A scroll bar enables the browsing of earlier discussion.
Writing a Module
To create a module that can be embedded in a web page
you should follow the following sequence of steps:
- Install the free Inferno download
- You can fetch a free copy of Inferno for Nt,
Linux, Plan 9 or Solaris from the Vita Nuova
website.
The download contains a complete development environment that
can be used to edit, compile, debug and check
your module before placing it in a web page.
- Write the module in Limbo
- Create your Limbo program using any editor and save it to
a file with a .b suffix.
The download contains many examples of Limbo programs,
a set of manual pages that document the functions in each
of the builtin modules, and some editing tools including
the Acme development environment.
- Compile the module
- Use the Limbo compiler to compile your Limbo program
to a portable Dis module. Dis modules conventionally have a
.dis suffix.
- Add an <OBJECT> tag to your web page
- Refer to the Dis module with an OBJECT tag that you
include in the HTML on your web page. The tag contains information
that the browser can use to find and run the module.
- Place the web page and Dis module on your web site
- The Dis module should be placed on the web site so that it can be
delivered by your web server when requested by a browser.
In this preliminary release the module will only run from Internet Explorer.
We plan to announce soon a plug-in for Netscape navigator that will
allow the same module to run, unaltered, from both popular browsers.
More information anout the Limbo programming language and how to embed
a Dis module in a web page are given later in this document.
Limbo
Plug-in modules are written in Limbo, a language that is instantly
familiar to any C programmer. Limbo has the same
expression syntax and flow control as C but in addition is
strongly typed, provides automatic garbage collection, supports
a restricted form of pointer and compiles into machine independent
byte-code for execution on a virtual machine. Unlike C, Limbo is
a concurrent programming language (and unlike Java, concurrency
is built in to the language, applying the results of research done since the 1970s.)
A Limbo program is a set of one or more modules that communicate to
perform a task. Programs are type-checked at compile time and further
when modules are loaded.
Limbo has the numeric types byte (unsigned, 8bits),
int (signed, 32 bits), big (signed, 64 bits) and
real (IEEE long float, 64 bits) with the size and signedness the same
on every virtual machine. Character constants are expressed as in C using
single quotes and can include the same set of escapes such as `\n` but the
characters are themselves Unicode and have type int.
Limbo also provides a Unicode string type, arrays of arbitrary types,
lists of arbitrary types, tuples, abstract data types (adts, which
are like a C struct but may contain function members as well as
data members), reference types and typed channels (chans) for
passing objects between processes.
Statements and control flow in Limbo are similar to those in C.
A statement is an expression followed by a semicolon,
or a sequence of statements enclosed in braces.
The similar control flow statements are:
if (expr) statement
if (expr) statement else statement
while (expr) statement
for (expr; expr; expr) statement
do statement while (expr) ;
return expr ;
exit ;
The
exit
statement terminates a process and frees its resources.
There is also a
case
statement analogous to C's
switch
which also supports string and range tests.
A
break
or
continue
followed by a label
causes a break out of, or the next iteration of, the enclosing
construct that is labeled with the same label.
Comments begin with
#
and extend to the end of the line.
There is no preprocessor, but an
include
statement can be used to include source code, usually module declaration files.
Limbo provides most of the C operators, but not ? : or the 'comma'
(sequential execution) operator.
Arrays and strings may be sliced, and passed around as first class types and strings
may be concatenated with the + and += operators.
The operator := combines the declaration of a variable and the assignment
of a value to it. The type of the variable on the left of the := is given
by the type of the expression on the right.
New processes are created with the spawn statement which creates
a separate process by calling a specified function. The process has its own stack
but shares memory with the process that spawned it. Synchronisation between
processes is handled by channels. A channel may be passed as an
argument to the spawned function and used to provide communication and
synchronisation between the two processes.
The operator <-= writes an expression to a channel; the operator
=<- reads from a channel and assignes to a variable. Channels are
unbuffered and so a writing process will block until another process reads from the
same channel this provides convenient synchronisation.
A good introduction to Limbo programming can be found in Brian Kernighan's
A Descent into Limbo on the Vita Nuova web site.
A more complete treatment of the language is available in Dennis Ritchie's
reference manual
The Limbo Programming Language at the same location.
A module can be developed and tested using the free Inferno download
available from the Vita Nuova website
on Linux, Windows, Plan 9, FreeBSD and Solaris. The download contains
the Limbo compiler and the source code for many Limbo modules
ranging from familiar Unix utilities through to more complex applications
such as the Charon web-browser. Indeed, it is possible (although not
necessarily very useful) to run the Charon web browser as a module
inside a plug-in window in an Internet Explorer web page!
Embedding Modules in a Web Page
Modules are written in Limbo and then compiled with the Limbo compiler
to produce machine independent Dis bytecode.
Modules can be run on any installation of Inferno, and from a web page
without recompilation - the Dis module is completely portable between
any of the Windows Nt, Linux, Solaris, Internet Explorer, Plan 9 or other
Inferno platforms.
To host a module in a web page, the HTML on the web page must contain
at least the following components:
- an <OBJECT>
tag that provides the class ID of the Inferno plug-in,
- an init <PARAM> tag containing the name of the module to run, and
- one or more file <PARAM> tags for each file the program
needs to access from the internet.
The ticker page contains the following <OBJECT> and
<PARAM> tags:
<OBJECT
classid="clsid:C0316421-4BE6-11d3-A893-004095E0A888"
codebase="http://www.vitanuova.com/plugin/ieplugin.cab"
width=500 height=80
>
<PARAM name="init" value="ticker.dis">
<PARAM name="file1" value="ticker.dis http://www.vitanuova.com/inferno/pi/ticker/ticker.dis">
</OBJECT>
The <OBJECT> tag contains a classid attribute
that gives the class ID that is unique to the Inferno
plug-in and width and height attributes
for the size of the area
(in pixels) on the web page
that the plug-in will occupy. All three of these attributes are required.
The Inferno Internet Explorer plug-in is always uniquely identified
by the class ID: C0316421-4BE6-11d3-A893-004095E0A888
To ensure that the Inferno plug-in is installed an
<OBJECT> tag should also contain a codebase attribute:
codebase="http://www.vitanuova.com/plugin/ieplugin.cab"
The URL in the codebase attribute gives the location of a CAB
file containing the plug-in.
The codebase attribute can also contain version information.
codebase="http://www.vitanuova.com/plugin/ieplugin.cab#Version=1,0,0,1"
If the plug-in has not yet been installed, or if it has been installed but the installed
version is earlier than the version specified in the codebase attribute the
plug-in will be downloaded and installed from the given URL.
If an <OBJECT> tag contains a codebase attribute
in which all the version digits are minus one:
codebase="http://www.vitanuova.com/plugin/ieplugin.cab#Version=-1,-1,-1,-1"
the plug-in will be downloaded from the given URL if its release date
is later than the installation date on the computer. If the plug-in has already
been installed and the release date is the same as or earlier than the
installation date, only an HTTP header transaction will occur.
This technique insures that the latest version of the plug-in is installed,
but at the cost and delay of an Internet access to date stamps each time
the plug-in is used.
If you omit the version information altogether, the browser simply checks for
the presence of the plug-in.
In practice it is probably best to include the codebase attribute
in each <OBJECT> tag without version information
to ensure that the user has the plug-in, even if not necessarily the latest version.
Additionally, hspace and vspace attributes
can be used to define a margin, in pixels, around the visible area
and a title text string may be supplied that Internet Explorer
will use to identify the space occupied by the browser when the cursor
hovers above it:
<OBJECT
classid="clsid:C0316421-4BE6-11d3-A893-004095E0A888"
codebase="http://www.vitanuova.com/plugin/ieplugin.cab"
width=500 height=80
vspace=50 hspace=50
title="Inferno Ticker"
>
<PARAM name="init" value="ticker.dis">
<PARAM name="file1" value="ticker.dis http://www.vitanuova.com/inferno/pi/ticker/ticker.dis">
</OBJECT>
In this example ticker.dis is executed by the plug-in once it has
been downloaded from the Vita Nuova website and if the plug-in has not been
installed it will be retrieved from the same web site.
How the Browser Initialises a Module
When the browser discovers the <OBJECT> tag
in a web page it examines it to find a classid
attribute. It uses the class ID to check the Windows registry
to find the location of the plug-in in the Windows filesystem.
If the plug-in has been installed it loads it and initialises it.
If there is no corresponding entry in the registry for the class ID
it uses the codebase attribute to download a
CAB format file from the Internet. The CAB file contains
the plug-in and instructions to the browser that enable it to install
it. The browser will confirm that the user wishes to install
the plug-in before following the instructions. Once installed,
the plug-in is loaded and initialised.
On initialisation, the plug-in invokes the Dis module emuinit.dis
found in the plug-in installation directory:
-
...\Program Files\Vita Nuova\Inferno\Plug-in
In turn, this module constructs a namespace by opening
the file plugin.kfs which contains an initial filesystem image
and mounting it (read-only) at the root of the, initially empty, namespace.
It then creates a small RAM filesystem and binds this over the top
of the empty directory /usr/internet as writeable and creates
a new subdirectory /usr/internet/tmp which it then
binds over the top of the /tmp directory.
The startup module changes directory to /usr/internet which
will become the home directory of the downloaded plug-in module.
As a result, files created by a
plug-in module in its home directory or /tmp
will appear in the RAM filesystem and files in
the KFS filesystem will be readable but not writeable to the module.
The startup code then binds the Inferno server registry into
/chan, the prog filesystem into /prog
and the console devices and graphics draw device into /dev
before calling sys->pctl(Sys->NODEVS, nil) to ensure that
a plug-in module has no further access to devices. This basic namespace
is the sandbox in which a plug-in Dis module will run.
Once the namespace has been constructed, the files named for
downloading in the HTML file are requested from the plug-in
and are placed in the home directory (/usr/internet).
The plug-in recognises <PARAM> tags with the consecutive
names:
file1, file2, ... filen.
The first word of the value attribute of these tags determines
the name the file will be given, once downloaded. The rest of the
value attribute string is a URL giving the Internet
location of the file to download.
The <PARAM> tag with name init has a value string
that determines the Dis module to invoke at startup.
The first word in the string is assumed to be the name of a Dis module
to invoke, the remainder of the string is passed to the module
as an argument list.
A web page is likely to contain at least one <PARAM> tag to name
the Dis file that needs to be downloaded and executed.
In the ticker example the following tags were required:
<PARAM name="init" value="ticker.dis">
<PARAM name="file1" value="ticker.dis http://www.vitanuova.com/inferno/pi/ticker/ticker.dis">
In that example, only one file was downloaded from the internet
and the same file was executed by
the virtual machine once the sandbox had been constructed
by the plug-in.
Fetching Files
Most web pages that include a Dis module are likely to download at least one
file from the Internet - the module to run.
The web page containing the ticker module was an example of
such a page, only a single file was downloaded -
ticker.dis.
A look at the source code for ticker.b shows that it
accesses a font file, unicode.8.font:
-
FONTPATH : con "/fonts/pelm/unicode.8.font";
...
font := Font.open(disp, FONTPATH);
and loads two modules:
-
sys = load Sys Sys->PATH;
draw = load Draw Draw->PATH;
The font file is included in the plugin.kfs filesystem that
the startup code mounts as read-only when constructing the sandbox,
the complete set of fonts being:
-
/fonts/pelm/unicode.8.font
/fonts/lucidasans/unicode.8.font
/fonts/lucidasans/unicode.7.font
The Sys and Draw modules are builtin to the
plug-in. Detail of the builtin modules are given elsewhere in this document.
An example of a web page that uses the plug-in and downloads more than
one file is the
polyhedra
example on the Vita Nuova web site.
The polyhedra example downloads three files:
the polyhedra Dis module, a polyhedra database and a shell script to manipulate
the namespace before starting the polyhedra module.
The polyhedra database is 361 Kbytes in size and may take a little while to
download depending upon the speed of your Internet connection.
The HTML page for the polyhedra example contains the following code:
<PARAM name="init" value="pi/wm sh polywrap">
<PARAM name="file1" value="tmp/polyhedra http://www.vitanuova.com/inferno/pi/polyhedra/polyhedra">
<PARAM name="file2" value="polywrap http://www.vitanuova.com/inferno/pi/polyhedra/polywrap">
<PARAM name="file3" value="polyhedra.dis http://www.vitanuova.com/inferno/pi/polyhedra/polyhedra.dis">
The init parameter arranges that the wm window manager
invokes the inferno shell, sh, which in turn runs the shell script,
polywrap, which looks like this:
-
#!/dis/sh
# Wrapper for polyhedra, which looks for its data file in /lib
bind -a tmp /lib
polyhedra.dis
The polyhedra module expects to find its database in the directory /lib,
it is downloaded to a writeable directory (in this case tmp) which
is then bound over the top of the /lib before polyhedra is started.
Starting the Module
The module that is started by the plug-in has /usr/internet as its
current directory.
The init <PARAM> tag contains the name of the
module that the plug-in will run. The first word is assumed to be the
name of a Dis module that must either be found in the current directory
or else in the /dis directory. Files and modules loaded from the Internet
are placed in the current directory unless
given a relative path in their file <PARAM> tag.
The second and subsequent words in the init <PARAM> tag
are passed to the command as arguments.
If the HTML on the web page contains
a compile <PARAM> tag
with a value of 1:
<PARAM name="compile" value="1">
The plug-in will invoke a JIT compiler to compile each Dis module to
native x86 code before running it, otherwise the default behaviour
is for the code to be interpreted by the virtual machine.
A compiled module will run faster than an interpreted
module.
You can force a module to invoke the JIT compiler
by compiling it from Limbo with the -c flag to the Limbo compiler:
limbo -c module.b
You can prevent a module from invoking the JIT compiler,
even if the compile <PARAM> tag has been
given a value of 1 in the web page,
by compiling it from
Limbo with the -C flag to the Limbo compiler:
limbo -C module.b
Once started, a module can load other modules with the load
statement and launch new threads of execution with the spawn
statement.
Builtin Modules
Certain modules are built in to the plug-in. Although they function as if
loaded from Dis files they are actually implemented in C, inside the Inferno kernel.
Such modules are known as builtin modules.
The plug-in contains a set of builtin modules. The modules are accessed,
as for ordinary modules,
through a module reference to them obtained by loading them
with a load statement:
-
ref = load Mod Mod->PATH
For example,
-
sys = load Sys Sys->PATH;
math = load Math Math->PATH;
draw = load Draw Draw->PATH;
The complete set of builtin modules is:
- Sys
- Inferno system calls are provided by the built-in module
declared by sys.m. It contains the fundamental system data
structures and interfaces. There are currently 39 calls,
providing: file access; basic I/O; name space manipulation;
formatted output for Limbo; exception handling; and basic
character and string manipulation. See sys-intro(2).
- Draw
- The Draw module provides basic graphics facilities,
defining drawing contexts, images, character fonts, and
rectangular geometric operations. See the Tk module
and Prefab module
for higher level operations, such as windows and menu handling.
See draw-intro(2).
- Tk
- The Tk module provides primitives for building user
interfaces, based on Ousterhout's Tcl/TK. The interface to
the toolkit itself is primarily the passing of strings to
and from the elements of the toolkit using the cmd function;
Section 9
of the Inferno manual contains information about the
syntax of those strings. See also tk(2).
- Prefab
- The Prefab module contains components for building graphics
objects suitable for Interactive Television (ITV)
applications using infrared remote controls. Using the Draw
module's operations for simple text and images
the toolkit can group individual items,
treat those groups as units, and then activate the items on
command. See
prefab-intro(2),
prefab-compound(2),
prefab-element(2),
prefab-environ(2),
prefab-style(2).
- Math
- Inferno's math(2)
module and the Limbo compiler provide the
fundamental floating point environment and ``elementary
functions'' of applied mathematics.
- Srv
- The Srv module provides an interface to the
the Internet name resolution services of the host operating system,
in this case, Windows.
- Keyring
- This module contains a mixed set of functions that variously:
The builtin modules provide enough functionality to perform many useful
tasks.
Most applications are likely to make use of the Sys module.
Applications that write directly to the display may use the services of the
Draw module. Modules that interact with the user through the
Tk interface will need to use the Tk module.
Environment Wrappers
Some modules require direct access to the display.
Such modules establish their own connection to the
display and write directly on the display using the services of the Draw
module.
Other console-style modules, may simply expect
to read from standard input and write to standard output. Another kind
of module may use the services of Tk, or expect to be running under the
Inferno window manager Wm.
To accomodate all these different kinds of module,
the plug-in KFS filesystem, plugin.kfs contains some module wrappers
that enable a program to operate under these different environments.
The Hello World examples in this document illustrate
the use of these wrappers.
The wrapper pi/text provides an environment that supports
an Inferno Tk console application. A module running under this wrapper
can read and write from standard input and output and is displayed
in a window with a Tk scroll bar to allow the review of earlier interaction.
The wrapper pi/wm
provides an environment that supports an Inferno Tk application that expects
to run under the Inferno Wm window manager, and provides an
implementation of wmlib(2), with certain default behaviours.
An application started with pi/wm will be given a window
sized to match the plug-in area in the web page. It will not
have a titlebar and so cannot be moved or minimised.
If it needs the full functionality of Wm it should be
started under the control of the program wm/wm
which is included in the plugin.kfs KFS filesystem.
Hello World Examples
These examples, although not particularly useful, illustrate some of
the mechanisms for producing output with a plug-in module.
They include applications that write directly to the display using the
Draw module, output to a scrollable console window,
and use the Tk sub-system.
An example is also given of using the an Inferno shell script
to control output. A shell script can be embedded in an HTML page
and interpreted by the Inferno shell.
Drawing to the Display
The most direct method to produce output from a plug-in module
is to draw directly to the display.
The Limbo code in the file hellod.b uses the Draw
module to display the text Hello World to the screen:
-
implement Hello;
include "sys.m";
include "draw.m";
Hello: module
{
init: fn(ctxt: ref Draw->Context, argv: list of string);
};
init(nil: ref Draw->Context, nil: list of string)
{
draw := load Draw Draw->PATH;
Display, Font, Image, Black: import draw;
disp := draw->Display.allocate(nil);
image := disp.image;
hue := disp.color(Black);
font := Font.open(disp, "*default*");
image.text((5,5), hue, (0,0), font, "Hello World");
<- chan of int; # wait forever
}
The receive from a new chan of int on the last line
will never complete and prevents the program from exiting.
The program, hellod.b is compiled with the Limbo
compiler to produce hellod.dis using:
limbo hellod.b
The resulting Dis module occupies 348 bytes.
The HTML fragment used to launch this module would look like this:
-
<OBJECT
classid="clsid:C0316421-4BE6-11d3-A893-004095E0A888"
codebase="http://www.vitanuova.com/plugin/ieplugin.cab"
width=500 height=80
>
<PARAM name="init" value="hellod.dis">
<PARAM name="file1" value="hellod.dis http://www.vitanuova.com/inferno/pidoc/intro/hellod.dis">
</OBJECT>
Click here to download and run this module (size 348 bytes).
Writing to Standard Output
A simpler way to display the same text and demonstrating the use of the
pi/text wrapper is demonstrated by
helloc.b. This uses the print
function from the Sys module to write the string
"Hello World" to standard output. Invoking the module with the
pi/text wrapper arranges that it will be run in a console
window and that standard output will appear in that window.
The Eliza example, shown earlier, uses standard input and output
and so employs this wrapper for the same effect.
-
implement Hello;
include "sys.m";
include "draw.m";
Hello: module
{
init: fn(ctxt: ref Draw->Context, argv: list of string);
};
init(nil: ref Draw->Context, nil: list of string)
{
sys := load Sys Sys->PATH;
sys->print("Hello World\n");
<- chan of int;
}
In this example, the print function from the Sys
module is used to put the message "Hello World" to standard output
and the receive from a channel on the last line stops the program from
exiting, as before. The program, helloc.b,
is compiled with the Limbo compiler:
limbo helloc.b
to produce the output helloc.dis which has size 120 bytes.
The HTML fragment used to launch helloc.dis
needs to use the text wrapper pi/text and so would look like this:
-
<OBJECT
classid="clsid:C0316421-4BE6-11d3-A893-004095E0A888"
codebase="http://www.vitanuova.com/plugin/ieplugin.cab"
width=500 height=80
>
<PARAM name="init" value="pi/text helloc.dis">
<PARAM name="file1" value="helloc.dis http://www.vitanuova.com/inferno/pidoc/intro/helloc.dis">
</OBJECT>
Click here to download and run this module (size 120 bytes).
Using Limbo/Tk
The Limbo code in the file hellow.b
uses Tk and the
pi/wm wrapper to display a Hello World button
in an area on the web page.
-
implement Hello;
include "sys.m";
include "draw.m";
include "tk.m";
include "wmlib.m";
Hello: module
{
init: fn(ctxt: ref Draw->Context, argv: list of string);
};
init(ctxt: ref Draw->Context, nil: list of string)
{
wmlib := load Wmlib Wmlib->PATH;
wmlib->init();
(top, nil) := wmlib->titlebar(ctxt.screen, nil, nil, 0);
cmds := array[] of {
"button .b -text {Hello World}",
"pack .b",
"update"
};
wmlib->tkcmds(top, cmds);
<- chan of int;
}
In this example, the titlebar function from the Wmlib
module gives us a Tk Toplevel, sized for the web page display
area, to which we can apply
Tk commands. The function tkcmds, conveniently, takes
an array of such commands which are applied in sequence.
The program, hellow.b,
is compiled with the Limbo compiler:
limbo hellow.b
to produce the output hellow.dis which has size 291 bytes.
The HTML fragment used to launch hellow.dis
needs to use the Wm wrapper pi/wm and so would look like this:
-
<OBJECT
classid="clsid:C0316421-4BE6-11d3-A893-004095E0A888"
codebase="http://www.vitanuova.com/plugin/ieplugin.cab"
width=200 height=50
>
<PARAM name="init" value="pi/wm hellow.dis">
<PARAM name="file1" value="hellow.dis http://www.vitanuova.com/inferno/pidoc/intro/hellow.dis">
</OBJECT>
Click here to download and run this module (size 291 bytes).
Using Echo
The module echo.dis is part of the plug-in KFS filesystem,
plugin.kfs and can be invoked from a web page without
downloading any Dis modules like so:
-
<OBJECT
classid="clsid:C0316421-4BE6-11d3-A893-004095E0A888"
codebase="http://www.vitanuova.com/plugin/ieplugin.cab"
width=500 height=80
>
<PARAM name="init" value="pi/text echo hello world">
</OBJECT>
Click here to download and run this module.
Using the Inferno Shell
A script for the Inferno shell can be embedded in a web page.
See the Vita Nuova manual pages for more information about
shell(1)
commands, and for a
paper
that describes the Inferno shell.
-
<OBJECT
classid="clsid:C0316421-4BE6-11d3-A893-004095E0A888"
codebase="http://www.vitanuova.com/plugin/ieplugin.cab"
width=500 height=80
>
<PARAM name="init" value="pi/wm sh -c '
load tk
winid=${tk window Hello}
tk $winid button .b -text {Hello World}
tk $winid pack .b
tk $winid update
sleep 10
' ">
</OBJECT>
Click here to download and run this script.
A second example illustrates the use of shell flow control and
pipes in a web page script.
-
<OBJECT
classid="clsid:C0316421-4BE6-11d3-A893-004095E0A888"
codebase="http://www.vitanuova.com/plugin/ieplugin.cab"
width=500 height=80
>
<PARAM name="init" value="pi/text sh -c '
{
for i in (H e l l o) { echo -n $i}
echo '' World''
} | xd -c
cat
' ">
</OBJECT>
Click here to download and run this script.
The examples give some idea of the various ways that code
can be executed from a web page inside the Inferno sandbox.
Other examples can be found on the Vita Nuova
web site
Security
This preliminary release of the Inferno plug-in
has no support for signed modules,
all modules are assumed to be unsigned. Unsigned modules are run in a
very restricted sandbox which allows no access to the network, either
locally or remotely, and prevents the user from attaching any
devices to the namespace. Consequently, a module can add nothing
new to the namespace in which it finds itself when it is initialised
by the plug-in. All services, that allow a module to affect the world
outside of its sandbox are made available
through the namespace (including networking, and file storage).
Security in Inferno is enforced by restricting the namespace
of a module.
The initial namespace consists of the contents of
the read-only filesystem that it mounts from the file plugin.kfs
and the initially empty RAM file system that is mounted in the modules
home directory (/usr/internet) and in the temporary directory,
/tmp.
The next release of the plug-in will support signed modules.
Limitations
The preliminary release of the plug-in has no support for unsigned
modules and so prevents modules from accessing any resources
outside of the, very restricted, sandbox. In particular, this
means that a module can perform no networking
and has no access to file storage other than to a RAM filesystem
which disappears when the web page is closed.
We are aware of some unwanted control characters
in the output and some unusual interpretation of control
and movement keys
when using the text wrapper with
Internet Explorer version 5,
particularly annoying is the operation of the backspace key
- we are working on this problem.
Debugging
The Inferno download, available from the Vita Nuova
web site
allows debugging a Dis module before placing it in a web page.
It includes a graphical debugger that runs on all Inferno
host platforms.
When running the module under Internet Explorer
the F8 function key can be pressed to show the last few
lines of console output which can be used to help understand
why a module has failed to run.
Finally
We hope you can use the plug-in to develop some interesting
web page applications. We would love to hear about any unusual
applications that you develop, and also about any problems that
you encounter. Feel free to email us at:
-
support@vitanuova.com
Please remember that this version of the plug-in
is a preliminary release and is likely to require some further modification
before it becomes completely stable.