[mapserver] 01/04: Imported Upstream version 7.0.0~beta2
Sebastiaan Couwenberg
sebastic at moszumanska.debian.org
Tue Jul 7 20:21:29 UTC 2015
This is an automated email from the git hooks/post-receive script.
sebastic pushed a commit to branch experimental
in repository mapserver.
commit b22943a2e4276668e6e627c850c135be08082b45
Author: Bas Couwenberg <sebastic at xs4all.nl>
Date: Tue Jul 7 21:38:01 2015 +0200
Imported Upstream version 7.0.0~beta2
---
CMakeLists.txt | 4 +-
GD-COPYING | 50 ----
fontcache.c | 4 +-
mapdraw.c | 93 ++++----
mapgeos.c | 1 +
maplegend.c | 18 ++
mapmssql2008.c | 541 +++++++++++++++++++++++++++++++++++++++++---
mapogcfilter.c | 3 +-
mapogcfiltercommon.c | 208 ++++++++---------
mapows.c | 29 +++
mappluginlayer.c | 7 +
maprasterquery.c | 6 +-
maprendering.c | 65 +++++-
mapscript/php/map.c | 2 +-
mapserver.h | 3 +-
mapshape.c | 2 +-
mapsymbol.c | 3 +
mapwcs20.c | 12 +-
mapwfslayer.c | 2 -
mapwms.c | 48 +++-
scripts/vagrant/packages.sh | 2 +-
21 files changed, 824 insertions(+), 279 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 006910b..8a6ca68 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -16,9 +16,9 @@ include(CheckCSourceCompiles)
set (MapServer_VERSION_MAJOR 7)
-set (MapServer_VERSION_MINOR 1)
+set (MapServer_VERSION_MINOR 0)
set (MapServer_VERSION_REVISION 0)
-set (MapServer_VERSION_SUFFIX "")
+set (MapServer_VERSION_SUFFIX "-beta2")
set(TARGET_VERSION_MAJOR ${MapServer_VERSION_MAJOR})
set(TARGET_VERSION_MINOR ${MapServer_VERSION_MINOR})
diff --git a/GD-COPYING b/GD-COPYING
deleted file mode 100644
index 3e6ccc9..0000000
--- a/GD-COPYING
+++ /dev/null
@@ -1,50 +0,0 @@
-
- Portions copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
- 2002 by Cold Spring Harbor Laboratory. Funded under Grant
- P41-RR02188 by the National Institutes of Health.
-
- Portions copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002 by
- Boutell.Com, Inc.
-
- Portions relating to GD2 format copyright 1999, 2000, 2001, 2002
- Philip Warner.
-
- Portions relating to PNG copyright 1999, 2000, 2001, 2002 Greg
- Roelofs.
-
- Portions relating to gdttf.c copyright 1999, 2000, 2001, 2002 John
- Ellson (ellson at lucent.com).
-
- Portions relating to gdft.c copyright 2001, 2002 John Ellson
- (ellson at lucent.com).
-
- Portions relating to JPEG and to color quantization copyright 2000,
- 2001, 2002, Doug Becker and copyright (C) 1994, 1995, 1996, 1997,
- 1998, 1999, 2000, 2001, 2002, Thomas G. Lane. This software is
- based in part on the work of the Independent JPEG Group. See the
- file README-JPEG.TXT for more information.
-
- Portions relating to WBMP copyright 2000, 2001, 2002 Maurice
- Szmurlo and Johan Van den Brande.
-
- Permission has been granted to copy, distribute and modify gd in
- any context without fee, including a commercial application,
- provided that this notice is present in user-accessible supporting
- documentation.
-
- This does not affect your ownership of the derived work itself, and
- the intent is to assure proper credit for the authors of gd, not to
- interfere with your productive use of gd. If you have questions,
- ask. "Derived works" includes all programs that utilize the
- library. Credit must be given in user-accessible documentation.
-
- This software is provided "AS IS." The copyright holders disclaim
- all warranties, either express or implied, including but not
- limited to implied warranties of merchantability and fitness for a
- particular purpose, with respect to this code and accompanying
- documentation.
-
- Although their code does not appear in gd, the authors wish to thank
- David Koblas, David Rowley, and Hutchison Avenue Software Corporation
- for their prior contributions.
-
diff --git a/fontcache.c b/fontcache.c
index 4a12a13..e43eafe 100644
--- a/fontcache.c
+++ b/fontcache.c
@@ -86,6 +86,7 @@ void msFreeFontCache(ft_cache *c) {
}
#endif
FT_Done_Face(cur_face->face);
+ free(cur_face->font);
UT_HASH_DEL(c->face_cache,cur_face);
free(cur_face);
}
@@ -227,9 +228,10 @@ face_element* msGetFontFace(char *key, fontSetObj *fontset) {
FT_Select_Charmap(fc->face, FT_ENCODING_APPLE_ROMAN);
/* the previous calls may have failed, we ignore as there's nothing much left to do */
}
- fc->font = key;
+ fc->font = msStrdup(key);
UT_HASH_ADD_KEYPTR(hh,cache->face_cache,fc->font, strlen(key), fc);
}
+
return fc;
}
diff --git a/mapdraw.c b/mapdraw.c
index 5da1edb..1221b90 100644
--- a/mapdraw.c
+++ b/mapdraw.c
@@ -328,6 +328,8 @@ imageObj *msDrawMap(mapObj *map, int querymap)
for(i=0; i<map->numlayers; i++) {
if(map->layerorder[i] != -1) {
+ char *force_draw_label_cache = NULL;
+
lp = (GET_LAYER(map, map->layerorder[i]));
if(lp->postlabelcache) /* wait to draw */
@@ -389,6 +391,27 @@ imageObj *msDrawMap(mapObj *map, int querymap)
(endtime.tv_sec+endtime.tv_usec/1.0e6)-
(starttime.tv_sec+starttime.tv_usec/1.0e6) );
}
+
+ /* Flush layer cache in-between layers if requested by PROCESSING directive*/
+ force_draw_label_cache = msLayerGetProcessingKey(lp, "FORCE_DRAW_LABEL_CACHE");
+ if (force_draw_label_cache &&
+ strncasecmp(force_draw_label_cache,"FLUSH",5)==0) {
+ if(map->debug >= MS_DEBUGLEVEL_V)
+ msDebug("msDrawMap(): PROCESSING FORCE_DRAW_LABEL_CACHE=FLUSH found.\n");
+ if(msDrawLabelCache(map, image) != MS_SUCCESS) {
+ msFreeImage(image);
+#if defined(USE_WMS_LYR) || defined(USE_WFS_LYR)
+ if (pasOWSReqInfo) {
+ msHTTPFreeRequestObj(pasOWSReqInfo, numOWSRequests);
+ msFree(pasOWSReqInfo);
+ }
+#endif /* USE_WMS_LYR || USE_WFS_LYR */
+ return(NULL);
+ }
+ msFreeLabelCache(&(map->labelcache));
+ msInitLabelCache(&(map->labelcache));
+ } /* PROCESSING FORCE_DRAW_LABEL_CACHE */
+
}
}
@@ -431,8 +454,6 @@ imageObj *msDrawMap(mapObj *map, int querymap)
}
}
- if(map->debug >= MS_DEBUGLEVEL_TUNING) msGettimeofday(&starttime, NULL);
-
if(msDrawLabelCache(map, image) != MS_SUCCESS) {
msFreeImage(image);
#if defined(USE_WMS_LYR) || defined(USE_WFS_LYR)
@@ -444,12 +465,6 @@ imageObj *msDrawMap(mapObj *map, int querymap)
return(NULL);
}
- if(map->debug >= MS_DEBUGLEVEL_TUNING) {
- msGettimeofday(&endtime, NULL);
- msDebug("msDrawMap(): Drawing Label Cache, %.3fs\n",
- (endtime.tv_sec+endtime.tv_usec/1.0e6)-
- (starttime.tv_sec+starttime.tv_usec/1.0e6) );
- }
for(i=0; i<map->numlayers; i++) { /* for each layer, check for postlabelcache layers */
@@ -1007,7 +1022,6 @@ int msDrawVectorLayer(mapObj *map, layerObj *layer, imageObj *image)
if (cache) {
styleObj *pStyle = layer->class[shape.classindex]->styles[0];
- colorObj tmp;
if (pStyle->outlinewidth > 0) {
/*
* RFC 49 implementation
@@ -1017,17 +1031,7 @@ int msDrawVectorLayer(mapObj *map, layerObj *layer, imageObj *image)
* - draw the shape (the outline) in the first pass of the
* caching mechanism
*/
-
- /* adapt width (must take scalefactor into account) */
- pStyle->width += (pStyle->outlinewidth / (layer->scalefactor/image->resolutionfactor)) * 2;
- pStyle->minwidth += pStyle->outlinewidth * 2;
- pStyle->maxwidth += pStyle->outlinewidth * 2;
- pStyle->size += (pStyle->outlinewidth/layer->scalefactor*(map->resolution/map->defresolution));
-
- /*swap color and outlinecolor*/
- tmp = pStyle->color;
- pStyle->color = pStyle->outlinecolor;
- pStyle->outlinecolor = tmp;
+ msOutlineRenderingPrepareStyle(pStyle, map, layer, image);
}
status = msDrawShape(map, layer, &shape, image, 0, drawmode|MS_DRAWMODE_SINGLESTYLE); /* draw a single style */
if (pStyle->outlinewidth > 0) {
@@ -1036,17 +1040,7 @@ int msDrawVectorLayer(mapObj *map, layerObj *layer, imageObj *image)
* original state, so the line fill will be drawn in the
* second pass of the caching mechanism
*/
-
- /* reset widths to original state */
- pStyle->width -= (pStyle->outlinewidth / (layer->scalefactor/image->resolutionfactor)) * 2;
- pStyle->minwidth -= pStyle->outlinewidth * 2;
- pStyle->maxwidth -= pStyle->outlinewidth * 2;
- pStyle->size -= (pStyle->outlinewidth/layer->scalefactor*(map->resolution/map->defresolution));
-
- /*reswap colors to original state*/
- tmp = pStyle->color;
- pStyle->color = pStyle->outlinecolor;
- pStyle->outlinecolor = tmp;
+ msOutlineRenderingRestoreStyle(pStyle, map, layer, image);
}
}
@@ -1107,7 +1101,6 @@ int msDrawVectorLayer(mapObj *map, layerObj *layer, imageObj *image)
}
} else if(s>0) {
if (pStyle->outlinewidth > 0 && MS_VALID_COLOR(pStyle->outlinecolor)) {
- colorObj tmp;
/*
* RFC 49 implementation
* if an outlinewidth is used:
@@ -1116,17 +1109,7 @@ int msDrawVectorLayer(mapObj *map, layerObj *layer, imageObj *image)
* - draw the shape (the outline) in the first pass of the
* caching mechanism
*/
-
- /* adapt width (must take scalefactor into account) */
- pStyle->width += (pStyle->outlinewidth / (layer->scalefactor/image->resolutionfactor)) * 2;
- pStyle->minwidth += pStyle->outlinewidth * 2;
- pStyle->maxwidth += pStyle->outlinewidth * 2;
- pStyle->size += (pStyle->outlinewidth/layer->scalefactor*(map->resolution/map->defresolution));
-
- /*swap color and outlinecolor*/
- tmp = pStyle->color;
- pStyle->color = pStyle->outlinecolor;
- pStyle->outlinecolor = tmp;
+ msOutlineRenderingPrepareStyle(pStyle, map, layer, image);
if(UNLIKELY(MS_FAILURE == msDrawLineSymbol(map, image, ¤t->shape, pStyle, layer->scalefactor))) {
return MS_FAILURE;
}
@@ -1135,17 +1118,7 @@ int msDrawVectorLayer(mapObj *map, layerObj *layer, imageObj *image)
* original state, so the line fill will be drawn in the
* second pass of the caching mechanism
*/
-
- /* reset widths to original state */
- pStyle->width -= (pStyle->outlinewidth / (layer->scalefactor/image->resolutionfactor)) * 2;
- pStyle->minwidth -= pStyle->outlinewidth * 2;
- pStyle->maxwidth -= pStyle->outlinewidth * 2;
- pStyle->size -= (pStyle->outlinewidth/layer->scalefactor*(map->resolution/map->defresolution));
-
- /*reswap colors to original state*/
- tmp = pStyle->color;
- pStyle->color = pStyle->outlinecolor;
- pStyle->outlinecolor = tmp;
+ msOutlineRenderingRestoreStyle(pStyle, map, layer, image);
}
/* draw a valid line, i.e. one with a color defined or of type pixmap*/
if(MS_VALID_COLOR(pStyle->color) ||
@@ -2680,6 +2653,9 @@ void copyLabelBounds(label_bounds *dst, label_bounds *src) {
int msDrawLabelCache(mapObj *map, imageObj *image)
{
int nReturnVal = MS_SUCCESS;
+ struct mstimeval starttime, endtime;
+
+ if(map->debug >= MS_DEBUGLEVEL_TUNING) msGettimeofday(&starttime, NULL);
if(image) {
if(MS_RENDERER_PLUGIN(image->format)) {
@@ -3139,10 +3115,17 @@ int msDrawLabelCache(mapObj *map, imageObj *image)
}
#endif
- return MS_SUCCESS; /* necessary? */
+ nReturnVal = MS_SUCCESS; /* necessary? */
}
}
+ if(map->debug >= MS_DEBUGLEVEL_TUNING) {
+ msGettimeofday(&endtime, NULL);
+ msDebug("msDrawMap(): Drawing Label Cache, %.3fs\n",
+ (endtime.tv_sec+endtime.tv_usec/1.0e6)-
+ (starttime.tv_sec+starttime.tv_usec/1.0e6) );
+ }
+
return nReturnVal;
}
diff --git a/mapgeos.c b/mapgeos.c
index 08c9b64..b8f25f0 100644
--- a/mapgeos.c
+++ b/mapgeos.c
@@ -720,6 +720,7 @@ void msGEOSFreeGeometry(shapeObj *shape)
g = (GEOSGeom) shape->geometry;
GEOSGeom_destroy_r(handle,g);
+ shape->geometry = NULL;
#else
msSetError(MS_GEOSERR, "GEOS support is not available.", "msGEOSFreeGEOSGeom()");
return;
diff --git a/maplegend.c b/maplegend.c
index 7986b33..a8dd733 100644
--- a/maplegend.c
+++ b/maplegend.c
@@ -218,10 +218,28 @@ int msDrawLegendIcon(mapObj *map, layerObj *lp, classObj *theclass,
if (theclass->styles[i]->_geomtransform.type == MS_GEOMTRANSFORM_NONE ||
theclass->styles[i]->_geomtransform.type == MS_GEOMTRANSFORM_LABELPOINT ||
theclass->styles[i]->_geomtransform.type == MS_GEOMTRANSFORM_LABELPOLY) {
+ if (theclass->styles[i]->outlinewidth > 0) {
+ /* Swap the style contents to render the outline first,
+ * and then restore the style to render the interior of the line
+ */
+ msOutlineRenderingPrepareStyle(theclass->styles[i], map, lp, image);
+ ret = msDrawLineSymbol(map, image_draw, &zigzag, theclass->styles[i], lp->scalefactor * image_draw->resolutionfactor);
+ msOutlineRenderingRestoreStyle(theclass->styles[i], map, lp, image);
+ if(UNLIKELY(ret == MS_FAILURE)) goto legend_icon_cleanup;
+ }
ret = msDrawLineSymbol(map, image_draw, &zigzag, theclass->styles[i], lp->scalefactor * image_draw->resolutionfactor);
if(UNLIKELY(ret == MS_FAILURE)) goto legend_icon_cleanup;
}
else {
+ if (theclass->styles[i]->outlinewidth > 0) {
+ /* Swap the style contents to render the outline first,
+ * and then restore the style to render the interior of the line
+ */
+ msOutlineRenderingPrepareStyle(theclass->styles[i], map, lp, image);
+ ret = msDrawTransformedShape(map, image_draw, &zigzag, theclass->styles[i], lp->scalefactor * image_draw->resolutionfactor);
+ msOutlineRenderingRestoreStyle(theclass->styles[i], map, lp, image);
+ if(UNLIKELY(ret == MS_FAILURE)) goto legend_icon_cleanup;
+ }
ret = msDrawTransformedShape(map, image_draw, &zigzag, theclass->styles[i], lp->scalefactor * image_draw->resolutionfactor);
if(UNLIKELY(ret == MS_FAILURE)) goto legend_icon_cleanup;
}
diff --git a/mapmssql2008.c b/mapmssql2008.c
index b1b74d2..cea2026 100644
--- a/mapmssql2008.c
+++ b/mapmssql2008.c
@@ -49,7 +49,55 @@
#include <string.h>
#include <ctype.h> /* tolower() */
+/* SqlGeometry serialization format
+Simple Point (SerializationProps & IsSinglePoint)
+ [SRID][0x01][SerializationProps][Point][z][m]
+
+Simple Line Segment (SerializationProps & IsSingleLineSegment)
+ [SRID][0x01][SerializationProps][Point1][Point2][z1][z2][m1][m2]
+
+Complex Geometries
+ [SRID][0x01][SerializationProps][NumPoints][Point1]..[PointN][z1]..[zN][m1]..[mN]
+ [NumFigures][Figure]..[Figure][NumShapes][Shape]..[Shape]
+
+SRID
+ Spatial Reference Id (4 bytes)
+
+SerializationProps (bitmask) 1 byte
+ 0x01 = HasZValues
+ 0x02 = HasMValues
+ 0x04 = IsValid
+ 0x08 = IsSinglePoint
+ 0x10 = IsSingleLineSegment
+ 0x20 = IsWholeGlobe
+
+Point (2-4)x8 bytes, size depends on SerializationProps & HasZValues & HasMValues
+ [x][y] - SqlGeometry
+ [latitude][longitude] - SqlGeography
+
+Figure
+ [FigureAttribute][PointOffset]
+
+FigureAttribute (1 byte)
+ 0x00 = Interior Ring
+ 0x01 = Stroke
+ 0x02 = Exterior Ring
+
+Shape
+ [ParentFigureOffset][FigureOffset][ShapeType]
+
+ShapeType (1 byte)
+ 0x00 = Unknown
+ 0x01 = Point
+ 0x02 = LineString
+ 0x03 = Polygon
+ 0x04 = MultiPoint
+ 0x05 = MultiLineString
+ 0x06 = MultiPolygon
+ 0x07 = GeometryCollection
+
+*/
/* Native geometry parser macros */
@@ -118,6 +166,7 @@ typedef struct msGeometryParserInfo_t {
int nPointSize;
int nPointPos;
int nNumPoints;
+ int nNumPointsRead;
/* figure array */
int nFigurePos;
int nNumFigures;
@@ -156,6 +205,7 @@ typedef struct ms_MSSQL2008_layer_info_t {
msODBCconn * conn; /* Connection to db */
msGeometryParserInfo gpi; /* struct for the geometry parser */
int geometry_format; /* Geometry format to be retrieved from the database */
+ tokenListNodeObjPtr current_node; /* filter expression translation */
} msMSSQL2008LayerInfo;
#define SQL_COLUMN_NAME_MAX_LENGTH 128
@@ -170,7 +220,7 @@ typedef struct ms_MSSQL2008_layer_info_t {
"mapmssql2008.c - version of 2007/7/1.\n"
/* Native geometry parser code */
-void ReadPoint(msGeometryParserInfo* gpi, pointObj* p, int iPoint, int iOrder)
+void ReadPoint(msGeometryParserInfo* gpi, pointObj* p, int iPoint)
{
if (gpi->nColType == MSSQLCOLTYPE_GEOGRAPHY) {
p->x = ReadY(iPoint);
@@ -180,7 +230,7 @@ void ReadPoint(msGeometryParserInfo* gpi, pointObj* p, int iPoint, int iOrder)
p->y = ReadY(iPoint);
}
/* calculate bounds */
- if (iOrder == 0) {
+ if (gpi->nNumPointsRead++ == 0) {
gpi->minx = gpi->maxx = p->x;
gpi->miny = gpi->maxy = p->y;
} else {
@@ -202,6 +252,8 @@ int ParseSqlGeometry(msMSSQL2008LayerInfo* layerinfo, shapeObj *shape)
{
msGeometryParserInfo* gpi = &layerinfo->gpi;
+ gpi->nNumPointsRead = 0;
+
if (gpi->nLen < 10) {
msDebug("ParseSqlGeometry NOT_ENOUGH_DATA\n");
return NOT_ENOUGH_DATA;
@@ -239,7 +291,7 @@ int ParseSqlGeometry(msMSSQL2008LayerInfo* layerinfo, shapeObj *shape)
shape->line[0].numpoints = 1;
gpi->nPointPos = 6;
- ReadPoint(gpi, &shape->line[0].point[0], 0, 0);
+ ReadPoint(gpi, &shape->line[0].point[0], 0);
} else if ( gpi->chProps & SP_ISSINGLELINESEGMENT ) {
// single line segment with 2 points
gpi->nNumPoints = 2;
@@ -255,8 +307,8 @@ int ParseSqlGeometry(msMSSQL2008LayerInfo* layerinfo, shapeObj *shape)
shape->line[0].numpoints = 2;
gpi->nPointPos = 6;
- ReadPoint(gpi, &shape->line[0].point[0], 0, 0);
- ReadPoint(gpi, &shape->line[0].point[1], 1, 1);
+ ReadPoint(gpi, &shape->line[0].point[0], 0);
+ ReadPoint(gpi, &shape->line[0].point[1], 1);
} else {
int iShape, iFigure;
// complex geometries
@@ -335,7 +387,7 @@ int ParseSqlGeometry(msMSSQL2008LayerInfo* layerinfo, shapeObj *shape)
i = 0;
while (iPoint < iNextPoint) {
- ReadPoint(gpi, &shape->line[iFigure].point[i], iPoint, i);
+ ReadPoint(gpi, &shape->line[iFigure].point[i], iPoint);
++iPoint;
++i;
}
@@ -758,6 +810,28 @@ int msMSSQL2008LayerInitItemInfo(layerObj *layer)
return MS_SUCCESS;
}
+/* Get the layer extent as specified in the mapfile or a largest area */
+/* covering all features */
+int msMSSQL2008LayerGetExtent(layerObj *layer, rectObj *extent)
+{
+ if(layer->debug) {
+ msDebug("msMSSQL2008LayerGetExtent called\n");
+ }
+
+ if (layer->extent.minx == -1.0 && layer->extent.miny == -1.0 &&
+ layer->extent.maxx == -1.0 && layer->extent.maxy == -1.0) {
+ extent->minx = extent->miny = -1.0 * FLT_MAX;
+ extent->maxx = extent->maxy = FLT_MAX;
+ } else {
+ extent->minx = layer->extent.minx;
+ extent->miny = layer->extent.miny;
+ extent->maxx = layer->extent.maxx;
+ extent->maxy = layer->extent.maxy;
+ }
+
+ return MS_SUCCESS;
+}
+
/* Prepare and execute the SQL statement for this layer */
static int prepare_database(layerObj *layer, rectObj rect, char **query_string)
{
@@ -908,13 +982,19 @@ static int prepare_database(layerObj *layer, rectObj rect, char **query_string)
msMSSQL2008LayerGetExtent(layer, &extent);
if (rect.minx <= extent.minx && rect.miny <= extent.miny && rect.maxx >= extent.maxx && rect.maxy >= extent.maxy) {
/* no spatial filter used */
- if(msLayerGetProcessingKey(layer, "NATIVE_FILTER") == NULL) {
+ if ( layer->filter.native_string ) {
+ snprintf(query_string_temp, sizeof(query_string_temp), "SELECT %s from %s WHERE (%s)", columns_wanted, data_source, layer->filter.native_string );
+ }
+ else if(msLayerGetProcessingKey(layer, "NATIVE_FILTER") == NULL) {
snprintf(query_string_temp, sizeof(query_string_temp), "SELECT %s from %s", columns_wanted, data_source );
} else {
snprintf(query_string_temp, sizeof(query_string_temp), "SELECT %s from %s WHERE (%s)", columns_wanted, data_source, msLayerGetProcessingKey(layer, "NATIVE_FILTER"));
}
} else {
- if(msLayerGetProcessingKey(layer, "NATIVE_FILTER") == NULL) {
+ if ( layer->filter.native_string ) {
+ snprintf(query_string_temp, sizeof(query_string_temp), "SELECT %s from %s WHERE (%s) and %s.STIntersects(%s) = 1 ", columns_wanted, data_source, layer->filter.native_string, layerinfo->geom_column, box3d );
+ }
+ else if(msLayerGetProcessingKey(layer, "NATIVE_FILTER") == NULL) {
snprintf(query_string_temp, sizeof(query_string_temp), "SELECT %s from %s WHERE %s.STIntersects(%s) = 1 ", columns_wanted, data_source, layerinfo->geom_column, box3d );
} else {
snprintf(query_string_temp, sizeof(query_string_temp), "SELECT %s from %s WHERE (%s) and %s.STIntersects(%s) = 1 ", columns_wanted, data_source, msLayerGetProcessingKey(layer, "NATIVE_FILTER"), layerinfo->geom_column, box3d );
@@ -1900,28 +1980,6 @@ int msMSSQL2008LayerGetItems(layerObj *layer)
return msMSSQL2008LayerInitItemInfo(layer);
}
-/* Get the layer extent as specified in the mapfile or a largest area */
-/* covering all features */
-int msMSSQL2008LayerGetExtent(layerObj *layer, rectObj *extent)
-{
- if(layer->debug) {
- msDebug("msMSSQL2008LayerGetExtent called\n");
- }
-
- if (layer->extent.minx == -1.0 && layer->extent.miny == -1.0 &&
- layer->extent.maxx == -1.0 && layer->extent.maxy == -1.0) {
- extent->minx = extent->miny = -1.0 * FLT_MAX;
- extent->maxx = extent->maxy = FLT_MAX;
- } else {
- extent->minx = layer->extent.minx;
- extent->miny = layer->extent.miny;
- extent->maxx = layer->extent.maxx;
- extent->maxy = layer->extent.maxy;
- }
-
- return MS_SUCCESS;
-}
-
/* Get primary key column of table */
int msMSSQL2008LayerRetrievePK(layerObj *layer, char **urid_name, char* table_name, int debug)
{
@@ -2141,6 +2199,399 @@ static int msMSSQL2008LayerParseData(layerObj *layer, char **geom_column_name, c
return MS_SUCCESS;
}
+char *msMSSQL2008LayerEscapePropertyName(layerObj *layer, const char* pszString)
+{
+ char* pszEscapedStr=NULL;
+ int i, j = 0;
+
+ if (pszString && strlen(pszString) > 0) {
+ int nLength = strlen(pszString);
+
+ pszEscapedStr = (char*) msSmallMalloc( 1 + nLength + 1 + 1);
+ pszEscapedStr[j++] = '[';
+
+ for (i=0; i<nLength; i++)
+ pszEscapedStr[j++] = pszString[i];
+
+ pszEscapedStr[j++] = ']';
+ pszEscapedStr[j++] = 0;
+ }
+ return pszEscapedStr;
+}
+
+char *msMSSQL2008LayerEscapeSQLParam(layerObj *layer, const char *pszString)
+{
+ char *pszEscapedStr=NULL;
+ if (pszString) {
+ int nSrcLen;
+ char c;
+ int i=0, j=0;
+ nSrcLen = (int)strlen(pszString);
+ pszEscapedStr = (char*) msSmallMalloc( 2 * nSrcLen + 1);
+ for(i = 0, j = 0; i < nSrcLen; i++) {
+ c = pszString[i];
+ if (c == '\'') {
+ pszEscapedStr[j++] = '\'';
+ pszEscapedStr[j++] = '\'';
+ } else
+ pszEscapedStr[j++] = c;
+ }
+ pszEscapedStr[j] = 0;
+ }
+ return pszEscapedStr;
+}
+
+int process_node(layerObj* layer, expressionObj *filter)
+{
+ char *snippet = NULL;
+ char *strtmpl = NULL;
+ char *stresc = NULL;
+ msMSSQL2008LayerInfo *layerinfo = (msMSSQL2008LayerInfo *) layer->layerinfo;
+
+ if (!layerinfo->current_node)
+ {
+ msSetError(MS_MISCERR, "Unecpected end of expression", "msMSSQL2008LayerTranslateFilter()");
+ return 0;
+ }
+
+ switch(layerinfo->current_node->token) {
+ case '(':
+ filter->native_string = msStringConcatenate(filter->native_string, "(");
+ /* process subexpression */
+ layerinfo->current_node = layerinfo->current_node->next;
+ while (layerinfo->current_node != NULL) {
+ if (!process_node(layer, filter))
+ return 0;
+ if (!layerinfo->current_node)
+ break;
+ if (layerinfo->current_node->token == ')')
+ break;
+ layerinfo->current_node = layerinfo->current_node->next;
+ }
+ break;
+ case ')':
+ filter->native_string = msStringConcatenate(filter->native_string, ")");
+ break;
+ /* literal tokens */
+ case MS_TOKEN_LITERAL_BOOLEAN:
+ case MS_TOKEN_LITERAL_NUMBER:
+ strtmpl = "%lf";
+ snippet = (char *) msSmallMalloc(strlen(strtmpl) + 16);
+ sprintf(snippet, strtmpl, layerinfo->current_node->tokenval.dblval);
+ filter->native_string = msStringConcatenate(filter->native_string, snippet);
+ msFree(snippet);
+ break;
+ case MS_TOKEN_LITERAL_STRING:
+ strtmpl = "'%s'";
+ stresc = msMSSQL2008LayerEscapeSQLParam(layer, layerinfo->current_node->tokenval.strval);
+ snippet = (char *) msSmallMalloc(strlen(strtmpl) + strlen(stresc));
+ sprintf(snippet, strtmpl, stresc);
+ filter->native_string = msStringConcatenate(filter->native_string, snippet);
+ msFree(snippet);
+ msFree(stresc);
+ break;
+ case MS_TOKEN_LITERAL_TIME:
+ {
+ char buffer[30];
+ if(strftime(buffer,30,"'%Y-%m-%d %H:%M:%S'",&layerinfo->current_node->tokenval.tmval) == 0) {
+ msSetError(MS_MISCERR, "Invalid time literal in expression", "msMSSQL2008LayerTranslateFilter()");
+ return 0;
+ }
+ filter->native_string = msStringConcatenate(filter->native_string, buffer);
+ }
+ break;
+ case MS_TOKEN_LITERAL_SHAPE:
+ if (strcasecmp(layerinfo->geom_column_type, "geography") == 0)
+ filter->native_string = msStringConcatenate(filter->native_string, "geography::STGeomFromText('");
+ else
+ filter->native_string = msStringConcatenate(filter->native_string, "geometry::STGeomFromText('");
+ filter->native_string = msStringConcatenate(filter->native_string, msShapeToWKT(layerinfo->current_node->tokenval.shpval));
+ filter->native_string = msStringConcatenate(filter->native_string, "'");
+ if(layerinfo->user_srid && strcmp(layerinfo->user_srid, "") != 0) {
+ filter->native_string = msStringConcatenate(filter->native_string, ", ");
+ filter->native_string = msStringConcatenate(filter->native_string, layerinfo->user_srid);
+ }
+ filter->native_string = msStringConcatenate(filter->native_string, ")");
+ break;
+ case MS_TOKEN_BINDING_TIME:
+ case MS_TOKEN_BINDING_DOUBLE:
+ case MS_TOKEN_BINDING_INTEGER:
+ case MS_TOKEN_BINDING_STRING:
+ strtmpl = "%s";
+ stresc = msMSSQL2008LayerEscapePropertyName(layer, layerinfo->current_node->tokenval.bindval.item);
+ snippet = (char *) msSmallMalloc(strlen(strtmpl) + strlen(stresc));
+ sprintf(snippet, strtmpl, stresc);
+ filter->native_string = msStringConcatenate(filter->native_string, snippet);
+ msFree(snippet);
+ msFree(stresc);
+ break;
+ case MS_TOKEN_BINDING_SHAPE:
+ filter->native_string = msStringConcatenate(filter->native_string, layerinfo->geom_column);
+ break;
+ case MS_TOKEN_BINDING_MAP_CELLSIZE:
+ strtmpl = "%lf";
+ snippet = (char *) msSmallMalloc(strlen(strtmpl) + 16);
+ sprintf(snippet, strtmpl, layer->map->cellsize);
+ filter->native_string = msStringConcatenate(filter->native_string, snippet);
+ msFree(snippet);
+ break;
+
+ /* comparisons */
+ case MS_TOKEN_COMPARISON_IN:
+ filter->native_string = msStringConcatenate(filter->native_string, " IN ");
+ break;
+ case MS_TOKEN_COMPARISON_LIKE:
+ filter->native_string = msStringConcatenate(filter->native_string, " LIKE ");
+ break;
+ case MS_TOKEN_COMPARISON_EQ:
+ filter->native_string = msStringConcatenate(filter->native_string, " = ");
+ break;
+ case MS_TOKEN_COMPARISON_NE:
+ filter->native_string = msStringConcatenate(filter->native_string, " != ");
+ break;
+ case MS_TOKEN_COMPARISON_GT:
+ filter->native_string = msStringConcatenate(filter->native_string, " > ");
+ break;
+ case MS_TOKEN_COMPARISON_GE:
+ filter->native_string = msStringConcatenate(filter->native_string, " >= ");
+ break;
+ case MS_TOKEN_COMPARISON_LT:
+ filter->native_string = msStringConcatenate(filter->native_string, " < ");
+ break;
+ case MS_TOKEN_COMPARISON_LE:
+ filter->native_string = msStringConcatenate(filter->native_string, " <= ");
+ break;
+
+ /* logical ops */
+ case MS_TOKEN_LOGICAL_AND:
+ filter->native_string = msStringConcatenate(filter->native_string, " AND ");
+ break;
+ case MS_TOKEN_LOGICAL_OR:
+ filter->native_string = msStringConcatenate(filter->native_string, " OR ");
+ break;
+ case MS_TOKEN_LOGICAL_NOT:
+ filter->native_string = msStringConcatenate(filter->native_string, " NOT ");
+ break;
+
+ /* spatial comparison tokens */
+ case MS_TOKEN_COMPARISON_INTERSECTS:
+ filter->native_string = msStringConcatenate(filter->native_string, ".STIntersects(");
+ layerinfo->current_node = layerinfo->current_node->next;
+ if (!process_node(layer, filter))
+ return 0;
+ filter->native_string = msStringConcatenate(filter->native_string, ")=1");
+ break;
+
+ case MS_TOKEN_COMPARISON_DISJOINT:
+ filter->native_string = msStringConcatenate(filter->native_string, ".STDisjoint(");
+ layerinfo->current_node = layerinfo->current_node->next;
+ if (!process_node(layer, filter))
+ return 0;
+ filter->native_string = msStringConcatenate(filter->native_string, ")=1");
+ break;
+
+ case MS_TOKEN_COMPARISON_TOUCHES:
+ filter->native_string = msStringConcatenate(filter->native_string, ".STTouches(");
+ layerinfo->current_node = layerinfo->current_node->next;
+ if (!process_node(layer, filter))
+ return 0;
+ filter->native_string = msStringConcatenate(filter->native_string, ")=1");
+ break;
+
+ case MS_TOKEN_COMPARISON_OVERLAPS:
+ filter->native_string = msStringConcatenate(filter->native_string, ".STOverlaps(");
+ layerinfo->current_node = layerinfo->current_node->next;
+ if (!process_node(layer, filter))
+ return 0;
+ filter->native_string = msStringConcatenate(filter->native_string, ")=1");
+ break;
+
+ case MS_TOKEN_COMPARISON_CROSSES:
+ filter->native_string = msStringConcatenate(filter->native_string, ".STCrosses(");
+ layerinfo->current_node = layerinfo->current_node->next;
+ if (!process_node(layer, filter))
+ return 0;
+ filter->native_string = msStringConcatenate(filter->native_string, ")=1");
+ break;
+
+ case MS_TOKEN_COMPARISON_WITHIN:
+ filter->native_string = msStringConcatenate(filter->native_string, ".STWithin(");
+ layerinfo->current_node = layerinfo->current_node->next;
+ if (!process_node(layer, filter))
+ return 0;
+ filter->native_string = msStringConcatenate(filter->native_string, ")=1");
+ break;
+
+ case MS_TOKEN_COMPARISON_CONTAINS:
+ filter->native_string = msStringConcatenate(filter->native_string, ".STContains(");
+ layerinfo->current_node = layerinfo->current_node->next;
+ if (!process_node(layer, filter))
+ return 0;
+ filter->native_string = msStringConcatenate(filter->native_string, ")=1");
+ break;
+
+ case MS_TOKEN_COMPARISON_EQUALS:
+ filter->native_string = msStringConcatenate(filter->native_string, ".STEquals(");
+ layerinfo->current_node = layerinfo->current_node->next;
+ if (!process_node(layer, filter))
+ return 0;
+ filter->native_string = msStringConcatenate(filter->native_string, ")=1");
+ break;
+
+ case MS_TOKEN_COMPARISON_BEYOND:
+ msSetError(MS_MISCERR, "Beyond operator is unsupported.", "msMSSQL2008LayerTranslateFilter()");
+ return 0;
+
+ case MS_TOKEN_COMPARISON_DWITHIN:
+ msSetError(MS_MISCERR, "DWithin operator is unsupported.", "msMSSQL2008LayerTranslateFilter()");
+ return 0;
+
+ /* spatial functions */
+ case MS_TOKEN_FUNCTION_AREA:
+ filter->native_string = msStringConcatenate(filter->native_string, ".STArea(");
+ layerinfo->current_node = layerinfo->current_node->next;
+ if (!process_node(layer, filter))
+ return 0;
+ filter->native_string = msStringConcatenate(filter->native_string, ")");
+ break;
+
+ case MS_TOKEN_FUNCTION_BUFFER:
+ filter->native_string = msStringConcatenate(filter->native_string, ".STBuffer(");
+ layerinfo->current_node = layerinfo->current_node->next;
+ if (!process_node(layer, filter))
+ return 0;
+ filter->native_string = msStringConcatenate(filter->native_string, ")");
+ break;
+
+ case MS_TOKEN_FUNCTION_DIFFERENCE:
+ filter->native_string = msStringConcatenate(filter->native_string, ".STDifference(");
+ layerinfo->current_node = layerinfo->current_node->next;
+ if (!process_node(layer, filter))
+ return 0;
+ filter->native_string = msStringConcatenate(filter->native_string, ")");
+ break;
+
+ case MS_TOKEN_FUNCTION_FROMTEXT:
+ if (strcasecmp(layerinfo->geom_column_type, "geography") == 0)
+ filter->native_string = msStringConcatenate(filter->native_string, "geography::STGeomFromText");
+ else
+ filter->native_string = msStringConcatenate(filter->native_string, "geometry::STGeomFromText");
+ break;
+
+ case MS_TOKEN_FUNCTION_LENGTH:
+ filter->native_string = msStringConcatenate(filter->native_string, "len");
+ break;
+
+ case MS_TOKEN_FUNCTION_ROUND:
+ filter->native_string = msStringConcatenate(filter->native_string, "round");
+ break;
+
+ case MS_TOKEN_FUNCTION_TOSTRING:
+ break;
+
+ case MS_TOKEN_FUNCTION_COMMIFY:
+ break;
+
+ case MS_TOKEN_FUNCTION_SIMPLIFY:
+ filter->native_string = msStringConcatenate(filter->native_string, ".Reduce");
+ break;
+ case MS_TOKEN_FUNCTION_SIMPLIFYPT:
+ break;
+ case MS_TOKEN_FUNCTION_GENERALIZE:
+ filter->native_string = msStringConcatenate(filter->native_string, ".Reduce");
+ break;
+
+ default:
+ msSetError(MS_MISCERR, "Translation to native SQL failed.","msMSSQL2008LayerTranslateFilter()");
+ if (layer->debug) {
+ msDebug("Token not caught, exiting: Token is %i\n", layerinfo->current_node->token);
+ }
+ return 0;
+ }
+ return 1;
+}
+
+/* Translate filter expression to native msssql filter */
+int msMSSQL2008LayerTranslateFilter(layerObj *layer, expressionObj *filter, char *filteritem)
+{
+ char *snippet = NULL;
+ char *strtmpl = NULL;
+ char *stresc = NULL;
+ msMSSQL2008LayerInfo *layerinfo = (msMSSQL2008LayerInfo *) layer->layerinfo;
+
+ if(!filter->string) return MS_SUCCESS;
+
+ msFree(filter->native_string);
+ filter->native_string = NULL;
+
+ if(filter->type == MS_STRING && filter->string && filteritem) { /* item/value pair */
+ stresc = msMSSQL2008LayerEscapePropertyName(layer, filteritem);
+ if(filter->flags & MS_EXP_INSENSITIVE) {
+ filter->native_string = msStringConcatenate(filter->native_string, "upper(");
+ filter->native_string = msStringConcatenate(filter->native_string, stresc);
+ filter->native_string = msStringConcatenate(filter->native_string, ") = upper(");
+ } else {
+ filter->native_string = msStringConcatenate(filter->native_string, stresc);
+ filter->native_string = msStringConcatenate(filter->native_string, " = ");
+ }
+ msFree(stresc);
+
+ strtmpl = "'%s'"; /* don't have a type for the righthand literal so assume it's a string and we quote */
+ snippet = (char *) msSmallMalloc(strlen(strtmpl) + strlen(filter->string));
+ sprintf(snippet, strtmpl, filter->string); // TODO: escape filter->string
+ filter->native_string = msStringConcatenate(filter->native_string, snippet);
+ free(snippet);
+
+ if(filter->flags & MS_EXP_INSENSITIVE)
+ filter->native_string = msStringConcatenate(filter->native_string, ")");
+
+ } else if(filter->type == MS_REGEX && filter->string && filteritem) { /* item/regex pair */
+ /* NOTE: regex is not supported by MSSQL natively. We should install it in CLR UDF
+ according to https://msdn.microsoft.com/en-us/magazine/cc163473.aspx*/
+ filter->native_string = msStringConcatenate(filter->native_string, "dbo.RegexMatch(");
+ if(filter->flags & MS_EXP_INSENSITIVE) {
+ filter->native_string = msStringConcatenate(filter->native_string, "'(?i)");
+ }
+ filter->native_string = msStrdup(filteritem);
+ filter->native_string = msStringConcatenate(filter->native_string, ", ");
+ strtmpl = "'%s'";
+ snippet = (char *) msSmallMalloc(strlen(strtmpl) + strlen(filter->string));
+ sprintf(snippet, strtmpl, filter->string); // TODO: escape filter->string
+ filter->native_string = msStringConcatenate(filter->native_string, snippet);
+
+ filter->native_string = msStringConcatenate(filter->native_string, "')");
+ free(snippet);
+ } else if(filter->type == MS_EXPRESSION) {
+
+ if(layer->debug >= 2)
+ msDebug("msMSSQL2008LayerTranslateFilter. String: %s.\n", filter->string);
+
+ if(!filter->tokens) {
+ if(layer->debug >= 2)
+ msDebug("msMSSQL2008LayerTranslateFilter. There are tokens to process... \n");
+ return MS_SUCCESS;
+ }
+
+ /* start processing nodes */
+ layerinfo->current_node = filter->tokens;
+ while (layerinfo->current_node != NULL) {
+ if (!process_node(layer, filter))
+ {
+ msFree(filter->native_string);
+ filter->native_string = 0;
+ return MS_FAILURE;
+ }
+
+ if (!layerinfo->current_node)
+ break;
+
+ layerinfo->current_node = layerinfo->current_node->next;
+ }
+ }
+
+ return MS_SUCCESS;
+}
+
#else
/* prototypes if MSSQL2008 isnt supposed to be compiled */
@@ -2210,6 +2661,24 @@ int msMSSQL2008LayerGetItems(layerObj *layer)
return MS_FAILURE;
}
+int msMSSQL2008LayerTranslateFilter(layerObj *layer, expressionObj *filter, char *filteritem)
+{
+ msSetError(MS_QUERYERR, "msMSSQL2008LayerTranslateFilter called but unimplemented!(mapserver not compiled with MSSQL2008 support)", "msMSSQL2008LayerTranslateFilter()");
+ return MS_FAILURE;
+}
+
+char *msMSSQL2008LayerEscapeSQLParam(layerObj *layer, const char *pszString)
+{
+ msSetError(MS_QUERYERR, "msMSSQL2008EscapeSQLParam called but unimplemented!(mapserver not compiled with MSSQL2008 support)", "msMSSQL2008LayerEscapeSQLParam()");
+ return NULL;
+}
+
+char *msMSSQL2008LayerEscapePropertyName(layerObj *layer, const char *pszString)
+{
+ msSetError(MS_QUERYERR, "msMSSQL2008LayerEscapePropertyName called but unimplemented!(mapserver not compiled with MSSQL2008 support)", "msMSSQL2008LayerEscapePropertyName()");
+ return NULL;
+}
+
/* end above's #ifdef USE_MSSQL2008 */
#endif
@@ -2220,7 +2689,9 @@ MS_DLL_EXPORT int PluginInitializeVirtualTable(layerVTableObj* vtable, layerObj
assert(layer != NULL);
assert(vtable != NULL);
- /* vtable->LayerTranslateFilter, use default - need to add this... */
+ vtable->LayerTranslateFilter = msMSSQL2008LayerTranslateFilter;
+ vtable->LayerEscapeSQLParam = msMSSQL2008LayerEscapeSQLParam;
+ vtable->LayerEscapePropertyName = msMSSQL2008LayerEscapePropertyName;
vtable->LayerInitItemInfo = msMSSQL2008LayerInitItemInfo;
vtable->LayerFreeItemInfo = msMSSQL2008LayerFreeItemInfo;
@@ -2240,7 +2711,7 @@ MS_DLL_EXPORT int PluginInitializeVirtualTable(layerVTableObj* vtable, layerObj
/* vtable->LayerGetAutoStyle, not supported for this layer */
vtable->LayerCloseConnection = msMSSQL2008LayerClose;
- vtable->LayerSetTimeFilter = msLayerMakePlainTimeFilter;
+ vtable->LayerSetTimeFilter = msLayerMakeBackticsTimeFilter;
/* vtable->LayerCreateItems, use default */
/* vtable->LayerGetNumFeatures, use default */
/* layer->vtable->LayerGetAutoProjection, use defaut*/
@@ -2256,6 +2727,10 @@ msMSSQL2008LayerInitializeVirtualTable(layerObj *layer)
assert(layer != NULL);
assert(layer->vtable != NULL);
+ layer->vtable->LayerTranslateFilter = msMSSQL2008LayerTranslateFilter;
+ layer->vtable->LayerEscapeSQLParam = msMSSQL2008LayerEscapeSQLParam;
+ layer->vtable->LayerEscapePropertyName = msMSSQL2008LayerEscapePropertyName;
+
layer->vtable->LayerInitItemInfo = msMSSQL2008LayerInitItemInfo;
layer->vtable->LayerFreeItemInfo = msMSSQL2008LayerFreeItemInfo;
layer->vtable->LayerOpen = msMSSQL2008LayerOpen;
@@ -2274,7 +2749,7 @@ msMSSQL2008LayerInitializeVirtualTable(layerObj *layer)
/* layer->vtable->LayerGetAutoStyle, not supported for this layer */
layer->vtable->LayerCloseConnection = msMSSQL2008LayerClose;
- layer->vtable->LayerSetTimeFilter = msLayerMakePlainTimeFilter;
+ layer->vtable->LayerSetTimeFilter = msLayerMakeBackticsTimeFilter;
/* layer->vtable->LayerCreateItems, use default */
/* layer->vtable->LayerGetNumFeatures, use default */
diff --git a/mapogcfilter.c b/mapogcfilter.c
index aa6cc94..3d4bab8 100644
--- a/mapogcfilter.c
+++ b/mapogcfilter.c
@@ -66,7 +66,8 @@ int FLTIsNumeric(const char *pszValue)
return MS_TRUE;
#else
char * p;
- if (strtod(pszValue, &p) != 0 || *p == '\0') return MS_TRUE;
+ strtod(pszValue, &p);
+ if ( p != pszValue && *p == '\0') return MS_TRUE;
#endif
}
diff --git a/mapogcfiltercommon.c b/mapogcfiltercommon.c
index 11f9ff7..a77b3e3 100644
--- a/mapogcfiltercommon.c
+++ b/mapogcfiltercommon.c
@@ -51,9 +51,7 @@ char *FLTGetIsLikeComparisonCommonExpression(FilterEncodingNode *psFilterNode)
int nLength=0, i=0, iTmp=0;
-
- if (!psFilterNode || !psFilterNode->pOther || !psFilterNode->psLeftNode ||
- !psFilterNode->psRightNode || !psFilterNode->psRightNode->pszValue)
+ if (!psFilterNode || !psFilterNode->pOther || !psFilterNode->psLeftNode || !psFilterNode->psRightNode || !psFilterNode->psRightNode->pszValue)
return NULL;
propIsLike = (FEPropertyIsLike *)psFilterNode->pOther;
@@ -62,12 +60,9 @@ char *FLTGetIsLikeComparisonCommonExpression(FilterEncodingNode *psFilterNode)
pszEscape = propIsLike->pszEscapeChar;
bCaseInsensitive = propIsLike->bCaseInsensitive;
- if (!pszWild || strlen(pszWild) == 0 ||
- !pszSingle || strlen(pszSingle) == 0 ||
- !pszEscape || strlen(pszEscape) == 0)
+ if (!pszWild || strlen(pszWild) == 0 || !pszSingle || strlen(pszSingle) == 0 || !pszEscape || strlen(pszEscape) == 0)
return NULL;
-
/* -------------------------------------------------------------------- */
/* Use operand with regular expressions. */
/* -------------------------------------------------------------------- */
@@ -81,8 +76,8 @@ char *FLTGetIsLikeComparisonCommonExpression(FilterEncodingNode *psFilterNode)
strlcat(szBuffer, psFilterNode->psLeftNode->pszValue, bufferSize);
szBuffer[strlen(szBuffer)] = '\0';
- /*#3521 */
- if(bCaseInsensitive == 1)
+ /* #3521 */
+ if (bCaseInsensitive == 1)
sprintf(szTmp, "%s", "]\" ~* \"");
else
sprintf(szTmp, "%s", "]\" ~ \"");
@@ -90,35 +85,28 @@ char *FLTGetIsLikeComparisonCommonExpression(FilterEncodingNode *psFilterNode)
strlcat(szBuffer, szTmp, bufferSize);
szBuffer[strlen(szBuffer)] = '\0';
-
pszValue = psFilterNode->psRightNode->pszValue;
nLength = strlen(pszValue);
iTmp =0;
- if (nLength > 0 && pszValue[0] != pszWild[0] &&
- pszValue[0] != pszSingle[0] &&
- pszValue[0] != pszEscape[0]) {
+ if (nLength > 0 && pszValue[0] != pszWild[0] && pszValue[0] != pszSingle[0] && pszValue[0] != pszEscape[0]) {
szTmp[iTmp]= '^';
iTmp++;
}
for (i=0; i<nLength; i++) {
- if (pszValue[i] != pszWild[0] &&
- pszValue[i] != pszSingle[0] &&
- pszValue[i] != pszEscape[0]) {
+ if (pszValue[i] != pszWild[0] && pszValue[i] != pszSingle[0] && pszValue[i] != pszEscape[0]) {
szTmp[iTmp] = pszValue[i];
iTmp++;
szTmp[iTmp] = '\0';
- } else if (pszValue[i] == pszSingle[0]) {
+ } else if (pszValue[i] == pszSingle[0]) {
szTmp[iTmp] = '.';
iTmp++;
szTmp[iTmp] = '\0';
- } else if (pszValue[i] == pszEscape[0]) {
+ } else if (pszValue[i] == pszEscape[0]) {
szTmp[iTmp] = '\\';
iTmp++;
szTmp[iTmp] = '\0';
} else if (pszValue[i] == pszWild[0]) {
- /* strcat(szBuffer, "[0-9,a-z,A-Z,\\s]*"); */
- /* iBuffer+=17; */
szTmp[iTmp++] = '.';
szTmp[iTmp++] = '*';
szTmp[iTmp] = '\0';
@@ -139,10 +127,10 @@ char *FLTGetIsBetweenComparisonCommonExpresssion(FilterEncodingNode *psFilterNod
char **aszBounds = NULL;
int nBounds = 0;
int bString=0;
+ int bDateTime = 0;
char *pszExpression=NULL, *pszTmpEscaped;
- if (!psFilterNode ||
- !(strcasecmp(psFilterNode->pszValue, "PropertyIsBetween") == 0))
+ if (!psFilterNode || !(strcasecmp(psFilterNode->pszValue, "PropertyIsBetween") == 0))
return NULL;
if (psFilterNode->psLeftNode == NULL || psFilterNode->psRightNode == NULL )
@@ -156,27 +144,30 @@ char *FLTGetIsBetweenComparisonCommonExpresssion(FilterEncodingNode *psFilterNod
msFreeCharArray(aszBounds, nBounds);
return NULL;
}
+
/* -------------------------------------------------------------------- */
/* check if the value is a numeric value or alphanumeric. If it */
/* is alphanumeric, add quotes around attribute and values. */
/* -------------------------------------------------------------------- */
bString = 0;
if (aszBounds[0]) {
+ const char* pszType;
snprintf(szBuffer, bufferSize, "%s_type", psFilterNode->psLeftNode->pszValue);
- if (msOWSLookupMetadata(&(lp->metadata), "OFG", szBuffer) != NULL &&
- (strcasecmp(msOWSLookupMetadata(&(lp->metadata), "OFG", szBuffer), "Character") == 0))
+ pszType = msOWSLookupMetadata(&(lp->metadata), "OFG", szBuffer);
+ if (pszType != NULL && (strcasecmp(pszType, "Character") == 0))
bString = 1;
+ else if (pszType != NULL && (strcasecmp(pszType, "Date") == 0))
+ bDateTime = 1;
else if (FLTIsNumeric(aszBounds[0]) == MS_FALSE)
bString = 1;
}
- if (!bString) {
+ if (!bString && !bDateTime) {
if (aszBounds[1]) {
if (FLTIsNumeric(aszBounds[1]) == MS_FALSE)
bString = 1;
}
}
-
/* -------------------------------------------------------------------- */
/* build expresssion. */
/* -------------------------------------------------------------------- */
@@ -199,8 +190,10 @@ char *FLTGetIsBetweenComparisonCommonExpresssion(FilterEncodingNode *psFilterNod
pszExpression = msStringConcatenate(pszExpression, szBuffer);
if (bString) {
- sprintf(szBuffer,"%s", "\"");
- pszExpression = msStringConcatenate(pszExpression, szBuffer);
+ pszExpression = msStringConcatenate(pszExpression, "\"");
+ }
+ else if (bDateTime) {
+ pszExpression = msStringConcatenate(pszExpression, "`");
}
pszTmpEscaped = msStringEscape(aszBounds[0]);
@@ -208,8 +201,10 @@ char *FLTGetIsBetweenComparisonCommonExpresssion(FilterEncodingNode *psFilterNod
if(pszTmpEscaped != aszBounds[0] ) msFree(pszTmpEscaped);
pszExpression = msStringConcatenate(pszExpression, szBuffer);
if (bString) {
- sprintf(szBuffer, "%s", "\"");
- pszExpression = msStringConcatenate(pszExpression, szBuffer);
+ pszExpression = msStringConcatenate(pszExpression, "\"");
+ }
+ else if (bDateTime) {
+ pszExpression = msStringConcatenate(pszExpression, "`");
}
sprintf(szBuffer, "%s", " AND ");
@@ -233,17 +228,21 @@ char *FLTGetIsBetweenComparisonCommonExpresssion(FilterEncodingNode *psFilterNod
sprintf(szBuffer, "%s", " <= ");
pszExpression = msStringConcatenate(pszExpression, szBuffer);
if (bString) {
- sprintf(szBuffer,"%s", "\"");
- pszExpression = msStringConcatenate(pszExpression, szBuffer);
+ pszExpression = msStringConcatenate(pszExpression, "\"");
+ }
+ else if (bDateTime) {
+ pszExpression = msStringConcatenate(pszExpression, "`");
}
pszTmpEscaped = msStringEscape(aszBounds[1]);
snprintf(szBuffer, bufferSize, "%s", pszTmpEscaped);
- if(pszTmpEscaped != aszBounds[1] ) msFree(pszTmpEscaped);
+ if (pszTmpEscaped != aszBounds[1]) msFree(pszTmpEscaped);
pszExpression = msStringConcatenate(pszExpression, szBuffer);
if (bString) {
- sprintf(szBuffer,"\"");
- pszExpression = msStringConcatenate(pszExpression, szBuffer);
+ pszExpression = msStringConcatenate(pszExpression, "\"");
+ }
+ else if (bDateTime) {
+ pszExpression = msStringConcatenate(pszExpression, "`");
}
sprintf(szBuffer, "%s", ")");
pszExpression = msStringConcatenate(pszExpression, szBuffer);
@@ -258,6 +257,7 @@ char *FLTGetBinaryComparisonCommonExpression(FilterEncodingNode *psFilterNode, l
char szTmp[1024];
char *pszExpression = NULL, *pszTmpEscaped;
int bString;
+ int bDateTime;
if (psFilterNode == NULL)
return NULL;
@@ -267,23 +267,24 @@ char *FLTGetBinaryComparisonCommonExpression(FilterEncodingNode *psFilterNode, l
/* is alphanumeric, add quotes around attribute and values. */
/* -------------------------------------------------------------------- */
bString = 0;
+ bDateTime = 0;
if (psFilterNode->psRightNode->pszValue) {
+ const char* pszType;
snprintf(szTmp, sizeof(szTmp), "%s_type", psFilterNode->psLeftNode->pszValue);
- if (msOWSLookupMetadata(&(lp->metadata), "OFG", szTmp) != NULL &&
- (strcasecmp(msOWSLookupMetadata(&(lp->metadata), "OFG", szTmp), "Character") == 0))
+ pszType = msOWSLookupMetadata(&(lp->metadata), "OFG", szTmp);
+ if (pszType!= NULL && (strcasecmp(pszType, "Character") == 0))
bString = 1;
+ else if (pszType!= NULL && (strcasecmp(pszType, "Date") == 0))
+ bDateTime = 1;
else if (FLTIsNumeric(psFilterNode->psRightNode->pszValue) == MS_FALSE)
bString = 1;
}
/* specical case to be able to have empty strings in the expression. */
- /*propertyislike is always treated as string*/
- if (psFilterNode->psRightNode->pszValue == NULL ||
- strcasecmp(psFilterNode->pszValue, "PropertyIsLike") == 0)
+ /* propertyislike is always treated as string */
+ if (psFilterNode->psRightNode->pszValue == NULL || strcasecmp(psFilterNode->pszValue, "PropertyIsLike") == 0)
bString = 1;
-
-
/* attribute */
if (bString)
sprintf(szTmp, "%s", " (\"[");
@@ -298,32 +299,23 @@ char *FLTGetBinaryComparisonCommonExpression(FilterEncodingNode *psFilterNode, l
sprintf(szTmp, "%s", "] ");
pszExpression = msStringConcatenate(pszExpression, szTmp);
- if (strcasecmp(psFilterNode->pszValue,
- "PropertyIsEqualTo") == 0) {
- /*case insensitive set ? */
- if (psFilterNode->psRightNode->pOther &&
- (*(int *)psFilterNode->psRightNode->pOther) == 1) {
+ if (strcasecmp(psFilterNode->pszValue, "PropertyIsEqualTo") == 0) {
+ /* case insensitive set ? */
+ if (psFilterNode->psRightNode->pOther && (*(int *)psFilterNode->psRightNode->pOther) == 1)
sprintf(szTmp, "%s", "=*");
- } else
+ else
sprintf(szTmp, "%s", "=");
-
- } else if (strcasecmp(psFilterNode->pszValue,
- "PropertyIsNotEqualTo") == 0)
+ } else if (strcasecmp(psFilterNode->pszValue, "PropertyIsNotEqualTo") == 0)
sprintf(szTmp, "%s", " != ");
- else if (strcasecmp(psFilterNode->pszValue,
- "PropertyIsLessThan") == 0)
+ else if (strcasecmp(psFilterNode->pszValue, "PropertyIsLessThan") == 0)
sprintf(szTmp, "%s", " < ");
- else if (strcasecmp(psFilterNode->pszValue,
- "PropertyIsGreaterThan") == 0)
+ else if (strcasecmp(psFilterNode->pszValue, "PropertyIsGreaterThan") == 0)
sprintf(szTmp, "%s", " > ");
- else if (strcasecmp(psFilterNode->pszValue,
- "PropertyIsLessThanOrEqualTo") == 0)
+ else if (strcasecmp(psFilterNode->pszValue, "PropertyIsLessThanOrEqualTo") == 0)
sprintf(szTmp, "%s", " <= ");
- else if (strcasecmp(psFilterNode->pszValue,
- "PropertyIsGreaterThanOrEqualTo") == 0)
+ else if (strcasecmp(psFilterNode->pszValue, "PropertyIsGreaterThanOrEqualTo") == 0)
sprintf(szTmp, "%s", " >= ");
- else if (strcasecmp(psFilterNode->pszValue,
- "PropertyIsLike") == 0)
+ else if (strcasecmp(psFilterNode->pszValue, "PropertyIsLike") == 0)
sprintf(szTmp, "%s", " ~ ");
pszExpression = msStringConcatenate(pszExpression, szTmp);
@@ -333,6 +325,10 @@ char *FLTGetBinaryComparisonCommonExpression(FilterEncodingNode *psFilterNode, l
sprintf(szTmp, "%s", "\"");
pszExpression = msStringConcatenate(pszExpression, szTmp);
}
+ else if (bDateTime) {
+ sprintf(szTmp, "%s", "`");
+ pszExpression = msStringConcatenate(pszExpression, szTmp);
+ }
if (psFilterNode->psRightNode->pszValue) {
pszTmpEscaped = msStringEscape(psFilterNode->psRightNode->pszValue);
@@ -344,6 +340,10 @@ char *FLTGetBinaryComparisonCommonExpression(FilterEncodingNode *psFilterNode, l
sprintf(szTmp, "%s", "\"");
pszExpression = msStringConcatenate(pszExpression, szTmp);
}
+ else if (bDateTime) {
+ sprintf(szTmp, "%s", "`");
+ pszExpression = msStringConcatenate(pszExpression, szTmp);
+ }
sprintf(szTmp, "%s", ")");
pszExpression = msStringConcatenate(pszExpression, szTmp);
@@ -351,8 +351,6 @@ char *FLTGetBinaryComparisonCommonExpression(FilterEncodingNode *psFilterNode, l
return pszExpression;
}
-
-
char *FLTGetLogicalComparisonCommonExpression(FilterEncodingNode *psFilterNode, layerObj *lp)
{
char *pszExpression = NULL;
@@ -382,7 +380,6 @@ char *FLTGetLogicalComparisonCommonExpression(FilterEncodingNode *psFilterNode,
pszExpression = msStringConcatenate(pszExpression, psFilterNode->pszValue);
sprintf(szBuffer, "%s", " ");
-
pszTmp = FLTGetCommonExpression(psFilterNode->psRightNode, lp);
if (!pszTmp) {
msFree(pszExpression);
@@ -398,8 +395,7 @@ char *FLTGetLogicalComparisonCommonExpression(FilterEncodingNode *psFilterNode,
/* -------------------------------------------------------------------- */
/* NOT */
/* -------------------------------------------------------------------- */
- else if (psFilterNode->psLeftNode &&
- strcasecmp(psFilterNode->pszValue, "NOT") == 0) {
+ else if (psFilterNode->psLeftNode && strcasecmp(psFilterNode->pszValue, "NOT") == 0) {
pszTmp = FLTGetCommonExpression(psFilterNode->psLeftNode, lp);
if (!pszTmp)
return NULL;
@@ -412,14 +408,11 @@ char *FLTGetLogicalComparisonCommonExpression(FilterEncodingNode *psFilterNode,
sprintf(szBuffer, "%s", ") ");
pszExpression = msStringConcatenate(pszExpression, szBuffer);
-
}
-
return pszExpression;
}
-
char *FLTGetSpatialComparisonCommonExpression(FilterEncodingNode *psNode, layerObj *lp)
{
char *pszExpression = NULL;
@@ -442,7 +435,7 @@ char *FLTGetSpatialComparisonCommonExpression(FilterEncodingNode *psNode, layerO
return NULL;
/* get the shape */
- if(FLTIsBBoxFilter(psNode)) {
+ if (FLTIsBBoxFilter(psNode)) {
char szPolygon[512];
FLTGetBBOX(psNode, &sQueryRect);
@@ -456,38 +449,40 @@ char *FLTGetSpatialComparisonCommonExpression(FilterEncodingNode *psNode, layerO
psTmpShape = msShapeFromWKT(szPolygon);
- /* This is a horrible hack to deal with world-extent requests and */
- /* reprojection. msProjectRect() detects if reprojection from longlat to */
- /* projected SRS, and in that case it transforms the bbox to -1e-15,-1e-15,1e15,1e15 */
- /* to ensure that all features are returned */
- /* Make wfs_200_cite_filter_bbox_world.xml and wfs_200_cite_postgis_bbox_world.xml pass */
- if( fabs(sQueryRect.minx - -180.0) < 1e-5 &&
+ /*
+ ** This is a horrible hack to deal with world-extent requests and
+ ** reprojection. msProjectRect() detects if reprojection from longlat to
+ ** projected SRS, and in that case it transforms the bbox to -1e-15,-1e-15,1e15,1e15
+ ** to ensure that all features are returned.
+ **
+ ** Make wfs_200_cite_filter_bbox_world.xml and wfs_200_cite_postgis_bbox_world.xml pass
+ */
+ if (fabs(sQueryRect.minx - -180.0) < 1e-5 &&
fabs(sQueryRect.miny - -90.0) < 1e-5 &&
fabs(sQueryRect.maxx - 180.0) < 1e-5 &&
- fabs(sQueryRect.maxy - 90.0) < 1e-5 )
+ fabs(sQueryRect.maxy - 90.0) < 1e-5)
{
- if(lp->projection.numargs > 0) {
+ if (lp->projection.numargs > 0) {
if (psNode->pszSRS)
- msInitProjection(&sProjTmp);
+ msInitProjection(&sProjTmp);
if (psNode->pszSRS) {
- /* Use the non EPSG variant since axis swapping is done in FLTDoAxisSwappingIfNecessary */
- if (msLoadProjectionString(&sProjTmp, psNode->pszSRS) == 0) {
- msProjectRect(&sProjTmp, &lp->projection, &sQueryRect);
- }
+ /* Use the non EPSG variant since axis swapping is done in FLTDoAxisSwappingIfNecessary */
+ if (msLoadProjectionString(&sProjTmp, psNode->pszSRS) == 0) {
+ msProjectRect(&sProjTmp, &lp->projection, &sQueryRect);
+ }
} else if (lp->map->projection.numargs > 0)
- msProjectRect(&lp->map->projection, &lp->projection, &sQueryRect);
- if (psNode->pszSRS)
- msFreeProjection(&sProjTmp);
- }
- if( sQueryRect.minx <= -1e14 )
- {
- msFreeShape(psTmpShape);
- msFree(psTmpShape);
- psTmpShape = (shapeObj*) msSmallMalloc(sizeof(shapeObj));
- msInitShape(psTmpShape);
- msRectToPolygon(sQueryRect, psTmpShape);
- bAlreadyReprojected = 1;
- }
+ msProjectRect(&lp->map->projection, &lp->projection, &sQueryRect);
+ if (psNode->pszSRS)
+ msFreeProjection(&sProjTmp);
+ }
+ if (sQueryRect.minx <= -1e14) {
+ msFreeShape(psTmpShape);
+ msFree(psTmpShape);
+ psTmpShape = (shapeObj*) msSmallMalloc(sizeof(shapeObj));
+ msInitShape(psTmpShape);
+ msRectToPolygon(sQueryRect, psTmpShape);
+ bAlreadyReprojected = 1;
+ }
}
bBBoxQuery = 1;
@@ -517,7 +512,7 @@ char *FLTGetSpatialComparisonCommonExpression(FilterEncodingNode *psNode, layerO
/*
** target is layer projection
*/
- if(!bAlreadyReprojected && lp->projection.numargs > 0) {
+ if (!bAlreadyReprojected && lp->projection.numargs > 0) {
if (psNode->pszSRS)
msInitProjection(&sProjTmp);
if (psNode->pszSRS) {
@@ -575,9 +570,9 @@ char *FLTGetSpatialComparisonCommonExpression(FilterEncodingNode *psNode, layerO
/*
** Cleanup
*/
- if(bBBoxQuery) {
- msFreeShape(psTmpShape);
- msFree(psTmpShape);
+ if (bBBoxQuery) {
+ msFreeShape(psTmpShape);
+ msFree(psTmpShape);
}
return pszExpression;
@@ -585,13 +580,12 @@ char *FLTGetSpatialComparisonCommonExpression(FilterEncodingNode *psNode, layerO
char *FLTGetFeatureIdCommonExpression(FilterEncodingNode *psFilterNode, layerObj *lp)
{
-
char *pszExpression = NULL;
int nTokens = 0, i=0, bString=0;
char **tokens = NULL;
const char *pszAttribute=NULL;
-#if defined(USE_WMS_SVR) || defined (USE_WFS_SVR) || defined (USE_WCS_SVR) || defined(USE_SOS_SVR)
+#if defined(USE_WMS_SVR) || defined(USE_WFS_SVR) || defined(USE_WCS_SVR) || defined(USE_SOS_SVR)
if (psFilterNode->pszValue) {
pszAttribute = msOWSLookupMetadata(&(lp->metadata), "OFG", "featureid");
if (pszAttribute) {
@@ -610,7 +604,6 @@ char *FLTGetFeatureIdCommonExpression(FilterEncodingNode *psFilterNode, layerObj
bString = 1;
}
-
if (bString) {
bufferSize = 11+strlen(pszId)+strlen(pszAttribute)+1;
pszTmp = (char *)msSmallMalloc(bufferSize);
@@ -632,7 +625,8 @@ char *FLTGetFeatureIdCommonExpression(FilterEncodingNode *psFilterNode, layerObj
msFreeCharArray(tokens, nTokens);
}
}
- /*opening and closing brackets are needed for mapserver expressions*/
+
+ /* opening and closing brackets are needed for mapserver expressions */
if (pszExpression)
pszExpression = msStringConcatenate(pszExpression, ")");
}
@@ -654,13 +648,12 @@ char* FLTGetTimeExpression(FilterEncodingNode *psFilterNode, layerObj *lp)
return NULL;
pszTimeValue = FLTGetDuring(psFilterNode, &pszTimeField);
- if( pszTimeField && pszTimeValue )
- {
+ if (pszTimeField && pszTimeValue) {
expressionObj old_filter;
msInitExpression(&old_filter);
msCopyExpression(&old_filter, &lp->filter); /* save existing filter */
msFreeExpression(&lp->filter);
- if( msLayerSetTimeFilter(lp, pszTimeValue, pszTimeField) == MS_TRUE ) {
+ if (msLayerSetTimeFilter(lp, pszTimeValue, pszTimeField) == MS_TRUE) {
pszExpression = msStrdup(lp->filter.string);
}
msCopyExpression(&lp->filter, &old_filter); /* restore old filter */
@@ -669,7 +662,6 @@ char* FLTGetTimeExpression(FilterEncodingNode *psFilterNode, layerObj *lp)
return pszExpression;
}
-
char *FLTGetCommonExpression(FilterEncodingNode *psFilterNode, layerObj *lp)
{
char *pszExpression = NULL;
diff --git a/mapows.c b/mapows.c
index f1ce641..617abc3 100644
--- a/mapows.c
+++ b/mapows.c
@@ -80,6 +80,17 @@ static void msOWSClearRequestObj(owsRequestObj *ows_request)
}
}
+#if defined(USE_LIBXML2) && LIBXML_VERSION < 20900
+static int bExternalEntityAsked = FALSE;
+static xmlParserInputPtr dummyEntityLoader(const char * URL,
+ const char * ID,
+ xmlParserCtxtPtr context )
+{
+ bExternalEntityAsked = TRUE;
+ return NULL;
+}
+#endif
+
/*
** msOWSPreParseRequest() parses a cgiRequestObj either with GET/KVP
** or with POST/XML. Only SERVICE, VERSION (or WMTVER) and REQUEST are
@@ -121,6 +132,9 @@ static int msOWSPreParseRequest(cgiRequestObj *request,
} else if (request->type == MS_POST_REQUEST) {
#if defined(USE_LIBXML2)
xmlNodePtr root = NULL;
+#if LIBXML_VERSION < 20900
+ xmlExternalEntityLoader oldExternalEntityLoader;
+#endif
#elif defined(USE_GDAL)
CPLXMLNode *temp;
#endif
@@ -130,9 +144,24 @@ static int msOWSPreParseRequest(cgiRequestObj *request,
return MS_FAILURE;
}
#if defined(USE_LIBXML2)
+#if LIBXML_VERSION < 20900
+ oldExternalEntityLoader = xmlGetExternalEntityLoader();
+ /* to avoid XML External Entity vulnerability with libxml2 < 2.9 */
+ xmlSetExternalEntityLoader (dummyEntityLoader);
+ bExternalEntityAsked = FALSE;
+#endif
/* parse to DOM-Structure with libxml2 and get the root element */
ows_request->document = xmlParseMemory(request->postrequest,
strlen(request->postrequest));
+#if LIBXML_VERSION < 20900
+ xmlSetExternalEntityLoader (oldExternalEntityLoader);
+ if( bExternalEntityAsked )
+ {
+ msSetError(MS_OWSERR, "XML parsing error: %s",
+ "msOWSPreParseRequest()", "External entity fetch");
+ return MS_FAILURE;
+ }
+#endif
if (ows_request->document == NULL
|| (root = xmlDocGetRootElement(ows_request->document)) == NULL) {
xmlErrorPtr error = xmlGetLastError();
diff --git a/mappluginlayer.c b/mappluginlayer.c
index 8b01508..0099e9b 100644
--- a/mappluginlayer.c
+++ b/mappluginlayer.c
@@ -154,6 +154,8 @@ static void
copyVirtualTable(layerVTableObj *dest,
const layerVTableObj *src)
{
+ dest->LayerTranslateFilter = src->LayerTranslateFilter ? src->LayerTranslateFilter : dest->LayerTranslateFilter;
+ dest->LayerSupportsCommonFilters = src->LayerSupportsCommonFilters ? src->LayerSupportsCommonFilters : dest->LayerSupportsCommonFilters;
dest->LayerInitItemInfo = src->LayerInitItemInfo ? src->LayerInitItemInfo : dest->LayerInitItemInfo;
dest->LayerFreeItemInfo = src->LayerFreeItemInfo ? src->LayerFreeItemInfo : dest->LayerFreeItemInfo;
dest->LayerOpen = src->LayerOpen ? src->LayerOpen : dest->LayerOpen;
@@ -172,6 +174,11 @@ copyVirtualTable(layerVTableObj *dest,
dest->LayerCreateItems = src->LayerCreateItems ? src->LayerCreateItems : dest->LayerCreateItems;
dest->LayerGetNumFeatures = src->LayerGetNumFeatures ? src->LayerGetNumFeatures : dest->LayerGetNumFeatures;
dest->LayerGetAutoProjection = src->LayerGetAutoProjection ? src->LayerGetAutoProjection: dest->LayerGetAutoProjection;
+ dest->LayerEscapeSQLParam = src->LayerEscapeSQLParam ? src->LayerEscapeSQLParam: dest->LayerEscapeSQLParam;
+ dest->LayerEscapePropertyName = src->LayerEscapePropertyName ? src->LayerEscapePropertyName: dest->LayerEscapePropertyName;
+ dest->LayerEscapeSQLParam = src->LayerEscapeSQLParam ? src->LayerEscapeSQLParam: dest->LayerEscapeSQLParam;
+ dest->LayerEnablePaging = src->LayerEnablePaging ? src->LayerEnablePaging: dest->LayerEnablePaging;
+ dest->LayerGetPaging = src->LayerGetPaging ? src->LayerGetPaging: dest->LayerGetPaging;
}
int
diff --git a/maprasterquery.c b/maprasterquery.c
index a420e0b..80accfa 100644
--- a/maprasterquery.c
+++ b/maprasterquery.c
@@ -1286,12 +1286,14 @@ int msRASTERLayerGetItems(layerObj *layer)
#ifndef USE_GDAL
return MS_FAILURE;
#else
+ int maxnumitems = 0;
rasterLayerInfo *rlinfo = (rasterLayerInfo *) layer->layerinfo;
if( rlinfo == NULL )
return MS_FAILURE;
- layer->items = (char **) msSmallCalloc(sizeof(char *),10);
+ maxnumitems = 8 + (rlinfo->qc_values?rlinfo->band_count:0);
+ layer->items = (char **) msSmallCalloc(sizeof(char *),maxnumitems);
layer->numitems = 0;
if( rlinfo->qc_x_reproj )
@@ -1318,6 +1320,8 @@ int msRASTERLayerGetItems(layerObj *layer)
if( rlinfo->qc_count )
layer->items[layer->numitems++] = msStrdup("count");
+ assert(layer->numitems <= maxnumitems);
+
return msRASTERLayerInitItemInfo(layer);
#endif /* def USE_GDAL */
}
diff --git a/maprendering.c b/maprendering.c
index aec7386..2a24985 100644
--- a/maprendering.c
+++ b/maprendering.c
@@ -247,8 +247,8 @@ imageObj *getTile(imageObj *img, symbolObj *symbol, symbolStyleObj *s, int widt
if(UNLIKELY(!face)) { status = MS_FAILURE; break; }
msUTF8ToUniChar(symbol->character, &unicode);
unicode = msGetGlyphIndex(face,unicode);
- glyphc = msGetGlyphByIndex(face, s->scale, unicode);
- if(UNLIKELY(!face)) { status = MS_FAILURE; break; }
+ glyphc = msGetGlyphByIndex(face, MS_MAX(MS_NINT(s->scale),1), unicode);
+ if(UNLIKELY(!glyphc)) { status = MS_FAILURE; break; }
status = drawGlyphMarker(tileimg, face, glyphc, p_x, p_y, s->scale, s->rotation,
s->color, s->outlinecolor, s->outlinewidth);
}
@@ -311,7 +311,7 @@ imageObj *getTile(imageObj *img, symbolObj *symbol, symbolStyleObj *s, int widt
if(UNLIKELY(!face)) { status = MS_FAILURE; break; }
msUTF8ToUniChar(symbol->character, &unicode);
unicode = msGetGlyphIndex(face,unicode);
- glyphc = msGetGlyphByIndex(face, s->scale, unicode);
+ glyphc = msGetGlyphByIndex(face, MS_MAX(MS_NINT(s->scale),1), unicode);
if(UNLIKELY(!glyphc)) { status = MS_FAILURE; break; }
status = drawGlyphMarker(tileimg, face, glyphc, p_x, p_y, s->scale, s->rotation,
s->color, s->outlinecolor, s->outlinewidth);
@@ -384,7 +384,7 @@ int msImagePolylineMarkers(imageObj *image, shapeObj *p, symbolObj *symbol,
face = msGetFontFace(symbol->font, &image->map->fontset);
if(UNLIKELY(!face)) return MS_FAILURE;
unicode = msGetGlyphIndex(face,unicode);
- glyphc = msGetGlyphByIndex(face, style->scale, unicode);
+ glyphc = msGetGlyphByIndex(face, MS_MAX(MS_NINT(style->scale),1), unicode);
if(UNLIKELY(!glyphc)) return MS_FAILURE;
symbol_width = glyphc->metrics.maxx - glyphc->metrics.minx;
symbol_height = glyphc->metrics.maxy - glyphc->metrics.miny;
@@ -561,7 +561,7 @@ int msDrawLineSymbol(mapObj *map, imageObj *image, shapeObj *p,
rendererVTableObj *renderer = image->format->vtable;
symbolObj *symbol;
shapeObj *offsetLine = p;
- int i,ret=MS_SUCCESS;
+ int i;
double width;
double finalscalefactor;
@@ -922,7 +922,7 @@ int msDrawMarkerSymbol(mapObj *map, imageObj *image, pointObj *p, styleObj *styl
if(UNLIKELY(!face)) return MS_FAILURE;
msUTF8ToUniChar(symbol->character,&unicode);
unicode = msGetGlyphIndex(face,unicode);
- glyphc = msGetGlyphByIndex(face,s.scale,unicode);
+ glyphc = msGetGlyphByIndex(face, MS_MAX(MS_NINT(s.scale),1), unicode);
if(UNLIKELY(!glyphc)) return MS_FAILURE;
ret = drawGlyphMarker(image, face, glyphc, p_x, p_y, s.scale, s.rotation, s.color, s.outlinecolor, s.outlinewidth);
}
@@ -1023,7 +1023,7 @@ int msDrawTextSymbol(mapObj *map, imageObj *image, pointObj labelPnt, textSymbol
c = &ts->label->color;
if(MS_VALID_COLOR(ts->label->outlinecolor))
oc = &ts->label->outlinecolor;
- ow = ts->label->outlinewidth * ts->scalefactor;
+ ow = ts->label->outlinewidth * (ts->textpath->glyph_size / ts->label->size);
if(!renderer->renderGlyphs) return MS_FAILURE;
return renderer->renderGlyphs(image,ts->textpath,c,oc,ow);
@@ -1077,3 +1077,54 @@ int msDrawPieSlice(mapObj *map, imageObj *image, pointObj *p, styleObj *style, d
msFree(circle);
return status;
}
+
+/*
+ * RFC 49 implementation
+ * if an outlinewidth is used:
+ * - augment the style's width to account for the outline width
+ * - swap the style color and outlinecolor
+ * - draw the shape (the outline) in the first pass of the
+ * caching mechanism
+ */
+
+void msOutlineRenderingPrepareStyle(styleObj *pStyle, mapObj *map, layerObj *layer, imageObj *image)
+{
+ colorObj tmp;
+
+ if (pStyle->outlinewidth > 0) {
+ /* adapt width (must take scalefactor into account) */
+ pStyle->width += (pStyle->outlinewidth / (layer->scalefactor/image->resolutionfactor)) * 2;
+ pStyle->minwidth += pStyle->outlinewidth * 2;
+ pStyle->maxwidth += pStyle->outlinewidth * 2;
+ pStyle->size += (pStyle->outlinewidth/layer->scalefactor*(map->resolution/map->defresolution));
+
+ /*swap color and outlinecolor*/
+ tmp = pStyle->color;
+ pStyle->color = pStyle->outlinecolor;
+ pStyle->outlinecolor = tmp;
+ }
+}
+
+/*
+ * RFC 49 implementation: switch back the styleobj to its
+ * original state, so the line fill will be drawn in the
+ * second pass of the caching mechanism
+ */
+
+void msOutlineRenderingRestoreStyle(styleObj *pStyle, mapObj *map, layerObj *layer, imageObj *image)
+{
+ colorObj tmp;
+
+ if (pStyle->outlinewidth > 0) {
+ /* reset widths to original state */
+ pStyle->width -= (pStyle->outlinewidth / (layer->scalefactor/image->resolutionfactor)) * 2;
+ pStyle->minwidth -= pStyle->outlinewidth * 2;
+ pStyle->maxwidth -= pStyle->outlinewidth * 2;
+ pStyle->size -= (pStyle->outlinewidth/layer->scalefactor*(map->resolution/map->defresolution));
+
+ /*reswap colors to original state*/
+ tmp = pStyle->color;
+ pStyle->color = pStyle->outlinecolor;
+ pStyle->outlinecolor = tmp;
+ }
+}
diff --git a/mapscript/php/map.c b/mapscript/php/map.c
index 6943d8d..9ddb2eb 100644
--- a/mapscript/php/map.c
+++ b/mapscript/php/map.c
@@ -1951,7 +1951,7 @@ PHP_METHOD(mapObj, saveQuery)
zval *zobj = getThis();
char *filename;
long filename_len = 0;
- int results = MS_FALSE;
+ long results = MS_FALSE;
int status = MS_FAILURE;
php_map_object *php_map;
diff --git a/mapserver.h b/mapserver.h
index e2d396d..ec91380 100644
--- a/mapserver.h
+++ b/mapserver.h
@@ -2535,7 +2535,8 @@ void msPopulateTextSymbolForLabelAndString(textSymbolObj *ts, labelObj *l, char
MS_DLL_EXPORT int WARN_UNUSED msDrawPieSlice(mapObj *map, imageObj *image, pointObj *p, styleObj *style, double radius, double start, double end);
MS_DLL_EXPORT int WARN_UNUSED msDrawLabelBounds(mapObj *map, imageObj *image, label_bounds *bnds, styleObj *style, double scalefactor);
-
+ MS_DLL_EXPORT void msOutlineRenderingPrepareStyle(styleObj *pStyle, mapObj *map, layerObj *layer, imageObj *image);
+ MS_DLL_EXPORT void msOutlineRenderingRestoreStyle(styleObj *pStyle, mapObj *map, layerObj *layer, imageObj *image);
MS_DLL_EXPORT int WARN_UNUSED msDrawLabel(mapObj *map, imageObj *image, pointObj labelPnt, char *string, labelObj *label, double scalefactor);
MS_DLL_EXPORT int WARN_UNUSED msDrawTextSymbol(mapObj *map, imageObj *image, pointObj labelPnt, textSymbolObj *ts);
diff --git a/mapshape.c b/mapshape.c
index e139b5e..174407c 100644
--- a/mapshape.c
+++ b/mapshape.c
@@ -2688,7 +2688,7 @@ int msSHPLayerNextShape(layerObj *layer, shapeObj *shape)
msSHPReadShape(shpfile->hSHP, i, shape);
if(shape->type == MS_SHAPE_NULL) {
msFreeShape(shape);
- msSHPLayerNextShape(layer, shape); /* skip NULL shapes */
+ return msSHPLayerNextShape(layer, shape); /* skip NULL shapes */
}
shape->numvalues = layer->numitems;
shape->values = msDBFGetValueList(shpfile->hDBF, i, layer->iteminfo, layer->numitems);
diff --git a/mapsymbol.c b/mapsymbol.c
index 69b4a9f..6258ab2 100644
--- a/mapsymbol.c
+++ b/mapsymbol.c
@@ -318,6 +318,9 @@ void writeSymbol(symbolObj *s, FILE *stream)
if(s->filled == MS_TRUE) msIO_fprintf(stream, " FILLED TRUE\n");
if(s->imagepath != NULL) msIO_fprintf(stream, " IMAGE \"%s\"\n", s->imagepath);
+ if(s->anchorpoint_y!=0.5 || s->anchorpoint_x!=0.5) {
+ msIO_fprintf(stream, " ANCHORPOINT %g %g\n", s->anchorpoint_x, s->anchorpoint_y);
+ }
/* POINTS */
if(s->numpoints != 0) {
diff --git a/mapwcs20.c b/mapwcs20.c
index 69997cf..95351b8 100644
--- a/mapwcs20.c
+++ b/mapwcs20.c
@@ -3707,8 +3707,8 @@ static int msWCSGetCoverage20_FinalizeParamsObj(wcs20ParamsObjPtr params, wcs20A
params->subsetcrs = msStrdup(crs);
}
} else if (!params->subsetcrs) {
- /* default to imageCRS */
- params->subsetcrs = msStrdup("imageCRS");
+ /* default to CRS of image */
+ /* leave params->subsetcrs to null */
}
return MS_SUCCESS;
@@ -4126,7 +4126,7 @@ this request. Check wcs/ows_enable_request settings.", "msWCSGetCoverage20()", p
msWCSClearCoverageMetadata20(&cm);
msSetError(MS_WCSERR,
"Error loading CRS %s.",
- "msWCSGetCoverage20()", params->subsetcrs);
+ "msWCSGetCoverage20()", cm.srs);
return msWCSException(map, "InvalidParameterValue",
"projection", params->version);
}
@@ -4165,6 +4165,12 @@ this request. Check wcs/ows_enable_request settings.", "msWCSGetCoverage20()", p
subsets = params->bbox;
+ /* if no subsetCRS was specified use the coverages CRS
+ (Requirement 27 of the WCS 2.0 specification) */
+ if (!params->subsetcrs) {
+ params->subsetcrs = msStrdup(cm.srs);
+ }
+
if(EQUAL(params->subsetcrs, "imageCRS")) {
/* subsets are in imageCRS; reproject them to real coordinates */
rectObj orig_bbox = subsets;
diff --git a/mapwfslayer.c b/mapwfslayer.c
index 6eca05a..fe6560e 100644
--- a/mapwfslayer.c
+++ b/mapwfslayer.c
@@ -658,7 +658,6 @@ int msPrepareWFSLayerRequest(int nLayerId, mapObj *map, layerObj *lp,
pasReqInfo, *numRequests, map, "FO") != MS_SUCCESS) {
if (psParams) {
msWFSFreeParamsObj(psParams);
- free(psParams);
}
return MS_FAILURE;
}
@@ -690,7 +689,6 @@ int msPrepareWFSLayerRequest(int nLayerId, mapObj *map, layerObj *lp,
if (psParams) {
msWFSFreeParamsObj(psParams);
- free(psParams);
}
return nStatus;
diff --git a/mapwms.c b/mapwms.c
index 7418bbf..17a3a09 100644
--- a/mapwms.c
+++ b/mapwms.c
@@ -326,9 +326,15 @@ int msWMSApplyTime(mapObj *map, int version, char *time, char *wms_exception_for
*/
void msWMSPrepareNestedGroups(mapObj* map, int nVersion, char*** nestedGroups, int* numNestedGroups, int* isUsedInNestedGroup)
{
- int i, j, k;
+ int i, k;
const char* groups;
char* errorMsg;
+ //Create array to hold unique groups
+ int maxgroups = 2000;
+ int maxgroupiter = 1;
+ char** uniqgroups = malloc(maxgroups * sizeof(char*));
+ int uniqgroupcount = 0;
+
for (i = 0; i < map->numlayers; i++) {
nestedGroups[i] = NULL; /* default */
@@ -351,24 +357,42 @@ void msWMSPrepareNestedGroups(mapObj* map, int nVersion, char*** nestedGroups, i
} else {
/* split into subgroups. Start at address + 1 because the first '/' would cause an extra empty group */
nestedGroups[i] = msStringSplit(groups + 1, '/', &numNestedGroups[i]);
- /* */
- for (j = 0; j < map->numlayers; j++) {
- if (isUsedInNestedGroup[j])
- continue;
-
- for (k=0; k<numNestedGroups[i]; k++) {
- if ( GET_LAYER(map, j)->name && strcasecmp(GET_LAYER(map, j)->name, nestedGroups[i][k]) == 0 ) {
- isUsedInNestedGroup[j] = 1;
+ /* Iterate through the groups and add them to the unique groups array */
+ for (k=0; k<numNestedGroups[i]; k++) {
+ int found ,l = 0;
+ found = 0;
+ for (l=0; l<uniqgroupcount; l++) {
+ if ( strcasecmp(uniqgroups[l], nestedGroups[i][k]) == 0 ){
+ found = 1;
break;
}
}
- }
+ if(found == 0){
+ uniqgroups[uniqgroupcount] = nestedGroups[i][k];
+ uniqgroupcount++;
+ // Does need only when maximum unique groups exceed 2000
+ if ( uniqgroupcount == (maxgroups*maxgroupiter)){
+ uniqgroups = realloc(uniqgroups, (uniqgroupcount + maxgroups) * sizeof(char*));
+ maxgroupiter++;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ /* Iterate through layers to find out whether they are in any of the nested groups */
+ for (i = 0; i < map->numlayers; i++) {
+ for (k=0; k<uniqgroupcount; k++) {
+ if ( strcasecmp(GET_LAYER(map, i)->name ,uniqgroups[k]) == 0 ){
+ isUsedInNestedGroup[i] = 1;
+ break;
}
- }
- }
+ }
}
}
+
/*
** Validate that a given dimension is inside the extents defined
*/
diff --git a/scripts/vagrant/packages.sh b/scripts/vagrant/packages.sh
index 74d41d0..228fcd5 100755
--- a/scripts/vagrant/packages.sh
+++ b/scripts/vagrant/packages.sh
@@ -14,6 +14,6 @@ apt-get -y upgrade
apt-get install -q -y git build-essential pkg-config cmake libgeos-dev rake \
libpq-dev python-all-dev libproj-dev libxml2-dev postgis php5-dev \
postgresql-server-dev-9.1 postgresql-9.1-postgis-2.1 vim bison flex swig \
- librsvg2-dev libpng12-dev libjpeg-dev libgif-dev libgd2-xpm-dev \
+ librsvg2-dev libpng12-dev libjpeg-dev libgif-dev \
libfreetype6-dev libfcgi-dev libcurl4-gnutls-dev libcairo2-dev \
libgdal1-dev libfribidi-dev libexempi-dev
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-grass/mapserver.git
More information about the Pkg-grass-devel
mailing list