[mapserver] 01/06: Imported Upstream version 7.0.2

Bas Couwenberg sebastic at debian.org
Wed Sep 21 19:41:03 UTC 2016


This is an automated email from the git hooks/post-receive script.

sebastic pushed a commit to branch master
in repository mapserver.

commit 6ff28f09891aa3aeac2b663da616e7ab2d99208f
Author: Bas Couwenberg <sebastic at xs4all.nl>
Date:   Wed Sep 21 20:56:40 2016 +0200

    Imported Upstream version 7.0.2
---
 CMakeLists.txt                              |    2 +-
 HISTORY.TXT                                 |    4 +-
 hittest.c                                   |   11 +
 kerneldensity.c                             |    1 +
 mapcairo.c                                  |    5 +-
 mapchart.c                                  |    7 +-
 mapcluster.c                                |   57 +-
 mapcopy.c                                   |   15 +-
 mapdraw.c                                   |   60 +-
 mapdrawgdal.c                               |    9 +
 mapfile.c                                   |  164 +++-
 mapgraticule.c                              |   23 +-
 maplabel.c                                  |    9 +-
 maplegend.c                                 |   12 +-
 maplibxml2.c                                |    7 +-
 mapmssql2008.c                              |  111 ++-
 mapogcfilter.c                              |  103 ++-
 mapogcfilter.h                              |    1 +
 mapogcfiltercommon.c                        |   29 +-
 mapogcsld.c                                 |    1 +
 mapogcsos.c                                 |    2 +-
 mapogr.cpp                                  | 1303 +++++++++++++++++++++------
 mapogroutput.c                              |   35 +-
 mapowscommon.c                              |   56 +-
 mappostgis.c                                |   76 +-
 mapprimitive.c                              |   12 +-
 mapquery.c                                  |   53 +-
 mapraster.c                                 |   36 +-
 maprasterquery.c                            |   10 +-
 mapscript/csharp/CMakeLists.txt             |    8 +-
 mapscript/csharp/Makefile.vc                |    3 +-
 mapscript/csharp/csmodule.i                 |   26 +-
 mapscript/csharp/examples/drawmapGDIPlus.cs |   97 ++
 mapscript/csharp/examples/drawmapWPF.cs     |  109 +++
 mapscript/csharp/swig_csharp_extensions.i   |   50 +
 mapscript/php/layer.c                       |  100 +-
 mapscript/swiginc/class.i                   |    9 +-
 mapscript/swiginc/color.i                   |    2 +-
 mapserver.h                                 |    2 +-
 mapsymbol.c                                 |    6 +
 maputfgrid.cpp                              |   58 +-
 mapwcs20.c                                  |   21 +-
 mapwfs.c                                    |    7 +-
 mapwfs11.c                                  |   20 +-
 mapwfs20.c                                  |    6 +-
 45 files changed, 2097 insertions(+), 641 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 3788c1a..1ca6472 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -17,7 +17,7 @@ include(CheckCSourceCompiles)
 
 set (MapServer_VERSION_MAJOR 7)
 set (MapServer_VERSION_MINOR 0)
-set (MapServer_VERSION_REVISION 1)
+set (MapServer_VERSION_REVISION 2)
 set (MapServer_VERSION_SUFFIX "")
 
 set(TARGET_VERSION_MAJOR ${MapServer_VERSION_MAJOR})
diff --git a/HISTORY.TXT b/HISTORY.TXT
index 7ddb075..13d2340 100644
--- a/HISTORY.TXT
+++ b/HISTORY.TXT
@@ -8,7 +8,9 @@ next.  Developers are strongly encouraged to document their changes and
 their impacts on the users here.  (Please add the most recent changes to
 the top of the list.)
 
-For a complete change history, please see the Git log comments.
+For a complete change history, please see the Git log comments.  For more
+details about recent point releases, please see the online changelog at:
+http://mapserver.org/development/changelog/
 
 7.0.0 release (2015/07/24)
 --------------------------
diff --git a/hittest.c b/hittest.c
index 073442c..bec7cb7 100644
--- a/hittest.c
+++ b/hittest.c
@@ -189,10 +189,16 @@ int msHitTestLayer(mapObj *map, layerObj *layer, layer_hittest *hittest) {
 
     status = msLayerWhichShapes(layer, searchrect, MS_FALSE);
     if(status == MS_DONE) { /* no overlap */
+#ifdef USE_GEOS
+      msFreeShape(&searchpoly);
+#endif
       msLayerClose(layer);
       hittest->status = 0;
       return MS_SUCCESS;
     } else if(status != MS_SUCCESS) {
+#ifdef USE_GEOS
+      msFreeShape(&searchpoly);
+#endif
       msLayerClose(layer);
       return MS_FAILURE;
     }
@@ -245,6 +251,7 @@ int msHitTestLayer(mapObj *map, layerObj *layer, layer_hittest *hittest) {
       hittest->status = 1;
 
       if(maxfeatures >=0 && featuresdrawn >= maxfeatures) {
+        msFreeShape(&shape);
         status = MS_DONE;
         break;
       }
@@ -258,6 +265,10 @@ int msHitTestLayer(mapObj *map, layerObj *layer, layer_hittest *hittest) {
       msFreeShape(&shape);
     }
 
+#ifdef USE_GEOS
+    msFreeShape(&searchpoly);
+#endif
+
     if (classgroup)
       msFree(classgroup);
 
diff --git a/kerneldensity.c b/kerneldensity.c
index bc65a50..93a3a9e 100644
--- a/kerneldensity.c
+++ b/kerneldensity.c
@@ -318,6 +318,7 @@ int msComputeKernelDensityDataset(mapObj *map, imageObj *image, layerObj *kernel
       msSetError(MS_MISCERR,"msComputeKernelDensityDataset()","failed to create in-memory gdal dataset for interpolated data");
       status = MS_FAILURE;
       free(iValues);
+      return status;
     }
     adfGeoTransform[0] = map->extent.minx - map->cellsize * 0.5; /* top left x */
     adfGeoTransform[1] = map->cellsize;/* w-e pixel resolution */
diff --git a/mapcairo.c b/mapcairo.c
index 9da189b..600530b 100644
--- a/mapcairo.c
+++ b/mapcairo.c
@@ -174,7 +174,7 @@ static cairoFaceCache* getCairoFontFace(cairoCacheData *cache, FT_Face ftface) {
   cur->options = cairo_font_options_create();
   cairo_font_options_set_hint_style(cur->options,CAIRO_HINT_STYLE_NONE);
   return cur;
-} 
+}
 
 #define msCairoSetSourceColor(cr, c) cairo_set_source_rgba((cr),(c)->red/255.0,(c)->green/255.0,(c)->blue/255.0,(c)->alpha/255.0);
 
@@ -1043,8 +1043,7 @@ int msRenderRasterizedSVGSymbol(imageObj *img, double x, double y, symbolObj *sy
       height = surface_h = symbol->sizey;
     }
     if (style->rotation != 0) {
-      surface_w = MS_NINT(width * 1.415);
-      surface_h = MS_NINT(height * 1.415);
+      surface_w = surface_h = MS_NINT(MS_MAX(height, width) * 1.415);
     }
 
     surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, surface_w, surface_h);
diff --git a/mapchart.c b/mapchart.c
index 40cc911..c788ea6 100644
--- a/mapchart.c
+++ b/mapchart.c
@@ -250,10 +250,8 @@ int getNextShape(mapObj *map, layerObj *layer, double *values, int *nvalues, sty
   status = msLayerNextShape(layer, shape);
   if(status == MS_SUCCESS) {
 #ifdef USE_PROJ
-    if(layer->project && msProjectionsDiffer(&(layer->projection), &(map->projection)))
+    if(layer->project)
       msProjectShape(&layer->projection, &map->projection, shape);
-    else
-      layer->project = MS_FALSE;
 #endif
 
     if(msBindLayerToShape(layer, shape, MS_DRAWMODE_FEATURES|MS_DRAWMODE_LABELS) != MS_SUCCESS)
@@ -363,6 +361,9 @@ int msDrawPieChartLayer(mapObj *map, layerObj *layer, imageObj *image)
       return MS_FAILURE;
     }
   }
+#ifdef USE_PROJ
+  layer->project = msProjectionsDiffer(&(layer->projection), &(map->projection));
+#endif
   /* step through the target shapes */
   msInitShape(&shape);
 
diff --git a/mapcluster.c b/mapcluster.c
index 9abb4bd..39d6a5d 100644
--- a/mapcluster.c
+++ b/mapcluster.c
@@ -1497,6 +1497,52 @@ int msClusterLayerOpen(layerObj *layer)
   return MS_SUCCESS;
 }
 
+int msClusterLayerTranslateFilter(layerObj *layer, expressionObj *filter, char *filteritem)
+{
+  msClusterLayerInfo* layerinfo = layer->layerinfo;
+
+  if (!layerinfo) {
+    msSetError(MS_MISCERR, "Layer is not open: %s", "msClusterLayerTranslateFilter()", layer->name);
+    return MS_FAILURE;
+  }
+
+  return layerinfo->srcLayer.vtable->LayerTranslateFilter(&layerinfo->srcLayer, filter, filteritem);
+}
+
+char* msClusterLayerEscapeSQLParam(layerObj *layer, const char* pszString)
+{
+  msClusterLayerInfo* layerinfo = layer->layerinfo;
+
+  if (!layerinfo) {
+    msSetError(MS_MISCERR, "Layer is not open: %s", "msClusterLayerEscapeSQLParam()", layer->name);
+    return msStrdup("");
+  }
+
+  return layerinfo->srcLayer.vtable->LayerEscapeSQLParam(&layerinfo->srcLayer, pszString);
+}
+
+int msClusterLayerGetAutoProjection(layerObj *layer, projectionObj* projection)
+{
+  msClusterLayerInfo* layerinfo = layer->layerinfo;
+
+  if (!layerinfo) {
+    msSetError(MS_MISCERR, "Layer is not open: %s", "msClusterLayerGetAutoProjection()", layer->name);
+    return MS_FAILURE;
+  }
+
+  return layerinfo->srcLayer.vtable->LayerGetAutoProjection(&layerinfo->srcLayer, projection);
+}
+
+int msClusterLayerGetPaging(layerObj *layer)
+{
+  return MS_FALSE;
+}
+
+void msClusterLayerEnablePaging(layerObj *layer, int value)
+{
+  return;
+}
+
 void msClusterLayerCopyVirtualTable(layerVTableObj* vtable)
 {
   vtable->LayerInitItemInfo = msClusterLayerInitItemInfo;
@@ -1514,6 +1560,14 @@ void msClusterLayerCopyVirtualTable(layerVTableObj* vtable)
 
   vtable->LayerGetNumFeatures = msClusterLayerGetNumFeatures;
   vtable->LayerGetAutoStyle = msClusterLayerGetAutoStyle;
+  vtable->LayerTranslateFilter = msClusterLayerTranslateFilter;
+  /* vtable->LayerSupportsCommonFilters, use driver implementation */
+  vtable->LayerEscapeSQLParam = msClusterLayerEscapeSQLParam;
+  /* vtable->LayerEscapePropertyName, use driver implementation */
+
+  vtable->LayerEnablePaging = msClusterLayerEnablePaging;
+  vtable->LayerGetPaging = msClusterLayerGetPaging;
+  vtable->LayerGetAutoProjection = msClusterLayerGetAutoProjection;
 }
 
 #ifdef USE_CLUSTER_PLUGIN
@@ -1531,8 +1585,7 @@ PluginInitializeVirtualTable(layerVTableObj* vtable, layerObj *layer)
 
 #endif
 
-int
-msClusterLayerInitializeVirtualTable(layerObj *layer)
+int msClusterLayerInitializeVirtualTable(layerObj *layer)
 {
   assert(layer != NULL);
   assert(layer->vtable != NULL);
diff --git a/mapcopy.c b/mapcopy.c
index 30d893d..0d50943 100644
--- a/mapcopy.c
+++ b/mapcopy.c
@@ -925,6 +925,19 @@ int msCopyScaleToken(scaleTokenObj *src, scaleTokenObj *dst) {
   return MS_SUCCESS;
 }
 
+int msCopyCompositingFilter(CompositingFilter **pdst, CompositingFilter *src) {
+  CompositingFilter *dst = NULL;
+  if(!src) {
+    *pdst = NULL;
+    return MS_SUCCESS;
+  }
+  if(!dst) {
+    dst = *pdst = msSmallMalloc(sizeof(CompositingFilter));
+  } 
+  dst->filter = msStrdup(src->filter);
+  return MS_SUCCESS;
+}
+
 int msCopyCompositer(LayerCompositer **ldst, LayerCompositer *src) {
   LayerCompositer *dst = NULL;
   if(!src) {
@@ -942,7 +955,7 @@ int msCopyCompositer(LayerCompositer **ldst, LayerCompositer *src) {
     dst->comp_op = src->comp_op;
     dst->opacity = src->opacity;
     dst->next = NULL;
-    /* TODO dst->filter */
+    msCopyCompositingFilter(&dst->filter, src->filter);
     src = src->next;
   }
   return MS_SUCCESS;
diff --git a/mapdraw.c b/mapdraw.c
index 825f1b4..1ccc0fe 100644
--- a/mapdraw.c
+++ b/mapdraw.c
@@ -665,9 +665,9 @@ int msDrawLayer(mapObj *map, layerObj *layer, imageObj *image)
   if(layer->compositer && !layer->compositer->next && layer->compositer->opacity == 0) return MS_SUCCESS; /* layer is completely transparent, skip it */
   
 
-  /* conditions may have changed since this layer last drawn, so set
-     layer->project true to recheck projection needs (Bug #673) */
-  layer->project = MS_TRUE;
+  /* conditions may have changed since this layer last drawn, so retest
+     layer->project (Bug #673) */
+  layer->project = msProjectionsDiffer(&(layer->projection),&(map->projection));
 
   /* make sure labelcache setting is set correctly if postlabelcache is set. This is done by the parser but
      may have been altered by a mapscript. see #5142 */
@@ -771,6 +771,7 @@ int msDrawLayer(mapObj *map, layerObj *layer, imageObj *image)
                      "msDrawLayer()");
           return (MS_FAILURE);
         }
+        image_draw->map = map;
         renderer->startLayer(image_draw,map,layer);
       }
     }
@@ -1182,9 +1183,9 @@ int msDrawQueryLayer(mapObj *map, layerObj *layer, imageObj *image)
 
   if(!msLayerIsVisible(map, layer)) return(MS_SUCCESS); /* not an error, just nothing to do */
 
-  /* conditions may have changed since this layer last drawn, so set
-     layer->project true to recheck projection needs (Bug #673) */
-  layer->project = MS_TRUE;
+  /* conditions may have changed since this layer last drawn, so reset
+     layer->project to recheck projection needs (Bug #673) */
+  layer->project = msProjectionsDiffer(&(layer->projection),&(map->projection));
 
   /* set annotation status */
   annotate = msEvalContext(map, layer, layer->labelrequires);
@@ -1239,7 +1240,7 @@ int msDrawQueryLayer(mapObj *map, layerObj *layer, imageObj *image)
           colorbuffer[i] = layer->class[i]->styles[0]->outlinecolor; /* if no color, save the outlinecolor from the BOTTOM style */
           layer->class[i]->styles[0]->outlinecolor = map->querymap.color;
         }
-      } else {
+      } else if (layer->class[i]->numstyles > 0) {
         if(MS_VALID_COLOR(layer->class[i]->styles[layer->class[i]->numstyles-1]->color)) {
           colorbuffer[i] = layer->class[i]->styles[layer->class[i]->numstyles-1]->color; /* save the color from the TOP style */
           layer->class[i]->styles[layer->class[i]->numstyles-1]->color = map->querymap.color;
@@ -1247,6 +1248,9 @@ int msDrawQueryLayer(mapObj *map, layerObj *layer, imageObj *image)
           colorbuffer[i] = layer->class[i]->styles[layer->class[i]->numstyles-1]->outlinecolor; /* if no color, save the outlinecolor from the TOP style */
           layer->class[i]->styles[layer->class[i]->numstyles-1]->outlinecolor = map->querymap.color;
         }
+      } else if (layer->class[i]->numlabels > 0) {
+          colorbuffer[i] = layer->class[i]->labels[0]->color;
+          layer->class[i]->labels[0]->color = map->querymap.color;
       }
 
       mindistancebuffer[i] = -1; /* RFC77 TODO: only using the first label, is that cool? */
@@ -1355,12 +1359,16 @@ int msDrawQueryLayer(mapObj *map, layerObj *layer, imageObj *image)
           layer->class[i]->styles[0]->color = colorbuffer[i];
         else if(MS_VALID_COLOR(layer->class[i]->styles[0]->outlinecolor))
           layer->class[i]->styles[0]->outlinecolor = colorbuffer[i]; /* if no color, restore outlinecolor for the BOTTOM style */
-      } else {
+      } else if (layer->class[i]->numstyles > 0) {
         if(MS_VALID_COLOR(layer->class[i]->styles[layer->class[i]->numstyles-1]->color))
           layer->class[i]->styles[layer->class[i]->numstyles-1]->color = colorbuffer[i];
         else if(MS_VALID_COLOR(layer->class[i]->styles[layer->class[i]->numstyles-1]->outlinecolor))
           layer->class[i]->styles[layer->class[i]->numstyles-1]->outlinecolor = colorbuffer[i]; /* if no color, restore outlinecolor for the TOP style */
       }
+      else if (layer->class[i]->numlabels > 0) {
+          if(MS_VALID_COLOR(layer->class[i]->labels[0]->color))
+            layer->class[i]->labels[0]->color = colorbuffer[i];
+      }
 
       if(layer->class[i]->numlabels > 0)
         layer->class[i]->labels[0]->mindistance = mindistancebuffer[i]; /* RFC77 TODO: again, only using the first label, is that cool? */
