Skip to content

Commit 673ad22

Browse files
committed
UTFGRID: implement escaping of item and data values
1 parent f4b969d commit 673ad22

File tree

5 files changed

+107
-7
lines changed

5 files changed

+107
-7
lines changed

mapserver.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2158,6 +2158,7 @@ void msPopulateTextSymbolForLabelAndString(textSymbolObj *ts, labelObj *l, char
21582158
MS_DLL_EXPORT int msEncodeChar(const char);
21592159
MS_DLL_EXPORT char *msEncodeUrlExcept(const char*, const char);
21602160
MS_DLL_EXPORT char *msEncodeUrl(const char*);
2161+
MS_DLL_EXPORT char *msEscapeJSonString(const char* pszJSonString);
21612162
MS_DLL_EXPORT char *msEncodeHTMLEntities(const char *string);
21622163
MS_DLL_EXPORT void msDecodeHTMLEntities(const char *string);
21632164
MS_DLL_EXPORT int msIsXMLTagValid(const char *string);
@@ -2580,6 +2581,7 @@ void msPopulateTextSymbolForLabelAndString(textSymbolObj *ts, labelObj *l, char
25802581
MS_DLL_EXPORT int msGetLabelStatus(mapObj *map, layerObj *layer, shapeObj *shape, labelObj *lbl);
25812582
MS_DLL_EXPORT int msAdjustImage(rectObj rect, int *width, int *height);
25822583
MS_DLL_EXPORT char *msEvalTextExpression(expressionObj *expr, shapeObj *shape);
2584+
MS_DLL_EXPORT char *msEvalTextExpressionJSonEscape(expressionObj *expr, shapeObj *shape);
25832585
MS_DLL_EXPORT double msAdjustExtent(rectObj *rect, int width, int height);
25842586
MS_DLL_EXPORT int msConstrainExtent(rectObj *bounds, rectObj *rect, double overlay);
25852587
MS_DLL_EXPORT int *msGetLayersIndexByGroup(mapObj *map, char *groupname, int *nCount);

mapstring.c

Lines changed: 72 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1125,7 +1125,7 @@ char *msEncodeUrl(const char *data)
11251125

11261126
char *msEncodeUrlExcept(const char *data, const char except)
11271127
{
1128-
char *hex = "0123456789ABCDEF";
1128+
static const char *hex = "0123456789ABCDEF";
11291129
const char *i;
11301130
char *j, *code;
11311131
int inc;
@@ -1155,6 +1155,77 @@ char *msEncodeUrlExcept(const char *data, const char except)
11551155
return code;
11561156
}
11571157

1158+
/************************************************************************/
1159+
/* msEscapeJSonString() */
1160+
/************************************************************************/
1161+
1162+
/* The input (and output) string are not supposed to start/end with double */
1163+
/* quote characters. It is the responsibility of the caller to do that. */
1164+
char* msEscapeJSonString(const char* pszJSonString)
1165+
{
1166+
/* Worst case is one character to become \uABCD so 6 characters */
1167+
char* pszRet;
1168+
int i = 0, j = 0;
1169+
static const char* pszHex = "0123456789ABCDEF";
1170+
1171+
pszRet = (char*) msSmallMalloc(strlen(pszJSonString) * 6 + 1);
1172+
/* From http://www.json.org/ */
1173+
for(i = 0; pszJSonString[i] != '\0'; i++)
1174+
{
1175+
unsigned char ch = pszJSonString[i];
1176+
if( ch == '\b' )
1177+
{
1178+
pszRet[j++] = '\\';
1179+
pszRet[j++] = 'b';
1180+
}
1181+
else if( ch == '\f' )
1182+
{
1183+
pszRet[j++] = '\\';
1184+
pszRet[j++] = 'f';
1185+
}
1186+
else if( ch == '\n' )
1187+
{
1188+
pszRet[j++] = '\\';
1189+
pszRet[j++] = 'n';
1190+
}
1191+
else if( ch == '\r' )
1192+
{
1193+
pszRet[j++] = '\\';
1194+
pszRet[j++] = 'r';
1195+
}
1196+
else if( ch == '\t' )
1197+
{
1198+
pszRet[j++] = '\\';
1199+
pszRet[j++] = 't';
1200+
}
1201+
else if( ch < 32 )
1202+
{
1203+
pszRet[j++] = '\\';
1204+
pszRet[j++] = 'u';
1205+
pszRet[j++] = '0';
1206+
pszRet[j++] = '0';
1207+
pszRet[j++] = pszHex[ch / 16];
1208+
pszRet[j++] = pszHex[ch % 16];
1209+
}
1210+
else if( ch == '"' )
1211+
{
1212+
pszRet[j++] = '\\';
1213+
pszRet[j++] = '"';
1214+
}
1215+
else if( ch == '\\' )
1216+
{
1217+
pszRet[j++] = '\\';
1218+
pszRet[j++] = '\\';
1219+
}
1220+
else
1221+
{
1222+
pszRet[j++] = ch;
1223+
}
1224+
}
1225+
pszRet[j] = '\0';
1226+
return pszRet;
1227+
}
1228+
11581229
/* msEncodeHTMLEntities()
11591230
**
11601231
** Return a copy of string after replacing some problematic chars with their

maputfgrid.cpp

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,7 @@ band_type addToTable(UTFGridRenderer *r, shapeObj *p)
267267
utfvalue = encodeForRendering(utfvalue);
268268

269269
/* Datas are added to the table */
270-
r->data->table[r->data->counter].datavalues = msEvalTextExpression(&r->utflayer->utfdata, p);
270+
r->data->table[r->data->counter].datavalues = msEvalTextExpressionJSonEscape(&r->utflayer->utfdata, p);
271271

272272
/* If UTFITEM is set in the mapfiles we add its value to the table */
273273
if(r->useutfitem)
@@ -366,6 +366,7 @@ int utfgridSaveImage(imageObj *img, mapObj *map, FILE *fp, outputFormatObj *form
366366
{
367367
int row, col, i, imgheight, imgwidth;
368368
band_type pixelid;
369+
char* pszEscaped;
369370

370371
UTFGridRenderer *renderer = UTFGRID_RENDERER(img);
371372

@@ -412,7 +413,11 @@ int utfgridSaveImage(imageObj *img, mapObj *map, FILE *fp, outputFormatObj *form
412413
fprintf(fp,",");
413414

414415
if(renderer->useutfitem)
415-
fprintf(fp,"\"%s\"", renderer->data->table[i].itemvalue);
416+
{
417+
pszEscaped = msEscapeJSonString(renderer->data->table[i].itemvalue);
418+
fprintf(fp,"\"%s\"", pszEscaped);
419+
msFree(pszEscaped);
420+
}
416421
/* If no UTFITEM specified use the serial ID as the key */
417422
else
418423
fprintf(fp,"\"%i\"", renderer->data->table[i].serialid);
@@ -427,10 +432,15 @@ int utfgridSaveImage(imageObj *img, mapObj *map, FILE *fp, outputFormatObj *form
427432
fprintf(fp,",");
428433

429434
if(renderer->useutfitem)
430-
fprintf(fp,"\"%s\":", renderer->data->table[i].itemvalue);
435+
{
436+
pszEscaped = msEscapeJSonString(renderer->data->table[i].itemvalue);
437+
fprintf(fp,"\"%s\":", pszEscaped);
438+
msFree(pszEscaped);
439+
}
431440
/* If no UTFITEM specified use the serial ID as the key */
432441
else
433442
fprintf(fp,"\"%i\":", renderer->data->table[i].serialid);
443+
434444
fprintf(fp,"%s", renderer->data->table[i].datavalues);
435445
}
436446
}

maputil.c

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -611,7 +611,8 @@ int msShapeGetClass(layerObj *layer, mapObj *map, shapeObj *shape, int *classgro
611611
return(-1); /* no match */
612612
}
613613

614-
char *msEvalTextExpression(expressionObj *expr, shapeObj *shape)
614+
static
615+
char *msEvalTextExpressionInternal(expressionObj *expr, shapeObj *shape, int bJSonEscape)
615616
{
616617
char *result=NULL;
617618

@@ -620,6 +621,7 @@ char *msEvalTextExpression(expressionObj *expr, shapeObj *shape)
620621
switch(expr->type) {
621622
case(MS_STRING): {
622623
char *target=NULL;
624+
char *pszEscaped;
623625
tokenListNodeObjPtr node=NULL;
624626
tokenListNodeObjPtr nextNode=NULL;
625627

@@ -632,7 +634,12 @@ char *msEvalTextExpression(expressionObj *expr, shapeObj *shape)
632634
if(node->token == MS_TOKEN_BINDING_DOUBLE || node->token == MS_TOKEN_BINDING_INTEGER || node->token == MS_TOKEN_BINDING_STRING || node->token == MS_TOKEN_BINDING_TIME) {
633635
target = (char *) msSmallMalloc(strlen(node->tokenval.bindval.item) + 3);
634636
sprintf(target, "[%s]", node->tokenval.bindval.item);
635-
result = msReplaceSubstring(result, target, shape->values[node->tokenval.bindval.index]);
637+
if( bJSonEscape )
638+
pszEscaped = msEscapeJSonString(shape->values[node->tokenval.bindval.index]);
639+
else
640+
pszEscaped = msStrdup(shape->values[node->tokenval.bindval.index]);
641+
result = msReplaceSubstring(result, target, pszEscaped);
642+
msFree(pszEscaped);
636643
msFree(target);
637644
}
638645
node = nextNode;
@@ -673,6 +680,16 @@ char *msEvalTextExpression(expressionObj *expr, shapeObj *shape)
673680
return result;
674681
}
675682

683+
char *msEvalTextExpressionJSonEscape(expressionObj *expr, shapeObj *shape)
684+
{
685+
return msEvalTextExpressionInternal(expr, shape, TRUE);
686+
}
687+
688+
char *msEvalTextExpression(expressionObj *expr, shapeObj *shape)
689+
{
690+
return msEvalTextExpressionInternal(expr, shape, FALSE);
691+
}
692+
676693
char* msShapeGetLabelAnnotation(layerObj *layer, shapeObj *shape, labelObj *lbl) {
677694
assert(shape && lbl);
678695
if(lbl->text.string) {

msautotest

Submodule msautotest updated from a65ae12 to 2843082

0 commit comments

Comments
 (0)