Any SWI-Prolog web server can be pengine enabled by loading
library(pengines) and configuring the access rights. Clients can then
create pengines that execute code in the module pengine_sandbox
. By
default, they can only execute white-listed code as defined by the
library(sandbox), i.e., mostly Prolog code that has no side effects.
Typically, a server serves a particular application. This application
comes with a particular API. A nice and clean example is the RDF library
as realised by library(semweb/rdf_db). If the pengine server wishes to
make this library available to pengines, it must import this library
into the module pengine_sandbox
using the following query:
:- use_module(pengine_sandbox:library(semweb/rdf_db)).
This declaration allows pengines to use the side effect free RDF query
predicates, in particular rdf/3.
An application that wishes to provide similar functionality should take
the following steps:
- Define a module that exports the desired API. Remember that the
client can easily add predicates that combine API calls and massage
data into a format suitable for the application, so you don't have
to think about these application oriented queries. Instead, make
your queries general and purely declarative!
- Import this library into
pengine_sandbox
as illustrated above.
That is all, except that library(sandbox) may not like your code. What
now? There are several reasons and work-arounds.
- The sandbox library does not understand my code
-
This shows up as instantiation errors and implies that the
sandboxing libraries finds meta-calls but cannot determine what
will be called. There are two remedies:
- Make the source easier to track. Avoid some meta-calling by
passing terms that indicate what should happen and a static
predicate that interprets these terms. This is often a good
idea if the intend is to meta-call to a well defined set of
predicates.
- Isolate the most deeply nested bit of code that is safe,
regardless how it is called and declare this to be safe
using sandbox:safe_primitive/1 or, if it is a meta-predicate,
using sandbox:safe_meta/2.
- The API calls foreign code
-
Library(sandbox) cannot prove anything about foreign code. Make sure
it is written properly and declare it using sandbox:safe_primitive/1.
- The API has side effects, but that it what it should do
-
Make sure that the API correctly validates arguments and really
cannot do anything unintended and declare it using
sandbox:safe_primitive/1.