Acorn URI Handler Functional Specification
==========================================

Document Status
---------------
  Distribution:  General Release
         Title:  URI Handler Functional Specification
Drawing Number:  1307,260/FS
         Issue:  8
     Author(s):  Carl Elkins
                 Stewart Brodie
                 Kevin Bracey
                 Simon Middleton
                 Ben Laughton
                 Andrew Hodgkinson
          Date:  11/12/97
 Change Number:  N/A
    Last Issue:  7


Contents
--------
Document Status
Issue History
Overview
Deliverable 'product'
Programmer's Interface
        URI SWIs
                URI_Version (&4E380)
                URI_Dispatch (&4E381)
                URI_RequestURI (&4E382)
                URI_InvalidateURI (&4E383)
        URI Service calls
                Reason 0: Service_URI_Started      - URI handler started
                Reason 1: Service_URI_Dying        - URI handler dying
                Reason 2: Service_URI_Process      - check or process URI
                Reason 3: Service_URI_ReturnResult - return result of dispatch
        WIMP messages
                Message &4E380: URI_MStarted       - URI handler started
                Message &4E381: URI_MDying         - URI handler dying
                Message &4E382: URI_MProcess       - check or process URI
                Message &4E383: URI_MReturnResult  - return result of dispatch
                Message &4E384: URI_MProcessAck    - acknowledge URI_MProcess
        * Commands
                *Desktop_AcornURI   - starts the URI handler
                *URIinfo            - display information about the URI handler
                *URIdispatch        - try to launch a URI
        URI Handler errors
                Defined errors
                Error generators
        Use of the URI filetype
        Use of URI environment variables
Performance targets
Development test strategy


Issue History
-------------
1       13/12/96        Original Version
2       21/12/96        Added 'handles' concept after discussions with
                        S.Brodie.
3       22/02/97        Corrected omission of URI handle from
                        Message_ReturnResult, clarified responsibility for
                        invalidation of URIs.
4       21/04/97        Added URI_ProcessAck message and *command documentation
                        and updated URI filetype section
5       13/06/97        Service calls given flags, so 'Check' service call
                        removed. R0 return of URI_Dispatch now a bitfield,
                        not a return value. Added Service_MReturnResult.
                        Desktop_URI renamed to Desktop_AcornURI to match the
                        actual module task name. URI file contents specified;
                        includes a version number linked to the module
                        version, so this specifies a version 5 file.
6       20/06/97        Following review of draft 5, some minor wording
                        changes here and there; performance targets and
                        development test strategy sections added.
7       21/06/97        Reworded away from future tense to form an externally
                        releasable specification.
8       10/12/97        A couple of implied future tense references missed
                        in Draft 7, now corrected; some minor rewording
                        associated with this.
        11/12/97        No longer draft; settled on WIMP rather than Wimp;
                        couple of minor typos corrected.

Overview
--------
This document addresses the recognised lack of existing RISCOS specifications
that describe a standard method for different applications to communicate URIs
(of which URLs are an example) between themselves; for example, to provide for
an address book requesting that a Web browser display someone's home page.

The first part of this requirement addressed is the provision of a mechanism
for applications to pass URIs between themselves in a uniform manner. To date,
several third party developers have independently solved this problem in a
variety of different ways, as there was no centrally published, universally
available standard for developers to work to. This is such a standard.

This 'central resource broker' will be extended in the future to provide
mechanisms to enable more efficient handling of URIs. For example, data
may be passed to an appropriate application based on the type of data as
opposed to simply the method specified for retrieval of the data, as is often
the case with URLs. This too will be via a service interface to the central
broker.


Deliverable 'product'
---------------------
This document describes the API created to fulfil the above stated
requirement, and relates to existing software providing the underlying
functionality.

The software takes the form of a RISCOS relocatable module, entitled
'AcornURI'. This is a generic, OS-level software component that could
as equally sit beneath a text editor which was aware of the form of URIs
as sit beneath a Web browser or mail / news reader. Distributed alongside
the module are four sprite definitions for URI files.

