In May 2024, POBox.com’s URL redirection for life is ending, so this page is moving to http://flash-sheridan.name/urlcop/NewtonGetURL.html.
This is a proposed standard for the Newton
Standards Mailing List. It is based on "URL-AE Standard" and the
Internet Config application by John Norstad, Peter Lewis, Quinn the
Eskimo, et al.
Draft 0.3.0, 10/15/96 [Editing in progress.]
Changed method name to RegisterURLHandler, and changed number of arguments to two. (The old method name will still be supported.)
Applications which can handle URL types can declare their ability to do so in two ways. The first is simply to implement at their base level methods called GetURL and/or FetchURL, each taking two arguments; the first is a URL string, the second is an options frame which may be ignored. The GetURL method should display to the user the item denoted by the URL string; the FetchURL method should return the value of the item, but not display it.
The second thing the application should do to make its ability known is to call in a delayed action, when installed,
GetRoot().urlCop:?RegisterURLHandler(appSymbol, {types: array, GetURL: true, FetchURL: true, version: n})
appSymbol: The application's symbol.
types: An array of strings or symbols, indicating which URL types the registering app is offering to handle, e.g., ['http, 'ftp].
version: An integer.
An application which cannot handle the FetchURL (or GetURL) method should omit the corresponding slot from the fourth argument.
URL-Aware applications (or
transports) should implement the following two methods. For backward
compatibility, and for apps which do not know which internet apps are
available, I've implemented a generic GetURL and FetchURL
method in a package; these methods simply read a registry of which
applications are available to handle the specified URL type, and then
call the appropriate method in the appropriate app.
There are some
unresolved issues involving transports which result in some awkwardness
in when a transport is handled like an app, and when it isn't.
GetRoot().(yourAppSymbol):?GetURL(string,
optionsFrame)
Get a URL and display it in a view or save
it as an entry in a soup (normally as an attachment in the InBox
soup).
Result: true if successful, nil otherwise.
string: the URL to get. Developers who call this method are encouraged to make this string of class '|string.url|, or '|string.url.urlType| but this is not required, and the method must be able to handle untyped strings. Developers who implement this method are encouraged, but not required, to accept strings in non-canonical format, and to have an intelligent default behavior or URL type. (E.g., An html browser might resolve a string which does not begin with a URL type as if it began with "http:".)
optionsFrame: This argument may be a frame or
nil. All the slots in this argument are optional, and the precise
interpretation of a slot is up to the implementor. Implementors are free
to invent other options slots, e.g., for passing state information.
Slot Name Type
Meaning
Save boolean or
string If true, save to the default location, normally as an
attachment in the InBox. If a string, save to the soup with the
specified name on the default store. If nil, do not save, but display if
possible.
Autoconnect boolean
If true, connect without further user intervention.
Autodisconnect boolean If true,
disconnect after resource is obtained, or after failure.
Age integer If the
URL is cached and its age is less than this number of minutes, get the
cached URL instead. If this is missing or nil, the implementor may
always use the cached URL. To ensure that the implementor always gets a
fresh copy, make this value -1.
ScrollPercentage integer (0 to 100) If present and
supported by the receiver, the initial display should be as though the
user had scolled scroll% through the resource. (This is
definitely optional, but many existing web pages have no significant
information until the second Newton screen-full.)
Worksite Worksite to use for connection.
Parts an array of symbols, indicating the
only parts that are of interest, e.g., 'title, 'links. 'header.
For a mailto URL, open a mail message window addressed to the email
address in
the URL. The Save slot in the optionsFrame parameter has
no meaning for a mailto URL, and must be ignored if it is specified.
For ftp URLs, if the path in the URL resolves to a directory, display the directory contents in a window. If Save is non-nil and the path resolves to a non-text file, save the file to the specified soup. If the path resolves to a text file and Save is non nil, behavior is up to the application; it might display the file, save it as a Notepad entry, or save it in some other format. For ftp URLs, the implementor may do further processing, or call additional handlers.
GetRoot().(yourAppSymbol):?FetchURL(string,
optionsFrame)
Get a URL and return it, if possible,
without displaying it.
Result: non-nil value of the URL if
successful, nil otherwise.
string: the URL to get.
optionsFrame: This argument may be a frame or nil.
In addition to the slots listed for GetURL, implementors
may support an additional slot, converted. If non-nil, this
method may return an application
dependent version of the resource,
rather than the unconverted value of the URL. If this slot is missing or
nil, and the implementor is unable to return the raw resource, the method
should return nil.
(The converted slot is a kludge. But,
for instance, a browser which talks to an intermediary client on a Mac
may never see the raw html; it may get a newton-specific version instead.
This version of the html might still nonetheless be of some use to the
caller, e.g., if it's just looking for text.)
If the caller does not know where it should send a
GetURL or FetchURL method, it should send it to the URL Traffic Cop, a
package which is a generic URL handler. The URL Traffic Cop will
consult a database of registered apps (and transports) to determine which
app and which method to pass the call to. If it ever becomes possible to
register a transport and an application with the same appSymbol, the
registry will call the transport instead of the application.
GetRoot().urlCop:?RegisterURLHandler(appSymbol,
{types: typesArray, suitability: nil, integer, or array,
GetURL: boolean, symbol, or function,
FetchURL: boolean, symbol, or function})
appSymbol: a symbol, normally your application's symbol.
types: An array of strings or symbols, indicating which URL types
the registering app is offering to handle.
suitability:
An integer, indicating how suitable the app denoted by appSymbol
is for handling one of the URL types. Larger is better.
This may also be missing or nil, which has the same effect as 0, the default
suitability. In future versions it may also be an array of integers,
in which case each integer represents the suitability of the corresponding
type in the Types array.
handlersFrame: Obsolete.
:PreferredApp(URLString, method,
optionsFrame)
Returns the symbol for the preferred
application or transport for the given URL and method.
The following two methods are now deprecated:
:RegInetConnected(appSymbol)
:RegInetDisconnected(appSymbol)
Instead, add InetConnected:TRUE or InetDisconnected:TRUE to your registration
frame. The application or transport denoted by appSymbol will be sent the
InetConnected or InetDisconnected method when the Internet Enabler connects
or disconnects.
:InetConnected()
:InetDisconnected()
_______
The following information is for the use of implentors of URLCop and associated utilities only. I probably should not have documented it in the first place, and implementors of future URL dispatchers are free to break it or ignore it.
The registry will be stored in a soup. The
idea behind the data structure is to make it easy, first to find all
entries which can handle the requested type and the GetURL (respectively
FetchURL) method, and then to go to the app with the highest suitability.
For efficiency, the implementation will signal its ability to
handle a URL type and the GetURL (or FetchURL) method using a soup tag,
which must be a symbol. (This should be transparent to the caller and
receiver, though.) The Newton object store only allows a single tags
array, so both items must be stored in the same array, but it may be
clearer to think of them separately. (This would cause a conflict if a
URL type had the same name as a handler method, but this seems
unlikely.)
A typical entry might look like this:
{
types: ['http,
'shttp, 'GetURL],
appSymbol: '|NetSurfer:WebLizards|,
Suitability: -42
FetchURL: nil,
GetURL:
'MyURLMethod
}
When an app sends the GetURL
method to the generic handler:
If Method is a symbol, then
GetRoot().(AppSymbol) is opened, and
GetRoot().(AppSymbol).(Method) is looked up. If
GetRoot().(AppSymbol).(Method) takes two arguments, the
method is called with the original string and optionsFrame arguments.
For backwards compatibility, if the arg count is one, only the URL string
is passed to the method.
If Method is TRUE, then the
arguments are passed to GetRoot().(AppSymbol).GetURL.
If Method is a function, then the value of the function slot is
performed in the context of the entry with the original two arguments.
If AppSymbol is a
registered transport, instead of the above, the following happens:
If Method is a symbol, then the transport is sent the method
Method with the original string and optionsFrame arguments, via
the TransportNotify global function. (The single-argument
backward-compatibility hack is not supported for transports.)
If Method is TRUE, then the arguments are sent to GetURL
method of the transport.
If Method is a
function, then the value of the function slot is called with the original
two arguments.
If multiple apps have registered to handle
type, then the app with the highest Suitability value gets the call.
The FetchURL slot in the description frame is treated similarly. If the
entry has a non-nil slot entitled 'NoAutoOpen, the app is not opened
before the message is sent.
Jim Bailey suggested being able to
send a method to a transport; I've revised urlCop to handle this.
[examples deleted]
An app can then be looked up as
follows:
mySoup := GetUnionSoup("urlCop");
myCursor :=
mySoup:query(
{indexpath: 'suitability,
tagSpec:
{all:['http, 'GetURL]},
validTest: func(e)
GetRoot().(e.appSymbol)
});
myCursor:entry();
This will give the app with highest
suitability which can handle method GetURL and type http.
Calling myCursor:next() will move to the second-most suitable app.
urlCop internal methods and slots: Should these
be documented? (They should be over-rideable.)
ParseURLForType(string, optionsFrame)
defaultURLType (a symbol)
URLRegistryQuery(theType, theMethod, optionsFrame)
The URL
Traffic Cop will be free; I'll either post the source, or make it
available to anyone who wants to implement a superset of its features.
The current version should be on my home page,
http://flash-sheridan.name.
I'm not speaking officially, and I
did this on my own time.
Flash Sheridan
FlaSheridn@pobox.com