Permalink
Browse files

Enable runtime substitutions using `class` level `validation` blocks (#…

…4600)

 As well as now honouring
class level validation blocks a validation hierarchy is implemented
across `web`, `layer` and `class` level validation blocks.  This
hierarchy *only* takes effect when identical validation keys appear in
`web`, `layer` or `class` such that keys in more specialised blocks
override those in more generalised blocks. i.e. `class` overrides
`layer` which overrides `web`.

In conjunction with the above, default class level substitutions are
also enabled and also implement the precedence rules above. i.e. a
default substitution in `class` overrides `layer` which overrides
`web`.

Ensure validation *always* occurs when a substitution is requested
Fixes #4596
Fixes #4600
  • Loading branch information...
homme authored and tbonfort committed Mar 5, 2013
1 parent 2de943a commit 4e79097f2151ff9291f3c9511422033d6e46a7fa
Showing with 108 additions and 25 deletions.
  1. +107 −24 mapfile.c
  2. +1 −1 msautotest
131 mapfile.c
@@ -6450,42 +6450,41 @@ int msUpdateMapFromURL(mapObj *map, char *variable, char *string)
return(MS_SUCCESS);
}

static int classNeedsSubstitutions(classObj *class, char *from) {
if(class->expression.string && (strcasestr(class->expression.string, from) != NULL)) return MS_TRUE;
if(class->text.string && (strcasestr(class->text.string, from) != NULL)) return MS_TRUE;
if(class->title && (strcasestr(class->title, from) != NULL)) return MS_TRUE;

return MS_FALSE;
}

static int layerNeedsSubstitutions(layerObj *layer, char *from)
{
int i;

if(layer->data && (strcasestr(layer->data, from) != NULL)) return MS_TRUE;
if(layer->tileindex && (strcasestr(layer->tileindex, from) != NULL)) return MS_TRUE;
if(layer->connection && (strcasestr(layer->connection, from) != NULL)) return MS_TRUE;
if(layer->filter.string && (strcasestr(layer->filter.string, from) != NULL)) return MS_TRUE;

for(i=0; i<layer->numclasses; i++) {
if(layer->class[i]->expression.string && (strcasestr(layer->class[i]->expression.string, from) != NULL)) return MS_TRUE;
if(layer->class[i]->text.string && (strcasestr(layer->class[i]->text.string, from) != NULL)) return MS_TRUE;
if(layer->class[i]->title && (strcasestr(layer->class[i]->title, from) != NULL)) return MS_TRUE;
}

if(!msHashIsEmpty(&layer->bindvals)) return MS_TRUE;

return MS_FALSE;
}

static void classSubstituteString(classObj *class, char *from, char *to) {
if(class->expression.string) class->expression.string = msCaseReplaceSubstring(class->expression.string, from, to);
if(class->text.string) class->text.string = msCaseReplaceSubstring(class->text.string, from, to);
if(class->title) class->title = msCaseReplaceSubstring(class->title, from, to);
}