The module is suitable for RISC OS 3.10 upwards, and should be stored
in !System.310.Modules.Network as 'URI'.


Programmer's Interface
----------------------
The application programmer's interface to the services provided by the Acorn
URI handler is detailed in the following sections. This interface will be
enhanced in the future, as outlined in the overview, to provide a more
comprehensive set of services; so it's worth emphasising that only those
details and features of the interface specified in the following sections
should be considered to be supported. Any behaviour which is not specified
below should be considered to be an implementation feature of a particular
version of the software, and as such liable to change, alteration or omission
without notice.

The following have been allocated for the use of the Acorn URI handler:

Module name             URI
SWI prefix              URI
SWI chunk               &4E380
WIMP message chunk      &4E380
Error code chunk        &810A00
Service Call            &A7
FileType                &F91

All environment variables containing the string _URI_ (i.e. matching *_URI_*)

URI 'handles' are utilised to identify a specific URI request when
communicating with the URI handler; tasks may assume nothing about these
handle values, other than that they identify a particular URI to the handler
for the period of their validity.


URI SWIs
--------
The following SWIs are provided for external applications' use: all other
URI SWIs are reserved.

URI_Version (&4E380)

On Entry
R0      =       flags:  bit     meaning if set
                        0-31    reserved (0)

On Exit
R0      =       current version * 100

Interrupts
Undefined.

Re-entrancy
Undefined.

Use
This SWI is used to inquire of the URI handler module's version number, and
should be used to check for a suitable version being present before using the
facilities provided.

The number returned is of the form (major version * 100) + minor version.

URI_Dispatch (&4E381)

On Entry
R0      =       flags:  bit     meaning if set
                        0       inform caller of result (=>R2 valid)
                        1       check only, don't process (R0:0 must be set)
                        2       don't attempt external process startup
                        3-31    reserved (0)
R1      =       pointer to 0 terminated URI string
R2      =       0, or source task handle if bit R0:0 is set and the caller
                is a WIMP task

On Exit
R0      =       flags:  bit     meaning if set
                        0       request rejected, URI won't be dispatched
                        1-31    reserved (0)
R2      =       task handle of URI handler
R3      =       handle of this URI (request identifier)
All other registers preserved.

Interrupts
Undefined.

Re-entrancy
SWI is not re-entrant.

Use
This SWI is used by an application to pass a URI string to the handler for
dispatch, or checking for the presence of a potential servicer. Dispatch
provides for optional requesting of a success/failure indication (R0:0
set) via a WIMP message (URI_MReturnResult) or service call reason code
(Service_URI_ReturnResult) - necessary since the dispatch of the URI occurs
asynchronously.

If R0:0 is set, module clients must signal that a URI_MReturnResult message
is not necessary by setting R2 to 0. In this case, only the service call
will be sent out. Conversely, WIMP task clients must specify a valid task
handle in R2 - in this case, only the WIMP message will be sent out.

When requesting a check only (R0:1 set), it is an error not to set R0:0
and fill in R2 as described above.

The URI will be copied to the URI handler's workspace, optionally transformed
(future enhancement, such as canonicalisation), then relocatable modules will
be offered the chance to handle the URI via service call &A7 with an
appropriate reason code (Service_URI_Process); if the service call is
unclaimed, then a User_Message_Recorded WIMP message will be broadcasted
(URI_MProcess), offering other tasks the chance of handling the URI; if
neither of these mechanisms elicits a response, then the request will
be deemed to have failed (in so far as active tasks are concerned).

If R0:2 is clear, then the 'fallback' position of checking a subset of the
environment variables will be used to attempt to start a suitable task to
handle the URI. The handle ceases to be valid at this point if notification
has not been requested, irrespective of whether or not the URI has processed.

If R0:0 is set, the originating task will be informed of the results of the
dispatch process (via a User_Message_Recorded WIMP message URI_MReturnResult
if R2 contains a valid task handle, or service call Service_URI_ReturnResult
if R2 is zero). If the message is not acknowledged or service call claimed,
the handle will cease to be valid; otherwise, the originating task becomes
responsible for indicating that it no longer needs the URI by calling SWI
URI_InvalidateURI.

