Description: This RFC addresses the ability of the MapServer tokenizer
(in maplexer.l and mapfile.c) to work from strings as well as files. A
mapfile-wide ability was added to 5.0 source and this RFC looks at loading
MapServer objects (layers, scalebars, etc…) via MapScript and via URLs.

Presently MapServer can load entire mapfile’s from a text block using
msLoadMapFromString. This is a new capability in 5.0. MapServer has long been
able to load/modify individual values via URL using a map_object_property
syntax (e.g. map_scalebar_units).

The problem with the URL support is that it is cumbersome for the user and
results in a ton of duplicative code in mapfile.c making maintenance difficult.
Developers will often add a parameter but forget to add a URL equivalent. This
proposal removes that redundant code and relies on a single tokenizing function
for each object.

All major objects would get a new …LoadFromString function (e.g.
msLoadLayerFromString and so on). These functions would be very simple and
would take an existing reference to an object and a string snippet. They would:

establish lexer thread locks

set lexer state to MS_TOKENIZE_STRING

call loadObject (e.g. loadLayer)

In effect this would be a way to load an empty object or update a new one.

The loadObject functions would need minor changes:

Each function would need to remove restrictions for duplicate properties.
That is setting a parameter twice should not generate an error as is
does now.

Properties with allocated memory (e.g. char * ) should be free’d if they
already have values and are being updated.

the object main keyword (e.g. LAYER or CLASS) should be allowed as a token
within that object loader. When parsing a file the object identifier
(e.g. LAYER) is stripped off with the parent object. For example, a CLASS
is recognized by loadLayer so that token never is encountered by loadClass.
It makes the most sense to pass entire object definitions including the
object identifier for ease of use.

I’m open to suggestions but I think the easiest thing to do would be to add an
updateFromString method to all major objects. It would simply take a string
snippet and would wrap the …LoadFromString methods mentioned above. They
would return MS_SUCCESS or MS_FAILURE. Might consider adding a “clear” method
to (freeObject then initObject) so that users could clean things out and reload
from a string. I’m not sure about the effects on reference counting here.

The major objects would still be referenced by map_scalebar or map_legend or
map_layername, but all other properties would be loaded through snippets.

The function msLoadMapParameter would become msUpdateMapFromURL and it would
set the lexer state, acquire a thread lock and then call the appropriate
loadObject function.

One issue is that the loadObject functions have traditionally worked just
from files so there are no limitations on what can be altered. Obviously from
a URL you can’t allow just anything to be altered (e.g. CONNECTION, DUMP
and so on). So, we would create a new lexer state, MS_TOKENIZE_URL, that
would only recognize the parameters that we want. In that state the lexer
would not return tokens like DUMP or CONNECTION so the loadObject functions
would not handle those cases. This is a simple addition to the lexer. Any
parameter exposed to URL modification will have the relevant loading block
examined so that there are no memory leaks or buffer overflow possibilities.

In addition, it was pointed out that URL configuration should not be a
default behavior but should be enabled explicitly. Enabling this feature
would happen by way of a new parameter within the webObj- URLCONFIG [pattern],
with a default of NULL. The pattern would be a regular expression that would
be applied against any map_* variables. So, one could limit changes to just
the scalebar object with URLCONFIG ‘scalebar’ or allow more with
URLCONFIG ‘.’. The default would not to be allow any URL configuration.

Apparently a number of folks are having trouble with porting applications to
use the new url configuration. Below are more examples and lists of supported
keywords by object type. Rule of thumb one: when there is the opportunity for
more than one of a particular object (e.g. layers, classes and styles) the
syntax must uniquely identify the object in question in the variable name
(e.g. map.layer[lakes]) and then the mapfile snippet to modify the object is
given as the variable value. We have no way to modify 5 styles at once because
the mapfile syntax is so freeform. Rule of thumb two: any parameters or
objects that hang off the mapObj must be referenced in the variable name
(e.g. map.imagetype).