static void layerSubstituteString(layerObj *layer, char *from, char *to)
{
int i;
char *bindvals_key, *bindvals_val;

if(layer->data) layer->data = msCaseReplaceSubstring(layer->data, from, to);
if(layer->tileindex) layer->tileindex = msCaseReplaceSubstring(layer->tileindex, from, to);
if(layer->connection) layer->connection = msCaseReplaceSubstring(layer->connection, from, to);
if(layer->filter.string) layer->filter.string = msCaseReplaceSubstring(layer->filter.string, from, to);

for(i=0; i<layer->numclasses; i++) {
if(layer->class[i]->expression.string) layer->class[i]->expression.string = msCaseReplaceSubstring(layer->class[i]->expression.string, from, to);
if(layer->class[i]->text.string) layer->class[i]->text.string = msCaseReplaceSubstring(layer->class[i]->text.string, from, to);
if(layer->class[i]->title) layer->class[i]->title = msCaseReplaceSubstring(layer->class[i]->title, from, to);
}

/* The bindvalues are most useful when able to substitute values from the URL */
bindvals_key = (char*)msFirstKeyFromHashTable(&layer->bindvals);
while(bindvals_key != NULL) {
@@ -6524,16 +6523,39 @@ static void applyOutputFormatDefaultSubstitutions(outputFormatObj *format, const
return;
}

static void applyClassDefaultSubstitutions(classObj *class, hashTableObj *table)
{
const char *default_key = msFirstKeyFromHashTable(table);
while(default_key) {
if(!strncmp(default_key,"default_",8)) {
size_t buffer_size = (strlen(default_key)-5);
char *tag = (char *)msSmallMalloc(buffer_size);
snprintf(tag, buffer_size, "%%%s%%", &(default_key[8]));


classSubstituteString(class, tag, msLookupHashTable(table, default_key));
free(tag);
}
default_key = msNextKeyFromHashTable(table, default_key);
}
return;
}

static void applyLayerDefaultSubstitutions(layerObj *layer, hashTableObj *table)
{
int i;
const char *default_key = msFirstKeyFromHashTable(table);
while(default_key) {
if(!strncmp(default_key,"default_",8)) {
size_t buffer_size = (strlen(default_key)-5);
char *to = msLookupHashTable(table, default_key);
char *tag = (char *)msSmallMalloc(buffer_size);
snprintf(tag, buffer_size, "%%%s%%", &(default_key[8]));

layerSubstituteString(layer, tag, msLookupHashTable(table, default_key));
for(i=0; i<layer->numclasses; i++) {
classSubstituteString(layer->class[i], tag, to);
}
layerSubstituteString(layer, tag, to);
free(tag);
}
default_key = msNextKeyFromHashTable(table, default_key);
@@ -6547,7 +6569,7 @@ static void applyLayerDefaultSubstitutions(layerObj *layer, hashTableObj *table)
*/
void msApplyDefaultSubstitutions(mapObj *map)
{
int i;
int i,j;

/* output formats (#3751) */
for(i=0; i<map->numoutputformats; i++) {
@@ -6557,16 +6579,23 @@ void msApplyDefaultSubstitutions(mapObj *map)

for(i=0; i<map->numlayers; i++) {
layerObj *layer = GET_LAYER(map, i);
applyLayerDefaultSubstitutions(layer, &(layer->validation)); /* layer settings take precedence */

for(j=0; j<layer->numclasses; j++) { /* class settings take precedence... */
classObj *class = GET_CLASS(map, i, j);
applyClassDefaultSubstitutions(class, &(class->validation));
applyClassDefaultSubstitutions(class, &(class->metadata));
}

applyLayerDefaultSubstitutions(layer, &(layer->validation)); /* ...then layer settings... */
applyLayerDefaultSubstitutions(layer, &(layer->metadata));
applyLayerDefaultSubstitutions(layer, &(map->web.validation));
applyLayerDefaultSubstitutions(layer, &(map->web.validation)); /* ...and finally web settings */
applyLayerDefaultSubstitutions(layer, &(map->web.metadata));
}
}

void msApplySubstitutions(mapObj *map, char **names, char **values, int npairs)
{
int i,j;
int i,j,k;

char *tag=NULL;
char *validation_pattern_key=NULL;
@@ -6577,7 +6606,7 @@ void msApplySubstitutions(mapObj *map, char **names, char **values, int npairs)
tag = (char *) msSmallMalloc(sizeof(char)*strlen(names[i]) + 3);
sprintf(tag, "%%%s%%", names[i]);

/* validation pattern key - depricated */
/* validation pattern key - deprecated */
validation_pattern_key = (char *) msSmallMalloc(sizeof(char)*strlen(names[i]) + 20);
sprintf(validation_pattern_key,"%s_validation_pattern", names[i]);

@@ -6597,15 +6626,69 @@ void msApplySubstitutions(mapObj *map, char **names, char **values, int npairs)
for(j=0; j<map->numlayers; j++) {
layerObj *layer = GET_LAYER(map, j);

/* perform class level substitutions (#4596) */
for(k=0; k<layer->numclasses; k++) {
classObj *class = GET_CLASS(map, j, k);

if(!classNeedsSubstitutions(class, tag)) continue;

if(layer->debug >= MS_DEBUGLEVEL_V)
msDebug( " runtime substitution - Layer %s, Class %s, tag %s...\n", layer->name, class->name, tag);

if (msLookupHashTable(&(class->validation), names[i]) ||
msLookupHashTable(&(class->metadata), validation_pattern_key)) {
if (msValidateParameter(values[i],
msLookupHashTable(&(class->validation), names[i]),
msLookupHashTable(&(class->metadata), validation_pattern_key),
NULL, NULL) != MS_SUCCESS) {
/* skip as the name exists in the class validation but does not validate */
continue;
}
} else if (msLookupHashTable(&(layer->validation), names[i]) ||
msLookupHashTable(&(layer->metadata), validation_pattern_key)) {
if (msValidateParameter(values[i],
msLookupHashTable(&(layer->validation), names[i]),
msLookupHashTable(&(layer->metadata), validation_pattern_key),
NULL, NULL) != MS_SUCCESS) {
/* skip as the name exists in the layer validation but does not validate */
continue;
}
} else if (msValidateParameter(values[i],
msLookupHashTable(&(map->web.validation), names[i]),
msLookupHashTable(&(map->web.metadata), validation_pattern_key),
NULL, NULL) != MS_SUCCESS) {
/* skip as the web validation fails */
continue;
}

/* validation has succeeded in either class, layer or web */
classSubstituteString(class, tag, values[i]);
}

if(!layerNeedsSubstitutions(layer, tag)) continue;

if(layer->debug >= MS_DEBUGLEVEL_V)
msDebug( " runtime substitution - Layer %s, tag %s...\n", layer->name, tag);

if(msValidateParameter(values[i], msLookupHashTable(&(layer->validation), names[i]), msLookupHashTable(&(map->web.validation), names[i]),
msLookupHashTable(&(layer->metadata), validation_pattern_key), msLookupHashTable(&(map->web.metadata), validation_pattern_key)) == MS_SUCCESS) {
layerSubstituteString(layer, tag, values[i]);
if (msLookupHashTable(&(layer->validation), names[i]) ||
msLookupHashTable(&(layer->metadata), validation_pattern_key)) {
if (msValidateParameter(values[i],
msLookupHashTable(&(layer->validation), names[i]),
msLookupHashTable(&(layer->metadata), validation_pattern_key),
NULL, NULL) != MS_SUCCESS) {
/* skip as the name exists in the layer validation but does not validate */
continue;
}
} else if (msValidateParameter(values[i],
msLookupHashTable(&(map->web.validation), names[i]),
msLookupHashTable(&(map->web.metadata), validation_pattern_key),
NULL, NULL) != MS_SUCCESS) {
/* skip as the web validation fails */
continue;
}

/* validation has succeeded in either layer or web */
layerSubstituteString(layer, tag, values[i]);
}

msFree(tag);
Submodule msautotest updated from d1a4b5 to f6966c

0 comments on commit 4e79097

Please sign in to comment.