URI_RequestURI (&4E382)

On Entry
R0      =       flags:  bit     meaning
                        0-31    reserved (0)
R1      =       pointer to buffer to hold URI or 0 to read required size
R2      =       length of buffer or unused (if R1 = 0)
R3      =       URI handle

On Exit
R2      =       offset into buffer of terminating null,
                or size of buffer required (if R1 = 0 on entry)
All other registers preserved.

Interrupts
Undefined.

Re-entrancy
SWI is not re-entrant.

Use
This SWI is used to inquire what size of buffer is required to hold the
specified URI (if R1 is zero on entry), or to pass details of a buffer into
which your task desires the URI to be copied.

If this is successful, then R2 should be equal to the size of the buffer: if
the buffer specified on entry is not large enough, then R2 will be returned
negative (indicating the number of unreturned characters), and the string
returned in the buffer will still be zero-terminated i.e. buffersize-1
characters of the string are returned.

URI_InvalidateURI (&4E383)

On Entry
R0      =       flags:  bit     meaning
                        0-31    reserved (0)
R3      =       URI handle

On Exit
All registers preserved.

Interrupts
Undefined.

Re-entrancy
SWI is not re-entrant.

Use
This SWI is used to mark the specified URI as being invalid.


URI Service calls
-----------------
Service call &A7 has been allocated for the use of the URI handler; the
following sub-reason codes are defined for the use of external applications.
All other service call reason codes are reserved: a module may assume
nothing about these, and should always ignore unrecognised reason codes -
NEVER claim such service calls.

A deliberate degree of similarly exists between the WIMP messages and
the service calls, since both provide essentially the same functionality;
clearly, messages will be convenient in environments where service calls
are not and vice versa, hence the duplication of functionality between
the two.

Reason 0: Service_URI_Started - URI handler started
On Entry
R0      =       0       reason code
R1      =       &A7     service call
R2      =       flags:  bit     meaning
                0-31    reserved (0)

On Exit
All registers must be preserved - the call must be passed on.

Use
This service call indicates that the URI handler has started. It is intended
for more specific use defined in future versions of this specification.

Reason 1: Service_URI_Dying - URI handler dying
On Entry
R0      =       1       reason code
R1      =       &A7     service call
R2      =       flags:  bit     meaning
                0-31    reserved (0)

On Exit
All registers must be preserved - the call must be passed on.

Use
This service call indicates that the URI handler is dying. It is intended for
more specific use defined in future versions of this specification.

Reason 2: Service_URI_Process - process or check URI
On Entry
R0      =       2       reason code
R1      =       &A7     service call
R2      =       flags:  bit     meaning
                        0       check URI only, do not process
                        1-31    reserved (0)
R3      =       pointer to URI string (readonly access)
R4      =       handle of this URI

On Exit
R1      preserved or 0 to claim
All other registers preserved.

This service call indicates that the URI handler has been requested to
dispatch the given URI for either processing (R2:0 clear), or just checking
(R2:0 set). The URI string is held in the URI handler's workspace; this
buffer must not be written to - if it is, behaviour is undefined. It is
intended that modules should inspect the string at the given address, and
if they decide they can process the given URI, claim the service call. If
R2:0 is set, this is all that is required.

However, if R2:0 is clear, i.e. process URI, then a call to SWI
URI_RequestURI to obtain a local copy to work with must be made; this step
may NOT be omitted, since the internal buffer is not guaranteed to remain
valid after return from the service handler.

If a module cannot process the given URI, it must pass the call on with all
registers preserved to allow the remainder of the dispatch mechanism to
function.

Reason 3: Service_URI_ReturnResult - return result of a dispatch
R0      =       3       reason code
R1      =       &A7     service call
R2      =       flags:  bit     meaning
                        0       0 => URI was claimed for processing
                                1 => URI was not claimed for processing
                        1-31    reserved (0)
R3      =       undefined (reserved (0))
R4      =       handle of this URI