@@ -1511,10 +1519,8 @@ int circleLayerDrawShape(mapObj *map, imageObj *image, layerObj *layer, shapeObj
   if (layer->transform == MS_TRUE) {
 
 #ifdef USE_PROJ
-    if (layer->project && msProjectionsDiffer(&(layer->projection), &(map->projection)))
+    if (layer->project)
       msProjectPoint(&layer->projection, &map->projection, &center);
-    else
-      layer->project = MS_FALSE;
 #endif
 
     center.x = MS_MAP2IMAGE_X(center.x, map->extent.minx, map->cellsize);
@@ -1542,10 +1548,8 @@ int pointLayerDrawShape(mapObj *map, imageObj *image, layerObj *layer, shapeObj
   pointObj *point;
 
 #ifdef USE_PROJ
-  if (layer->project && layer->transform == MS_TRUE && msProjectionsDiffer(&(layer->projection), &(map->projection)))
+  if (layer->project && layer->transform == MS_TRUE)
     msProjectShape(&layer->projection, &map->projection, shape);
-  else
-    layer->project = MS_FALSE;
 #endif
 
   for (l = 0; l < layer->class[c]->numlabels; l++)
@@ -1572,7 +1576,7 @@ int pointLayerDrawShape(mapObj *map, imageObj *image, layerObj *layer, shapeObj
       }
       if(MS_DRAW_LABELS(drawmode)) {
         if (layer->labelcache) {
-          if (msAddLabelGroup(map, image, layer->index, c, shape, point, -1) != MS_SUCCESS) return (MS_FAILURE);
+          if (msAddLabelGroup(map, image, layer, c, shape, point, -1) != MS_SUCCESS) return (MS_FAILURE);
         } else {
           for (l = 0; l < layer->class[c]->numlabels; l++)
             if(msGetLabelStatus(map,layer,shape,layer->class[c]->labels[l]) == MS_ON) {
@@ -1769,7 +1773,7 @@ int polygonLayerDrawShape(mapObj *map, imageObj *image, layerObj *layer,
         for (i = 0; i < layer->class[c]->numlabels; i++)
           if (layer->class[c]->labels[i]->angle != 0) layer->class[c]->labels[i]->angle -= map->gt.rotation_angle; /* TODO: is this correct ??? */
         if (layer->labelcache) {
-          if (msAddLabelGroup(map, image, layer->index, c, anno_shape, &annopnt,
+          if (msAddLabelGroup(map, image, layer, c, anno_shape, &annopnt,
                               MS_MIN(shape->bounds.maxx - shape->bounds.minx, shape->bounds.maxy - shape->bounds.miny)) != MS_SUCCESS) {
             return MS_FAILURE;
           }
@@ -1840,10 +1844,8 @@ int msDrawShape(mapObj *map, layerObj *layer, shapeObj *shape, imageObj *image,
   }
 
 #ifdef USE_PROJ
-  if (layer->project && layer->transform == MS_TRUE && msProjectionsDiffer(&(layer->projection), &(map->projection)))
+  if (layer->project && layer->transform == MS_TRUE)
     msProjectShape(&layer->projection, &map->projection, shape);
-  else
-    layer->project = MS_FALSE;
 #endif
 
   /* check if we'll need the unclipped shape */
@@ -2028,10 +2030,8 @@ int msDrawPoint(mapObj *map, layerObj *layer, pointObj *point, imageObj *image,
   labelObj *label=NULL;
 
 #ifdef USE_PROJ
-  if(layer->transform == MS_TRUE && layer->project && msProjectionsDiffer(&(layer->projection), &(map->projection)))
+  if(layer->transform == MS_TRUE && layer->project)
     msProjectPoint(&layer->projection, &map->projection, point);
-  else
-    layer->project = MS_FALSE;
 #endif
 
   if(labeltext && theclass->numlabels > 0) {
@@ -2269,7 +2269,7 @@ void offsetAndTest(mapObj *map, labelCacheMemberObj *cachePtr, double ox, double
       }
     }
     for(j=0; j<ts->label->numstyles; j++) {
-      if(ts->label->styles[i]->_geomtransform.type == MS_GEOMTRANSFORM_LABELPOINT) {
+      if(ts->label->styles[j]->_geomtransform.type == MS_GEOMTRANSFORM_LABELPOINT) {
         scratch->poly = scratch_line;
         offset_label_bounds(ts->style_bounds[j], scratch, ox, oy);
         status = msTestLabelCacheCollisions(map, cachePtr, scratch, priority, label_idx);
@@ -2313,8 +2313,8 @@ void offsetAndTest(mapObj *map, labelCacheMemberObj *cachePtr, double ox, double
     }
     if(ts->style_bounds) {
       for(j=0; j<ts->label->numstyles; j++) {
-        if(ts->label->styles[i]->_geomtransform.type == MS_GEOMTRANSFORM_LABELPOINT ||
-            ts->label->styles[i]->_geomtransform.type == MS_GEOMTRANSFORM_LABELPOLY) {
+        if(ts->label->styles[j]->_geomtransform.type == MS_GEOMTRANSFORM_LABELPOINT ||
+            ts->label->styles[j]->_geomtransform.type == MS_GEOMTRANSFORM_LABELPOLY) {
           offset_label_bounds(ts->style_bounds[j], ts->style_bounds[j], ox, oy);
         }
       }
@@ -2386,8 +2386,8 @@ int msDrawOffsettedLabels(imageObj *image, mapObj *map, int priority)
 
 #define otest(ox,oy) if((x0+(ox)) >= labelcache->gutter &&\
                 (y0+(oy)) >= labelcache->gutter &&\
-                (x0+(ox)) < image->width + labelcache->gutter &&\
-                (y0+(oy)) < image->height + labelcache->gutter) {\
+                (x0+(ox)) < image->width - labelcache->gutter &&\
+                (y0+(oy)) < image->height - labelcache->gutter) {\
                    scratch_line.point = scratch_points;\
                    scratch.poly = &scratch_line; \
                    offsetAndTest(map,cachePtr,(ox),(oy),priority,l,&scratch); \
@@ -2511,7 +2511,7 @@ int msDrawOffsettedLabels(imageObj *image, mapObj *map, int priority)
             /* here's where we draw the label styles */
             for(i=0; i<ts->label->numstyles; i++) {
               if(ts->label->styles[i]->_geomtransform.type == MS_GEOMTRANSFORM_LABELPOINT) {
-                retval = msDrawMarkerSymbol(map, image, &(cachePtr->point), ts->label->styles[i], layerPtr->scalefactor);
+                retval = msDrawMarkerSymbol(map, image, &(labelLeader.line->point[1]), ts->label->styles[i], layerPtr->scalefactor);
                 if(UNLIKELY(retval == MS_FAILURE)) {
                   goto offset_cleanup;
                 }
@@ -2952,7 +2952,7 @@ int msDrawLabelCache(mapObj *map, imageObj *image)
                                                            textSymbolPtr->rotation, textSymbolPtr->label->buffer * textSymbolPtr->scalefactor,
                                                            &metrics_bounds);
                     if(need_labelpoly) get_metrics(&(cachePtr->point), MS_CC, textSymbolPtr->textpath,
-                                                              marker_offset_x + label_offset_x, marker_offset_y + label_offset_y,
+                                                              label_offset_x, label_offset_y,
                                                               textSymbolPtr->rotation, 1, &labelpoly_bounds);
                   }
                 } else { /* explicit position */
@@ -2960,7 +2960,7 @@ int msDrawLabelCache(mapObj *map, imageObj *image)
                     metrics_bounds.poly = &metrics_line;
                     textSymbolPtr->annopoint = get_metrics(&(cachePtr->point), MS_CC, textSymbolPtr->textpath, label_offset_x, label_offset_y,
                             textSymbolPtr->rotation, textSymbolPtr->label->buffer * textSymbolPtr->scalefactor, &metrics_bounds);
-                    if(need_labelpoly) get_metrics(&(cachePtr->point), textSymbolPtr->label->position, textSymbolPtr->textpath,
+                    if(need_labelpoly) get_metrics(&(cachePtr->point), MS_CC, textSymbolPtr->textpath,
                                                               label_offset_x, label_offset_y, textSymbolPtr->rotation, 1, &labelpoly_bounds);
                   } else {
                     metrics_bounds.poly = &metrics_line;
diff --git a/mapdrawgdal.c b/mapdrawgdal.c
index f90f2ac..eb4ca15 100644
--- a/mapdrawgdal.c
+++ b/mapdrawgdal.c
@@ -1270,6 +1270,9 @@ LoadGDALImages( GDALDatasetH hDS, int band_numbers[4], int band_count,
         if( bGotNoData && pafRawData[i] == fNoDataValue )
           continue;
 
+        if( CPLIsNan(pafRawData[i]) )
+          continue;
+
         if( !bMinMaxSet ) {
           dfScaleMin = dfScaleMax = pafRawData[i];
           bMinMaxSet = TRUE;
@@ -1764,6 +1767,9 @@ msDrawRasterLayerGDAL_16BitClassification(
     if( bGotNoData && pafRawData[i] == fNoDataValue )
       continue;
 
+    if( CPLIsNan(pafRawData[i]) )
+      continue;
+
     if( !bGotFirstValue ) {
       fDataMin = fDataMax = pafRawData[i];
       bGotFirstValue = TRUE;
@@ -1915,6 +1921,9 @@ msDrawRasterLayerGDAL_16BitClassification(
         continue;
       }
 
+      if( CPLIsNan(fRawValue) )
+        continue;
+
       if(SKIP_MASK(j,i))
         continue;
 
diff --git a/mapfile.c b/mapfile.c
index 244c0d6..a8a48bf 100644
--- a/mapfile.c
+++ b/mapfile.c
@@ -3709,6 +3709,22 @@ int initLayerCompositer(LayerCompositer *compositer) {
   compositer->filter = NULL;
   return MS_SUCCESS;
 }
+
+int freeLayerCompositers(LayerCompositer * item) {
+  while(item) {
+    LayerCompositer * next = item->next;
+
+    if (item->filter) {
+      msFree(item->filter->filter);
+      msFree(item->filter);
+      }
+    msFree(item);
+
+    item=next;
+    }
+  return MS_SUCCESS;
+}
+
 /*
 ** Initialize, load and free a single layer structure
 */
@@ -3978,6 +3994,8 @@ int freeLayer(layerObj *layer)
       msFree(layer->sortBy.properties[i].item);
   msFree(layer->sortBy.properties);
 
+  freeLayerCompositers(layer->compositer);
+
   return MS_SUCCESS;
 }
 
@@ -4108,7 +4126,11 @@ int loadLayerCompositer(LayerCompositer *compositer) {
       case COMPFILTER:
         compositer->filter = msSmallMalloc(sizeof(CompositingFilter));
         initCompositingFilter(compositer->filter);
-        if(getString(&compositer->filter->filter) == MS_FAILURE) return(MS_FAILURE);
+        if(getString(&compositer->filter->filter) == MS_FAILURE) {
+          msFree(compositer->filter);
+          compositer->filter=NULL;
+          return(MS_FAILURE);
+          }
         break;
       case COMPOP: {
         char *compop=NULL;
@@ -4172,6 +4194,11 @@ int loadLayerCompositer(LayerCompositer *compositer) {
         else {
           msSetError(MS_PARSEERR,"Unknown COMPOP \"%s\"", "loadLayerCompositer()", compop);
           free(compop);
+          if (compositer->filter) {
+            msFree(compositer->filter->filter);
+            msFree(compositer->filter);
+            compositer->filter=NULL;
+            }
           return MS_FAILURE;
         }
         free(compop);
@@ -4180,14 +4207,30 @@ int loadLayerCompositer(LayerCompositer *compositer) {
       case END:
         return MS_SUCCESS;
       case OPACITY:
-        if (getInteger(&(compositer->opacity)) == -1)
+        if (getInteger(&(compositer->opacity)) == -1) {
+          if (compositer->filter) {
+            msFree(compositer->filter->filter);
+            msFree(compositer->filter);
+            compositer->filter=NULL;
+            }
           return MS_FAILURE;
+          }
         if(compositer->opacity<0 || compositer->opacity>100) {
+          if (compositer->filter) {
+            msFree(compositer->filter->filter);
+            msFree(compositer->filter);
+            compositer->filter=NULL;
+            }
           msSetError(MS_PARSEERR,"OPACITY must be between 0 and 100 (line %d)","loadLayerCompositer()",msyylineno);
           return MS_FAILURE;
         }
         break;
       default:
+        if (compositer->filter) {
+          msFree(compositer->filter->filter);
+          msFree(compositer->filter);
+          compositer->filter=NULL;
+          }
         msSetError(MS_IDENTERR, "Parsing error 2 near (%s):(line %d)", "loadLayerCompositer()",  msyystring_buffer, msyylineno );
         return(MS_FAILURE);
     }
@@ -4240,7 +4283,10 @@ int loadLayer(layerObj *layer, mapObj *map)
       case(COMPOSITE): {
         LayerCompositer *compositer = msSmallMalloc(sizeof(LayerCompositer));
         initLayerCompositer(compositer);
-        if(MS_FAILURE == loadLayerCompositer(compositer)) return -1;
+        if(MS_FAILURE == loadLayerCompositer(compositer)) {
+          msFree(compositer);
+          return -1;
+          }
         if(!layer->compositer) {
           layer->compositer = compositer;
         } else {
@@ -4695,6 +4741,110 @@ int msUpdateLayerFromString(layerObj *layer, char *string, int url_string)
   return MS_SUCCESS;
 }
 
+static void writeCompositingFilter(FILE *stream, int indent, CompositingFilter *filter) {
+  if(filter) {
+    writeString(stream, indent, "COMPFILTER", "", filter->filter);
+  }
+}
+
+static void writeLayerCompositer(FILE *stream, int indent, LayerCompositer *compositor) {
+  indent++;
+  while(compositor) {
+    writeBlockBegin(stream, indent, "COMPOSITE");
+    writeCompositingFilter(stream, indent, compositor->filter);
+    if(compositor->comp_op != MS_COMPOP_SRC_OVER) {
+      switch(compositor->comp_op) {
+        case MS_COMPOP_CLEAR:
+          writeString(stream, indent, "COMPOP", NULL, "clear");
+          break;
+        case MS_COMPOP_COLOR_BURN:
+          writeString(stream, indent, "COMPOP", NULL, "color-burn");
+          break;
+        case MS_COMPOP_COLOR_DODGE:
+          writeString(stream, indent, "COMPOP", NULL, "color-dodge");
+          break;
+        case MS_COMPOP_CONTRAST:
+          writeString(stream, indent, "COMPOP", NULL, "contrast");
+          break;
+        case MS_COMPOP_DARKEN:
+          writeString(stream, indent, "COMPOP", NULL, "darken");
+          break;
+        case MS_COMPOP_DIFFERENCE:
+          writeString(stream, indent, "COMPOP", NULL, "difference");
+          break;
+        case MS_COMPOP_DST:
+          writeString(stream, indent, "COMPOP", NULL, "dst");
+          break;
+        case MS_COMPOP_DST_ATOP:
+          writeString(stream, indent, "COMPOP", NULL, "dst-atop");
+          break;
+        case MS_COMPOP_DST_IN:
+          writeString(stream, indent, "COMPOP", NULL, "dst-in");
+          break;
+        case MS_COMPOP_DST_OUT:
+          writeString(stream, indent, "COMPOP", NULL, "dst-out");
+          break;
+        case MS_COMPOP_DST_OVER:
+          writeString(stream, indent, "COMPOP", NULL, "dst-over");
+          break;
+        case MS_COMPOP_EXCLUSION:
+          writeString(stream, indent, "COMPOP", NULL, "exclusion");
+          break;
+        case MS_COMPOP_HARD_LIGHT:
+          writeString(stream, indent, "COMPOP", NULL, "hard-light");
+          break;
+        case MS_COMPOP_INVERT:
+          writeString(stream, indent, "COMPOP", NULL, "invert");
+          break;
+        case MS_COMPOP_INVERT_RGB:
+          writeString(stream, indent, "COMPOP", NULL, "invert-rgb");
+          break;
+        case MS_COMPOP_LIGHTEN:
+          writeString(stream, indent, "COMPOP", NULL, "lighten");
+          break;
+        case MS_COMPOP_MINUS:
+          writeString(stream, indent, "COMPOP", NULL, "minus");
+          break;
+        case MS_COMPOP_MULTIPLY:
+          writeString(stream, indent, "COMPOP", NULL, "multiply");
+          break;
+        case MS_COMPOP_OVERLAY:
+          writeString(stream, indent, "COMPOP", NULL, "overlay");
+          break;
+        case MS_COMPOP_PLUS:
+          writeString(stream, indent, "COMPOP", NULL, "plus");
+          break;
+        case MS_COMPOP_SCREEN:
+          writeString(stream, indent, "COMPOP", NULL, "screen");
+          break;
+        case MS_COMPOP_SOFT_LIGHT:
+          writeString(stream, indent, "COMPOP", NULL, "soft-light");
+          break;
+        case MS_COMPOP_SRC:
+          writeString(stream, indent, "COMPOP", NULL, "src");
+          break;
+        case MS_COMPOP_SRC_ATOP:
+          writeString(stream, indent, "COMPOP", NULL, "src-atop");
+          break;
+        case MS_COMPOP_SRC_IN:
+          writeString(stream, indent, "COMPOP", NULL, "src-in");
+          break;
+        case MS_COMPOP_SRC_OUT:
+          writeString(stream, indent, "COMPOP", NULL, "src-out");
+          break;
+        case MS_COMPOP_SRC_OVER:
+          writeString(stream, indent, "COMPOP", NULL, "src-over");
+          break;
+        case MS_COMPOP_XOR:
+          writeString(stream, indent, "COMPOP", NULL, "xor");
+          break;
+      }
+    }
+    writeNumber(stream,indent,"OPACITY",100,compositor->opacity);
+    writeBlockEnd(stream,indent,"COMPOSITE");
+    compositor = compositor->next;
+  }
+}
 static void writeLayer(FILE *stream, int indent, layerObj *layer)
 {
   int i;
@@ -4710,6 +4860,7 @@ static void writeLayer(FILE *stream, int indent, layerObj *layer)
   writeString(stream, indent, "CLASSGROUP", NULL, layer->classgroup);
   writeString(stream, indent, "CLASSITEM", NULL, layer->classitem);
   writeCluster(stream, indent, &(layer->cluster));
+  writeLayerCompositer(stream, indent, layer->compositer);
   writeString(stream, indent, "CONNECTION", NULL, layer->connection);
   writeKeyword(stream, indent, "CONNECTIONTYPE", layer->connectiontype, 10, MS_OGR, "OGR", MS_POSTGIS, "POSTGIS", MS_WMS, "WMS", MS_ORACLESPATIAL, "ORACLESPATIAL", MS_WFS, "WFS", MS_PLUGIN, "PLUGIN", MS_UNION, "UNION", MS_UVRASTER, "UVRASTER", MS_CONTOUR, "CONTOUR", MS_KERNELDENSITY, "KERNELDENSITY");
   writeString(stream, indent, "DATA", NULL, layer->data);
@@ -4760,7 +4911,7 @@ static void writeLayer(FILE *stream, int indent, layerObj *layer)
   writeNumber(stream, indent, "TOLERANCE", -1, layer->tolerance);
   writeKeyword(stream, indent, "TOLERANCEUNITS", layer->toleranceunits, 7, MS_INCHES, "INCHES", MS_FEET ,"FEET", MS_MILES, "MILES", MS_METERS, "METERS", MS_KILOMETERS, "KILOMETERS", MS_NAUTICALMILES, "NAUTICALMILES", MS_DD, "DD");
   writeKeyword(stream, indent, "TRANSFORM", layer->transform, 10, MS_FALSE, "FALSE", MS_UL, "UL", MS_UC, "UC", MS_UR, "UR", MS_CL, "CL", MS_CC, "CC", MS_CR, "CR", MS_LL, "LL", MS_LC, "LC", MS_LR, "LR");
-  writeKeyword(stream, indent, "TYPE", layer->type, 8, MS_LAYER_POINT, "POINT", MS_LAYER_LINE, "LINE", MS_LAYER_POLYGON, "POLYGON", MS_LAYER_RASTER, "RASTER", MS_LAYER_QUERY, "QUERY", MS_LAYER_CIRCLE, "CIRCLE", MS_LAYER_TILEINDEX, "TILEINDEX", MS_LAYER_CHART, "CHART");
+  writeKeyword(stream, indent, "TYPE", layer->type, 9, MS_LAYER_POINT, "POINT", MS_LAYER_LINE, "LINE", MS_LAYER_POLYGON, "POLYGON", MS_LAYER_RASTER, "RASTER", MS_LAYER_ANNOTATION, "ANNOTATION", MS_LAYER_QUERY, "QUERY", MS_LAYER_CIRCLE, "CIRCLE", MS_LAYER_TILEINDEX, "TILEINDEX", MS_LAYER_CHART, "CHART");
   writeKeyword(stream, indent, "UNITS", layer->units, 9, MS_INCHES, "INCHES", MS_FEET ,"FEET", MS_MILES, "MILES", MS_METERS, "METERS", MS_KILOMETERS, "KILOMETERS", MS_NAUTICALMILES, "NAUTICALMILES", MS_DD, "DD", MS_PIXELS, "PIXELS", MS_PERCENTAGES, "PERCENTATGES");
   writeHashTable(stream, indent, "VALIDATION", &(layer->validation));
 
@@ -6868,11 +7019,14 @@ int msUpdateMapFromURL(mapObj *map, char *variable, char *string)
 
 static void hashTableSubstituteString(hashTableObj *hash, const char *from, const char *to) {
   const char *key, *val;
+  char *new_val;
   key = msFirstKeyFromHashTable(hash);
   while(key != NULL) {
     val = msLookupHashTable(hash, key);
     if(strcasestr(val, from)) {
-      msInsertHashTable(hash, key, msCaseReplaceSubstring(msStrdup(val), from, to));
+      new_val = msCaseReplaceSubstring(msStrdup(val), from, to);
+      msInsertHashTable(hash, key, new_val);
+      msFree(new_val);
     }
     key = msNextKeyFromHashTable(hash, key);
   }
diff --git a/mapgraticule.c b/mapgraticule.c
index 239e38a..688b45b 100644
--- a/mapgraticule.c
+++ b/mapgraticule.c
@@ -205,10 +205,9 @@ int msGraticuleLayerWhichShapes(layerObj *layer, rectObj rect, int isQuery)
     pInfo->pboundinglines[0].point[1].y = rectMapCoordinates.maxy;
 
 #ifdef USE_PROJ
-    if(layer->project && msProjectionsDiffer(&(layer->projection), &(layer->map->projection)))
+    layer->project = msProjectionsDiffer(&(layer->projection), &(layer->map->projection));
+    if(layer->project)
       msProjectLine(&layer->map->projection, &layer->projection, &pInfo->pboundinglines[0]);
-    else
-      layer->project = MS_FALSE;
 #endif
 
     /*
@@ -222,10 +221,8 @@ int msGraticuleLayerWhichShapes(layerObj *layer, rectObj rect, int isQuery)
     pInfo->pboundinglines[1].point[1].y = rectMapCoordinates.miny;
 
 #ifdef USE_PROJ
-    if(layer->project && msProjectionsDiffer(&(layer->projection), &(layer->map->projection)))
+    if(layer->project)
       msProjectLine(&layer->map->projection, &layer->projection, &pInfo->pboundinglines[1]);
-    else
-      layer->project = MS_FALSE;
 #endif
 
     /*
@@ -239,10 +236,8 @@ int msGraticuleLayerWhichShapes(layerObj *layer, rectObj rect, int isQuery)
     pInfo->pboundinglines[2].point[1].y   = rectMapCoordinates.maxy;
 
 #ifdef USE_PROJ
-    if(layer->project && msProjectionsDiffer(&(layer->projection), &(layer->map->projection)))
+    if(layer->project)
       msProjectLine(&layer->map->projection, &layer->projection, &pInfo->pboundinglines[2]);
-    else
-      layer->project = MS_FALSE;
 #endif
 
     /*
@@ -256,10 +251,8 @@ int msGraticuleLayerWhichShapes(layerObj *layer, rectObj rect, int isQuery)
     pInfo->pboundinglines[3].point[1].y = rectMapCoordinates.maxy;
 
 #ifdef USE_PROJ
-    if(layer->project && msProjectionsDiffer(&(layer->projection), &(layer->map->projection)))
+    if(layer->project)
       msProjectLine(&layer->map->projection, &layer->projection, &pInfo->pboundinglines[3]);
-    else
-      layer->project = MS_FALSE;
 #endif
   }
 
@@ -680,7 +673,7 @@ graticuleIntersectionObj *msGraticuleLayerGetIntersectionPoints(mapObj *map,
     msCopyShape(&shapegrid, &tmpshape);
     /* status = msDrawShape(map, layer, &tmpshape, image, -1); */
 
-    if(layer->project && msProjectionsDiffer(&(layer->projection), &(map->projection)))
+    if(layer->project)
       msProjectShape(&layer->projection, &map->projection, &shapegrid);
 
     msClipPolylineRect(&shapegrid, cliprect);
@@ -1045,7 +1038,7 @@ static int _AdjustLabelPosition( layerObj *pLayer, shapeObj *pShape, msGraticule
   ptPoint = pShape->line->point[0];
 
 #ifdef USE_PROJ
-  if(pLayer->project && msProjectionsDiffer( &pLayer->projection, &pLayer->map->projection ))
+  if(pLayer->project)
     msProjectShape( &pLayer->projection, &pLayer->map->projection, pShape );
 #endif
 
@@ -1087,7 +1080,7 @@ static int _AdjustLabelPosition( layerObj *pLayer, shapeObj *pShape, msGraticule
     msTransformPixelToShape( pShape, pLayer->map->extent, pLayer->map->cellsize );
 
 #ifdef USE_PROJ
-  if(pLayer->project && msProjectionsDiffer( &pLayer->map->projection, &pLayer->projection ))
+  if(pLayer->project)
     msProjectShape( &pLayer->map->projection, &pLayer->projection, pShape );
 #endif
 
diff --git a/maplabel.c b/maplabel.c
index 87989b7..dffab3c 100644
--- a/maplabel.c
+++ b/maplabel.c
@@ -273,7 +273,7 @@ void msPopulateTextSymbolForLabelAndString(textSymbolObj *ts, labelObj *l, char
   ts->rotation = l->angle * MS_DEG_TO_RAD;
 }
 
-int msAddLabelGroup(mapObj *map, imageObj *image, int layerindex, int classindex, shapeObj *shape, pointObj *point, double featuresize)
+int msAddLabelGroup(mapObj *map, imageObj *image, layerObj* layer, int classindex, shapeObj *shape, pointObj *point, double featuresize)
 {
   int l,s, priority;
   labelCacheSlotObj *cacheslot;
@@ -283,9 +283,12 @@ int msAddLabelGroup(mapObj *map, imageObj *image, int layerindex, int classindex
   classObj *classPtr=NULL;
   int numtextsymbols = 0;
   textSymbolObj **textsymbols, *ts;
+  int layerindex = layer->index;
 
-  layerPtr = (GET_LAYER(map, layerindex)); /* set up a few pointers for clarity */
-  classPtr = GET_LAYER(map, layerindex)->class[classindex];
+  // We cannot use GET_LAYER here because in drawQuery the drawing may happen
+  // on a temp layer only.
+  layerPtr = layer;
+  classPtr = layer->class[classindex];
 
   if(classPtr->numlabels == 0) return MS_SUCCESS; /* not an error just nothing to do */
   
diff --git a/maplegend.c b/maplegend.c
index 2dcc91b..74dc490 100644
--- a/maplegend.c
+++ b/maplegend.c
@@ -523,7 +523,7 @@ int msLegendCalcSize(mapObj *map, int scale_independent, int *size_x, int *size_
 
       if(*text) {
         initTextSymbol(&ts);
-        msPopulateTextSymbolForLabelAndString(&ts,&map->legend.label,msStrdup(text),lp->scalefactor*resolutionfactor,resolutionfactor, 0);
+        msPopulateTextSymbolForLabelAndString(&ts,&map->legend.label,msStrdup(text),resolutionfactor,resolutionfactor, 0);
         if(UNLIKELY(MS_FAILURE == msGetTextSymbolSize(map,&ts,&rect))) {
           freeTextSymbol(&ts);
           return MS_FAILURE;
@@ -638,7 +638,7 @@ imageObj *msDrawLegend(mapObj *map, int scale_independent, map_hittest *hittest)
       cur = (legendlabel*) msSmallMalloc(sizeof(legendlabel));
       initTextSymbol(&cur->ts);
       if(*text) {
-        msPopulateTextSymbolForLabelAndString(&cur->ts,&map->legend.label,msStrdup(text),lp->scalefactor*map->resolution/map->defresolution,map->resolution/map->defresolution, 0);
+        msPopulateTextSymbolForLabelAndString(&cur->ts,&map->legend.label,msStrdup(text),map->resolution/map->defresolution,map->resolution/map->defresolution, 0);
         if(UNLIKELY(MS_FAILURE == msComputeTextPath(map,&cur->ts))) {
           ret = MS_FAILURE;
           goto cleanup;
@@ -697,11 +697,13 @@ imageObj *msDrawLegend(mapObj *map, int scale_independent, map_hittest *hittest)
     pnt.y += cur->height;
 
     if(cur->ts.annotext) {
-      pnt.y -= cur->ts.textpath->bounds.bbox.maxy;
-      ret = msDrawTextSymbol(map,image,pnt,&cur->ts);
+      pointObj textPnt = pnt;
+      textPnt.y -= cur->ts.textpath->bounds.bbox.maxy;
+      textPnt.y += map->legend.label.offsety;
+      textPnt.x += map->legend.label.offsetx;
+      ret = msDrawTextSymbol(map,image,textPnt,&cur->ts);
       if(UNLIKELY(ret == MS_FAILURE))
         goto cleanup;
-      pnt.y += cur->ts.textpath->bounds.bbox.maxy;
       freeTextSymbol(&cur->ts);
     }
     
diff --git a/maplibxml2.c b/maplibxml2.c
index 7a0c97c..cd3fcfa 100644
--- a/maplibxml2.c
+++ b/maplibxml2.c
@@ -58,7 +58,12 @@ void msLibXml2GenerateList(xmlNodePtr psParent, xmlNsPtr psNs, const char *elnam
   int i = 0;
   tokens = msStringSplit(values, delim, &n);
   for (i=0; i<n; i++) {
-    xmlNewChild(psParent, psNs, BAD_CAST elname, BAD_CAST tokens[i]);
+    // Not sure we really need to distinguish empty vs non-empty case, but
+    // this does change the result of msautotest/wxs/expected/wcs_empty_cap111.xml otherwise
+    if( tokens[i] && tokens[i][0] != '\0' )
+      xmlNewTextChild(psParent, psNs, BAD_CAST elname, BAD_CAST tokens[i]);
+    else
+      xmlNewChild(psParent, psNs, BAD_CAST elname, BAD_CAST tokens[i]);
   }
   msFreeCharArray(tokens, n);
 }
diff --git a/mapmssql2008.c b/mapmssql2008.c
index 904c3e3..c01019f 100644
--- a/mapmssql2008.c
+++ b/mapmssql2008.c
@@ -38,6 +38,7 @@
 #include <assert.h>
 #include "mapserver.h"
 #include "maptime.h"
+#include "mapows.h"
 
 #ifdef USE_MSSQL2008
 
@@ -420,7 +421,7 @@ void setMSSQL2008LayerInfo(layerObj *layer, msMSSQL2008LayerInfo *MSSQL2008layer
 void handleSQLError(layerObj *layer)
 {
   SQLCHAR       SqlState[6], Msg[SQL_MAX_MESSAGE_LENGTH];
-  SQLINTEGER    NativeError;
+  SQLLEN     NativeError;
   SQLSMALLINT   i, MsgLen;
   SQLRETURN  rc;
   msMSSQL2008LayerInfo *layerinfo = getMSSQL2008LayerInfo(layer);
@@ -602,14 +603,14 @@ static int executeSQL(msODBCconn *conn, const char * sql)
 }
 
 /* Get columns name from query results */
-static int columnName(msODBCconn *conn, int index, char *buffer, int bufferLength)
+static int columnName(msODBCconn *conn, int index, char *buffer, int bufferLength, layerObj *layer, char pass_field_def)
 {
   SQLRETURN rc;
 
   SQLCHAR columnName[SQL_COLUMN_NAME_MAX_LENGTH + 1];
   SQLSMALLINT columnNameLen;
   SQLSMALLINT dataType;
-  SQLUINTEGER columnSize;
+  SQLULEN columnSize;
   SQLSMALLINT decimalDigits;
   SQLSMALLINT nullable;
 
@@ -629,6 +630,72 @@ static int columnName(msODBCconn *conn, int index, char *buffer, int bufferLengt
       strlcpy(buffer, (const char *)columnName, bufferLength);
     else
       strlcpy(buffer, (const char *)columnName, SQL_COLUMN_NAME_MAX_LENGTH + 1);
+
+    if (pass_field_def) {
+      char md_item_name[256];
+      char gml_width[32], gml_precision[32];
+      const char *gml_type = NULL;
+
+      gml_width[0] = '\0';
+      gml_precision[0] = '\0';
+
+      switch( dataType ) {
+        case SQL_INTEGER:
+        case SQL_SMALLINT:
+        case SQL_TINYINT:
+          gml_type = "Integer";
+          break;
+
+        case SQL_BIGINT:
+          gml_type = "Long";
+          break;
+
+        case SQL_REAL:
+        case SQL_FLOAT:
+        case SQL_DOUBLE:
+        case SQL_DECIMAL:
+        case SQL_NUMERIC:
+          gml_type = "Real";
+          if( decimalDigits > 0 )
+            sprintf( gml_precision, "%d", decimalDigits );
+          break;
+
+        case SQL_TYPE_DATE:
+        case SQL_TYPE_TIME:
+        case SQL_TYPE_TIMESTAMP:
+          gml_type = "Date";
+          break;
+
+        case SQL_BIT:
+          gml_type = "Boolean";
+          break;
+
+        default:
+          gml_type = "Character";
+          break;
+      }
+
+      if( columnSize > 0 )
+            sprintf( gml_width, "%d", columnSize );
+
+      snprintf( md_item_name, sizeof(md_item_name), "gml_%s_type", buffer );
+      if( msOWSLookupMetadata(&(layer->metadata), "G", "type") == NULL )
+        msInsertHashTable(&(layer->metadata), md_item_name, gml_type );
+
+      snprintf( md_item_name, sizeof(md_item_name), "gml_%s_width", buffer );
+      if( strlen(gml_width) > 0
+          && msOWSLookupMetadata(&(layer->metadata), "G", "width") == NULL )
+        msInsertHashTable(&(layer->metadata), md_item_name, gml_width );
+
+      snprintf( md_item_name, sizeof(md_item_name), "gml_%s_precision",buffer );
+      if( strlen(gml_precision) > 0
+          && msOWSLookupMetadata(&(layer->metadata), "G", "precision")==NULL )
+        msInsertHashTable(&(layer->metadata), md_item_name, gml_precision );
+
+      snprintf( md_item_name, sizeof(md_item_name), "gml_%s_nillable",buffer );
+      if( nullable > 0 )
+        msInsertHashTable(&(layer->metadata), md_item_name, "true" );
+    }
     return 1;
   } else {
     setStmntError(conn);
@@ -726,7 +793,7 @@ int msMSSQL2008LayerOpen(layerObj *layer)
                  "This error occured when trying to make a connection to the specified SQL server.  \n"
                  "<br>\nMost commonly this is caused by <br>\n"
                  "(1) incorrect connection string <br>\n"
-                 "(2) you didnt specify a 'user id=...' in your connection string <br>\n"
+                 "(2) you didn't specify a 'user id=...' in your connection string <br>\n"
                  "(3) SQL server isnt running <br>\n"
                  "(4) TCPIP not enabled for SQL Client or server <br>\n\n",
                  "msMSSQL2008LayerOpen()", maskeddata, errMess);
@@ -909,7 +976,11 @@ static int prepare_database(layerObj *layer, rectObj rect, char **query_string)
     char buffer[10000] = "";
 
     for(t = 0; t < layer->numitems; t++) {
+#ifdef USE_ICONV      
+      snprintf(buffer + strlen(buffer), sizeof(buffer) - strlen(buffer), "convert(nvarchar(max), [%s]),", layer->items[t]);
+#else
       snprintf(buffer + strlen(buffer), sizeof(buffer) - strlen(buffer), "convert(varchar(max), [%s]),", layer->items[t]);
+#endif
     }
 
     if (layerinfo->geometry_format == MSSQLGEOMETRY_NATIVE)
@@ -1578,8 +1649,8 @@ int msMSSQL2008LayerGetShapeRandom(layerObj *layer, shapeObj *shape, long *recor
 {
   msMSSQL2008LayerInfo  *layerinfo;
   int                 result;
-  SQLINTEGER needLen = 0;
-  SQLINTEGER retLen = 0;
+  SQLLEN needLen = 0;
+  SQLLEN retLen = 0;
   char dummyBuffer[1];
   char *wkbBuffer;
   char *valueBuffer;
@@ -1606,7 +1677,7 @@ int msMSSQL2008LayerGetShapeRandom(layerObj *layer, shapeObj *shape, long *recor
   shape->type = MS_SHAPE_NULL;
 
   while(shape->type == MS_SHAPE_NULL) {
-    /* SQLRETURN rc = SQLFetchScroll(layerinfo->conn->hstmt, SQL_FETCH_ABSOLUTE, (SQLINTEGER) (*record) + 1); */
+    /* SQLRETURN rc = SQLFetchScroll(layerinfo->conn->hstmt, SQL_FETCH_ABSOLUTE, (SQLLEN) (*record) + 1); */
 
     /* We only do forward fetches. the parameter 'record' is ignored, but is incremented */
     SQLRETURN rc = SQLFetch(layerinfo->conn->hstmt);
@@ -1632,7 +1703,7 @@ int msMSSQL2008LayerGetShapeRandom(layerObj *layer, shapeObj *shape, long *recor
 
         if (needLen > 0) {
           /* allocate the buffer - this will be a null-terminated string so alloc for the null too */
-          valueBuffer = (char*) msSmallMalloc( needLen + 1 );
+          valueBuffer = (char*) msSmallMalloc( needLen + 2 );
           if ( valueBuffer == NULL ) {
             msSetError( MS_QUERYERR, "Could not allocate value buffer.", "msMSSQL2008LayerGetShapeRandom()" );
             return MS_FAILURE;
@@ -1647,7 +1718,13 @@ int msMSSQL2008LayerGetShapeRandom(layerObj *layer, shapeObj *shape, long *recor
           valueBuffer[retLen] = 0; /* null terminate it */
 
           /* Pop the value into the shape's value array */
+#ifdef USE_ICONV
+          valueBuffer[retLen + 1] = 0;
+          shape->values[t] = msConvertWideStringToUTF8((wchar_t*)valueBuffer, "UCS-2LE");
+          msFree(valueBuffer);
+#else
           shape->values[t] = valueBuffer;
+#endif
         } else
           /* Copy empty sting for NULL values */
           shape->values[t] = msStrdup("");
@@ -1914,6 +1991,13 @@ int msMSSQL2008LayerGetItems(layerObj *layer)
   char                found_geom = 0;
   int                 item_num;
   SQLSMALLINT cols = 0;
+  const char *value;
+  /*
+  * Pass the field definitions through to the layer metadata in the
+  * "gml_[item]_{type,width,precision}" set of metadata items for
+  * defining fields.
+  */
+  char                pass_field_def = 0;
 
   if(layer->debug) {
     msDebug("in msMSSQL2008LayerGetItems  (find column names)\n");
@@ -1957,10 +2041,15 @@ int msMSSQL2008LayerGetItems(layerObj *layer)
   found_geom = 0; /* havent found the geom field */
   item_num = 0;
 
+  /* consider populating the field definitions in metadata */
+  if((value = msOWSLookupMetadata(&(layer->metadata), "G", "types")) != NULL
+      && strcasecmp(value,"auto") == 0 )
+    pass_field_def = 1;
+
   for(t = 0; t < cols; t++) {
     char colBuff[256];
 
-    columnName(layerinfo->conn, t + 1, colBuff, sizeof(colBuff));
+    columnName(layerinfo->conn, t + 1, colBuff, sizeof(colBuff), layer, pass_field_def);
 
     if(strcmp(colBuff, layerinfo->geom_column) != 0) {
       /* this isnt the geometry column */
@@ -2038,7 +2127,7 @@ int msMSSQL2008LayerRetrievePK(layerObj *layer, char **urid_name, char* table_na
 
   {
     char buff[100];
-    SQLINTEGER retLen;
+    SQLLEN retLen;
     rc = SQLGetData(layerinfo->conn->hstmt, 1, SQL_C_BINARY, buff, sizeof(buff), &retLen);
 
     rc = SQLFetch(layerinfo->conn->hstmt);
@@ -2099,7 +2188,7 @@ static int msMSSQL2008LayerParseData(layerObj *layer, char **geom_column_name, c
   } else {
     slength = strspn(pos_srid + 12, "-0123456789");
     if(!slength) {
-      msSetError(MS_QUERYERR, DATA_ERROR_MESSAGE, "msMSSQL2008LayerParseData()", "Error parsing MSSQL2008 data variable: You specified 'using SRID=#' but didnt have any numbers!<br><br>\n\nMore Help:<br><br>\n\n", data);
+      msSetError(MS_QUERYERR, DATA_ERROR_MESSAGE, "msMSSQL2008LayerParseData()", "Error parsing MSSQL2008 data variable: You specified 'using SRID=#' but didn't have any numbers!<br><br>\n\nMore Help:<br><br>\n\n", data);
 
       msFree(data);
       return MS_FAILURE;
diff --git a/mapogcfilter.c b/mapogcfilter.c
index 05f017a..8b19a64 100644
--- a/mapogcfilter.c
+++ b/mapogcfilter.c
@@ -42,7 +42,9 @@
 #include "mapows.h"
 #include <ctype.h>
 
+#if 0
 static int FLTHasUniqueTopLevelDuringFilter(FilterEncodingNode *psFilterNode);
+#endif
 
 int FLTIsNumeric(const char *pszValue)
 {
@@ -569,8 +571,6 @@ int FLTApplySimpleSQLFilter(FilterEncodingNode *psNode, mapObj *map, int iLayerI
 /************************************************************************/
 int FLTIsSimpleFilter(FilterEncodingNode *psNode)
 {
-  return MS_FALSE;
-
   if (FLTValidForBBoxFilter(psNode)) {
     if (FLTNumberOfFilterType(psNode, "DWithin") == 0 &&
         FLTNumberOfFilterType(psNode, "Intersect") == 0 &&
@@ -614,17 +614,43 @@ int FLTApplyFilterToLayer(FilterEncodingNode *psNode, mapObj *map, int iLayerInd
 /************************************************************************/
 int FLTLayerApplyCondSQLFilterToLayer(FilterEncodingNode *psNode, mapObj *map, int iLayerIndex)
 {
-  /* ==================================================================== */
-  /*      Check here to see if it is a simple filter and if that is       */
-  /*      the case, we are going to use the FILTER element on             */
-  /*      the layer.                                                      */
-  /* ==================================================================== */
-  layerObj* lp = GET_LAYER(map, iLayerIndex);
-  if (FLTIsSimpleFilter(psNode) && !(lp->connectiontype == MS_OGR && !FLTHasUniqueTopLevelDuringFilter(psNode)) ) {
-    return FLTApplySimpleSQLFilter(psNode, map, iLayerIndex);
+  return FLTLayerApplyPlainFilterToLayer(psNode, map, iLayerIndex);
+}
+
+
+/************************************************************************/
+/*                           FLTGetTopBBOX                              */
+/*                                                                      */
+/* Return the "top" BBOX if there's a unique one.                       */
+/************************************************************************/
+static int FLTGetTopBBOXInternal(FilterEncodingNode *psNode, FilterEncodingNode** ppsTopBBOX, int *pnCount)
+{
+  if (psNode->pszValue && strcasecmp(psNode->pszValue, "BBOX") == 0) {
+    (*pnCount) ++;
+    if( *pnCount == 1 )
+    {
+      *ppsTopBBOX = psNode;
+      return TRUE;
+    }
+    *ppsTopBBOX = NULL;
+    return FALSE;
   }
+  else if (psNode->pszValue && strcasecmp(psNode->pszValue, "AND") == 0) {
+    return FLTGetTopBBOXInternal(psNode->psLeftNode, ppsTopBBOX, pnCount) &&
+           FLTGetTopBBOXInternal(psNode->psRightNode, ppsTopBBOX, pnCount);
+  }
+  else
+  {
+    return TRUE;
+  }
+}
 
-  return FLTLayerApplyPlainFilterToLayer(psNode, map, iLayerIndex);
+static FilterEncodingNode* FLTGetTopBBOX(FilterEncodingNode *psNode)
+{
+  int nCount = 0;
+  FilterEncodingNode* psTopBBOX = NULL;
+  FLTGetTopBBOXInternal(psNode, &psTopBBOX, &nCount);
+  return psTopBBOX;
 }
 
 /************************************************************************/
@@ -637,12 +663,56 @@ int FLTLayerApplyPlainFilterToLayer(FilterEncodingNode *psNode, mapObj *map,
 {
   char *pszExpression  =NULL;
   int status =MS_FALSE;
+  layerObj* lp = GET_LAYER(map, iLayerIndex);
 
-  pszExpression = FLTGetCommonExpression(psNode,  GET_LAYER(map, iLayerIndex));
-  if(map->debug == MS_DEBUGLEVEL_VVV)
-    msDebug("FLTLayerApplyPlainFilterToLayer(): %s\n", pszExpression);
+  pszExpression = FLTGetCommonExpression(psNode,  lp);
   if (pszExpression) {
-    status = FLTApplyFilterToLayerCommonExpression(map, iLayerIndex, pszExpression);
+    FilterEncodingNode* psTopBBOX;
+    rectObj rect = map->extent;
+
+    psTopBBOX = FLTGetTopBBOX(psNode);
+    if( psTopBBOX )
+    {
+      int can_remove_expression = MS_TRUE;
+      const char* pszEPSG = FLTGetBBOX(psNode, &rect);
+      if(pszEPSG && map->projection.numargs > 0) {
+        projectionObj sProjTmp;
+        msInitProjection(&sProjTmp);
+        /* Use the non EPSG variant since axis swapping is done in FLTDoAxisSwappingIfNecessary */
+        if (msLoadProjectionString(&sProjTmp, pszEPSG) == 0) {
+          rectObj oldRect = rect;
+          msProjectRect(&sProjTmp, &map->projection, &rect);
+          /* If reprojection is involved, do not remove the expression */
+          if( rect.minx != oldRect.minx ||
+              rect.miny != oldRect.miny ||
+              rect.maxx != oldRect.maxx ||
+              rect.maxy != oldRect.maxy )
+          {
+            can_remove_expression = MS_FALSE;
+          }
+        }
+        msFreeProjection(&sProjTmp);
+      }
+
+      /* Small optimization: if the query is just a BBOX, then do a */
+      /* msQueryByRect() */
+      if( psTopBBOX == psNode && can_remove_expression )
+      {
+        msFree(pszExpression);
+        pszExpression = NULL;
+      }
+    }
+
+    if(map->debug == MS_DEBUGLEVEL_VVV)
+    {
+      if( pszExpression )
+        msDebug("FLTLayerApplyPlainFilterToLayer(): %s, rect=%f,%f,%f,%f\n", pszExpression, rect.minx, rect.miny, rect.maxx, rect.maxy);
+      else
+        msDebug("FLTLayerApplyPlainFilterToLayer(): rect=%f,%f,%f,%f\n", rect.minx, rect.miny, rect.maxx, rect.maxy);
+    }
+
+    status = FLTApplyFilterToLayerCommonExpressionWithRect(map, iLayerIndex,
+                                                           pszExpression, rect);
     msFree(pszExpression);
   }
 
@@ -1784,6 +1854,7 @@ int FLTValidForBBoxFilter(FilterEncodingNode *psFilterNode)
   return 0;
 }
 
+#if 0
 static int FLTHasUniqueTopLevelDuringFilter(FilterEncodingNode *psFilterNode)
 {
   int nCount = 0;
@@ -1809,7 +1880,7 @@ static int FLTHasUniqueTopLevelDuringFilter(FilterEncodingNode *psFilterNode)
 
   return 0;
 }
-
+#endif
 
 int FLTIsLineFilter(FilterEncodingNode *psFilterNode)
 {
diff --git a/mapogcfilter.h b/mapogcfilter.h
index 7d7828d..970d02e 100644
--- a/mapogcfilter.h
+++ b/mapogcfilter.h
@@ -148,6 +148,7 @@ int FLTCheckInvalidProperty(FilterEncodingNode *psFilterNode,
                             mapObj *map, int i);
 FilterEncodingNode* FLTSimplify(FilterEncodingNode *psFilterNode,
                                 int* pnEvaluation);
+int FLTApplyFilterToLayerCommonExpressionWithRect(mapObj *map, int iLayerIndex, const char *pszExpression, rectObj rect);
 
 #endif
 
diff --git a/mapogcfiltercommon.c b/mapogcfiltercommon.c
index 3105d3f..e21395a 100644
--- a/mapogcfiltercommon.c
+++ b/mapogcfiltercommon.c
@@ -694,6 +694,12 @@ char *FLTGetCommonExpression(FilterEncodingNode *psFilterNode, layerObj *lp)
 
 int FLTApplyFilterToLayerCommonExpression(mapObj *map, int iLayerIndex, const char *pszExpression)
 {
+  return FLTApplyFilterToLayerCommonExpressionWithRect(map, iLayerIndex, pszExpression, map->extent);
+}
+
+/* rect must be in map->projection */
+int FLTApplyFilterToLayerCommonExpressionWithRect(mapObj *map, int iLayerIndex, const char *pszExpression, rectObj rect)
+{
   int retval;
   int save_startindex;
   int save_maxfeatures;
@@ -707,18 +713,25 @@ int FLTApplyFilterToLayerCommonExpression(mapObj *map, int iLayerIndex, const ch
   map->query.maxfeatures = save_maxfeatures;
   map->query.only_cache_result_count = save_only_cache_result_count;
 
-  map->query.type = MS_QUERY_BY_FILTER;
   map->query.mode = MS_QUERY_MULTIPLE;
-
-  msInitExpression(&map->query.filter);
-  map->query.filter.string = msStrdup(pszExpression);
-  map->query.filter.type = MS_EXPRESSION; /* a logical expression */
   map->query.layer = iLayerIndex;
 
-  /* TODO: if there is a bbox in the node, get it and set the map extent (projected to map->projection */
-  map->query.rect = map->extent;
+  map->query.rect = rect;
 
-  retval = msQueryByFilter(map);
+  if( pszExpression )
+  {
+    map->query.type = MS_QUERY_BY_FILTER;
+    msInitExpression(&map->query.filter);
+    map->query.filter.string = msStrdup(pszExpression);
+    map->query.filter.type = MS_EXPRESSION; /* a logical expression */
+
+    retval = msQueryByFilter(map);
+  }
+  else
+  {
+    map->query.type = MS_QUERY_BY_RECT;
+    retval = msQueryByRect(map);
+  }
 
   return retval;
 }
diff --git a/mapogcsld.c b/mapogcsld.c
index 465421d..8b76ea2 100644
--- a/mapogcsld.c
+++ b/mapogcsld.c
@@ -106,6 +106,7 @@ int msSLDApplySLDURL(mapObj *map, char *szURL, int iLayer,
         unlink(pszSLDTmpFile);
         msSetError(MS_WMSERR, "Could not open SLD %s and save it in a temporary file. Please make sure that the sld url is valid and that the temporary path is set. The temporary path can be defined for example by setting TMPPATH in the map file. Please check the MapServer documentation on temporary path settings.", "msSLDApplySLDURL", szURL);
       }
+      msFree(pszSLDTmpFile);
       if (pszSLDbuf)
         nStatus = msSLDApplySLD(map, pszSLDbuf, iLayer, pszStyleLayerName, ppszLayerNames);
     }
diff --git a/mapogcsos.c b/mapogcsos.c
index f709c48..8563e50 100644
--- a/mapogcsos.c
+++ b/mapogcsos.c
@@ -284,7 +284,7 @@ void msSOSAddPropertyNode(xmlNsPtr psNsSwe, xmlNsPtr psNsXLink, xmlNodePtr psPar
     pszValue = msOWSLookupMetadata(&(lp->metadata), "S",
                                    "observedproperty_name");
     if (pszValue)
-      psNode = xmlNewChild(psCompNode, psNsGml,
+      psNode = xmlNewTextChild(psCompNode, psNsGml,
                            BAD_CAST "name", BAD_CAST pszValue);
 
     /* add components */
diff --git a/mapogr.cpp b/mapogr.cpp
index 881250f..333810c 100644
--- a/mapogr.cpp
+++ b/mapogr.cpp
@@ -46,6 +46,7 @@
 
 #ifdef USE_OGR
 
+// GDAL 1.x API
 #include "ogr_api.h"
 
 typedef struct ms_ogr_file_info_t {
@@ -59,10 +60,20 @@ typedef struct ms_ogr_file_info_t {
   int         nTileId;                  /* applies on the tiles themselves. */
 
   struct ms_ogr_file_info_t *poCurTile; /* exists on tile index, -> tiles */
-  rectObj     rect;                     /* set by WhichShapes */
+  bool        rect_is_defined;
+  rectObj     rect;                     /* set by TranslateMsExpression (possibly) and WhichShapes */
 
   int         last_record_index_read;
 
+  const char* dialect; /* NULL, Spatialite or PostgreSQL */
+  char *pszSelect;
+  char *pszSpatialFilterTableName ;
+  char *pszMainTableName;
+  char *pszRowId;
+  int   bIsOKForSQLCompose;
+
+  int   bPaging;
+
 } msOGRFileInfo;
 
 static int msOGRLayerIsOpen(layerObj *layer);
@@ -1258,9 +1269,197 @@ msOGRFileOpen(layerObj *layer, const char *connection )
 
   psInfo->nTileId = 0;
   psInfo->poCurTile = NULL;
+  psInfo->rect_is_defined = false;
   psInfo->rect.minx = psInfo->rect.maxx = 0;
   psInfo->rect.miny = psInfo->rect.maxy = 0;
   psInfo->last_record_index_read = -1;
+  psInfo->dialect = NULL;
+
+    // GDAL 1.x API
+  OGRSFDriverH dr = OGR_DS_GetDriver(hDS);
+  const char *name = OGR_Dr_GetName(dr);
+  if (strcmp(name, "SQLite") == 0) {
+    bool have_spatialite = false;
+
+    CPLPushErrorHandler(CPLQuietErrorHandler);
+
+    // test for Spatialite support in driver
+    const char *test_spatialite = "SELECT spatialite_version()";
+    OGRLayerH l = OGR_DS_ExecuteSQL(hDS, test_spatialite, NULL, NULL);
+    if (l) {
+        OGR_DS_ReleaseResultSet(hDS, l);
+        have_spatialite = true;
+    }
+
+    // test for Spatialite enabled db
+    if (have_spatialite) {
+        have_spatialite = false;
+        const char *test_sql = "select 1 from sqlite_master where name = 'geometry_columns' and sql LIKE '%spatial_index_enabled%'";
+        OGRLayerH l = OGR_DS_ExecuteSQL(hDS, test_sql, NULL, NULL);
+        if (l) {
+            if (OGR_L_GetFeatureCount(l, TRUE) == 1)
+                have_spatialite = true;
+            OGR_DS_ReleaseResultSet(hDS, l);
+        }
+    }
+
+    CPLPopErrorHandler();
+
+    if (have_spatialite)
+        psInfo->dialect = "Spatialite";
+    else
+        msDebug("msOGRTranslateMsExpressionToOGRSQL: Native SQL not available, no Spatialite support and/or not a Spatialite enabled db\n");
+  } else if (strcmp(name, "PostgreSQL") == 0) {
+    psInfo->dialect = "PostgreSQL";
+    // todo: PostgreSQL not yet tested
+
+  } // todo: other dialects, for example OGR SQL
+
+
+  psInfo->pszSelect = NULL;
+  psInfo->pszSpatialFilterTableName = NULL;
+  psInfo->pszMainTableName = NULL;
+  psInfo->pszRowId = NULL;
+  psInfo->bIsOKForSQLCompose = true;
+
+  // In the case of a SQLite DB, check that we can identify the
+  // underlying table
+  if( psInfo->nLayerIndex == -1 &&
+      psInfo->dialect != NULL && EQUAL(psInfo->dialect, "Spatialite") )
+  {
+      psInfo->bIsOKForSQLCompose = false;
+
+      const char* from = strstr( psInfo->pszLayerDef, " from ");
+      if( from == NULL )
+        from = strstr( psInfo->pszLayerDef, " FROM ");
+      if( from )
+      {
+        const char* pszBeginningOfTable = from + strlen(" FROM ");
+        const char* pszIter = pszBeginningOfTable;
+        while( *pszIter && *pszIter != ' ' )
+          pszIter ++;
+        if( strchr(pszIter, ',') == NULL &&
+            strstr(pszIter, " where ") == NULL && strstr(pszIter, " WHERE ") == NULL &&
+            strstr(pszIter, " join ") == NULL && strstr(pszIter, " JOIN ") == NULL &&
+            strstr(pszIter, " order by ") == NULL && strstr(pszIter, " ORDER BY ") == NULL)
+        {
+          psInfo->bIsOKForSQLCompose = true;
+          psInfo->pszMainTableName = msStrdup(pszBeginningOfTable);
+          psInfo->pszMainTableName[pszIter - pszBeginningOfTable] = '\0';
+          psInfo->pszSpatialFilterTableName = msStrdup(psInfo->pszMainTableName);
+
+          char* pszRequest = NULL;
+          pszRequest = msStringConcatenate(pszRequest,
+              "SELECT * FROM sqlite_master WHERE type = 'table' AND name = lower('");
+          pszRequest = msStringConcatenate(pszRequest, psInfo->pszMainTableName);
+          pszRequest = msStringConcatenate(pszRequest, "')");
+          OGRLayerH hLayer = OGR_DS_ExecuteSQL( psInfo->hDS, pszRequest, NULL, NULL );
+          msFree(pszRequest);
+
+          if( hLayer )
+          {
+              OGRFeatureH hFeature = OGR_L_GetNextFeature(hLayer);
+              psInfo->bIsOKForSQLCompose = (hFeature != NULL);
+              if( hFeature )
+                OGR_F_Destroy(hFeature);
+              OGR_DS_ReleaseResultSet( psInfo->hDS, hLayer );
+          }
+          if( psInfo->bIsOKForSQLCompose )
+          {
+            psInfo->pszSelect = msStrdup(psInfo->pszLayerDef);
+          }
+          else
+          {
+            // Test if it is a spatial view
+            pszRequest = msStringConcatenate(NULL,
+              "SELECT f_table_name, view_rowid FROM views_geometry_columns WHERE view_name = lower('");
+            pszRequest = msStringConcatenate(pszRequest, psInfo->pszMainTableName);
+            pszRequest = msStringConcatenate(pszRequest, "')");
+            CPLPushErrorHandler(CPLQuietErrorHandler);
+            OGRLayerH hLayer = OGR_DS_ExecuteSQL( psInfo->hDS, pszRequest, NULL, NULL );
+            CPLPopErrorHandler();
+            msFree(pszRequest);
+
+            if( hLayer )
+            {
+                OGRFeatureH hFeature = OGR_L_GetNextFeature(hLayer);
+                psInfo->bIsOKForSQLCompose = (hFeature != NULL);
+                if( hFeature )
+                {
+                  psInfo->pszSelect = msStrdup(psInfo->pszLayerDef);
+                  msFree(psInfo->pszSpatialFilterTableName);
+                  psInfo->pszSpatialFilterTableName = msStrdup( OGR_F_GetFieldAsString( hFeature, 0 ) );
+                  psInfo->pszRowId = msStrdup( OGR_F_GetFieldAsString( hFeature, 1 ) );
+                  OGR_F_Destroy(hFeature);
+                }
+                OGR_DS_ReleaseResultSet( psInfo->hDS, hLayer );
+            }
+          }
+        }
+      }
+  }
+  else if( psInfo->dialect != NULL && EQUAL(psInfo->dialect, "Spatialite") )
+  {
+      psInfo->bIsOKForSQLCompose = false;
+
+      char* pszRequest = NULL;
+      pszRequest = msStringConcatenate(pszRequest,
+          "SELECT * FROM sqlite_master WHERE type = 'table' AND name = lower('");
+      pszRequest = msStringConcatenate(pszRequest, OGR_FD_GetName(OGR_L_GetLayerDefn(psInfo->hLayer)));
+      pszRequest = msStringConcatenate(pszRequest, "')");
+      OGRLayerH hLayer = OGR_DS_ExecuteSQL( psInfo->hDS, pszRequest, NULL, NULL );
+      msFree(pszRequest);
+
+      if( hLayer )
+      {
+          OGRFeatureH hFeature = OGR_L_GetNextFeature(hLayer);
+          psInfo->bIsOKForSQLCompose = (hFeature != NULL);
+          if( hFeature )
+            OGR_F_Destroy(hFeature);
+          OGR_DS_ReleaseResultSet( psInfo->hDS, hLayer );
+      }
+      if( psInfo->bIsOKForSQLCompose )
+      {
+        psInfo->pszMainTableName = msStrdup(OGR_FD_GetName(OGR_L_GetLayerDefn(psInfo->hLayer)));
+        psInfo->pszSpatialFilterTableName = msStrdup(psInfo->pszMainTableName);
+      }
+      else
+      {
+        // Test if it is a spatial view
+        pszRequest = msStringConcatenate(NULL,
+          "SELECT f_table_name, view_rowid FROM views_geometry_columns WHERE view_name = lower('");
+        pszRequest = msStringConcatenate(pszRequest, OGR_FD_GetName(OGR_L_GetLayerDefn(psInfo->hLayer)));
+        pszRequest = msStringConcatenate(pszRequest, "')");
+        CPLPushErrorHandler(CPLQuietErrorHandler);
+        OGRLayerH hLayer = OGR_DS_ExecuteSQL( psInfo->hDS, pszRequest, NULL, NULL );
+        CPLPopErrorHandler();
+        msFree(pszRequest);
+
+        if( hLayer )
+        {
+            OGRFeatureH hFeature = OGR_L_GetNextFeature(hLayer);
+            psInfo->bIsOKForSQLCompose = (hFeature != NULL);
+            if( hFeature )
+            {
+              psInfo->pszMainTableName = msStrdup(OGR_FD_GetName(OGR_L_GetLayerDefn(psInfo->hLayer)));
+              psInfo->pszSpatialFilterTableName = msStrdup( OGR_F_GetFieldAsString( hFeature, 0 ) );
+              psInfo->pszRowId = msStrdup( OGR_F_GetFieldAsString( hFeature, 1 ) );
+              OGR_F_Destroy(hFeature);
+            }
+            OGR_DS_ReleaseResultSet( psInfo->hDS, hLayer );
+        }
+      }
+  }
+
+  // in the case we cannot handle the native string, go back to the client
+  // side evaluation by unsetting it.
+  if( !psInfo->bIsOKForSQLCompose && psInfo->dialect != NULL )
+  {
+      msDebug("msOGRFileOpen(): Falling back to MapServer only evaluation\n");
+      psInfo->dialect = NULL;
+  }
+
+  psInfo->bPaging = (psInfo->dialect != NULL);
 
   return psInfo;
 }
@@ -1313,6 +1512,11 @@ static int msOGRFileClose(layerObj *layer, msOGRFileInfo *psInfo )
   // Free current tile if there is one.
   if( psInfo->poCurTile != NULL )
     msOGRFileClose( layer, psInfo->poCurTile );
+  
+  msFree(psInfo->pszSelect);
+  msFree(psInfo->pszSpatialFilterTableName);
+  msFree(psInfo->pszMainTableName);
+  msFree(psInfo->pszRowId);
 
   CPLFree(psInfo);
 
@@ -1348,155 +1552,290 @@ static char *msOGREscapeSQLParam(layerObj *layer, const char *pszString)
 
 #ifdef USE_OGR
 
-#if 0 /*left over code from filter translation development */
-/**********************************************************************
- *                     msOGRTranslateMsExpressionToOGRSQL()
- *
- * Tries to translate a mapserver expression to OGR SQL, and also
- * try to extract spatial filter
- **********************************************************************/
-static char* msOGRTranslateMsExpressionToOGRSQL(layerObj* layer,
-                                          expressionObj* psFilter,
-                                          rectObj* psRect)
-{
-    char* msSQLExpression = NULL;
-    rectObj sBBOX;
-    int sBBOXValid = MS_FALSE;
-    tokenListNodeObjPtr node = NULL;
-    char *stresc = NULL;
-    char *snippet = NULL;
-    const char* strtmpl = NULL;
-    int bIsIntersectRectangle = MS_FALSE;
-
-    node = psFilter->tokens;
-    while (node != NULL) {      
-
-      switch(node->token) {
-
-        /* literal tokens */
-
-        case MS_TOKEN_LITERAL_NUMBER:
-          snippet = (char *) msSmallMalloc(strlen(strtmpl) + 16);
-          sprintf(snippet, "%lf", node->tokenval.dblval);
-          msSQLExpression = msStringConcatenate(msSQLExpression, snippet);
-          msFree(snippet);
-          break;
-        case MS_TOKEN_LITERAL_STRING:
-          stresc = msOGREscapeSQLParam(layer, node->tokenval.strval);
-          snippet = (char *) msSmallMalloc(strlen(strtmpl) + strlen(stresc));
-          sprintf(snippet, "'%s'", stresc);
-          msSQLExpression = msStringConcatenate(msSQLExpression, snippet);
-          msFree(snippet);
-          msFree(stresc);
-          break;
+// http://www.sqlite.org/lang_expr.html
+// http://www.gaia-gis.it/gaia-sins/spatialite-sql-4.3.0.html
 
-        case MS_TOKEN_BINDING_DOUBLE:
-        case MS_TOKEN_BINDING_INTEGER:
-        case MS_TOKEN_BINDING_STRING:
-          if(node->token == MS_TOKEN_BINDING_STRING || node->next->token == MS_TOKEN_COMPARISON_RE || node->next->token == MS_TOKEN_COMPARISON_IRE)
-            strtmpl = "CAST(%s AS CHARACTER)"; /* explicit cast necessary for certain operators */
-          else
-            strtmpl = "%s";
-          stresc = msLayerEscapePropertyName(layer, node->tokenval.bindval.item);
-          snippet = (char *) msSmallMalloc(strlen(strtmpl) + strlen(stresc));
-          sprintf(snippet, strtmpl, stresc);
-          msSQLExpression = msStringConcatenate(msSQLExpression, snippet);
-          msFree(snippet);
-          msFree(stresc);
-          break;
+static
+char *msOGRGetToken(layerObj* layer, tokenListNodeObjPtr *node) {
+    msOGRFileInfo *info = (msOGRFileInfo *)layer->layerinfo;
+    tokenListNodeObjPtr n = *node;
+    if (!n) return NULL;
+    char *out = NULL;
+    size_t nOutSize;
 
-    /* spatial comparison tokens */
-        case MS_TOKEN_COMPARISON_INTERSECTS:
-        {
-          shapeObj* shape;
-          if(node->next->token != '(') goto cleanup;
-          if(node->next->next->token != MS_TOKEN_BINDING_SHAPE) goto cleanup;
-          if(node->next->next->next->token != ',' ) goto cleanup;
-          if(node->next->next->next->next->token != MS_TOKEN_LITERAL_SHAPE ) goto cleanup;
-          if(node->next->next->next->next->next->token != ')' ) goto cleanup;
-          if(node->next->next->next->next->next->next->token != MS_TOKEN_COMPARISON_EQ ) goto cleanup;
-          if(node->next->next->next->next->next->next->next->token != MS_TOKEN_LITERAL_BOOLEAN ) goto cleanup;
-          if(node->next->next->next->next->next->next->next->tokenval.dblval != MS_TRUE) goto cleanup;
-
-          shape = node->next->next->next->next->tokenval.shpval;
-          memcpy(&sBBOX, &(shape->bounds), sizeof(rectObj));
-          sBBOXValid = TRUE;
-          
-          if( shape->type == MS_SHAPE_POLYGON &&
-              shape->numlines == 1 &&
-              shape->line[0].numpoints == 5 )
-          {
-              if( shape->line[0].point[0].x == shape->line[0].point[1].x &&
-                  shape->line[0].point[0].y == shape->line[0].point[3].y &&
-                  shape->line[0].point[2].x == shape->line[0].point[3].x &&
-                  shape->line[0].point[1].y == shape->line[0].point[2].y &&
-                  shape->line[0].point[0].x == shape->line[0].point[4].x &&
-                  shape->line[0].point[0].y == shape->line[0].point[4].y )
-              {
-                  bIsIntersectRectangle = MS_TRUE;
-              }
-          }
+    switch(n->token) {
+    case MS_TOKEN_LOGICAL_AND:
+        out = msStrdup(" AND ");
+        break;
+    case MS_TOKEN_LOGICAL_OR:
+        out = msStrdup(" OR ");
+        break;
+    case MS_TOKEN_LOGICAL_NOT:
+        out = msStrdup(" NOT ");
+        break;
+    case MS_TOKEN_LITERAL_NUMBER:
+        nOutSize = 80;
+        out = (char *)msSmallMalloc(nOutSize);
+        snprintf(out, nOutSize, "%lf",  n->tokenval.dblval);
+        break;
+    case MS_TOKEN_LITERAL_STRING: {
+        char *stresc = msOGREscapeSQLParam(layer, n->tokenval.strval);
+        nOutSize = strlen(stresc)+3;
+        out = (char *)msSmallMalloc(nOutSize);
+        snprintf(out, nOutSize, "'%s'", stresc);
+        msFree(stresc);
+        break;
+    }
+    case MS_TOKEN_LITERAL_TIME:
+        // seems to require METADATA gml_types => auto
+        nOutSize = 80;
+        out = (char *)msSmallMalloc(nOutSize);
+#if 0
+        // FIXME? or perhaps just remove me. tm_zone is not supported on Windows, and not used anywhere else in the code base
+        if (n->tokenval.tmval.tm_zone)
+            snprintf(out, nOutSize, "'%d-%02d-%02dT%02d:%02d:%02d%s'",
+                     n->tokenval.tmval.tm_year+1900, n->tokenval.tmval.tm_mon+1, n->tokenval.tmval.tm_mday,
+                     n->tokenval.tmval.tm_hour, n->tokenval.tmval.tm_min, n->tokenval.tmval.tm_sec,
+                     n->tokenval.tmval.tm_zone);
+        else
+#endif
+            snprintf(out, nOutSize, "'%d-%02d-%02dT%02d:%02d:%02d'",  
+                     n->tokenval.tmval.tm_year+1900, n->tokenval.tmval.tm_mon+1, n->tokenval.tmval.tm_mday,
+                     n->tokenval.tmval.tm_hour, n->tokenval.tmval.tm_min, n->tokenval.tmval.tm_sec);
+        break;
+    case MS_TOKEN_LITERAL_SHAPE: {
+        // assumed to be in right srs after FLTGetSpatialComparisonCommonExpression
+        char *wkt = msShapeToWKT(n->tokenval.shpval);
+        const char *col = OGR_L_GetGeometryColumn(info->hLayer); // which geom field??
+        nOutSize = strlen(wkt)+strlen(col)+35;
+        out = (char *)msSmallMalloc(nOutSize);
+        snprintf(out, nOutSize, "ST_GeomFromText('%s',ST_SRID(\"%s\"))", wkt, col);
+        msFree(wkt);
+        break;
+    }
+    case MS_TOKEN_LITERAL_BOOLEAN:
+        out = msStrdup(n->tokenval.dblval == 0 ? "FALSE" : "TRUE");
+        break;
+    case MS_TOKEN_COMPARISON_EQ:
+        out = msStrdup(" = ");
+        break;
+    case MS_TOKEN_COMPARISON_NE:
+        out = msStrdup(" != ");
+        break;
+    case MS_TOKEN_COMPARISON_GT:
+        out = msStrdup(" > ");
+        break;
+    case MS_TOKEN_COMPARISON_LT:
+        out = msStrdup(" < ");
+        break;
+    case MS_TOKEN_COMPARISON_LE:
+        out = msStrdup(" <= ");
+        break;
+    case MS_TOKEN_COMPARISON_GE:
+        out = msStrdup(" >= ");
+        break;
+    case MS_TOKEN_COMPARISON_IEQ:
+        out = msStrdup(" = ");
+        break;
+    case MS_TOKEN_COMPARISON_IN:
+        out = msStrdup(" IN ");
+        break;
+    // the origin may be mapfile (complex regexes, layer->map.query.filter.string == NULL, regex may have //) or 
+    // OGC Filter (simple patterns only, layer->map.query.filter.string != NULL)
+    case MS_TOKEN_COMPARISON_RE: 
+    case MS_TOKEN_COMPARISON_IRE: 
+    case MS_TOKEN_COMPARISON_LIKE: {
+        int case_sensitive = n->token == MS_TOKEN_COMPARISON_RE || n->token == MS_TOKEN_COMPARISON_LIKE;
+        // in PostgreSQL and OGR: LIKE (case sensitive) and ILIKE (case insensitive)
+        // in SQLite: LIKE (case insensitive) and GLOB (case sensitive)
+        const char *op = case_sensitive ? "LIKE" : "ILIKE";
+        char wild_any =  '%';
+        char wild_one = '_';
+
+        if (EQUAL(info->dialect, "Spatialite")) {
+            if (case_sensitive) {
+                op = "GLOB";
+                wild_any = '*';
+                wild_one = '?';
+            } else {
+                op = "LIKE";
+            }
+        }
 
-          node = node->next->next->next->next->next->next->next;
-          if( node && node->next && node->next->token == MS_TOKEN_LOGICAL_AND )
-              node = node->next;
+        n = n->next;
+        if (n->token != MS_TOKEN_LITERAL_STRING) return NULL;
 
-          break;
-        }
+        char *regex = msStrdup(n->tokenval.strval);
+        int complex_regex = *n->tokenval.strval == '/'; // could be non-complex but that is soo corner case
 
-        case MS_TOKEN_COMPARISON_EQ:
-        case MS_TOKEN_COMPARISON_NE:
-        case MS_TOKEN_COMPARISON_GT:
-        case MS_TOKEN_COMPARISON_GE:
-        case MS_TOKEN_COMPARISON_LT:
-        case MS_TOKEN_COMPARISON_LE:
-        case MS_TOKEN_LOGICAL_AND:
-        case MS_TOKEN_LOGICAL_NOT:
-        case MS_TOKEN_LOGICAL_OR:
-        case '(':
-        case ')':
-            if( node->token == MS_TOKEN_LOGICAL_AND && node->next &&
-                node->next->token == MS_TOKEN_COMPARISON_INTERSECTS )
-                node = node->next;
+        // PostgreSQL has POSIX regexes, SQLite does not by default, OGR does not
+        if (complex_regex) {
+            if (!EQUAL(info->dialect, "PostgreSQL")) {
+                msFree(regex);
+                return NULL;
+            }
+            // remove //
+            regex++;
+            regex[strlen(regex) - 1] = '\0';
+            if (case_sensitive)
+                op = "~";
             else
-                msSQLExpression = msStringConcatenate(msSQLExpression, msExpressionTokenToString(node->token));
-            break;
-
-        default:
-          goto cleanup;
-          break;
+                op = "~*";
         }
 
-      node = node->next;
-  }
-  
-  if( !sBBOXValid || bIsIntersectRectangle )
-  {
-      /* We can translate completely the filter as a OGR expression, */
-      /* so no need for msEvalExpression() to do more work */
+        char *re = (char *) msSmallMalloc(strlen(regex)+3);
+        size_t i = 0, j = 0;
+        re[j++] = '\'';
+        while (i < strlen(regex)) {
+            char c = regex[i];
+            char c_next = regex[i+1];
+                
+            if (c == '.' && c_next == '*') {
+                i++;
+                c = wild_any;
+            }
+            else if (c == '.')
+                c = wild_one;
 
-      if (layer->debug >= MS_DEBUGLEVEL_VVV)
-            msDebug("msOGRTranslateMsExpressionToOGRSQL: filter can be evaluated completely on OGR side\n");
+            if (i == 0 && c == '^') {
+                i++;
+                continue;
+            }
+                
+            re[j++] = c;
+            i++;
+                
+        }
+        re[j++] = '\'';
+        re[j] = '\0';
+
+        nOutSize = 1 + strlen(op)+ 1 + strlen(re) + 1;
+        out = (char *)msSmallMalloc(nOutSize);
+        snprintf(out, nOutSize, " %s %s", op, re);
+        msFree(re);
+        msFree(regex);
+        break;
+    }
+    case MS_TOKEN_COMPARISON_INTERSECTS:
+        out = msStrdup("ST_Intersects");
+        break;
+    case MS_TOKEN_COMPARISON_DISJOINT:
+        out = msStrdup("ST_Disjoint");
+        break;
+    case MS_TOKEN_COMPARISON_TOUCHES:
+        out = msStrdup("ST_Touches");
+        break;
+    case MS_TOKEN_COMPARISON_OVERLAPS:
+        out = msStrdup("ST_Overlaps");
+        break;
+    case MS_TOKEN_COMPARISON_CROSSES:
+        out = msStrdup("ST_Crosses");
+        break;
+    case MS_TOKEN_COMPARISON_WITHIN:
+        out = msStrdup("ST_Within");
+        break;
+    case MS_TOKEN_COMPARISON_DWITHIN:
+        out = msStrdup("ST_Distance");
+        break;
+    case MS_TOKEN_COMPARISON_BEYOND:
+        out = msStrdup("ST_Distance");
+        break;
+    case MS_TOKEN_COMPARISON_CONTAINS:
+        out = msStrdup("ST_Contains");
+        break;
+    case MS_TOKEN_COMPARISON_EQUALS:
+        out = msStrdup("ST_Equals");
+        break;
+    case MS_TOKEN_FUNCTION_LENGTH:
+        out = msStrdup("ST_Length");
+        break;
+    case MS_TOKEN_FUNCTION_AREA:
+        out = msStrdup("ST_Area");
+        break;
+    case MS_TOKEN_BINDING_DOUBLE: {
+        char *stresc = msLayerEscapePropertyName(layer, n->tokenval.bindval.item);
+        nOutSize = strlen(stresc)+30;
+        out = (char *)msSmallMalloc(nOutSize);
+        const char *type = "float(16)";
+        if (EQUAL(info->dialect, "Spatialite"))
+            type = "REAL";
+        else if (EQUAL(info->dialect, "PostgreSQL"))
+            type = "double precision";
+        snprintf(out, nOutSize, "CAST(\"%s\" AS %s)", stresc, type);
+        msFree(stresc);
+        break;
+    }
+    case MS_TOKEN_BINDING_INTEGER: {
+        char *stresc = msLayerEscapePropertyName(layer, n->tokenval.bindval.item);
+        nOutSize = strlen(stresc)+20;
+        out = (char *)msSmallMalloc(nOutSize);
+        snprintf(out, nOutSize, "CAST(\"%s\" AS integer)", stresc);
+        msFree(stresc);
+        break;
+    }
+    case MS_TOKEN_BINDING_STRING: {
+        char *stresc = msLayerEscapePropertyName(layer, n->tokenval.bindval.item);
+        nOutSize = strlen(stresc)+30;
+        out = (char *)msSmallMalloc(nOutSize);
+        snprintf(out, nOutSize, "CAST(\"%s\" AS text)", stresc);
+        msFree(stresc);
+        break;
+    }
+    case MS_TOKEN_BINDING_TIME: {
+        // won't get here unless col is parsed as time and they are not
+        char *stresc = msLayerEscapePropertyName(layer, n->tokenval.bindval.item);
+        nOutSize = strlen(stresc)+10;
+        out = (char *)msSmallMalloc(nOutSize);
+        snprintf(out, nOutSize, "\"%s\"", stresc);
+        msFree(stresc);
+        break;
+    }
+    case MS_TOKEN_BINDING_SHAPE: {
+        const char *col = OGR_L_GetGeometryColumn(info->hLayer); // which geom field??
+        nOutSize = strlen(col)+10;
+        out = (char *)msSmallMalloc(nOutSize);
+        snprintf(out, nOutSize, "\"%s\"", col);
+        break;
+    }
 
-      msFree( layer->filter.native_string );
-      layer->filter.native_string = msStrdup(msSQLExpression);
-  }
-  
-  if( sBBOXValid )
-  {
-      psRect->minx = MS_MAX(psRect->minx, sBBOX.minx);
-      psRect->miny = MS_MAX(psRect->miny, sBBOX.miny);
-      psRect->maxx = MS_MIN(psRect->maxx, sBBOX.maxx);
-      psRect->maxy = MS_MAX(psRect->maxy, sBBOX.maxy);
-  }
+    // unhandled below until default
+
+    case MS_TOKEN_FUNCTION_TOSTRING:
+    case MS_TOKEN_FUNCTION_COMMIFY:
+    case MS_TOKEN_FUNCTION_ROUND:
+    case MS_TOKEN_FUNCTION_FROMTEXT:
+    case MS_TOKEN_FUNCTION_BUFFER:
+    case MS_TOKEN_FUNCTION_DIFFERENCE:
+    case MS_TOKEN_FUNCTION_SIMPLIFY:
+    case MS_TOKEN_FUNCTION_SIMPLIFYPT:
+    case MS_TOKEN_FUNCTION_GENERALIZE:
+    case MS_TOKEN_FUNCTION_SMOOTHSIA:
+    case MS_TOKEN_FUNCTION_JAVASCRIPT:
+    case MS_TOKEN_FUNCTION_UPPER:
+    case MS_TOKEN_FUNCTION_LOWER:
+    case MS_TOKEN_FUNCTION_INITCAP:
+    case MS_TOKEN_FUNCTION_FIRSTCAP:
+    case MS_TOKEN_BINDING_MAP_CELLSIZE:
+    case MS_TOKEN_BINDING_DATA_CELLSIZE:
+    case MS_PARSE_TYPE_BOOLEAN:
+    case MS_PARSE_TYPE_STRING:
+    case MS_PARSE_TYPE_SHAPE:
+        break;
 
-  return msSQLExpression;
+    default:
+        if (n->token < 128) {
+            char c = n->token;
+            out = (char *)msSmallMalloc(2);
+            sprintf(out, "%c", c);
+        }
+        break;
+    }
 
-cleanup:
-  msFree(msSQLExpression);
-  return NULL;
+    n = n->next;
+    *node = n;
+    return out;
 }
-#endif //0
+
 
 /**********************************************************************
  *                     msOGRFileWhichShapes()
@@ -1508,178 +1847,315 @@ cleanup:
  **********************************************************************/
 static int msOGRFileWhichShapes(layerObj *layer, rectObj rect, msOGRFileInfo *psInfo)
 {
-  if (psInfo == NULL || psInfo->hLayer == NULL) {
-    msSetError(MS_MISCERR, "Assertion failed: OGR layer not opened!!!", "msOGRFileWhichShapes()");
-    return(MS_FAILURE);
-  }
-    
-  char *pszOGRFilter = NULL;
-
-  /*
-  ** Build the OGR filter from two potential sources:
-  **   1) the NATIVE_FILTER processing option
-  **   2) a translated MapServer layer->filter (stored in layer->native_string)
-  */
-  if(msLayerGetProcessingKey(layer, "NATIVE_FILTER") != NULL) {
-    pszOGRFilter = msStringConcatenate(pszOGRFilter, "(");
-    pszOGRFilter = msStringConcatenate(pszOGRFilter, msLayerGetProcessingKey(layer, "NATIVE_FILTER"));
-    pszOGRFilter = msStringConcatenate(pszOGRFilter, ")");
-    if(layer->filter.native_string) {
-      pszOGRFilter = msStringConcatenate(pszOGRFilter, "AND (");
-      pszOGRFilter = msStringConcatenate(pszOGRFilter, layer->filter.native_string);
-      pszOGRFilter = msStringConcatenate(pszOGRFilter, ")");
+    // rect is from BBOX parameter in query (In lieu of a FEATUREID or FILTER) or mapfile somehow
+    if (psInfo == NULL || psInfo->hLayer == NULL) {
+        msSetError(MS_MISCERR, "Assertion failed: OGR layer not opened!!!", "msOGRFileWhichShapes()");
+        return(MS_FAILURE);
     }
-  } else if(layer->filter.native_string) {
-    pszOGRFilter = msStringConcatenate(pszOGRFilter, "(");
-    pszOGRFilter = msStringConcatenate(pszOGRFilter, layer->filter.native_string);
-    pszOGRFilter = msStringConcatenate(pszOGRFilter, ")");
-  }
 
-  /* apply sortBy */
-  if( layer->sortBy.nProperties > 0 ) {
-    char* strOrderBy;
-    char* pszLayerDef = NULL;
+    char *select = (psInfo->pszSelect) ? msStrdup(psInfo->pszSelect) : NULL;
 
-    strOrderBy = msLayerBuildSQLOrderBy(layer);
+    // we'll go strictly two possible ways: 
+    // 1) GetLayer + SetFilter
+    // 2) ExecuteSQL (psInfo->hLayer is an SQL result OR sortBy was requested OR have native_string
+    // and start from the second
 
-    if( psInfo->nLayerIndex == -1 ) {
-      pszLayerDef = msStrdup(psInfo->pszLayerDef);
-      if( strcasestr(psInfo->pszLayerDef, " ORDER BY ") == NULL )
-        pszLayerDef = msStringConcatenate(pszLayerDef, " ORDER BY ");
-      else
-        pszLayerDef = msStringConcatenate(pszLayerDef, ", ");
-    } else {
-      const char* pszGeometryColumn;
-      int i;
-      pszLayerDef = msStringConcatenate(pszLayerDef, "SELECT ");
-      for(i = 0; i < layer->numitems; i++) {
-        if( i > 0 )
-          pszLayerDef = msStringConcatenate(pszLayerDef, ", ");
-        pszLayerDef = msStringConcatenate(pszLayerDef, "\"");
-        pszLayerDef = msStringConcatenate(pszLayerDef, layer->items[i]);
-        pszLayerDef = msStringConcatenate(pszLayerDef, "\"");
-      }
+    if ( psInfo->bIsOKForSQLCompose && (psInfo->nLayerIndex == -1 ||
+                                        layer->sortBy.nProperties > 0 ||
+                                        layer->filter.native_string ||
+                                        (psInfo->bPaging && layer->maxfeatures > 0)) ) {
 
-      pszLayerDef = msStringConcatenate(pszLayerDef, ", ");
-      pszGeometryColumn = OGR_L_GetGeometryColumn(psInfo->hLayer);
-      if( pszGeometryColumn != NULL && pszGeometryColumn[0] != '\0' ) {
-        pszLayerDef = msStringConcatenate(pszLayerDef, "\"");
-        pszLayerDef = msStringConcatenate(pszLayerDef, pszGeometryColumn);
-        pszLayerDef = msStringConcatenate(pszLayerDef, "\"");
-      } else {
-        /* Add ", *" so that we still have an hope to get the geometry */
-        pszLayerDef = msStringConcatenate(pszLayerDef, "*");
-      }
-      pszLayerDef = msStringConcatenate(pszLayerDef, " FROM \"");
-      pszLayerDef = msStringConcatenate(pszLayerDef, OGR_FD_GetName(OGR_L_GetLayerDefn(psInfo->hLayer)));
-      pszLayerDef = msStringConcatenate(pszLayerDef, "\"");
-      if( pszOGRFilter != NULL ) {
-        pszLayerDef = msStringConcatenate(pszLayerDef, " WHERE ");
-        pszLayerDef = msStringConcatenate(pszLayerDef, pszOGRFilter);
-        msFree(pszOGRFilter);
-        pszOGRFilter = NULL;
-      }
-      pszLayerDef = msStringConcatenate(pszLayerDef, " ORDER BY ");
-    }
+        if( psInfo->nLayerIndex == -1 && select == NULL ) {
+            select = msStrdup(psInfo->pszLayerDef);
+            /* If nLayerIndex == -1 then the layer is an SQL result ... free it */
+            OGR_DS_ReleaseResultSet( psInfo->hDS, psInfo->hLayer );
+            psInfo->hLayer = NULL;
+        }
+        else if( select == NULL ) {
+            const char* pszGeometryColumn;
+            int i;
+            select = msStringConcatenate(select, "SELECT ");
+            for(i = 0; i < layer->numitems; i++) {
+                if( i > 0 )
+                    select = msStringConcatenate(select, ", ");
+                select = msStringConcatenate(select, "\"");
+                select = msStringConcatenate(select, layer->items[i]);
+                select = msStringConcatenate(select, "\"");
+            }
+            if( layer->numitems > 0 )
+                select = msStringConcatenate(select, ", ");
+            pszGeometryColumn = OGR_L_GetGeometryColumn(psInfo->hLayer);
+            if( pszGeometryColumn != NULL && pszGeometryColumn[0] != '\0' ) {
+                select = msStringConcatenate(select, "\"");
+                select = msStringConcatenate(select, pszGeometryColumn);
+                select = msStringConcatenate(select, "\"");
+            } else {
+                /* Add ", *" so that we still have an hope to get the geometry */
+                select = msStringConcatenate(select, "*");
+            }
+            select = msStringConcatenate(select, " FROM ");
+            if( psInfo->nLayerIndex == -1 )
+            {
+              select = msStringConcatenate(select, "(");
+              select = msStringConcatenate(select, psInfo->pszLayerDef);
+              select = msStringConcatenate(select, ") MSSUBSELECT");
+            }
+            else
+            {
+              select = msStringConcatenate(select, "\"");
+              select = msStringConcatenate(select, OGR_FD_GetName(OGR_L_GetLayerDefn(psInfo->hLayer)));
+              select = msStringConcatenate(select, "\"");
+            }
+        }
 
-    pszLayerDef = msStringConcatenate(pszLayerDef, strOrderBy);
-    msFree(strOrderBy);
-    strOrderBy = NULL;
+        char *filter = NULL;
 
-    if( layer->debug )
-      msDebug("msOGRFileWhichShapes: SQL = %s.\n", pszLayerDef);
+        if (msLayerGetProcessingKey(layer, "NATIVE_FILTER") != NULL) {
+            filter = msStringConcatenate(filter, "(");
+            filter = msStringConcatenate(filter, msLayerGetProcessingKey(layer, "NATIVE_FILTER"));
+            filter = msStringConcatenate(filter, ")");
+        }
 
-    /* If nLayerIndex == -1 then the layer is an SQL result ... free it */
-    if( psInfo->nLayerIndex == -1 )
-      OGR_DS_ReleaseResultSet( psInfo->hDS, psInfo->hLayer );
-    psInfo->nLayerIndex = -1;
+        if (psInfo->dialect) {
+            if (EQUAL(psInfo->dialect, "Spatialite") || EQUAL(psInfo->dialect, "PostgreSQL")) {
+                const char *sql = layer->filter.native_string;
+                if (sql && *sql != '\0') {
+                    if (filter) filter = msStringConcatenate(filter, "AND ");
+                    filter = msStringConcatenate(filter, "(");
+                    filter = msStringConcatenate(filter, sql);
+                    filter = msStringConcatenate(filter, ")");
+                }
+            }
+        }
 
-    ACQUIRE_OGR_LOCK;
-    psInfo->hLayer = OGR_DS_ExecuteSQL( psInfo->hDS, pszLayerDef, NULL, NULL );
-    RELEASE_OGR_LOCK;
-    if( psInfo->hLayer == NULL ) {
-      msSetError(MS_OGRERR, "ExecuteSQL(%s) failed.\n%s", "msOGRFileWhichShapes()", pszLayerDef, CPLGetLastErrorMsg());
-      msFree(pszLayerDef);
-      msFree(pszOGRFilter);
-      return MS_FAILURE;
-    }
-    msFree(pszLayerDef);
-  } /* end sort-by */
+        /* ------------------------------------------------------------------
+         * Set Spatial filter... this may result in no features being returned
+         * if layer does not overlap current view.
+         *
+         * __TODO__ We should return MS_DONE if no shape overlaps the selected
+         * region and matches the layer's FILTER expression, but there is currently
+         * no _efficient_ way to do that with OGR.
+         * ------------------------------------------------------------------ */
+        if (psInfo->rect_is_defined) {
+            rect.minx = MAX(psInfo->rect.minx, rect.minx);
+            rect.miny = MAX(psInfo->rect.miny, rect.miny);
+            rect.maxx = MIN(psInfo->rect.maxx, rect.maxx);
+            rect.maxy = MIN(psInfo->rect.maxy, rect.maxy);
+        }
+        psInfo->rect = rect;
+
+        bool bOffsetAlreadyAdded = false;
+        // use spatial index
+        if (psInfo->dialect) {
+            if (EQUAL(psInfo->dialect, "PostgreSQL")) {
+                if (filter) filter = msStringConcatenate(filter, " AND");
+                const char *col = OGR_L_GetGeometryColumn(psInfo->hLayer); // which geom field??
+                filter = msStringConcatenate(filter, " (");
+                filter = msStringConcatenate(filter, col);
+                filter = msStringConcatenate(filter, " && ST_MakeEnvelope(");
+                char *points = (char *)msSmallMalloc(30*2*5);
+                snprintf(points, 30*4, "%lf,%lf,%lf,%lf", rect.minx, rect.miny, rect.maxx, rect.maxy);
+                filter = msStringConcatenate(filter, points);
+                msFree(points);
+                filter = msStringConcatenate(filter, "))");
+            } else if (EQUAL(psInfo->dialect, "Spatialite")) {
+                if (filter) filter = msStringConcatenate(filter, " AND");
+                filter = msStringConcatenate(filter, " ");
+                filter = msStringConcatenate(filter, psInfo->pszMainTableName);
+                filter = msStringConcatenate(filter, ".");
+                const char* pszFIDColumn = OGR_L_GetFIDColumn(psInfo->hLayer);
+                if( psInfo->pszRowId )
+                  filter = msStringConcatenate(filter, psInfo->pszRowId);
+                else if( pszFIDColumn != NULL && pszFIDColumn[0] != '\0' )
+                  filter = msStringConcatenate(filter, pszFIDColumn);
+                else
+                  filter = msStringConcatenate(filter, "ROWID");
+                filter = msStringConcatenate(filter, " IN (SELECT ROWID FROM SpatialIndex WHERE f_table_name = '");
+                filter = msStringConcatenate(filter, psInfo->pszSpatialFilterTableName);
+                filter = msStringConcatenate(filter, "' ");
+                const char* pszGeometryColumn = OGR_L_GetGeometryColumn(psInfo->hLayer);
+                if( pszGeometryColumn != NULL && pszGeometryColumn[0] != '\0' ) {
+                  filter = msStringConcatenate(filter, "AND f_geometry_column = '");
+                  filter = msStringConcatenate(filter, pszGeometryColumn);
+                  filter = msStringConcatenate(filter, "' ");
+                }
+                filter = msStringConcatenate(filter, "AND search_frame = GeomFromText('POLYGON((");
+                char *points = (char *)msSmallMalloc(30*2*5);
+                snprintf(points, 30*2*5, "%lf %lf,%lf %lf,%lf %lf,%lf %lf,%lf %lf", rect.minx, rect.miny, rect.maxx, rect.miny, rect.maxx, rect.maxy, rect.minx, rect.maxy, rect.minx, rect.miny);
+                filter = msStringConcatenate(filter, points);
+                msFree(points);
+                filter = msStringConcatenate(filter, "))')");
+
+                // We put the limit in the sub-query, only if we don't have a
+                // order by later. We accept a startindex, provided there's no
+                // other attribute filter combined
+                if ( psInfo->bPaging && layer->maxfeatures >= 0 &&
+                    (layer->startindex <= 0 || layer->filter.native_string == NULL) &&
+                    layer->sortBy.nProperties == 0 )
+                {
+                    char szLimit[50];
+                    snprintf(szLimit, sizeof(szLimit), " LIMIT %d", layer->maxfeatures);
+                    filter = msStringConcatenate(filter, szLimit);
+
+                    if( layer->startindex > 0 && layer->filter.native_string == NULL )
+                    {
+                        bOffsetAlreadyAdded = true;
+                        char szOffset[50];
+                        snprintf(szOffset, sizeof(szOffset), " OFFSET %d", layer->startindex);
+                        filter = msStringConcatenate(filter, szOffset);
+                    }
+                }
+
+                filter = msStringConcatenate(filter, ")");
+            }
+        }
 
+        /* get sortBy */
+        char *sort = NULL;
+        if( layer->sortBy.nProperties > 0) {
+
+            char *strOrderBy = msLayerBuildSQLOrderBy(layer);
+            if (strOrderBy) {
+                if( psInfo->nLayerIndex == -1 ) {
+                    if( strcasestr(psInfo->pszLayerDef, " ORDER BY ") == NULL )
+                        sort = msStringConcatenate(sort, " ORDER BY ");
+                    else
+                        sort = msStringConcatenate(sort, ", ");
+                } else {
+                    sort = msStringConcatenate(sort, " ORDER BY ");
+                }
+                sort = msStringConcatenate(sort, strOrderBy);
+                msFree(strOrderBy);
+            }
+        }
 
-  /* ------------------------------------------------------------------
-   * Set Spatial filter... this may result in no features being returned
-   * if layer does not overlap current view.
-   *
-   * __TODO__ We should return MS_DONE if no shape overlaps the selected
-   * region and matches the layer's FILTER expression, but there is currently
-   * no _efficient_ way to do that with OGR.
-   * ------------------------------------------------------------------ */
-  ACQUIRE_OGR_LOCK;
+        // compose SQL
+        if (filter) {
+            select = msStringConcatenate(select, " WHERE ");
+            select = msStringConcatenate(select, filter);
+            msFree(filter);
+        }
+        if (sort) {
+            select = msStringConcatenate(select, " ");
+            select = msStringConcatenate(select, sort);
+            msFree(sort);
+        }
 
-  if (rect.minx == rect.maxx && rect.miny == rect.maxy) {
-    OGRGeometryH hSpatialFilterPoint = OGR_G_CreateGeometry( wkbPoint );
+        if ( psInfo->bPaging && layer->maxfeatures >= 0 ) {
+            char szLimit[50];
+            snprintf(szLimit, sizeof(szLimit), " LIMIT %d", layer->maxfeatures);
+            select = msStringConcatenate(select, szLimit);
+        }
 
-    OGR_G_SetPoint_2D( hSpatialFilterPoint, 0, rect.minx, rect.miny );    
-    OGR_L_SetSpatialFilter( psInfo->hLayer, hSpatialFilterPoint );
-    OGR_G_DestroyGeometry( hSpatialFilterPoint );
-  } else if (rect.minx == rect.maxx || rect.miny == rect.maxy) {
-    OGRGeometryH hSpatialFilterLine = OGR_G_CreateGeometry( wkbLineString );
+        if ( !bOffsetAlreadyAdded && psInfo->bPaging && layer->startindex > 0 ) {
+            char szOffset[50];
+            snprintf(szOffset, sizeof(szOffset), " OFFSET %d", layer->startindex);
+            select = msStringConcatenate(select, szOffset);
+        }
 
-    OGR_G_AddPoint_2D( hSpatialFilterLine, rect.minx, rect.miny );
-    OGR_G_AddPoint_2D( hSpatialFilterLine, rect.maxx, rect.maxy );
-    OGR_L_SetSpatialFilter( psInfo->hLayer, hSpatialFilterLine );
-    OGR_G_DestroyGeometry( hSpatialFilterLine );
-  } else {
-    OGRGeometryH hSpatialFilterPolygon = OGR_G_CreateGeometry( wkbPolygon );
-    OGRGeometryH hRing = OGR_G_CreateGeometry( wkbLinearRing );
+        if( layer->debug )
+            msDebug("msOGRFileWhichShapes: SQL = %s.\n", select);
 
-    OGR_G_AddPoint_2D( hRing, rect.minx, rect.miny);
-    OGR_G_AddPoint_2D( hRing, rect.maxx, rect.miny);
-    OGR_G_AddPoint_2D( hRing, rect.maxx, rect.maxy);
-    OGR_G_AddPoint_2D( hRing, rect.minx, rect.maxy);
-    OGR_G_AddPoint_2D( hRing, rect.minx, rect.miny);
-    OGR_G_AddGeometryDirectly( hSpatialFilterPolygon, hRing );
-    OGR_L_SetSpatialFilter( psInfo->hLayer, hSpatialFilterPolygon );
-    OGR_G_DestroyGeometry( hSpatialFilterPolygon );
-  }
+        ACQUIRE_OGR_LOCK;
+        if( psInfo->nLayerIndex == -1 && psInfo->hLayer != NULL )
+        {
+          OGR_DS_ReleaseResultSet( psInfo->hDS, psInfo->hLayer );
+        }
+        psInfo->hLayer = OGR_DS_ExecuteSQL( psInfo->hDS, select, NULL, NULL );
+        psInfo->nLayerIndex = -1;
+
+        if( psInfo->hLayer == NULL ) {
+            RELEASE_OGR_LOCK;
+            msSetError(MS_OGRERR, "ExecuteSQL(%s) failed.\n%s", "msOGRFileWhichShapes()", select, CPLGetLastErrorMsg());
+            msFree(select);
+            return MS_FAILURE;
+        }
 
-  psInfo->rect = rect;
+        // Update itemindexes / layer->iteminfo
+        msOGRLayerInitItemInfo(layer);
+    } 
+    else {
 
-  if (layer->debug >= MS_DEBUGLEVEL_VVV)
-    msDebug("msOGRFileWhichShapes: Setting spatial filter to %f %f %f %f\n", rect.minx, rect.miny, rect.maxx, rect.maxy );
+        // case of 1) GetLayer + SetFilter
 
-  /* ------------------------------------------------------------------
-   * Apply an attribute filter if we have one prefixed with a WHERE
-   * keyword in the filter string.  Otherwise, ensure the attribute
-   * filter is clear.
-   * ------------------------------------------------------------------ */
-  
-  if( pszOGRFilter != NULL ) {
+        char *pszOGRFilter = NULL;
+        if (msLayerGetProcessingKey(layer, "NATIVE_FILTER") != NULL) {
+            pszOGRFilter = msStringConcatenate(pszOGRFilter, "(");
+            pszOGRFilter = msStringConcatenate(pszOGRFilter, msLayerGetProcessingKey(layer, "NATIVE_FILTER"));
+            pszOGRFilter = msStringConcatenate(pszOGRFilter, ")");
+        }
 
-    if (layer->debug >= MS_DEBUGLEVEL_VVV)
-      msDebug("msOGRFileWhichShapes: Setting attribute filter to %s\n", pszOGRFilter );
+        ACQUIRE_OGR_LOCK;
+
+        if( OGR_L_GetGeomType( psInfo->hLayer ) != wkbNone ) {
+            if (rect.minx == rect.maxx && rect.miny == rect.maxy) {
+                OGRGeometryH hSpatialFilterPoint = OGR_G_CreateGeometry( wkbPoint );
+
+                OGR_G_SetPoint_2D( hSpatialFilterPoint, 0, rect.minx, rect.miny );    
+                OGR_L_SetSpatialFilter( psInfo->hLayer, hSpatialFilterPoint );
+                OGR_G_DestroyGeometry( hSpatialFilterPoint );
+            } else if (rect.minx == rect.maxx || rect.miny == rect.maxy) {
+                OGRGeometryH hSpatialFilterLine = OGR_G_CreateGeometry( wkbLineString );
+
+                OGR_G_AddPoint_2D( hSpatialFilterLine, rect.minx, rect.miny );
+                OGR_G_AddPoint_2D( hSpatialFilterLine, rect.maxx, rect.maxy );
+                OGR_L_SetSpatialFilter( psInfo->hLayer, hSpatialFilterLine );
+                OGR_G_DestroyGeometry( hSpatialFilterLine );
+            } else {
+                OGRGeometryH hSpatialFilterPolygon = OGR_G_CreateGeometry( wkbPolygon );
+                OGRGeometryH hRing = OGR_G_CreateGeometry( wkbLinearRing );
+
+                OGR_G_AddPoint_2D( hRing, rect.minx, rect.miny);
+                OGR_G_AddPoint_2D( hRing, rect.maxx, rect.miny);
+                OGR_G_AddPoint_2D( hRing, rect.maxx, rect.maxy);
+                OGR_G_AddPoint_2D( hRing, rect.minx, rect.maxy);
+                OGR_G_AddPoint_2D( hRing, rect.minx, rect.miny);
+                OGR_G_AddGeometryDirectly( hSpatialFilterPolygon, hRing );
+                OGR_L_SetSpatialFilter( psInfo->hLayer, hSpatialFilterPolygon );
+                OGR_G_DestroyGeometry( hSpatialFilterPolygon );
+            }
+        }
 
-    CPLErrorReset();
-    if( OGR_L_SetAttributeFilter( psInfo->hLayer, pszOGRFilter ) != OGRERR_NONE ) {
-      msSetError(MS_OGRERR, "SetAttributeFilter(%s) failed on layer %s.\n%s", "msOGRFileWhichShapes()", layer->filter.string+6, layer->name?layer->name:"(null)", CPLGetLastErrorMsg() );
-      RELEASE_OGR_LOCK;
-      msFree(pszOGRFilter);
-      return MS_FAILURE;
-    }
-    msFree(pszOGRFilter);
-  } else
-    OGR_L_SetAttributeFilter( psInfo->hLayer, NULL );
+        psInfo->rect = rect;
 
-  /* ------------------------------------------------------------------
-   * Reset current feature pointer
-   * ------------------------------------------------------------------ */
-  OGR_L_ResetReading( psInfo->hLayer );
-  psInfo->last_record_index_read = -1;
+        if (layer->debug >= MS_DEBUGLEVEL_VVV)
+            msDebug("msOGRFileWhichShapes: Setting spatial filter to %f %f %f %f\n", rect.minx, rect.miny, rect.maxx, rect.maxy );
+
+        /* ------------------------------------------------------------------
+         * Apply an attribute filter if we have one prefixed with a WHERE
+         * keyword in the filter string.  Otherwise, ensure the attribute
+         * filter is clear.
+         * ------------------------------------------------------------------ */
+        if( pszOGRFilter != NULL ) {
+
+            if (layer->debug >= MS_DEBUGLEVEL_VVV)
+                msDebug("msOGRFileWhichShapes: Setting attribute filter to %s\n", pszOGRFilter );
+
+            CPLErrorReset();
+            if( OGR_L_SetAttributeFilter( psInfo->hLayer, pszOGRFilter ) != OGRERR_NONE ) {
+                msSetError(MS_OGRERR, "SetAttributeFilter(%s) failed on layer %s.\n%s", "msOGRFileWhichShapes()", layer->filter.string+6, layer->name?layer->name:"(null)", CPLGetLastErrorMsg() );
+                RELEASE_OGR_LOCK;
+                msFree(pszOGRFilter);
+                msFree(select);
+                return MS_FAILURE;
+            }
+            msFree(pszOGRFilter);
+        } else
+            OGR_L_SetAttributeFilter( psInfo->hLayer, NULL );
+        
+    }
 
-  RELEASE_OGR_LOCK;
+    msFree(select);
 
-  return MS_SUCCESS;
+    /* ------------------------------------------------------------------
+     * Reset current feature pointer
+     * ------------------------------------------------------------------ */
+    OGR_L_ResetReading( psInfo->hLayer );
+    psInfo->last_record_index_read = -1;
+    
+    RELEASE_OGR_LOCK;
+  
+    return MS_SUCCESS;
 }
 
 /**********************************************************************
@@ -2171,6 +2647,206 @@ NextFile:
  * ================================================================== */
 
 /**********************************************************************
+ *                     msOGRTranslateMsExpressionToOGRSQL()
+ *
+ * Tries to translate a mapserver expression to OGR or driver native SQL
+ **********************************************************************/
+static int msOGRTranslateMsExpressionToOGRSQL(layerObj* layer,
+                                              expressionObj* psFilter,
+                                              char *filteritem)
+{
+#ifdef USE_OGR
+    msOGRFileInfo *info = (msOGRFileInfo *)layer->layerinfo;
+
+    // reasons to not produce native string: not simple layer, or an explicit deny
+    char *do_this = msLayerGetProcessingKey(layer, "NATIVE_SQL"); // default is YES
+    if (do_this && strcmp(do_this, "NO") == 0) {
+        return MS_SUCCESS;
+    }
+
+    // more reasons to not produce native string: not a recognized driver
+    if (!info->dialect) {
+        return MS_SUCCESS;
+    }
+
+    char *sql = NULL;
+
+    tokenListNodeObjPtr node = psFilter->tokens;
+    // node may be NULL if layer->filter.string != NULL and layer->filteritem != NULL
+    // this is simple filter but string is regex
+    if (node == NULL && layer->filteritem != NULL && layer->filter.string != NULL) {
+        sql = msStringConcatenate(sql, "\"");
+        sql = msStringConcatenate(sql, layer->filteritem);
+        sql = msStringConcatenate(sql, "\"");
+        if (EQUAL(info->dialect, "PostgreSQL") ) {
+            sql = msStringConcatenate(sql, " ~ ");
+        } else {
+            sql = msStringConcatenate(sql, " LIKE ");
+        }
+        sql = msStringConcatenate(sql, "'");
+        sql = msStringConcatenate(sql, layer->filter.string);
+        sql = msStringConcatenate(sql, "'");
+    }
+    // test if there is a "top" level intersects (see FLTValidForBBoxFilter) for a bounding box
+    if (node != NULL) {
+        int is_top_level_and = 0;
+        int has_bounding_box = 0;
+        tokenListNodeObjPtr bounding_box_node = NULL;
+        tokenListNodeObjPtr x = psFilter->tokens;
+        int d = 0;
+        while (x != NULL) {
+            if (x->token == '(') d++;
+            if (x->token == ')') d--;
+            if (x->token == MS_TOKEN_COMPARISON_INTERSECTS && d == 0) {
+                has_bounding_box = 1;
+                bounding_box_node = x;
+            }
+            if (d == 1) {
+                if (x->token == MS_TOKEN_COMPARISON_INTERSECTS)
+                    bounding_box_node = x;
+                else if (x->token == MS_TOKEN_LOGICAL_AND)
+                    is_top_level_and = 1;
+            }
+            if (is_top_level_and && bounding_box_node)
+                has_bounding_box = 1;
+            x = x->next;
+        }
+        if (has_bounding_box) {
+            x = bounding_box_node;
+            x = x->next; // skip fct
+            x = x->next; // skip (
+            x = x->next; // skip field name
+            x = x->next; // skip ,
+            char *a = msOGRGetToken(layer, &x);
+            // skip "ST_GeomFromText(' from a
+            char *wkt = a+17;
+            OGRGeometryH hSpatialFilter;
+            OGRErr e = OGR_G_CreateFromWkt(&wkt, NULL, &hSpatialFilter);
+            msFree(a);
+            if (e == OGRERR_NONE) {
+                OGREnvelope env;
+                OGR_G_GetEnvelope(hSpatialFilter, &env);
+                info->rect.minx = env.MinX;
+                info->rect.miny = env.MinY;
+                info->rect.maxx = env.MaxX;
+                info->rect.maxy = env.MaxY;
+                info->rect_is_defined = true;
+                OGR_G_DestroyGeometry(hSpatialFilter);
+            }
+        }
+    }
+    while (node != NULL) {
+
+        if (node->next && node->next->token == MS_TOKEN_COMPARISON_IEQ) {
+            char *left = msOGRGetToken(layer, &node);
+            node = node->next; // skip =
+            char *right = msOGRGetToken(layer, &node);
+            sql = msStringConcatenate(sql, "upper(");
+            sql = msStringConcatenate(sql, left);
+            sql = msStringConcatenate(sql, ")");
+            sql = msStringConcatenate(sql, "=");
+            sql = msStringConcatenate(sql, "upper(");
+            sql = msStringConcatenate(sql, right);
+            sql = msStringConcatenate(sql, ")");
+            int ok = left && right;
+            msFree(left);
+            msFree(right);
+            if (!ok) {
+                goto fail;
+            }
+            continue;
+        }
+
+        switch(node->token) {
+        case MS_TOKEN_COMPARISON_INTERSECTS:
+        case MS_TOKEN_COMPARISON_DISJOINT:
+        case MS_TOKEN_COMPARISON_TOUCHES:
+        case MS_TOKEN_COMPARISON_OVERLAPS:
+        case MS_TOKEN_COMPARISON_CROSSES:
+        case MS_TOKEN_COMPARISON_DWITHIN:
+        case MS_TOKEN_COMPARISON_BEYOND:
+        case MS_TOKEN_COMPARISON_WITHIN:
+        case MS_TOKEN_COMPARISON_CONTAINS:
+        case MS_TOKEN_COMPARISON_EQUALS:{
+            int token = node->token;
+            char *fct = msOGRGetToken(layer, &node);
+            node = node->next; // skip (
+            char *a1 = msOGRGetToken(layer, &node);
+            node = node->next; // skip ,
+            char *a2 = msOGRGetToken(layer, &node);
+            char *a3 = NULL;
+            if (token == MS_TOKEN_COMPARISON_DWITHIN || token == MS_TOKEN_COMPARISON_BEYOND) {
+                node = node->next; // skip ,
+                a3 = msOGRGetToken(layer, &node);
+            }
+            node = node->next; // skip )
+            char *eq = msOGRGetToken(layer, &node);
+            char *rval = msOGRGetToken(layer, &node);
+            if (strcmp(eq, " != ") == 0 || strcmp(rval, "FALSE") == 0) {
+                sql = msStringConcatenate(sql, "NOT ");
+            }
+            // FIXME: case rval is more complex
+            sql = msStringConcatenate(sql, fct);
+            sql = msStringConcatenate(sql, "(");
+            sql = msStringConcatenate(sql, a1);
+            sql = msStringConcatenate(sql, ",");
+            sql = msStringConcatenate(sql, a2);
+            if (token == MS_TOKEN_COMPARISON_DWITHIN || token == MS_TOKEN_COMPARISON_BEYOND) {
+                sql = msStringConcatenate(sql, ")");
+                if (token == MS_TOKEN_COMPARISON_DWITHIN)
+                    sql = msStringConcatenate(sql, "<=");
+                else 
+                    sql = msStringConcatenate(sql, ">");
+                sql = msStringConcatenate(sql, a3);
+            } else {
+                sql = msStringConcatenate(sql, ")");
+            }
+            int ok = fct && a1 && a2 && eq && rval;
+            if (token == MS_TOKEN_COMPARISON_DWITHIN) {
+                ok = ok && a3;
+            }
+            msFree(fct);
+            msFree(a1);
+            msFree(a2);
+            msFree(a3);
+            msFree(eq);
+            msFree(rval);
+            if (!ok) {
+                goto fail;
+            }
+            break;
+        }
+        default: {
+            char *token = msOGRGetToken(layer, &node);
+            if (!token) {
+                goto fail;
+            }
+            sql = msStringConcatenate(sql, token);
+            msFree(token);
+        }
+        }
+    }
+
+    layer->filter.native_string = sql;
+    return MS_SUCCESS;
+fail:
+    // error producing native string
+    fprintf(stderr, "Note: Error parsing token list, could produce only: %s\n", sql);
+    msFree(sql);
+    return MS_FAILURE;
+#else
+  /* ------------------------------------------------------------------
+   * OGR Support not included...
+   * ------------------------------------------------------------------ */
+
+  msSetError(MS_MISCERR, "OGR support is not available.",
+             "msOGRTranslateMsExpressionToOGRSQL()");
+  return(MS_FAILURE);
+
+#endif /* USE_OGR */
+}
+
+/**********************************************************************
  *                     msOGRLayerOpen()
  *
  * Open OGR data source for the specified map layer.
@@ -3639,6 +4315,55 @@ static int msOGRLayerSupportsCommonFilters(layerObj *layer)
   return MS_FALSE;
 }
 
+static void msOGREnablePaging(layerObj *layer, int value)
+{
+#ifdef USE_OGR
+  msOGRFileInfo *layerinfo = NULL;
+
+  if (layer->debug) {
+    msDebug("msOGREnablePaging(%d) called.\n", value);
+  }
+
+  if(!msOGRLayerIsOpen(layer))
+    msOGRLayerOpenVT(layer);
+
+  assert( layer->layerinfo != NULL);
+
+  layerinfo = (msOGRFileInfo *)layer->layerinfo;
+  layerinfo->bPaging = value;
+
+#else
+  msSetError( MS_MISCERR,
+              "OGR support is not available.",
+              "msOGREnablePaging()");
+#endif
+  return;
+}
+
+static int msOGRGetPaging(layerObj *layer)
+{
+#ifdef USE_OGR
+  msOGRFileInfo *layerinfo = NULL;
+
+  if (layer->debug) {
+    msDebug("msOGRGetPaging called.\n");
+  }
+
+  if(!msOGRLayerIsOpen(layer))
+    msOGRLayerOpenVT(layer);
+
+  assert( layer->layerinfo != NULL);
+
+  layerinfo = (msOGRFileInfo *)layer->layerinfo;
+  return layerinfo->bPaging;
+#else
+  msSetError( MS_MISCERR,
+              "OGR support is not available.",
+              "msOGREnablePaging()");
+  return MS_FAILURE;
+#endif
+}
+
 /************************************************************************/
 /*                  msOGRLayerInitializeVirtualTable()                  */
 /************************************************************************/
@@ -3647,7 +4372,7 @@ int msOGRLayerInitializeVirtualTable(layerObj *layer)
   assert(layer != NULL);
   assert(layer->vtable != NULL);
 
-  /* layer->vtable->LayerTranslateFilter, use default */
+  layer->vtable->LayerTranslateFilter = msOGRTranslateMsExpressionToOGRSQL;
 
   layer->vtable->LayerSupportsCommonFilters = msOGRLayerSupportsCommonFilters;
   layer->vtable->LayerInitItemInfo = msOGRLayerInitItemInfo;
@@ -3670,7 +4395,8 @@ int msOGRLayerInitializeVirtualTable(layerObj *layer)
 
   layer->vtable->LayerEscapeSQLParam = msOGREscapeSQLParam;
   layer->vtable->LayerEscapePropertyName = msOGREscapePropertyName;
-
+  layer->vtable->LayerEnablePaging = msOGREnablePaging;
+  layer->vtable->LayerGetPaging = msOGRGetPaging;
   return MS_SUCCESS;
 }
 
@@ -3803,4 +4529,3 @@ char *msOGRShapeToWKT(shapeObj *shape)
   return NULL;
 #endif
 }
-
diff --git a/mapogroutput.c b/mapogroutput.c
index b6efb46..c105fdf 100644
--- a/mapogroutput.c
+++ b/mapogroutput.c
@@ -247,7 +247,7 @@ static void msOGRSetPoints( OGRGeometryH hGeom, lineObj *line, int bWant2DOutput
 
 static int msOGRWriteShape( layerObj *map_layer, OGRLayerH hOGRLayer,
                             shapeObj *shape, gmlItemListObj *item_list,
-                            int nFirstOGRFieldIndex )
+                            int nFirstOGRFieldIndex, const char *pszFeatureid )
 
 {
   OGRGeometryH hGeom = NULL;
@@ -489,6 +489,15 @@ static int msOGRWriteShape( layerObj *map_layer, OGRLayerH hOGRLayer,
   for( i = 0; i < item_list->numitems; i++ ) {
     gmlItemObj *item = item_list->items + i;
 
+    if(pszFeatureid && !strcmp(pszFeatureid, item->name)) {
+      char *endptr;
+      long feature_id = strtol(shape->values[i],&endptr,10);
+      if(endptr && *endptr==0) {
+        /* only set the featureid if it is numeric */
+        OGR_F_SetFID(hFeat, feature_id);
+      }
+    }
+
     if( !item->visible )
       continue;
 
@@ -689,6 +698,7 @@ int msOGRWriteFromQuery( mapObj *map, outputFormatObj *format, int sendheaders )
   char **file_list = NULL;
   int iLayer, i;
   int bDataSourceNameIsRequestDir = FALSE;
+  int bUseFeatureId = MS_FALSE;
 
   /* -------------------------------------------------------------------- */
   /*      Fetch the output format driver.                                 */
@@ -713,6 +723,9 @@ int msOGRWriteFromQuery( mapObj *map, outputFormatObj *format, int sendheaders )
       ds_options = CSLAddString( ds_options,
                                  format->formatoptions[i] + 5 );
   }
+  if(!strcasecmp("true",msGetOutputFormatOption(format,"USE_FEATUREID","false"))) {
+    bUseFeatureId = MS_TRUE;
+  }
 
   /* ==================================================================== */
   /*      Determine the output datasource name to use.                    */
@@ -870,8 +883,8 @@ int msOGRWriteFromQuery( mapObj *map, outputFormatObj *format, int sendheaders )
     gmlItemListObj *item_list = NULL;
     const char *value;
     char *pszWKT;
-    int  reproject = MS_FALSE;
     int  nFirstOGRFieldIndex = -1;
+    const char *pszFeatureid = NULL;
 
     if( !layer->resultcache )
       continue;
@@ -879,11 +892,9 @@ int msOGRWriteFromQuery( mapObj *map, outputFormatObj *format, int sendheaders )
     /* -------------------------------------------------------------------- */
     /*      Will we need to reproject?                                      */
     /* -------------------------------------------------------------------- */
-    if(layer->transform == MS_TRUE
-        && layer->project
-        && msProjectionsDiffer(&(layer->projection),
-                               &(layer->map->projection)) )
-      reproject = MS_TRUE;
+    if(layer->transform == MS_TRUE)
+        layer->project = msProjectionsDiffer(&(layer->projection),
+                               &(layer->map->projection));
 
     /* -------------------------------------------------------------------- */
     /*      Establish the geometry type to use for the created layer.       */
@@ -902,6 +913,9 @@ int msOGRWriteFromQuery( mapObj *map, outputFormatObj *format, int sendheaders )
         value = "Geometry";
     }
 
+    if(bUseFeatureId)
+      pszFeatureid = msOWSLookupMetadata(&(layer->metadata), "FOG", "featureid");
+
     if( strcasecmp(value,"Point") == 0 )
       eGeomType = wkbPoint;
     else if( strcasecmp(value,"LineString") == 0 )
@@ -964,7 +978,7 @@ int msOGRWriteFromQuery( mapObj *map, outputFormatObj *format, int sendheaders )
     }
 
     if( srs != NULL )
-      OSRDestroySpatialReference( srs );
+      OSRRelease( srs );
 
     /* -------------------------------------------------------------------- */
     /*      Create appropriate attributes on this layer.                    */
@@ -1027,6 +1041,7 @@ int msOGRWriteFromQuery( mapObj *map, outputFormatObj *format, int sendheaders )
 
         OGR_DS_Destroy( hDS );
         msOGRCleanupDS( datasource_name );
+        msGMLFreeItems(item_list);
         return MS_FAILURE;
       }
 
@@ -1101,7 +1116,7 @@ int msOGRWriteFromQuery( mapObj *map, outputFormatObj *format, int sendheaders )
         }
       }
 
-      if( reproject ) {
+      if( layer->project ) {
         status =
           msProjectShape(&layer->projection, &layer->map->projection,
                          &resultshape);
@@ -1113,7 +1128,7 @@ int msOGRWriteFromQuery( mapObj *map, outputFormatObj *format, int sendheaders )
 
       if( status == MS_SUCCESS )
         status = msOGRWriteShape( layer, hOGRLayer, &resultshape,
-                                  item_list, nFirstOGRFieldIndex );
+                                  item_list, nFirstOGRFieldIndex, pszFeatureid );
 
       if(status != MS_SUCCESS) {
         OGR_DS_Destroy( hDS );
diff --git a/mapowscommon.c b/mapowscommon.c
index 0c86c87..24609a4 100644
--- a/mapowscommon.c
+++ b/mapowscommon.c
@@ -83,7 +83,7 @@ xmlNodePtr msOWSCommonServiceIdentification(xmlNsPtr psNsOws, mapObj *map,
 
   value = msOWSLookupMetadataWithLanguage(&(map->web.metadata), namespaces, "title", validated_language);
 
-  psNode = xmlNewChild(psRootNode, psNsOws, BAD_CAST "Title", BAD_CAST value);
+  psNode = xmlNewTextChild(psRootNode, psNsOws, BAD_CAST "Title", BAD_CAST value);
 
   if (!value) {
     xmlAddSibling(psNode, xmlNewComment(BAD_CAST "WARNING: Optional metadata \"ows_title\" missing for ows:Title"));
@@ -91,7 +91,7 @@ xmlNodePtr msOWSCommonServiceIdentification(xmlNsPtr psNsOws, mapObj *map,
 
   value = msOWSLookupMetadataWithLanguage(&(map->web.metadata), namespaces, "abstract", validated_language);
 
-  psNode = xmlNewChild(psRootNode, psNsOws, BAD_CAST "Abstract", BAD_CAST value);
+  psNode = xmlNewTextChild(psRootNode, psNsOws, BAD_CAST "Abstract", BAD_CAST value);
 
   if (!value) {
     xmlAddSibling(psNode, xmlNewComment(BAD_CAST "WARNING: Optional metadata \"ows_abstract\" was missing for ows:Abstract"));
@@ -100,7 +100,7 @@ xmlNodePtr msOWSCommonServiceIdentification(xmlNsPtr psNsOws, mapObj *map,
   value = msOWSLookupMetadataWithLanguage(&(map->web.metadata), namespaces, "keywordlist", validated_language);
 
   if (value) {
-    psNode = xmlNewChild(psRootNode, psNsOws, BAD_CAST "Keywords", NULL);
+    psNode = xmlNewTextChild(psRootNode, psNsOws, BAD_CAST "Keywords", NULL);
     msLibXml2GenerateList(psNode, psNsOws, "Keyword", value, ',');
   }
 
@@ -108,7 +108,7 @@ xmlNodePtr msOWSCommonServiceIdentification(xmlNsPtr psNsOws, mapObj *map,
     xmlAddSibling(psNode, xmlNewComment(BAD_CAST "WARNING: Optional metadata \"ows_keywordlist\" was missing for ows:KeywordList"));
   }
 
-  psNode = xmlNewChild(psRootNode, psNsOws, BAD_CAST "ServiceType", BAD_CAST servicetype);
+  psNode = xmlNewTextChild(psRootNode, psNsOws, BAD_CAST "ServiceType", BAD_CAST servicetype);
 
   xmlNewProp(psNode, BAD_CAST "codeSpace", BAD_CAST MS_OWSCOMMON_OGC_CODESPACE);
 
@@ -116,7 +116,7 @@ xmlNodePtr msOWSCommonServiceIdentification(xmlNsPtr psNsOws, mapObj *map,
 
   value = msOWSLookupMetadataWithLanguage(&(map->web.metadata), namespaces, "fees", validated_language);
 
-  psNode = xmlNewChild(psRootNode, psNsOws, BAD_CAST "Fees", BAD_CAST value);
+  psNode = xmlNewTextChild(psRootNode, psNsOws, BAD_CAST "Fees", BAD_CAST value);
 
   if (!value) {
     xmlAddSibling(psNode, xmlNewComment(BAD_CAST "WARNING: Optional metadata \"ows_fees\" was missing for ows:Fees"));
@@ -124,7 +124,7 @@ xmlNodePtr msOWSCommonServiceIdentification(xmlNsPtr psNsOws, mapObj *map,
 
   value = msOWSLookupMetadataWithLanguage(&(map->web.metadata), namespaces, "accessconstraints", validated_language);
 
-  psNode = xmlNewChild(psRootNode, psNsOws, BAD_CAST "AccessConstraints", BAD_CAST value);
+  psNode = xmlNewTextChild(psRootNode, psNsOws, BAD_CAST "AccessConstraints", BAD_CAST value);
 
   if (!value) {
     xmlAddSibling(psNode, xmlNewComment(BAD_CAST "WARNING: Optional metadata \"ows_accessconstraints\" was missing for ows:AccessConstraints"));
@@ -169,13 +169,13 @@ xmlNodePtr msOWSCommonServiceProvider(xmlNsPtr psNsOws, xmlNsPtr psNsXLink,
 
   value = msOWSLookupMetadataWithLanguage(&(map->web.metadata), namespaces, "contactorganization", validated_language);
 
-  psNode = xmlNewChild(psRootNode, psNsOws, BAD_CAST "ProviderName", BAD_CAST value);
+  psNode = xmlNewTextChild(psRootNode, psNsOws, BAD_CAST "ProviderName", BAD_CAST value);
 
   if (!value) {
     xmlAddSibling(psNode, xmlNewComment(BAD_CAST "WARNING: Mandatory metadata \"ows_contactorganization\" was missing for ows:ProviderName"));
   }
 
-  psNode = xmlNewChild(psRootNode, psNsOws, BAD_CAST "ProviderSite", NULL);
+  psNode = xmlNewTextChild(psRootNode, psNsOws, BAD_CAST "ProviderSite", NULL);
 
   xmlNewNsProp(psNode, psNsXLink, BAD_CAST "type", BAD_CAST "simple");
 
@@ -187,11 +187,11 @@ xmlNodePtr msOWSCommonServiceProvider(xmlNsPtr psNsOws, xmlNsPtr psNsXLink,
     xmlAddSibling(psNode, xmlNewComment(BAD_CAST "WARNING: Optional metadata \"ows_service_onlineresource\" was missing for ows:ProviderSite/@xlink:href"));
   }
 
-  psNode = xmlNewChild(psRootNode, psNsOws, BAD_CAST "ServiceContact", NULL);
+  psNode = xmlNewTextChild(psRootNode, psNsOws, BAD_CAST "ServiceContact", NULL);
 
   value = msOWSLookupMetadataWithLanguage(&(map->web.metadata), namespaces, "contactperson", validated_language);
 
-  psSubNode = xmlNewChild(psNode, psNsOws, BAD_CAST "IndividualName", BAD_CAST  value);
+  psSubNode = xmlNewTextChild(psNode, psNsOws, BAD_CAST "IndividualName", BAD_CAST  value);
 
   if (!value) {
     xmlAddSibling(psSubNode, xmlNewComment(BAD_CAST "WARNING: Optional metadata \"ows_contactperson\" was missing for ows:IndividualName"));
@@ -199,19 +199,19 @@ xmlNodePtr msOWSCommonServiceProvider(xmlNsPtr psNsOws, xmlNsPtr psNsXLink,
 
   value = msOWSLookupMetadataWithLanguage(&(map->web.metadata), namespaces, "contactposition", validated_language);
 
-  psSubNode = xmlNewChild(psNode, psNsOws, BAD_CAST "PositionName", BAD_CAST value);
+  psSubNode = xmlNewTextChild(psNode, psNsOws, BAD_CAST "PositionName", BAD_CAST value);
 
   if (!value) {
     xmlAddSibling(psSubNode, xmlNewComment(BAD_CAST "WARNING: Optional metadata \"ows_contactposition\" was missing for ows:PositionName"));
   }
 
-  psSubNode = xmlNewChild(psNode, psNsOws, BAD_CAST "ContactInfo", NULL);
+  psSubNode = xmlNewTextChild(psNode, psNsOws, BAD_CAST "ContactInfo", NULL);
 
-  psSubSubNode = xmlNewChild(psSubNode, psNsOws, BAD_CAST "Phone", NULL);
+  psSubSubNode = xmlNewTextChild(psSubNode, psNsOws, BAD_CAST "Phone", NULL);
 
   value = msOWSLookupMetadataWithLanguage(&(map->web.metadata), namespaces, "contactvoicetelephone", validated_language);
 
-  psSubSubSubNode = xmlNewChild(psSubSubNode, psNsOws, BAD_CAST "Voice", BAD_CAST value);
+  psSubSubSubNode = xmlNewTextChild(psSubSubNode, psNsOws, BAD_CAST "Voice", BAD_CAST value);
 
   if (!value) {
     xmlAddSibling(psSubSubSubNode, xmlNewComment(BAD_CAST "WARNING: Optional metadata \"ows_contactvoicetelephone\" was missing for ows:Voice"));
@@ -219,17 +219,17 @@ xmlNodePtr msOWSCommonServiceProvider(xmlNsPtr psNsOws, xmlNsPtr psNsXLink,
 
   value = msOWSLookupMetadataWithLanguage(&(map->web.metadata), namespaces, "contactfacsimiletelephone", validated_language);
 
-  psSubSubSubNode = xmlNewChild(psSubSubNode, psNsOws, BAD_CAST "Facsimile", BAD_CAST value);
+  psSubSubSubNode = xmlNewTextChild(psSubSubNode, psNsOws, BAD_CAST "Facsimile", BAD_CAST value);
 
   if (!value) {
     xmlAddSibling(psSubSubSubNode, xmlNewComment(BAD_CAST "WARNING: Optional metadata \"ows_contactfacsimiletelephone\" was missing for ows:Facsimile"));
   }
 
-  psSubSubNode = xmlNewChild(psSubNode, psNsOws, BAD_CAST "Address", NULL);
+  psSubSubNode = xmlNewTextChild(psSubNode, psNsOws, BAD_CAST "Address", NULL);
 
   value = msOWSLookupMetadataWithLanguage(&(map->web.metadata), namespaces, "address", validated_language);
 
-  psSubSubSubNode = xmlNewChild(psSubSubNode, psNsOws, BAD_CAST "DeliveryPoint", BAD_CAST value);
+  psSubSubSubNode = xmlNewTextChild(psSubSubNode, psNsOws, BAD_CAST "DeliveryPoint", BAD_CAST value);
 
   if (!value) {
     xmlAddSibling(psSubSubSubNode, xmlNewComment(BAD_CAST "WARNING: Optional metadata \"ows_address\" was missing for ows:DeliveryPoint"));
@@ -237,7 +237,7 @@ xmlNodePtr msOWSCommonServiceProvider(xmlNsPtr psNsOws, xmlNsPtr psNsXLink,
 
   value = msOWSLookupMetadataWithLanguage(&(map->web.metadata), namespaces, "city", validated_language);
 
-  psSubSubSubNode = xmlNewChild(psSubSubNode, psNsOws, BAD_CAST "City", BAD_CAST value);
+  psSubSubSubNode = xmlNewTextChild(psSubSubNode, psNsOws, BAD_CAST "City", BAD_CAST value);
 
   if (!value) {
     xmlAddSibling(psSubSubSubNode, xmlNewComment(BAD_CAST "WARNING: Optional metadata \"ows_city\" was missing for ows:City"));
@@ -245,7 +245,7 @@ xmlNodePtr msOWSCommonServiceProvider(xmlNsPtr psNsOws, xmlNsPtr psNsXLink,
 
   value = msOWSLookupMetadataWithLanguage(&(map->web.metadata), namespaces, "stateorprovince", validated_language);
 
-  psSubSubSubNode = xmlNewChild(psSubSubNode, psNsOws, BAD_CAST "AdministrativeArea", BAD_CAST value);
+  psSubSubSubNode = xmlNewTextChild(psSubSubNode, psNsOws, BAD_CAST "AdministrativeArea", BAD_CAST value);
 
   if (!value) {
     xmlAddSibling(psSubSubSubNode, xmlNewComment(BAD_CAST "WARNING: Optional metadata \"ows_stateorprovince\" was missing for ows:AdministrativeArea"));
@@ -253,7 +253,7 @@ xmlNodePtr msOWSCommonServiceProvider(xmlNsPtr psNsOws, xmlNsPtr psNsXLink,
 
   value = msOWSLookupMetadataWithLanguage(&(map->web.metadata), namespaces, "postcode", validated_language);
 
-  psSubSubSubNode = xmlNewChild(psSubSubNode, psNsOws, BAD_CAST "PostalCode", BAD_CAST value);
+  psSubSubSubNode = xmlNewTextChild(psSubSubNode, psNsOws, BAD_CAST "PostalCode", BAD_CAST value);
 
   if (!value) {
     xmlAddSibling(psSubSubSubNode, xmlNewComment(BAD_CAST "WARNING: Optional metadata \"ows_postcode\" was missing for ows:PostalCode"));
@@ -261,7 +261,7 @@ xmlNodePtr msOWSCommonServiceProvider(xmlNsPtr psNsOws, xmlNsPtr psNsXLink,
 
   value = msOWSLookupMetadataWithLanguage(&(map->web.metadata), namespaces, "country", validated_language);
 
-  psSubSubSubNode = xmlNewChild(psSubSubNode, psNsOws, BAD_CAST "Country", BAD_CAST value);
+  psSubSubSubNode = xmlNewTextChild(psSubSubNode, psNsOws, BAD_CAST "Country", BAD_CAST value);
 
   if (!value) {
     xmlAddSibling(psSubSubSubNode, xmlNewComment(BAD_CAST "WARNING: Optional metadata \"ows_country\" was missing for ows:Country"));
@@ -269,13 +269,13 @@ xmlNodePtr msOWSCommonServiceProvider(xmlNsPtr psNsOws, xmlNsPtr psNsXLink,
 
   value = msOWSLookupMetadataWithLanguage(&(map->web.metadata), namespaces, "contactelectronicmailaddress", validated_language);
 
-  psSubSubSubNode = xmlNewChild(psSubSubNode, psNsOws, BAD_CAST "ElectronicMailAddress", BAD_CAST value);
+  psSubSubSubNode = xmlNewTextChild(psSubSubNode, psNsOws, BAD_CAST "ElectronicMailAddress", BAD_CAST value);
 
   if (!value) {
     xmlAddSibling(psSubSubSubNode, xmlNewComment(BAD_CAST "WARNING: Optional metadata \"ows_contactelectronicmailaddress\" was missing for ows:ElectronicMailAddress"));
   }
 
-  psSubSubNode = xmlNewChild(psSubNode, psNsOws, BAD_CAST "OnlineResource", NULL);
+  psSubSubNode = xmlNewTextChild(psSubNode, psNsOws, BAD_CAST "OnlineResource", NULL);
 
   xmlNewNsProp(psSubSubNode, psNsXLink, BAD_CAST "type", BAD_CAST "simple");
 
@@ -289,7 +289,7 @@ xmlNodePtr msOWSCommonServiceProvider(xmlNsPtr psNsOws, xmlNsPtr psNsXLink,
 
   value = msOWSLookupMetadataWithLanguage(&(map->web.metadata), namespaces, "hoursofservice", validated_language);
 
-  psSubSubNode = xmlNewChild(psSubNode, psNsOws, BAD_CAST "HoursOfService", BAD_CAST value);
+  psSubSubNode = xmlNewTextChild(psSubNode, psNsOws, BAD_CAST "HoursOfService", BAD_CAST value);
 
   if (!value) {
     xmlAddSibling(psSubSubNode, xmlNewComment(BAD_CAST "WARNING: Optional metadata \"ows_hoursofservice\" was missing for ows:HoursOfService"));
@@ -297,7 +297,7 @@ xmlNodePtr msOWSCommonServiceProvider(xmlNsPtr psNsOws, xmlNsPtr psNsXLink,
 
   value = msOWSLookupMetadataWithLanguage(&(map->web.metadata), namespaces, "contactinstructions", validated_language);
 
-  psSubSubNode = xmlNewChild(psSubNode, psNsOws, BAD_CAST "ContactInstructions", BAD_CAST value);
+  psSubSubNode = xmlNewTextChild(psSubNode, psNsOws, BAD_CAST "ContactInstructions", BAD_CAST value);
 
   if (!value) {
     xmlAddSibling(psSubSubNode, xmlNewComment(BAD_CAST "WARNING: Optional metadata \"ows_contactinstructions\" was missing for ows:ContactInstructions"));
@@ -305,7 +305,7 @@ xmlNodePtr msOWSCommonServiceProvider(xmlNsPtr psNsOws, xmlNsPtr psNsXLink,
 
   value = msOWSLookupMetadataWithLanguage(&(map->web.metadata), namespaces, "role", validated_language);
 
-  psSubNode = xmlNewChild(psNode, psNsOws, BAD_CAST "Role", BAD_CAST value);
+  psSubNode = xmlNewTextChild(psNode, psNsOws, BAD_CAST "Role", BAD_CAST value);
 
   if (!value) {
     xmlAddSibling(psSubNode, xmlNewComment(BAD_CAST "WARNING: Optional metadata \"ows_role\" was missing for ows:Role"));
@@ -489,9 +489,7 @@ xmlNodePtr msOWSCommonExceptionReport(xmlNsPtr psNsOws, int ows_version, const c
   }
 
   if (ExceptionText != NULL) {
-    char* errorMessage = msEncodeHTMLEntities(ExceptionText);
-    xmlNewChild(psMainNode, NULL, BAD_CAST "ExceptionText", BAD_CAST errorMessage);
-    msFree(errorMessage);
+    xmlNewTextChild(psMainNode, NULL, BAD_CAST "ExceptionText", BAD_CAST ExceptionText);
   }
 
   free(xsi_schemaLocation);
diff --git a/mappostgis.c b/mappostgis.c
index 650ade0..2bddf9a 100644
--- a/mappostgis.c
+++ b/mappostgis.c
@@ -766,57 +766,13 @@ int
 arcCircleCenter(const pointObj *p1, const pointObj *p2, const pointObj *p3, pointObj *center, double *radius)
 {
   pointObj c;
-  double r;
-
-  /* Components of the matrices. */
-  double x1sq = p1->x * p1->x;
-  double x2sq = p2->x * p2->x;
-  double x3sq = p3->x * p3->x;
-  double y1sq = p1->y * p1->y;
-  double y2sq = p2->y * p2->y;
-  double y3sq = p3->y * p3->y;
-  double matrix_num_x[9];
-  double matrix_num_y[9];
-  double matrix_denom[9];
-
-  /* Intialize matrix_num_x */
-  matrix_num_x[0] = x1sq+y1sq;
-  matrix_num_x[1] = p1->y;
-  matrix_num_x[2] = 1.0;
-  matrix_num_x[3] = x2sq+y2sq;
-  matrix_num_x[4] = p2->y;
-  matrix_num_x[5] = 1.0;
-  matrix_num_x[6] = x3sq+y3sq;
-  matrix_num_x[7] = p3->y;
-  matrix_num_x[8] = 1.0;
-
-  /* Intialize matrix_num_y */
-  matrix_num_y[0] = p1->x;
-  matrix_num_y[1] = x1sq+y1sq;
-  matrix_num_y[2] = 1.0;
-  matrix_num_y[3] = p2->x;
-  matrix_num_y[4] = x2sq+y2sq;
-  matrix_num_y[5] = 1.0;
-  matrix_num_y[6] = p3->x;
-  matrix_num_y[7] = x3sq+y3sq;
-  matrix_num_y[8] = 1.0;
-
-  /* Intialize matrix_denom */
-  matrix_denom[0] = p1->x;
-  matrix_denom[1] = p1->y;
-  matrix_denom[2] = 1.0;
-  matrix_denom[3] = p2->x;
-  matrix_denom[4] = p2->y;
-  matrix_denom[5] = 1.0;
-  matrix_denom[6] = p3->x;
-  matrix_denom[7] = p3->y;
-  matrix_denom[8] = 1.0;
+  double dx21, dy21, dx31, dy31, h21, h31, d, r;
 
   /* Circle is closed, so p2 must be opposite p1 & p3. */
-  if ( FP_EQ(p1->x,p3->x) && FP_EQ(p1->y,p3->y) ) {
-    c.x = (p1->x + p2->x) / 2.0;
-    c.y = (p1->y + p2->y) / 2.0;
-    r = sqrt( (p1->x - p2->x) * (p1->x - p2->x) + (p1->y - p2->y) * (p1->y - p2->y) ) / 2.0;
+  if ((fabs(p1->x - p3->x) < FP_EPSILON) && (fabs(p1->y-p3->y) < FP_EPSILON)) {
+    c.x = p1->x + (p2->x - p1->x) / 2.0;
+    c.y = p1->y + (p2->y - p1->y) / 2.0;
+    r = sqrt(pow(c.x - p1->x, 2.0) + pow(c.y - p1->y, 2.0));
   }
   /* There is no circle here, the points are actually co-linear */
   else if ( arcSegmentSide(p1, p3, p2) == FP_COLINEAR ) {
@@ -824,13 +780,22 @@ arcCircleCenter(const pointObj *p1, const pointObj *p2, const pointObj *p3, poin
   }
   /* Calculate the center and radius. */
   else {
-    double denom = 2.0 * arcDeterminant3x3(matrix_denom);
-    /* Center components */
-    c.x = arcDeterminant3x3(matrix_num_x) / denom;
-    c.y = arcDeterminant3x3(matrix_num_y) / denom;
 
     /* Radius */
-    r = sqrt((p1->x-c.x) * (p1->x-c.x) + (p1->y-c.y) * (p1->y-c.y));
+    dx21 = p2->x - p1->x;
+    dy21 = p2->y - p1->y;
+    dx31 = p3->x - p1->x;
+    dy31 = p3->y - p1->y;
+
+    h21 = pow(dx21, 2.0) + pow(dy21, 2.0);
+    h31 = pow(dx31, 2.0) + pow(dy31, 2.0);
+
+    /* 2 * |Cross product|, d<0 means clockwise and d>0 counterclockwise sweeping angle */
+    d = 2 * (dx21 * dy31 - dx31 * dy21);
+
+    c.x = p1->x + (h21 * dy31 - h31 * dy21) / d;
+    c.y = p1->y - (h21 * dx31 - h31 * dx21) / d;
+    r = sqrt(pow(c.x - p1->x, 2) + pow(c.y - p1->y, 2));
   }
 
   if ( radius ) *radius = r;
@@ -1394,7 +1359,7 @@ int msPostGISParseData(layerObj *layer)
   } else {
     slength = strspn(pos_srid + 12, "-0123456789");
     if (!slength) {
-      msSetError(MS_QUERYERR, "Error parsing PostGIS DATA variable. You specified 'USING SRID' but didnt have any numbers! %s", "msPostGISParseData()", data);
+      msSetError(MS_QUERYERR, "Error parsing PostGIS DATA variable. You specified 'USING SRID' but didn't have any numbers! %s", "msPostGISParseData()", data);
       return MS_FAILURE;
     } else {
       layerinfo->srid = (char*) msSmallMalloc(slength + 1);
@@ -3785,6 +3750,7 @@ int msPostGISLayerTranslateFilter(layerObj *layer, expressionObj *filter, char *
         default:
           /* by default accept the general token to string conversion */
 
+          if(node->token == MS_TOKEN_COMPARISON_EQ && node->next != NULL && node->next->token == MS_TOKEN_LITERAL_TIME) break; /* skip, handled with the next token */
           if(bindingToken == MS_TOKEN_BINDING_TIME && (node->token == MS_TOKEN_COMPARISON_EQ || node->token == MS_TOKEN_COMPARISON_NE)) break; /* skip, handled elsewhere */
 
           native_string = msStringConcatenate(native_string, msExpressionTokenToString(node->token));
diff --git a/mapprimitive.c b/mapprimitive.c
index 3d488d8..c7cd982 100644
--- a/mapprimitive.c
+++ b/mapprimitive.c
@@ -283,7 +283,17 @@ int *msGetInnerList(shapeObj *shape, int r, int *outerlist)
       continue;
     }
 
-    list[i] = msPointInPolygon(&(shape->line[i].point[0]), &(shape->line[r]));
+    /* A valid inner ring may touch its outer ring at most one point. */
+    /* In the case the first point matches a vertex of an outer ring, */
+    /* msPointInPolygon() might return 0 or 1 (depending on coordinate values, */
+    /* see msGetOuterList()), so test a second point if the first test */
+    /* returned that the point is not inside the outer ring. */
+    /* Fixes #5299 */
+    /* Of course all of this assumes that the geometries are indeed valid in */
+    /* OGC terms, otherwise all logic of msIsOuterRing(), msGetOuterList(), */
+    /* and msGetInnerList() has undefined behaviour. */
+    list[i] = msPointInPolygon(&(shape->line[i].point[0]), &(shape->line[r])) ||
+              msPointInPolygon(&(shape->line[i].point[1]), &(shape->line[r]));
   }
 
   return(list);
diff --git a/mapquery.c b/mapquery.c
index 184b83b..a94ccb1 100644
--- a/mapquery.c
+++ b/mapquery.c
@@ -762,10 +762,9 @@ int msQueryByFilter(mapObj *map)
 
     search_rect = map->query.rect;
 #ifdef USE_PROJ
-    if(lp->project && msProjectionsDiffer(&(lp->projection), &(map->projection))) {
+    lp->project = msProjectionsDiffer(&(lp->projection), &(map->projection));
+    if(lp->project)
       msProjectRect(&(map->projection), &(lp->projection), &search_rect); /* project the searchrect to source coords */
-    } else
-      lp->project = MS_FALSE;
 #endif
 
     status = msLayerWhichShapes(lp, search_rect, MS_TRUE);
@@ -809,10 +808,8 @@ int msQueryByFilter(mapObj *map)
       }
 
 #ifdef USE_PROJ
-      if(lp->project && msProjectionsDiffer(&(lp->projection), &(map->projection)))
+      if(lp->project)
         msProjectShape(&(lp->projection), &(map->projection), &shape);
-      else
-        lp->project = MS_FALSE;
 #endif
 
       /* Should we skip this feature? */
@@ -979,10 +976,9 @@ int msQueryByRect(mapObj *map)
     }
 
 #ifdef USE_PROJ
-    if(lp->project && msProjectionsDiffer(&(lp->projection), &(map->projection)))
+    lp->project = msProjectionsDiffer(&(lp->projection), &(map->projection));
+    if(lp->project)
       msProjectRect(&(map->projection), &(lp->projection), &searchrect); /* project the searchrect to source coords */
-    else
-      lp->project = MS_FALSE;
 #endif
 
     status = msLayerWhichShapes(lp, searchrect, MS_TRUE);
@@ -1031,10 +1027,8 @@ int msQueryByRect(mapObj *map)
       }
 
 #ifdef USE_PROJ
-      if(lp->project && msProjectionsDiffer(&(lp->projection), &(map->projection)))
+      if(lp->project)
         msProjectShape(&(lp->projection), &(map->projection), &shape);
-      else
-        lp->project = MS_FALSE;
 #endif
 
       if(msRectContained(&shape.bounds, &searchrectInMapProj) == MS_TRUE) { /* if the whole shape is in, don't intersect */
@@ -1142,7 +1136,7 @@ int msQueryByFeatures(mapObj *map)
 
   /* conditions may have changed since this layer last drawn, so set
      layer->project true to recheck projection needs (Bug #673) */
-  slp->project = MS_TRUE;
+  slp->project = msProjectionsDiffer(&(slp->projection), &(map->projection));
 
   if(map->query.layer < 0 || map->query.layer >= map->numlayers)
     start = map->numlayers-1;
@@ -1171,7 +1165,7 @@ int msQueryByFeatures(mapObj *map)
 
     /* conditions may have changed since this layer last drawn, so set
        layer->project true to recheck projection needs (Bug #673) */
-    lp->project = MS_TRUE;
+    lp->project = msProjectionsDiffer(&(lp->projection), &(map->projection));
 
     /* free any previous search results, do it now in case one of the next few tests fail */
     if(lp->resultcache) {
@@ -1234,11 +1228,8 @@ int msQueryByFeatures(mapObj *map)
       }
 
 #ifdef USE_PROJ
-      if(slp->project && msProjectionsDiffer(&(slp->projection), &(map->projection))) {
+      if(slp->project)
         msProjectShape(&(slp->projection), &(map->projection), &selectshape);
-        msComputeBounds(&selectshape); /* recompute the bounding box AFTER projection */
-      } else
-        slp->project = MS_FALSE;
 #endif
 
       /* identify target shapes */
@@ -1250,10 +1241,8 @@ int msQueryByFeatures(mapObj *map)
       searchrect.maxy += tolerance;
 
 #ifdef USE_PROJ
-      if(lp->project && msProjectionsDiffer(&(lp->projection), &(map->projection)))
+      if(lp->project)
         msProjectRect(&(map->projection), &(lp->projection), &searchrect); /* project the searchrect to source coords */
-      else
-        lp->project = MS_FALSE;
 #endif
 
       status = msLayerWhichShapes(lp, searchrect, MS_TRUE);
@@ -1309,10 +1298,8 @@ int msQueryByFeatures(mapObj *map)
         }
 
 #ifdef USE_PROJ
-        if(lp->project && msProjectionsDiffer(&(lp->projection), &(map->projection)))
+        if(lp->project)
           msProjectShape(&(lp->projection), &(map->projection), &shape);
-        else
-          lp->project = MS_FALSE;
 #endif
 
         switch(selectshape.type) { /* may eventually support types other than polygon on line */
@@ -1545,10 +1532,9 @@ int msQueryByPoint(mapObj *map)
     /* identify target shapes */
     searchrect = rect;
 #ifdef USE_PROJ
-    if(lp->project && msProjectionsDiffer(&(lp->projection), &(map->projection)))
+    lp->project = msProjectionsDiffer(&(lp->projection), &(map->projection));
+    if(lp->project)
       msProjectRect(&(map->projection), &(lp->projection), &searchrect); /* project the searchrect to source coords */
-    else
-      lp->project = MS_FALSE;
 #endif
     status = msLayerWhichShapes(lp, searchrect, MS_TRUE);
     if(status == MS_DONE) { /* no overlap */
@@ -1595,10 +1581,8 @@ int msQueryByPoint(mapObj *map)
       }
 
 #ifdef USE_PROJ
-      if(lp->project && msProjectionsDiffer(&(lp->projection), &(map->projection)))
+      if(lp->project)
         msProjectShape(&(lp->projection), &(map->projection), &shape);
-      else
-        lp->project = MS_FALSE;
 #endif
 
       d = msDistancePointToShape(&(map->query.point), &shape);
@@ -1767,10 +1751,9 @@ int msQueryByShape(mapObj *map)
     searchrect.maxy += tolerance;
 
 #ifdef USE_PROJ
-    if(lp->project && msProjectionsDiffer(&(lp->projection), &(map->projection)))
+    lp->project = msProjectionsDiffer(&(lp->projection), &(map->projection));
+    if(lp->project)
       msProjectRect(&(map->projection), &(lp->projection), &searchrect); /* project the searchrect to source coords */
-    else
-      lp->project = MS_FALSE;
 #endif
 
     status = msLayerWhichShapes(lp, searchrect, MS_TRUE);
@@ -1817,10 +1800,8 @@ int msQueryByShape(mapObj *map)
       }
 
 #ifdef USE_PROJ
-      if(lp->project && msProjectionsDiffer(&(lp->projection), &(map->projection)))
+      if(lp->project)
         msProjectShape(&(lp->projection), &(map->projection), &shape);
-      else
-        lp->project = MS_FALSE;
 #endif
 
       switch(qshape->type) { /* may eventually support types other than polygon or line */
diff --git a/mapraster.c b/mapraster.c
index 740b9af..e8ac0f9 100644
--- a/mapraster.c
+++ b/mapraster.c
@@ -691,8 +691,10 @@ int msDrawRasterLayerLow(mapObj *map, layerObj *layer, imageObj *image,
       msAcquireLock( TLOCK_GDAL );
       hDS = GDALOpenShared( decrypted_path, GA_ReadOnly );
     } else {
+      msAcquireLock( TLOCK_GDAL );
       status = msComputeKernelDensityDataset(map, image, layer, &hDS, &kernel_density_cleanup_ptr);
       if(status != MS_SUCCESS) {
+        msReleaseLock( TLOCK_GDAL );
         final_status = status;
         goto cleanup;
       }
@@ -702,6 +704,8 @@ int msDrawRasterLayerLow(mapObj *map, layerObj *layer, imageObj *image,
 
         /* Set the projection to the map file projection */
         if (msLoadProjectionString(&(layer->projection), mapProjStr) != 0) {
+          GDALClose( hDS );
+          msReleaseLock( TLOCK_GDAL );
           msSetError(MS_CGIERR, "Unable to set projection on interpolation layer.", "msDrawRasterLayerLow()");
           return(MS_FAILURE);
         }
@@ -745,6 +749,7 @@ int msDrawRasterLayerLow(mapObj *map, layerObj *layer, imageObj *image,
 
     if( msDrawRasterLoadProjection(layer, hDS, filename, tilesrsindex, tilesrsname) != MS_SUCCESS )
     {
+        GDALClose( hDS );
         msReleaseLock( TLOCK_GDAL );
         final_status = MS_FAILURE;
         break;
@@ -792,18 +797,31 @@ int msDrawRasterLayerLow(mapObj *map, layerObj *layer, imageObj *image,
     ** default to keeping open for single data files, and
     ** to closing for tile indexes
     */
-
-    close_connection = msLayerGetProcessingKey( layer,
+    if(layer->connectiontype == MS_KERNELDENSITY) {
+      /*
+      ** Fix issue #5330
+      ** The in-memory kernel density heatmap gdal dataset handle (hDS) gets re-used
+      ** but the associated rasterband cache doesn't get flushed, which causes old data
+      ** to be rendered instead of the newly generated imagery. To fix, simply close the
+      ** the handle and prevent further re-use.
+      ** Note that instead of this workaround, we could explicitely set 
+      ** CLOSE_CONNECTION=ALWAYS on the kerneldensity layer.
+      */
+      GDALClose( hDS );
+    }
+    else {
+      close_connection = msLayerGetProcessingKey( layer,
                        "CLOSE_CONNECTION" );
 
-    if( close_connection == NULL && layer->tileindex == NULL )
-      close_connection = "DEFER";
+      if( close_connection == NULL && layer->tileindex == NULL )
+        close_connection = "DEFER";
 
-    if( close_connection != NULL
-        && strcasecmp(close_connection,"DEFER") == 0 ) {
-      GDALDereferenceDataset( hDS );
-    } else {
-      GDALClose( hDS );
+      if( close_connection != NULL
+          && strcasecmp(close_connection,"DEFER") == 0 ) {
+        GDALDereferenceDataset( hDS );
+      } else {
+        GDALClose( hDS );
+      }
     }
     msReleaseLock( TLOCK_GDAL );
   } /* next tile */
diff --git a/maprasterquery.c b/maprasterquery.c
index 06f0ece..b6556be 100644
--- a/maprasterquery.c
+++ b/maprasterquery.c
@@ -416,7 +416,6 @@ msRasterQueryByRectLow(mapObj *map, layerObj *layer, GDALDatasetH hDS,
   CPLErr      eErr;
   rasterLayerInfo *rlinfo;
   rectObj     searchrect;
-  int         needReproject = MS_FALSE;
 
   rlinfo = (rasterLayerInfo *) layer->layerinfo;
 
@@ -426,12 +425,9 @@ msRasterQueryByRectLow(mapObj *map, layerObj *layer, GDALDatasetH hDS,
   /* -------------------------------------------------------------------- */
   searchrect = queryRect;
 #ifdef USE_PROJ
-  if(layer->project
-      && msProjectionsDiffer(&(layer->projection), &(map->projection))) {
+  layer->project = msProjectionsDiffer(&(layer->projection), &(map->projection));
+  if(layer->project)
     msProjectRect(&(map->projection), &(layer->projection), &searchrect);
-    needReproject = MS_TRUE;
-  } else
-    layer->project = MS_FALSE;
 #endif
 
   /* -------------------------------------------------------------------- */
@@ -582,7 +578,7 @@ msRasterQueryByRectLow(mapObj *map, layerObj *layer, GDALDatasetH hDS,
       /* in sPixelLocationInLayerSRS, so that we can return those */
       /* coordinates if we have a hit */
       sReprojectedPixelLocation = sPixelLocation;
-      if( needReproject )
+      if( layer->project )
         msProjectPoint( &(layer->projection), &(map->projection),
                         &sReprojectedPixelLocation);
 
diff --git a/mapscript/csharp/CMakeLists.txt b/mapscript/csharp/CMakeLists.txt
index 27a28b9..722ff86 100644
--- a/mapscript/csharp/CMakeLists.txt
+++ b/mapscript/csharp/CMakeLists.txt
@@ -21,6 +21,10 @@ if (WIN32)
   if (MSVC_VERSION GREATER 1500)
       set(PLATFORM_TARGET ${PLATFORM_TARGET} /define:CLR4)
   endif (MSVC_VERSION GREATER 1500)
+  MESSAGE(STATUS "Cmake build type: ${CMAKE_BUILD_TYPE}")
+  if (CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo") 
+      set(PLATFORM_TARGET ${PLATFORM_TARGET} /debug:full)
+  endif (CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo")
 endif(WIN32)
 
 MARK_AS_ADVANCED(CSHARP_COMPILER)
@@ -50,7 +54,9 @@ ADD_CUSTOM_COMMAND(TARGET csharpmapscript
 					  COMMAND ${CSHARP_COMPILER} ${PLATFORM_TARGET} /r:mapscript_csharp.dll /out:HTMLtemplate.exe ${PROJECT_SOURCE_DIR}\\mapscript\\csharp\\examples\\HTMLtemplate.cs
 					  COMMAND ${CSHARP_COMPILER} ${PLATFORM_TARGET} /r:mapscript_csharp.dll /out:RFC24.exe ${PROJECT_SOURCE_DIR}\\mapscript\\csharp\\examples\\RFC24.cs
 					  COMMAND ${CSHARP_COMPILER} ${PLATFORM_TARGET} /r:mapscript_csharp.dll /r:System.Drawing.dll /out:drawmapDirect.exe ${PROJECT_SOURCE_DIR}\\mapscript\\csharp\\examples\\drawmapDirect.cs
-					  COMMAND ${CSHARP_COMPILER} ${PLATFORM_TARGET} /r:mapscript_csharp.dll /r:System.Drawing.dll /out:drawmapDirectPrint.exe ${PROJECT_SOURCE_DIR}\\mapscript\\csharp\\examples\\drawmapDirectPrint.cs	
+					  COMMAND ${CSHARP_COMPILER} ${PLATFORM_TARGET} /r:mapscript_csharp.dll /r:System.Drawing.dll /out:drawmapDirectPrint.exe ${PROJECT_SOURCE_DIR}\\mapscript\\csharp\\examples\\drawmapDirectPrint.cs
+                      COMMAND ${CSHARP_COMPILER} ${PLATFORM_TARGET} /r:mapscript_csharp.dll /r:System.Drawing.dll /out:drawmapGDIPlus.exe ${PROJECT_SOURCE_DIR}\\mapscript\\csharp\\examples\\drawmapGDIPlus.cs
+					  #COMMAND ${CSHARP_COMPILER} ${PLATFORM_TARGET} /lib:C:\Windows\Microsoft.NET\Framework\v4.0.30319\WPF /r:mapscript_csharp.dll /r:System.Xaml.dll /r:WindowsBase.dll /r:PresentationCore.dll /out:drawmapWPF.exe ${PROJECT_SOURCE_DIR}\\mapscript\\csharp\\examples\\drawmapWPF.cs
                       COMMENT "Compiling c# source files"
                       )
 
diff --git a/mapscript/csharp/Makefile.vc b/mapscript/csharp/Makefile.vc
index 9fdc747..2297b88 100755
--- a/mapscript/csharp/Makefile.vc
+++ b/mapscript/csharp/Makefile.vc
@@ -95,7 +95,8 @@ $(CSHARP_DLL)::
 	$(CSC) $(CSFLAGS) /r:mapscript_csharp.dll /out:HTMLtemplate.exe examples\HTMLtemplate.cs
 	$(CSC) $(CSFLAGS) /r:mapscript_csharp.dll /out:RFC24.exe examples\RFC24.cs
 	$(CSC) $(CSFLAGS) /r:mapscript_csharp.dll /r:System.Drawing.dll /out:drawmapDirect.exe examples\drawmapDirect.cs
-	$(CSC) $(CSFLAGS) /r:mapscript_csharp.dll /r:System.Drawing.dll /out:drawmapDirectPrint.exe examples\drawmapDirectPrint.cs	
+	$(CSC) $(CSFLAGS) /r:mapscript_csharp.dll /r:System.Drawing.dll /out:drawmapDirectPrint.exe examples\drawmapDirectPrint.cs
+	$(CSC) $(CSFLAGS) /r:mapscript_csharp.dll /r:System.Drawing.dll /out:drawmapGDIPlus.exe examples\drawmapGDIPlus.cs
 
 test:
 !IFDEF MONO
diff --git a/mapscript/csharp/csmodule.i b/mapscript/csharp/csmodule.i
index 3bf2650..f680d2e 100644
--- a/mapscript/csharp/csmodule.i
+++ b/mapscript/csharp/csmodule.i
@@ -241,6 +241,11 @@ static SWIG_CSharpByteArrayHelperCallback SWIG_csharp_bytearray_callback = NULL;
 %typemap(in) SWIG_CSharpByteArrayHelperCallback %{ $1 = ($1_ltype)$input; %}
 %typemap(csin) SWIG_CSharpByteArrayHelperCallback "$csinput"
 
+%typemap(imtype) (unsigned char* pixels) "IntPtr"
+%typemap(cstype) (unsigned char* pixels) "IntPtr"
+%typemap(in) (unsigned char* pixels) %{ $1 = ($1_ltype)$input; %}
+%typemap(csin) (unsigned char* pixels) "$csinput"
+
 %csmethodmodifiers getBytes "private";
 %ignore imageObj::getBytes();
 %extend imageObj 
@@ -259,7 +264,26 @@ static SWIG_CSharpByteArrayHelperCallback SWIG_csharp_bytearray_callback = NULL;
         }
         callback(buffer.data, buffer.size);
         msFree(buffer.data);
-	}
+    }
+
+    int getRawPixels(unsigned char* pixels) {
+      if (MS_RENDERER_PLUGIN(self->format)) {
+        rendererVTableObj *renderer = self->format->vtable;
+        if(renderer->supports_pixel_buffer) {
+          rasterBufferObj rb;
+          int status = MS_SUCCESS;
+          int size = self->width * self->height * 4 * sizeof(unsigned char);
+          
+          status = renderer->getRasterBufferHandle(self,&rb);
+          if(UNLIKELY(status == MS_FAILURE)) {
+            return MS_FAILURE;
+          }
+          memcpy(pixels, rb.data.rgba.pixels, size);
+          return status;
+        }
+      }
+      return MS_FAILURE;
+    }
 }
 
 %ignore imageObj::write;
diff --git a/mapscript/csharp/examples/drawmapGDIPlus.cs b/mapscript/csharp/examples/drawmapGDIPlus.cs
new file mode 100644
index 0000000..c08ccd2
--- /dev/null
+++ b/mapscript/csharp/examples/drawmapGDIPlus.cs
@@ -0,0 +1,97 @@
+/******************************************************************************
+ * $Id$
+ *
+ * Project:  MapServer
+ * Purpose:  A C# based mapscript example to draw the map directly onto a GDI+ bitmap.
+ * Author:   Tamas Szekeres, szekerest at gmail.com
+ *
+ ******************************************************************************
+ * Copyright (c) 1996-2008 Regents of the University of Minnesota.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in 
+ * all copies of this Software or works derived from this Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *****************************************************************************/
+
+using System;
+using System.Diagnostics;
+using System.Drawing;
+using System.Drawing.Imaging;
+using OSGeo.MapServer;	
+
+/// <summary>
+/// A C# based mapscript example to draw the map directly onto a GDI+ bitmap.
+/// </summary>
+class DrawMap
+{
+  public static void usage() 
+  { 
+	Console.WriteLine("usage: DrawMapGDIPlus {mapfile} {outfile}");
+	System.Environment.Exit(-1);
+  }
+		  
+  public static void Main(string[] args)
+  {
+    Console.WriteLine("");
+	if (args.Length < 2) usage();
+    
+	mapObj map = new mapObj(args[0]);
+
+    Console.WriteLine("# Map layers " + map.numlayers + "; Map name = " + map.name);
+    for (int i = 0; i < map.numlayers; i++) 
+	{
+        Console.WriteLine("Layer [" + i + "] name: " + map.getLayer(i).name);
+	}
+
+    try
+    {
+        Bitmap mapImage = new Bitmap(map.width, map.height, PixelFormat.Format32bppRgb);
+        Stopwatch stopwatch = new Stopwatch();
+        stopwatch.Start();
+        using (imageObj image = map.draw())
+        {
+            BitmapData bitmapData = mapImage.LockBits(new Rectangle(0, 0, image.width, image.height), ImageLockMode.ReadWrite, PixelFormat.Format32bppRgb);
+            try
+            {
+                if (image.getRawPixels(bitmapData.Scan0) == (int)MS_RETURN_VALUE.MS_FAILURE)
+                {
+                    Console.WriteLine("Unable to get image contents");
+                }
+            }
+            finally
+            {
+                mapImage.UnlockBits(bitmapData);
+            }
+
+            Console.WriteLine("Rendering time: " + stopwatch.ElapsedMilliseconds + "ms");
+
+            mapImage.Save(args[1]);
+        }    
+    } 
+	catch (Exception ex) 
+	{
+        Console.WriteLine( "\nMessage ---\n{0}", ex.Message );
+        Console.WriteLine( 
+            "\nHelpLink ---\n{0}", ex.HelpLink );
+        Console.WriteLine( "\nSource ---\n{0}", ex.Source );
+        Console.WriteLine( 
+            "\nStackTrace ---\n{0}", ex.StackTrace );
+        Console.WriteLine( 
+            "\nTargetSite ---\n{0}", ex.TargetSite );	}	
+  }
+}
+
diff --git a/mapscript/csharp/examples/drawmapWPF.cs b/mapscript/csharp/examples/drawmapWPF.cs
new file mode 100644
index 0000000..2e6e833
--- /dev/null
+++ b/mapscript/csharp/examples/drawmapWPF.cs
@@ -0,0 +1,109 @@
+/******************************************************************************
+ * $Id$
+ *
+ * Project:  MapServer
+ * Purpose:  A C# based mapscript example to draw the map directly onto a WPF image.
+ * Author:   Tamas Szekeres, szekerest at gmail.com
+ *
+ ******************************************************************************
+ * Copyright (c) 1996-2008 Regents of the University of Minnesota.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in 
+ * all copies of this Software or works derived from this Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *****************************************************************************/
+
+using System;
+using System.IO;
+using System.Diagnostics;
+using System.Windows;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using OSGeo.MapServer;	
+
+/// <summary>
+/// A C# based mapscript example to draw the map directly onto a WPF image.
+/// </summary>
+class DrawMap
+{
+  public static void usage() 
+  { 
+	Console.WriteLine("usage: DrawMapWPF {mapfile} {outfile}");
+	System.Environment.Exit(-1);
+  }
+		  
+  public static void Main(string[] args)
+  {
+    Console.WriteLine("");
+	if (args.Length < 2) usage();
+    
+	mapObj map = new mapObj(args[0]);
+
+    Console.WriteLine("# Map layers " + map.numlayers + "; Map name = " + map.name);
+    for (int i = 0; i < map.numlayers; i++) 
+	{
+        Console.WriteLine("Layer [" + i + "] name: " + map.getLayer(i).name);
+	}
+
+    try
+    {
+        WriteableBitmap mapImage = new WriteableBitmap(map.width, map.height, 96, 96, PixelFormats.Bgr32, null);
+        Stopwatch stopwatch = new Stopwatch();
+        stopwatch.Start();
+        using (imageObj image = map.draw())
+        {
+            // Reserve the back buffer for updates.
+            mapImage.Lock();
+            try
+            {
+                if (image.getRawPixels(mapImage.BackBuffer) == (int)MS_RETURN_VALUE.MS_FAILURE)
+                {
+                    Console.WriteLine("Unable to get image contents");
+                }
+                // Specify the area of the bitmap that changed.
+                mapImage.AddDirtyRect(new Int32Rect(0, 0, map.width, map.height));
+            }
+            finally
+            {
+                // Release the back buffer and make it available for display.
+                mapImage.Unlock();
+            }
+
+            Console.WriteLine("Rendering time: " + stopwatch.ElapsedMilliseconds + "ms");
+
+            // Save the bitmap into a file.
+            using (FileStream stream = new FileStream(args[1], FileMode.Create))
+            {
+                PngBitmapEncoder encoder = new PngBitmapEncoder();
+                encoder.Frames.Add(BitmapFrame.Create(mapImage));
+                encoder.Save(stream);
+            }
+        }    
+    } 
+	catch (Exception ex) 
+	{
+        Console.WriteLine( "\nMessage ---\n{0}", ex.Message );
+        Console.WriteLine( 
+            "\nHelpLink ---\n{0}", ex.HelpLink );
+        Console.WriteLine( "\nSource ---\n{0}", ex.Source );
+        Console.WriteLine( 
+            "\nStackTrace ---\n{0}", ex.StackTrace );
+        Console.WriteLine( 
+            "\nTargetSite ---\n{0}", ex.TargetSite );	}	
+  }
+}
+
diff --git a/mapscript/csharp/swig_csharp_extensions.i b/mapscript/csharp/swig_csharp_extensions.i
index 07b8b8d..75f4399 100644
--- a/mapscript/csharp/swig_csharp_extensions.i
+++ b/mapscript/csharp/swig_csharp_extensions.i
@@ -33,8 +33,58 @@
 %pragma(csharp) imclasscode=%{
   static $imclassname() {
   }
+
+  public class UTF8Marshaler : ICustomMarshaler {
+    static UTF8Marshaler static_instance;
+
+    public IntPtr MarshalManagedToNative(object managedObj) {
+        if (managedObj == null)
+            return IntPtr.Zero;
+        if (!(managedObj is string))
+            throw new MarshalDirectiveException(
+                   "UTF8Marshaler must be used on a string.");
+
+        // not null terminated
+        byte[] strbuf = System.Text.Encoding.UTF8.GetBytes((string)managedObj); 
+        IntPtr buffer = Marshal.AllocHGlobal(strbuf.Length + 1);
+        Marshal.Copy(strbuf, 0, buffer, strbuf.Length);
+
+        // write the terminating null
+        Marshal.WriteByte(buffer, strbuf.Length, 0); 
+        return buffer;
+    }
+
+    public object MarshalNativeToManaged(IntPtr pNativeData) {	
+	    int len = Marshal.PtrToStringAnsi(pNativeData).Length;
+        byte[] utf8data = new byte[len];
+        Marshal.Copy(pNativeData, utf8data, 0, len);
+        return System.Text.Encoding.UTF8.GetString(utf8data);
+    }
+
+    public void CleanUpNativeData(IntPtr pNativeData) {
+        Marshal.FreeHGlobal(pNativeData);            
+    }
+
+    public void CleanUpManagedData(object managedObj) {
+    }
+
+    public int GetNativeDataSize() {
+        return -1;
+    }
+
+    public static ICustomMarshaler GetInstance(string cookie) {
+        if (static_instance == null) {
+            return static_instance = new UTF8Marshaler();
+        }
+        return static_instance;
+    }
+  }
 %}
 
+%typemap(imtype, inattributes="[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]", 
+  outattributes="[return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]") 
+  char *, char *&, char[ANY], char[]   "string"
+
 %typemap(csout, excode=SWIGEXCODE) SWIGTYPE {
     /* %typemap(csout, excode=SWIGEXCODE) SWIGTYPE */
     $&csclassname ret = new $&csclassname($imcall, true, null);$excode
diff --git a/mapscript/php/layer.c b/mapscript/php/layer.c
index 0b4a743..8567bc8 100644
--- a/mapscript/php/layer.c
+++ b/mapscript/php/layer.c
@@ -271,32 +271,33 @@ PHP_METHOD(layerObj, __get)
   php_layer = (php_layer_object *) zend_object_store_get_object(zobj TSRMLS_CC);
 
   IF_GET_LONG("numclasses",  php_layer->layer->numclasses)
-  else IF_GET_LONG("index", php_layer->layer->index)
-    else IF_GET_LONG("status", php_layer->layer->status)
-      else IF_GET_LONG("debug",  php_layer->layer->debug)
-        else IF_GET_STRING("bandsitem", php_layer->layer->bandsitem)
-          else IF_GET_STRING("classitem", php_layer->layer->classitem)
-            else IF_GET_STRING("classgroup", php_layer->layer->classgroup)
-              else IF_GET_STRING("name", php_layer->layer->name)
-                else IF_GET_STRING("group", php_layer->layer->group)
-                  else IF_GET_STRING("data", php_layer->layer->data)
-                    else IF_GET_LONG("type",  php_layer->layer->type)
-                      else IF_GET_LONG("dump", php_layer->layer->dump)
-                        else IF_GET_DOUBLE("tolerance", php_layer->layer->tolerance)
-                          else IF_GET_LONG("toleranceunits", php_layer->layer->toleranceunits)
-                            else IF_GET_LONG("sizeunits", php_layer->layer->sizeunits)
-                              else IF_GET_DOUBLE("symbolscaledenom", php_layer->layer->symbolscaledenom)
-                                else IF_GET_LONG("maxclasses",  php_layer->layer->maxclasses)
-                                  else IF_GET_DOUBLE("minscaledenom", php_layer->layer->minscaledenom)
-                                    else IF_GET_DOUBLE("maxscaledenom", php_layer->layer->maxscaledenom)
-                                      else IF_GET_DOUBLE("labelminscaledenom", php_layer->layer->labelminscaledenom)
-                                        else IF_GET_DOUBLE("labelmaxscaledenom", php_layer->layer->labelmaxscaledenom)
-                                          else IF_GET_DOUBLE("maxgeowidth", php_layer->layer->maxgeowidth)
-                                            else IF_GET_DOUBLE("mingeowidth", php_layer->layer->mingeowidth)
-                                              else IF_GET_STRING("mask", php_layer->layer->mask)
-                                                else IF_GET_LONG("minfeaturesize", php_layer->layer->minfeaturesize)
-                                                  else IF_GET_LONG("maxfeatures", php_layer->layer->maxfeatures)
-                                                    else IF_GET_LONG("startindex", php_layer->layer->startindex)
+  else IF_GET_STRING("encoding", php_layer->layer->encoding)
+    else IF_GET_LONG("index", php_layer->layer->index)
+      else IF_GET_LONG("status", php_layer->layer->status)
+        else IF_GET_LONG("debug",  php_layer->layer->debug)
+          else IF_GET_STRING("bandsitem", php_layer->layer->bandsitem)
+            else IF_GET_STRING("classitem", php_layer->layer->classitem)
+              else IF_GET_STRING("classgroup", php_layer->layer->classgroup)
+                else IF_GET_STRING("name", php_layer->layer->name)
+                  else IF_GET_STRING("group", php_layer->layer->group)
+                    else IF_GET_STRING("data", php_layer->layer->data)
+                      else IF_GET_LONG("type",  php_layer->layer->type)
+                        else IF_GET_LONG("dump", php_layer->layer->dump)
+                          else IF_GET_DOUBLE("tolerance", php_layer->layer->tolerance)
+                            else IF_GET_LONG("toleranceunits", php_layer->layer->toleranceunits)
+                              else IF_GET_LONG("sizeunits", php_layer->layer->sizeunits)
+                                else IF_GET_DOUBLE("symbolscaledenom", php_layer->layer->symbolscaledenom)
+                                  else IF_GET_LONG("maxclasses",  php_layer->layer->maxclasses)
+                                    else IF_GET_DOUBLE("minscaledenom", php_layer->layer->minscaledenom)
+                                      else IF_GET_DOUBLE("maxscaledenom", php_layer->layer->maxscaledenom)
+                                        else IF_GET_DOUBLE("labelminscaledenom", php_layer->layer->labelminscaledenom)
+                                          else IF_GET_DOUBLE("labelmaxscaledenom", php_layer->layer->labelmaxscaledenom)
+                                            else IF_GET_DOUBLE("maxgeowidth", php_layer->layer->maxgeowidth)
+                                              else IF_GET_DOUBLE("mingeowidth", php_layer->layer->mingeowidth)
+                                                else IF_GET_STRING("mask", php_layer->layer->mask)
+                                                  else IF_GET_LONG("minfeaturesize", php_layer->layer->minfeaturesize)
+                                                    else IF_GET_LONG("maxfeatures", php_layer->layer->maxfeatures)
+                                                      else IF_GET_LONG("startindex", php_layer->layer->startindex)
                                                         else IF_GET_LONG("transform", php_layer->layer->transform)
                                                           else IF_GET_LONG("labelcache", php_layer->layer->labelcache)
                                                             else IF_GET_LONG("postlabelcache", php_layer->layer->postlabelcache)
@@ -354,29 +355,30 @@ PHP_METHOD(layerObj, __set)
     msSetLayerOpacity(php_layer->layer,Z_LVAL_P(value));
   } else
   IF_SET_LONG("status", php_layer->layer->status, value)
-  else IF_SET_LONG("debug",  php_layer->layer->debug, value)
-    else IF_SET_STRING("classitem", php_layer->layer->classitem, value)
-      else IF_SET_STRING("bandsitem", php_layer->layer->bandsitem, value)
-        else IF_SET_STRING("classgroup", php_layer->layer->classgroup, value)
-          else IF_SET_STRING("name", php_layer->layer->name, value)
-            else IF_SET_STRING("group", php_layer->layer->group, value)
-              else IF_SET_STRING("data", php_layer->layer->data, value)
-                else IF_SET_LONG("type",  php_layer->layer->type, value)
-                  else IF_SET_LONG("dump", php_layer->layer->dump, value)
-                    else IF_SET_DOUBLE("tolerance", php_layer->layer->tolerance, value)
-                      else IF_SET_LONG("toleranceunits", php_layer->layer->toleranceunits, value)
-                        else IF_SET_LONG("sizeunits", php_layer->layer->sizeunits, value)
-                          else IF_SET_DOUBLE("symbolscaledenom", php_layer->layer->symbolscaledenom, value)
-                            else IF_SET_DOUBLE("minscaledenom", php_layer->layer->minscaledenom, value)
-                              else IF_SET_DOUBLE("maxscaledenom", php_layer->layer->maxscaledenom, value)
-                                else IF_SET_LONG("minfeaturesize", php_layer->layer->minfeaturesize, value)
-                                  else IF_SET_DOUBLE("labelminscaledenom", php_layer->layer->labelminscaledenom, value)
-                                    else IF_SET_DOUBLE("labelmaxscaledenom", php_layer->layer->labelmaxscaledenom, value)
-                                      else IF_SET_DOUBLE("maxgeowidth", php_layer->layer->maxgeowidth, value)
-                                        else IF_SET_DOUBLE("mingeowidth", php_layer->layer->mingeowidth, value)
-                                          else IF_SET_STRING("mask", php_layer->layer->mask, value)
-                                            else IF_SET_LONG("maxfeatures", php_layer->layer->maxfeatures, value)
-                                              else IF_SET_LONG("startindex", php_layer->layer->startindex, value)
+  else IF_SET_STRING("encoding",  php_layer->layer->encoding, value)
+    else IF_SET_LONG("debug",  php_layer->layer->debug, value)
+      else IF_SET_STRING("classitem", php_layer->layer->classitem, value)
+        else IF_SET_STRING("bandsitem", php_layer->layer->bandsitem, value)
+          else IF_SET_STRING("classgroup", php_layer->layer->classgroup, value)
+            else IF_SET_STRING("name", php_layer->layer->name, value)
+              else IF_SET_STRING("group", php_layer->layer->group, value)
+                else IF_SET_STRING("data", php_layer->layer->data, value)
+                  else IF_SET_LONG("type",  php_layer->layer->type, value)
+                    else IF_SET_LONG("dump", php_layer->layer->dump, value)
+                      else IF_SET_DOUBLE("tolerance", php_layer->layer->tolerance, value)
+                        else IF_SET_LONG("toleranceunits", php_layer->layer->toleranceunits, value)
+                          else IF_SET_LONG("sizeunits", php_layer->layer->sizeunits, value)
+                            else IF_SET_DOUBLE("symbolscaledenom", php_layer->layer->symbolscaledenom, value)
+                              else IF_SET_DOUBLE("minscaledenom", php_layer->layer->minscaledenom, value)
+                                else IF_SET_DOUBLE("maxscaledenom", php_layer->layer->maxscaledenom, value)
+                                  else IF_SET_LONG("minfeaturesize", php_layer->layer->minfeaturesize, value)
+                                    else IF_SET_DOUBLE("labelminscaledenom", php_layer->layer->labelminscaledenom, value)
+                                      else IF_SET_DOUBLE("labelmaxscaledenom", php_layer->layer->labelmaxscaledenom, value)
+                                        else IF_SET_DOUBLE("maxgeowidth", php_layer->layer->maxgeowidth, value)
+                                          else IF_SET_DOUBLE("mingeowidth", php_layer->layer->mingeowidth, value)
+                                            else IF_SET_STRING("mask", php_layer->layer->mask, value)
+                                              else IF_SET_LONG("maxfeatures", php_layer->layer->maxfeatures, value)
+                                                else IF_SET_LONG("startindex", php_layer->layer->startindex, value)
                                                   else IF_SET_LONG("transform", php_layer->layer->transform, value)
                                                     else IF_SET_LONG("labelcache", php_layer->layer->labelcache, value)
                                                       else IF_SET_LONG("postlabelcache", php_layer->layer->postlabelcache, value)
diff --git a/mapscript/swiginc/class.i b/mapscript/swiginc/class.i
index 425a3cd..8eb0ff7 100644
--- a/mapscript/swiginc/class.i
+++ b/mapscript/swiginc/class.i
@@ -176,7 +176,14 @@
     return (char *) msNextKeyFromHashTable(&(self->metadata), lastkey);
   }
   
-  int drawLegendIcon(mapObj *map, layerObj *layer, int width, int height, imageObj *dstImage, int dstX, int dstY) {
+  int drawLegendIcon(mapObj *map, layerObj *layer, int width, int height, imageObj *dstImage, int dstX, int dstY) {    
+    if(layer->sizeunits != MS_PIXELS) {
+      map->cellsize = msAdjustExtent(&(map->extent), map->width, map->height);
+      layer->scalefactor = (msInchesPerUnit(layer->sizeunits,0)/msInchesPerUnit(map->units,0)) / map->cellsize;
+    }
+    else
+      layer->scalefactor = map->resolution/map->defresolution;
+    
     return msDrawLegendIcon(map, layer, self, width, height, dstImage, dstX, dstY, MS_TRUE, NULL);
   }
  
diff --git a/mapscript/swiginc/color.i b/mapscript/swiginc/color.i
index 8b57dba..2910673 100644
--- a/mapscript/swiginc/color.i
+++ b/mapscript/swiginc/color.i
@@ -42,7 +42,7 @@
         
         /* Check colors */
         if (red > 255 || green > 255 || blue > 255 || alpha>255 ||
-            red<0 || green<0 || blue<0 || alpha<0 ) {
+            red<-1 || green<-1 || blue<-1 || alpha<0 ) {
             msSetError(MS_MISCERR, "Invalid color", "colorObj()");
             return NULL;
         }
diff --git a/mapserver.h b/mapserver.h
index 0526c00..cf3cd21 100644
--- a/mapserver.h
+++ b/mapserver.h
@@ -2308,7 +2308,7 @@ void msPopulateTextSymbolForLabelAndString(textSymbolObj *ts, labelObj *l, char
   MS_DLL_EXPORT int WARN_UNUSED msGetStringSize(mapObj *map, labelObj *label, int size, char *string, rectObj *r);
 
   MS_DLL_EXPORT int WARN_UNUSED msAddLabel(mapObj *map, imageObj *image, labelObj *label, int layerindex, int classindex, shapeObj *shape, pointObj *point, double featuresize, textSymbolObj *ts);
-  MS_DLL_EXPORT int WARN_UNUSED msAddLabelGroup(mapObj *map, imageObj *image, int layerindex, int classindex, shapeObj *shape, pointObj *point, double featuresize);
+  MS_DLL_EXPORT int WARN_UNUSED msAddLabelGroup(mapObj *map, imageObj *image, layerObj *layer, int classindex, shapeObj *shape, pointObj *point, double featuresize);
   MS_DLL_EXPORT void insertRenderedLabelMember(mapObj *map, labelCacheMemberObj *cachePtr);
   MS_DLL_EXPORT int msTestLabelCacheCollisions(mapObj *map, labelCacheMemberObj *cachePtr, label_bounds *lb, int current_priority, int current_label);
   MS_DLL_EXPORT int msTestLabelCacheLeaderCollision(mapObj *map, pointObj *lp1, pointObj *lp2);
diff --git a/mapsymbol.c b/mapsymbol.c
index e8029a1..edb53bc 100644
--- a/mapsymbol.c
+++ b/mapsymbol.c
@@ -300,12 +300,18 @@ void writeSymbol(symbolObj *s, FILE *stream)
     case(MS_SYMBOL_PIXMAP):
       msIO_fprintf(stream, "    TYPE PIXMAP\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);
+      }
       msIO_fprintf(stream, "    TRANSPARENT %d\n", s->transparentcolor);
       break;
     case(MS_SYMBOL_TRUETYPE):
       msIO_fprintf(stream, "    TYPE TRUETYPE\n");
       if (s->character != NULL) msIO_fprintf(stream, "    CHARACTER \"%s\"\n", s->character);
       if (s->font != NULL) msIO_fprintf(stream, "    FONT \"%s\"\n", s->font);
+      if(s->anchorpoint_y!=0.5 || s->anchorpoint_x!=0.5) {
+        msIO_fprintf(stream, "    ANCHORPOINT %g %g\n", s->anchorpoint_x, s->anchorpoint_y);
+      }
       break;
     default:
       if(s->type == MS_SYMBOL_ELLIPSE)
diff --git a/maputfgrid.cpp b/maputfgrid.cpp
index a1c57bb..60bf600 100644
--- a/maputfgrid.cpp
+++ b/maputfgrid.cpp
@@ -284,10 +284,10 @@ band_type addToTable(UTFGridRenderer *r, shapeObj *p)
   /* Simple operation so we don't have unavailable char in the JSON */
   utfvalue = encodeForRendering(utfvalue);
 
-  /* Datas are added to the table */
+  /* Data added to the table */
   r->data->table[r->data->counter].datavalues = msEvalTextExpressionJSonEscape(&r->utflayer->utfdata, p);
 
-  /* If UTFITEM is set in the mapfiles we add its value to the table */
+  /* If UTFITEM is set in the mapfile we add its value to the table */
   if(r->useutfitem)
     r->data->table[r->data->counter].itemvalue =  msStrdup(p->values[r->utflayer->utfitemindex]);
 
@@ -463,7 +463,7 @@ int utfgridCleanData(imageObj *img)
 }
 
 /*
- * Print the renderer datas as a JSON.
+ * Print the renderer data as JSON.
  */
 int utfgridSaveImage(imageObj *img, mapObj *map, FILE *fp, outputFormatObj *format)
 {
@@ -481,75 +481,75 @@ int utfgridSaveImage(imageObj *img, mapObj *map, FILE *fp, outputFormatObj *form
   imgheight = img->height/renderer->utfresolution;
   imgwidth = img->width/renderer->utfresolution;
 
-  fprintf(fp,"{\"grid\":[");
+  msIO_fprintf(fp,"{\"grid\":[");
 
-  /* Print the buffer, also */
+  /* Print the buffer */
   for(row=0; row<imgheight; row++) {
 
     wchar_t *string = (wchar_t*) msSmallMalloc ((imgwidth + 1) * sizeof(wchar_t));
     wchar_t *stringptr;
     stringptr = string;
-    /* Needs comma between each lines but JSON must not start with a comma. */
+    /* Need a comma between each line but JSON must not start with a comma. */
     if(row!=0)
-      fprintf(fp,",");
-    fprintf(fp,"\"");
+      msIO_fprintf(fp,",");
+    msIO_fprintf(fp,"\"");
     for(col=0; col<img->width/renderer->utfresolution; col++) {
-      /* Get the datas from buffer. */
+      /* Get the data from buffer. */
       pixelid = renderer->buffer[(row*imgwidth)+col];
 
       *stringptr = pixelid;
       stringptr++;
     }
 
-    /* Convertion to UTF-8 encoding */
+    /* Conversion to UTF-8 encoding */
     *stringptr = '\0';
     char * utf8;
     utf8 = msConvertWideStringToUTF8 (string, "UCS-4LE");
-    fprintf(fp,"%s", utf8);
+    msIO_fprintf(fp,"%s", utf8);
     msFree(utf8);
     msFree(string);
-    fprintf(fp,"\"");
+    msIO_fprintf(fp,"\"");
   }
 
-  fprintf(fp,"],\"keys\":[\"\"");
+  msIO_fprintf(fp,"],\"keys\":[\"\"");
 
-  /* Prints the key specified */
+  /* Print the specified key */
   for(i=0;i<renderer->data->counter;i++) {
-      fprintf(fp,",");
+      msIO_fprintf(fp,",");
 
     if(renderer->useutfitem)
     {
       pszEscaped = msEscapeJSonString(renderer->data->table[i].itemvalue);
-      fprintf(fp,"\"%s\"", pszEscaped);
+      msIO_fprintf(fp,"\"%s\"", pszEscaped);
       msFree(pszEscaped);
     }
     /* If no UTFITEM specified use the serial ID as the key */
     else
-      fprintf(fp,"\"%i\"", renderer->data->table[i].serialid);
+      msIO_fprintf(fp,"\"%i\"", renderer->data->table[i].serialid);
   }
 
-  fprintf(fp,"],\"data\":{");
+  msIO_fprintf(fp,"],\"data\":{");
 
-  /* Print the datas */
+  /* Print the data */
   if(renderer->useutfdata) {
     for(i=0;i<renderer->data->counter;i++) {
       if(i!=0)
-        fprintf(fp,",");
+        msIO_fprintf(fp,",");
 
       if(renderer->useutfitem)
       {
         pszEscaped = msEscapeJSonString(renderer->data->table[i].itemvalue);
-        fprintf(fp,"\"%s\":", pszEscaped);
+        msIO_fprintf(fp,"\"%s\":", pszEscaped);
         msFree(pszEscaped);
       }
       /* If no UTFITEM specified use the serial ID as the key */
       else
-        fprintf(fp,"\"%i\":", renderer->data->table[i].serialid);
+        msIO_fprintf(fp,"\"%i\":", renderer->data->table[i].serialid);
 
-      fprintf(fp,"%s", renderer->data->table[i].datavalues);
+      msIO_fprintf(fp,"%s", renderer->data->table[i].datavalues);
     }
   }
-  fprintf(fp,"}}");
+  msIO_fprintf(fp,"}}");
 
   return MS_SUCCESS;
 }
@@ -606,7 +606,7 @@ int utfgridEndLayer(imageObj *img, mapObj *map, layerObj *layer)
 }
 
 /*
- * Do the table operations on the shapes. Allow multiple type of data to be rendered.
+ * Do the table operations on the shapes. Allow multiple types of data to be rendered.
  */
 int utfgridStartShape(imageObj *img, shapeObj *shape)
 {
@@ -633,7 +633,7 @@ int utfgridEndShape(imageObj *img, shapeObj *shape)
 }
 
 /*
- * Function that render polygons into UTFGrid.
+ * Function that renders polygons into UTFGrid.
  */
 int utfgridRenderPolygon(imageObj *img, shapeObj *polygonshape, colorObj *color)
 {
@@ -652,8 +652,8 @@ int utfgridRenderPolygon(imageObj *img, shapeObj *polygonshape, colorObj *color)
 }
 
 /*
- * Function that render lines into UTFGrid. Starts by looking if the line is a polygon
- * outline. Then draw it if it's not.
+ * Function that renders lines into UTFGrid. Starts by looking if the line is a polygon
+ * outline, draw it if it's not.
  */
 int utfgridRenderLine(imageObj *img, shapeObj *lineshape, strokeStyleObj *linestyle)
 {
@@ -710,7 +710,7 @@ int utfgridRenderVectorSymbol(imageObj *img, double x, double y, symbolObj *symb
 }
 
 /*
- * Function that render Pixmap type symbols into UTFGrid.
+ * Function that renders Pixmap type symbols into UTFGrid.
  */
 int utfgridRenderPixmapSymbol(imageObj *img, double x, double y, symbolObj *symbol, symbolStyleObj * style)
 {
diff --git a/mapwcs20.c b/mapwcs20.c
index 266a07d..0b03893 100644
--- a/mapwcs20.c
+++ b/mapwcs20.c
@@ -331,6 +331,7 @@ void msWCSFreeParamsObj20(wcs20ParamsObjPtr params)
   }
   msFree(params->axes);
   CSLDestroy(params->range_subset);
+  CSLDestroy(params->format_options);
   msFree(params);
 }
 
@@ -960,14 +961,17 @@ static int msWCSParseRequest20_XMLGetCoverage(
 
       if(NULL == (axis = msWCSFindAxis20(params, axisName))) {
         if(NULL == (axis = msWCSCreateAxisObj20())) {
+          xmlFree(axisName);
           return MS_FAILURE;
         }
         axis->name = msStrdup(axisName);
         msWCSInsertAxisObj20(params, axis);
       }
+      xmlFree(axisName);
 
       content = (char *)xmlNodeGetContent(child);
       if(msStringParseInteger(content, &(axis->size)) != MS_SUCCESS) {
+        xmlFree(content);
         msSetError(MS_WCSERR, "Value of element 'Size' could not "
                    "be parsed to a valid integer.",
                    "msWCSParseRequest20_XMLGetCoverage()");
@@ -988,11 +992,13 @@ static int msWCSParseRequest20_XMLGetCoverage(
 
       if(NULL == (axis = msWCSFindAxis20(params, axisName))) {
         if(NULL == (axis = msWCSCreateAxisObj20())) {
+          xmlFree(axisName);
           return MS_FAILURE;
         }
         axis->name = msStrdup(axisName);
         msWCSInsertAxisObj20(params, axis);
       }
+      xmlFree(axisName);
 
       axis->resolutionUOM = (char *) xmlGetProp(child, BAD_CAST "uom");
 
@@ -3338,7 +3344,7 @@ int msWCSGetCapabilities20(mapObj *map, cgiRequestObj *req,
 
     /* Report the supported CRSs */
     {
-      char *crs_list;
+      char *crs_list = NULL;
       xmlNodePtr crsMetadataNode = xmlNewChild(psExtensionNode, psCrsNs,
                                                BAD_CAST "CrsMetadata", NULL);
 
@@ -3347,6 +3353,7 @@ int msWCSGetCapabilities20(mapObj *map, cgiRequestObj *req,
                                         "CO", MS_FALSE)) != NULL ) {
         msLibXml2GenerateList(crsMetadataNode, psCrsNs, "crsSupported",
                               crs_list, ' ');
+        msFree(crs_list);
       } else {
         /* could not determine list of CRSs */
       }
@@ -4126,6 +4133,7 @@ this request. Check wcs/ows_enable_request settings.", "msWCSGetCoverage20()", p
 
   msInitProjection(&imageProj);
   if (msLoadProjectionString(&imageProj, cm.srs) == -1) {
+    msFreeProjection(&imageProj);
     msWCSClearCoverageMetadata20(&cm);
     msSetError(MS_WCSERR,
                "Error loading CRS %s.",
@@ -4138,11 +4146,15 @@ this request. Check wcs/ows_enable_request settings.", "msWCSGetCoverage20()", p
   for(i = 0; i < params->numaxes; ++i) {
     if(params->axes[i]->subset != NULL) {
       if(params->axes[i]->subset->timeOrScalar == MS_WCS20_TIME_VALUE) {
+        msFreeProjection(&imageProj);
+        msWCSClearCoverageMetadata20(&cm);
         msSetError(MS_WCSERR, "Time values for subsets are not supported. ",
                    "msWCSGetCoverage20()");
         return msWCSException(map, "InvalidSubsetting", "subset", params->version);
       }
       if(params->axes[i]->subset->operation == MS_WCS20_SLICE) {
+        msFreeProjection(&imageProj);
+        msWCSClearCoverageMetadata20(&cm);
         msSetError(MS_WCSERR, "Subset operation 'slice' is not supported.",
                    "msWCSGetCoverage20()");
         return msWCSException(map, "InvalidSubsetting", "subset", params->version);
@@ -4154,11 +4166,13 @@ this request. Check wcs/ows_enable_request settings.", "msWCSGetCoverage20()", p
     wcs20AxisObjPtr *axes;
     axes = msSmallMalloc(sizeof(wcs20AxisObjPtr) * 2);
     if(msWCSValidateAndFindAxes20(params, axes) == MS_FAILURE) {
+      msFreeProjection(&imageProj);
       msWCSClearCoverageMetadata20(&cm);
       msFree(axes);
       return msWCSException(map, "InvalidAxisLabel", "subset", params->version);
     }
     if(msWCSGetCoverage20_FinalizeParamsObj(params, axes) == MS_FAILURE) {
+      msFreeProjection(&imageProj);
       msWCSClearCoverageMetadata20(&cm);
       msFree(axes);
       return msWCSException(map, "InvalidParameterValue", "extent", params->version);
@@ -4210,6 +4224,8 @@ this request. Check wcs/ows_enable_request settings.", "msWCSGetCoverage20()", p
     /* if the subsets have a crs given, project the image extent to it */
     msInitProjection(&subsetProj);
     if(msLoadProjectionString(&subsetProj, params->subsetcrs) != MS_SUCCESS) {
+      msFreeProjection(&subsetProj);
+      msFreeProjection(&imageProj);
       msWCSClearCoverageMetadata20(&cm);
       msSetError(MS_WCSERR,
                  "Error loading CRS %s.",
@@ -4336,6 +4352,9 @@ this request. Check wcs/ows_enable_request settings.", "msWCSGetCoverage20()", p
       params->resolutionX = (bbox.maxx - bbox.minx) / params->width;
       params->resolutionY = (bbox.maxy - bbox.miny) / params->height;
     }
+    else {
+      msFreeProjection(&outputProj);
+    }
   }
 
   /* set the bounding box as new map extent */
diff --git a/mapwfs.c b/mapwfs.c
index 68dc8df..7f41849 100644
--- a/mapwfs.c
+++ b/mapwfs.c
@@ -4151,6 +4151,7 @@ int msWFSGetPropertyValue(mapObj *map, wfsParamsObj *paramsObj, cgiRequestObj *r
                 if (z == geometryList->numgeometries) {
                   msSetError(MS_WFSERR,
                             "Invalid VALUEREFERENCE %s",  "msWFSGetPropertyValue()", paramsObj->pszValueReference);
+                  msFree(pszGMLGroups);
                   msGMLFreeItems(itemList);
                   msGMLFreeGroups(groupList);
                   msGMLFreeGeometries(geometryList);
@@ -4219,8 +4220,12 @@ int msWFSGetPropertyValue(mapObj *map, wfsParamsObj *paramsObj, cgiRequestObj *r
                                         &maxfeatures, &startindex);
 
   status = msWFSAnalyzeBBOX(map, paramsObj, &bbox, &sBBoxSrs);
-  if( status != 0 )
+  if( status != 0 ) {
+      msFree(pszGMLGroups);
+      msFree(pszGMLIncludeItems);
+      msFree(pszGMLGeometries);
       return status;
+      }
 
   if( iResultTypeHits == 1 )
   {
diff --git a/mapwfs11.c b/mapwfs11.c
index 20ab164..16077bb 100644
--- a/mapwfs11.c
+++ b/mapwfs11.c
@@ -119,10 +119,10 @@ xmlNodePtr msWFSDumpLayer11(mapObj *map, layerObj *lp, xmlNsPtr psNsOws,
     valueToFree = (char *) msSmallMalloc(sizeof(char*)*n);
     snprintf(valueToFree, n, "%s%s%s", (value ? value : ""), (value ? ":" : ""), lp->name);
 
-    psNode = xmlNewChild(psRootNode, NULL, BAD_CAST "Name", BAD_CAST valueToFree);
+    psNode = xmlNewTextChild(psRootNode, NULL, BAD_CAST "Name", BAD_CAST valueToFree);
     msFree(valueToFree);
   } else {
-    psNode = xmlNewChild(psRootNode, NULL, BAD_CAST "Name", BAD_CAST lp->name);
+    psNode = xmlNewTextChild(psRootNode, NULL, BAD_CAST "Name", BAD_CAST lp->name);
   }
 
   if (lp->name && strlen(lp->name) > 0 &&
@@ -140,12 +140,12 @@ xmlNodePtr msWFSDumpLayer11(mapObj *map, layerObj *lp, xmlNsPtr psNsOws,
   if (!value)
     value =(const char*)lp->name;
 
-  psNode = xmlNewChild(psRootNode, NULL, BAD_CAST "Title", BAD_CAST value);
+  psNode = xmlNewTextChild(psRootNode, NULL, BAD_CAST "Title", BAD_CAST value);
 
 
   value = msOWSLookupMetadataWithLanguage(&(lp->metadata), "FO", "abstract", validate_language);
   if (value)
-    psNode = xmlNewChild(psRootNode, NULL, BAD_CAST "Abstract", BAD_CAST value);
+    psNode = xmlNewTextChild(psRootNode, NULL, BAD_CAST "Abstract", BAD_CAST value);
 
 
 
@@ -165,15 +165,15 @@ xmlNodePtr msWFSDumpLayer11(mapObj *map, layerObj *lp, xmlNsPtr psNsOws,
     tokens = msStringSplit(valueToFree, ' ', &n);
     if (tokens && n > 0) {
       if( nWFSVersion == OWS_1_1_0 )
-        psNode = xmlNewChild(psRootNode, NULL, BAD_CAST "DefaultSRS", BAD_CAST tokens[0]);
+        psNode = xmlNewTextChild(psRootNode, NULL, BAD_CAST "DefaultSRS", BAD_CAST tokens[0]);
       else
-        psNode = xmlNewChild(psRootNode, NULL, BAD_CAST "DefaultCRS", BAD_CAST tokens[0]);
+        psNode = xmlNewTextChild(psRootNode, NULL, BAD_CAST "DefaultCRS", BAD_CAST tokens[0]);
       for (i=1; i<n; i++)
       {
         if( nWFSVersion == OWS_1_1_0 )
-          psNode = xmlNewChild(psRootNode, NULL, BAD_CAST "OtherSRS", BAD_CAST tokens[i]);
+          psNode = xmlNewTextChild(psRootNode, NULL, BAD_CAST "OtherSRS", BAD_CAST tokens[i]);
         else
-          psNode = xmlNewChild(psRootNode, NULL, BAD_CAST "OtherCRS", BAD_CAST tokens[i]);
+          psNode = xmlNewTextChild(psRootNode, NULL, BAD_CAST "OtherCRS", BAD_CAST tokens[i]);
       }
 
       msFreeCharArray(tokens, n);
@@ -198,7 +198,7 @@ xmlNodePtr msWFSDumpLayer11(mapObj *map, layerObj *lp, xmlNsPtr psNsOws,
     tokens = msStringSplit(formats_list, ',', &n);
 
     for( iformat = 0; iformat < n; iformat++ )
-      xmlNewChild(psNode, NULL, BAD_CAST "Format",
+      xmlNewTextChild(psNode, NULL, BAD_CAST "Format",
                   BAD_CAST tokens[iformat] );
     msFree( formats_list );
     msFreeCharArray( tokens, n );
@@ -236,7 +236,7 @@ xmlNodePtr msWFSDumpLayer11(mapObj *map, layerObj *lp, xmlNsPtr psNsOws,
     }
     else
     {
-        psNode = xmlNewChild(psRootNode, NULL, BAD_CAST "MetadataURL", BAD_CAST value);
+        psNode = xmlNewTextChild(psRootNode, NULL, BAD_CAST "MetadataURL", BAD_CAST value);
 
         value = msOWSLookupMetadata(&(lp->metadata), "FO", "metadataurl_format");
 
diff --git a/mapwfs20.c b/mapwfs20.c
index 710d444..b4402ec 100644
--- a/mapwfs20.c
+++ b/mapwfs20.c
@@ -163,7 +163,7 @@ xmlNodePtr msWFSConstraintDefaultValue(xmlNsPtr psNs, xmlNsPtr psNsOws, const ch
   xmlNewProp(psRootNode, BAD_CAST "name", BAD_CAST name);
 
   xmlNewChild(psRootNode, psNsOws, BAD_CAST "NoValues", NULL );
-  xmlNewChild(psRootNode, psNsOws, BAD_CAST "DefaultValue", BAD_CAST value);
+  xmlNewTextChild(psRootNode, psNsOws, BAD_CAST "DefaultValue", BAD_CAST value);
 
   return psRootNode;
 }
@@ -334,9 +334,9 @@ static void msWFSAddInspireDSID(mapObj *map,
         {
             xmlNodePtr pSDSI = xmlNewNode(psNsInspireDls, BAD_CAST "SpatialDataSetIdentifier");
             xmlAddChild(pDlsExtendedCapabilities, pSDSI);
-            xmlNewChild(pSDSI, psNsInspireCommon, BAD_CAST "Code", BAD_CAST tokensCode[i]);
+            xmlNewTextChild(pSDSI, psNsInspireCommon, BAD_CAST "Code", BAD_CAST tokensCode[i]);
             if( ntokensNS > 0 && tokensNS[i][0] != '\0' )
-                xmlNewChild(pSDSI, psNsInspireCommon, BAD_CAST "Namespace", BAD_CAST tokensNS[i]);
+                xmlNewTextChild(pSDSI, psNsInspireCommon, BAD_CAST "Namespace", BAD_CAST tokensNS[i]);
         }
         msFreeCharArray(tokensCode, ntokensCode);
         if( ntokensNS > 0 )

-- 
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