[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, &current->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