Use
This service call is used by the URI handler to return result status
information to a requesting module. The module requests the service call
when it calls the URI_Dispatch SWI; it must set R0:0 and R2=0 on entry. Such
modules must remember the URI handle returned in R3 by this SWI or they
cannot later determine if the service call was meant for them or another
client; any client setting R0:0 on entry to URI_Dispatch must see if it
recognises the URI handle in R4, and if so, claim the service call. If it
does not recognise the handle, it must not claim the service call. Any
clients which never set R0:0 on entry to URI_Dispatch can ignore the
service call.

Only success or failure is indicated, though this is likely to
be enhanced in future.


WIMP messages
-------------
As might be expected, the URI handler communicates with other WIMP tasks via
the WIMP message mechanism. The following message action codes are defined
for use by external applications, with all other codes being reserved.

Message &4E380: URI_MStarted - URI handler started
Poll block
R1+20   =       flags:  bit     meaning
                        0-31    reserved (0)
R1+24...        undefined (reserved)

Use
This message is broadcast (User_Message) to indicate that the URI handler has
started up. It must not be acknowledged - information only.

Message &4E381: URI_MDying - URI handler dying
Poll Block
R1+20   =       flags:  bit     meaning
                        0-31    reserved (0)
R1+24...        undefined (reserved)

Use
This message is broadcast (User_Message) to indicate that the URI handler is
shutting down. It must not be acknowledged - information only.

Message &4E382: URI_MProcess - process or check URI
Poll Block
R1+20   =       flags:  bit     meaning if set
                        0       check URI only, do not process
                        1-31    reserved (0)
R1+24   =       pointer to URI string (URI internal buffer)
R1+28   =       URI handle
R1+32...        undefined (reserved)

Use
This message is broadcast (User_Message_Recorded) to indicate that the URI
handler has been requested to dispatch the given URI for processing, or check
if any task can process the URI.

The URI string is held in the URI module's workspace; this buffer must not
be written to - if it is, behaviour is undefined.

It is intended that applications which can process URIs should inspect the
string at the given address to determine if they can process the URI. If R0
bit 0 is clear,  you must then call SWIURI_RequestURI to obtain a copy to
work with - this step may not be omitted, since the buffer given is not
guaranteed to remain unaltered.

If an application is able to check or process the given URI, then it should
acknowledge the broadcast by sending a URIProcessAck message to the URI
handler, thus preventing it being passed on to other applications, otherwise
it must not acknowledge the message.

Message &4E383: URI_MReturnResult - return result of a dispatch
Poll Block
R1+20   =       flags:  bit     meaning
                        0       0 => URI was claimed for processing
                                1 => URI was not claimed for processing
                        1-31    reserved (0)
R1+24           URI handle
R1+28...        undefined (reserved)

Use
This message is used by the URI handler to return result status information
to a requesting task. Only success or failure is indicated, though this is
likely to be enhanced in future.

Message &4E384: URI_MProcessAck - acknowledge URI_MProcess
Poll block
R1+12   =       my_ref from URI check/process message
R1+20   =       flags:  bit     meaning if set
                        0       check URI only, do not process
                        1-31    reserved (0)
R1+24   =       pointer to URI string (URI internal buffer)
R1+28   =       URI handle
R1+32...        undefined (reserved)

Use
This message is used by clients of the URI handler to indicate to the URI
handler that they can claim or process a given URI, thus preventing it being
passed on to other applications.  Claimants just change the message type to
&4E384 (URI_MProcessAck) and copy the supplied my_ref field into your_ref,
then send the message back to its originator (ie. the URI handler).


* Commands
----------
*Desktop_AcornURI - starts the URI handler
Syntax
*Desktop_AcornURI

Parameters
None

Use
*Desktop_AcornURI starts the Acorn URI handler.
Do not use *Desktop_AcornURI, use *Desktop instead.

Help text
Do not use *Desktop_AcornURI, use *Desktop instead.
Syntax: *Desktop_AcornURI

Example
*Desktop_AcornURI
Use *Desktop to start AcornURI

Related commands
None

Related SWIs
None

Related vectors
None

*URIinfo - display information about the URI handler
Syntax
*URIinfo

Parameters
None

Use
*URIinfo produces status information from the Acorn URI handler

Help text
URIinfo produces status information from the Acorn URI handler.
Syntax: *URIinfo

Example
*URIinfo
URI_taskhandle: 4b4016d8
URI chain start: 021cc844
URI handle: 022b60d4 (action:00020000) 'http://www.acorn.com/'

Related commands
None

Related SWIs
None

Related vectors
None

*URIdispatch - try to launch a URI
Syntax
*URIdispatch <uri>

Parameters
uri: the uri to be launched

Use
*URIdispatch tries to lauch a given URI. No indication is given of whether or
not the launch succeeded.

Help text
URIdispatch tries to launch a URI.
Syntax: *URIdispatch <uri>

Example
*URIdispatch http://www.acorn.com/

Related commands
None

Related SWIs
URI_Dispatch

Related vectors
None


* URI Handler errors
--------------------

The URI handler has a error chunk base of &810a00. Currently defined errors
are:

Name                  Number      Cause

Error_URI_NoMemory    Base + 1    There is not enough memory to complete an
                                  operation.
Error_URI_BadURI      Base + 2    An empty URI string is supplied (e.g. to
                                  URI_DispatchURI).
Error_URI_BadHandle   Base + 3    A bad URI handle has been supplied.
Error_URI_BadFile     Base + 4    Reported when there is an error accessing a
                                  URI file.

Generators of the errors are as follows:

URI_DispatchURI   may return Error_URI_NoMemory
                             Error_URI_BadURI

URI_RequestURI    may return Error_URI_BadHandle
URI_InvalidateURI may return Error_URI_BadHandle

*URIDispatch      may return Error_URI_NoMemory

Finally, the WIMP task may generate (through a standard WIMP error box)
Error_URI_NoMemory and Error_URI_BadFile.


Use of the URI filetype
-----------------------
URI files have the filetype &F91, with the text equivalent 'URI'. The URI
handler will deal with such files appropriately when the file is double-clicked
upon (currenly, it dispatches the URI inside the file - see the file format
description below). Applications must not set an Alias$@RunType variable for
the URI filetype, nor must they deal with DataOpen messages for this filetype.
Applications may respond to DataLoad messages for the filetype as they see fit.

Suitable sprites exist (four; medium and high resolution file sprites, small
and large variants). These are the only sprite definitions acceptable for use
in this context. The sprites should always be distributed alongside the
module.

URI files consist of a series of lines of characters. Lines are ended by
any number of control code characters (ASCII code less than 32) or the end
of the file. All lines in a file do not have to end in the same way provided
each individual line ends in a valid manner. Other white space is not ignored,
hence a single space character (ASCII code 32) followed by ASCII code 9 does
count as a line containing a single space followed by a line end marker.

URI files support comments. Comment lines start with a '#' (ASCII 35) and end
in the same way as all other lines. Comment lines are not counted; any file
reader that happened to keep track of the line number it was on should not
increment the counter for a comment line. A URI file may contain any number
of comment lines, but automatic file generators are encouraged to keep
comments to a bare minimum to keep file sizes down. Generator code must
never create special comment lines which mean something to accompanying
reader code - comment lines are always skipped by the reader code and never
parsed, beyond identifying them as comments.

The line ending type of a URI file is not fixed as a specific control code
or sequence of control codes (e.g. CR+LF) to allow simple generation from a
variety of sources, including manual authoring. Given this latter possibility,
it is important to stress that unlike, say, HTML, the URI file format is
rigorously defined and must be adhered to. Incorrectly formed files are not
guaranteed to work correctly with either the Acorn URI handler or applications
which support it.

That said, the use of ASCII code 13 followed by ASCII code 10 (CR+LF) to end
lines is strongly encouraged as this is a common line ending type supported
by many different editors on many platforms. ASCII code 9 (tab) could also
be used to give the file a better visual appearence in the editor - it is
still an end of line as far as the file reader is concerned. This convention
provides the potential for greater convenience for the end-user, but must
NOT be assumed in file reading code!

Currently defined formats:

Supporting URI     Line
module version     number   Contents

(None at present)  1        'URI' - this must be present before any comments
                            or other information.

                   2        Text equivalent of the earliest module version
                            number (as returned by URI_Version) that would
                            fully understand the file contents; e.g. '5'
                            for v0.05 (any number of preceeding '0's are
                            also valid). So if lines were added to this file
                            format to produce a version 6 file, this implies
                            that URI v0.06 is required to understand those
                            extra lines, even though v0.05 would still
                            understand lines 1 to 4.

                            The first general release version of the URI
                            handler will adopt a version number of 1.00, so
                            the first URI files will start with '100' in
                            this line.

                   3        A fully specified URI; v0.05 of the URI handler
                            does not attempt to canonicalise URIs, though
                            future versions may. If this line contains only
                            one character with ASCII code 42 ('*'), the file
                            does not contain a URI and should be ignored
                            (this is to allow future file formats to hold
                            non-fully specified URIs on later lines that
                            could be canonicalised by the URI module, without
                            breaking legacy file reading code).

                            Lines 1 to 3 are required in a minimal URI file.
                            Any other lines may or may not appear.

                   4        A title string to associate with the URI. Again, if
                            this line contains only one character with ASCII
                            code 42 ('*'), the file does not contain a title
                            string. Processors wishing to display title
                            information alongside a URI may well use the URI
                            itself instead, in this case.


Example 1 (simple, small URI file example)
---------

-Start of file-
URI
100
http://www.acorn.com/acorn/
Acorn Group plc
-End of file-


Example 2
---------

-Start of file-
URI
#No URI present, so this file will be ignored

100
*
-End of file-


Example 3 (someone sending in a brief fault report for some browser, say,
---------  in the form of a URI file)

-Start of file-
URI
100
# Browser complains about bad frames nesting, but the source looks OK to me!
http://www.acorn.co.uk/~someone/home_frames.html
*
-End of file-

Future file formats will be backwards compatible with this one, so clients
should only check the version number of the file to know what sort of contents
to expect. So for example, if a version 100 aware application encounters a
later version file, it can assume that the first 4 lines of the file are as
described for the version 100 file; though there may be other lines which
clearly it cannot understand, and must ignore.

For example, the file format rationale may be easier to understand given the
possibility of a future format - version 101, say - which allowed non-fully
specified URIs in line 5 which can be canonicalised, and a preferred external
process to start in line 6. The file could look like this:

-Start of file-
URI
6

*
Acorn Group PLC
www.acorn.com

<Browse$Dir>.!Run
-End of file-


Use of URI environment variables
--------------------------------

Currently defined variables are of the form:

Alias$Open_URI_<scheme> <file to run>

for example,

Alias$Open_URI_http <Browse$Dir>.!Run
Alias$Open_URI_ftp  <FTPClient$Dir>.!Run

If a variable such as the above is defined, then the task it names will
be run. If this is successful, the URI will be redispatched in the normal
way, so the task has the opportunity of dealing with it.

A comma separated list of handlers may be specified, so applications
must always *add* to the contents of the variables. At present, only
the first item in the list is used, though this may change in
future versions.

For compatability with existing applications, the URI handler will
support a similar scheme of system variables defined by ANT Ltd.
Details of these are at the time of writing freely available on
the ANT web site (http://www.ant.co.uk/).


Performance targets
-------------------

Final code size of version 1.00 should be about 26K. Quiescent memory
usage should be no more than 512 bytes. When active, the main
storage requirement for each URI being processed is storage of the URI
itself. This is, then, indeterminate, but unlikely to be more than
2K (not that the URI handler will have any such hard coded limits).
An additional overhead of no more than 128 bytes per URI is also
required.


Development test strategy
-------------------------

A test harness application and module will be created to run through
the various supported messages and services calls with a variety
of URI files.

(C) Acorn Computers Ltd. 1997
