[mapserver] 02/07: Imported Upstream version 7.0.5

Bas Couwenberg sebastic at debian.org
Tue May 9 20:42:30 UTC 2017


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

sebastic pushed a commit to branch experimental
in repository mapserver.

commit e8d579737239d45858950a293f037370a6e246ef
Author: Bas Couwenberg <sebastic at xs4all.nl>
Date:   Tue May 9 22:13:57 2017 +0200

    Imported Upstream version 7.0.5
---
 CMakeLists.txt              |   2 +-
 cmake/FindPHP5.cmake        |   4 +
 mapdraw.c                   |   1 +
 mapgraticule.c              | 131 ++++++-
 maphash.c                   |   4 +
 mapio.c                     | 120 +++++++
 mapio.h                     |   4 +-
 maplegend.c                 |   1 +
 mapogcfilter.c              |   3 +-
 mapogcsld.c                 |   6 +-
 mapogr.cpp                  | 825 ++++++++++++++++++++++++++++++++++++++++----
 maporaclespatial.c          |   3 +
 mappostgis.c                |  10 +-
 mapproject.c                |  34 ++
 mapquery.c                  |   7 +-
 mapresample.c               |  83 ++++-
 mapscript/python/pymodule.i |  40 +++
 mapscript/swiginc/msio.i    |   5 +
 mapshape.c                  |  21 +-
 mapwms.c                    |   2 +-
 20 files changed, 1191 insertions(+), 115 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 3e7304e..25bc2d1 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 4)
+set (MapServer_VERSION_REVISION 5)
 set (MapServer_VERSION_SUFFIX "")
 
 set(TARGET_VERSION_MAJOR ${MapServer_VERSION_MAJOR})
diff --git a/cmake/FindPHP5.cmake b/cmake/FindPHP5.cmake
index 92261b8..4b77f44 100644
--- a/cmake/FindPHP5.cmake
+++ b/cmake/FindPHP5.cmake
@@ -86,6 +86,10 @@ IF(PHP5_CONFIG_EXECUTABLE)
 
   MESSAGE(STATUS ${PHP5_MAIN_INCLUDE_DIR})
 
+  IF(NOT PHP5_INCLUDE_PATH)
+    set(PHP5_INCLUDE_PATH ${PHP5_INCLUDES})
+  ENDIF(NOT PHP5_INCLUDE_PATH)
+
   IF(PHP5_VERSION LESS 5)
     MESSAGE(FATAL_ERROR "PHP version is not 5 or later")
   ENDIF(PHP5_VERSION LESS 5)
diff --git a/mapdraw.c b/mapdraw.c
index 1ccc0fe..9fdacda 100644
--- a/mapdraw.c
+++ b/mapdraw.c
@@ -55,6 +55,7 @@ imageObj *msPrepareImage(mapObj *map, int allow_nonsquare)
     return(NULL);
   }
 
+  msFreeLabelCache(&(map->labelcache));
   msInitLabelCache(&(map->labelcache)); /* this clears any previously allocated cache */
 
   /* clear any previously created mask layer images */
diff --git a/mapgraticule.c b/mapgraticule.c
index 688b45b..eab39f8 100644
--- a/mapgraticule.c
+++ b/mapgraticule.c
@@ -187,6 +187,19 @@ int msGraticuleLayerWhichShapes(layerObj *layer, rectObj rect, int isQuery)
    * These lines will be used when generating labels to get correct placement at arc/rect edge intersections.
    */
   rectMapCoordinates = layer->map->extent;
+#ifdef USE_PROJ
+  layer->project = msProjectionsDiffer(&(layer->projection), &(layer->map->projection));
+  if( layer->project &&
+      strstr(layer->map->projection.args[0], "epsg:3857") &&
+      pj_is_latlong(layer->projection.proj) )
+  {
+      if( rectMapCoordinates.minx < -20037508)
+          rectMapCoordinates.minx = -20037508;
+      if( rectMapCoordinates.maxx > 20037508 )
+          rectMapCoordinates.maxx = 20037508;
+  }
+#endif
+
   msFree(pInfo->pboundinglines);
   pInfo->pboundinglines   = (lineObj *)  msSmallMalloc( sizeof( lineObj )  * 4 );
   msFree(pInfo->pboundingpoints);
@@ -205,7 +218,6 @@ int msGraticuleLayerWhichShapes(layerObj *layer, rectObj rect, int isQuery)
     pInfo->pboundinglines[0].point[1].y = rectMapCoordinates.maxy;
 
 #ifdef USE_PROJ
-    layer->project = msProjectionsDiffer(&(layer->projection), &(layer->map->projection));
     if(layer->project)
       msProjectLine(&layer->map->projection, &layer->projection, &pInfo->pboundinglines[0]);
 #endif
@@ -287,7 +299,7 @@ int msGraticuleLayerNextShape(layerObj *layer, shapeObj *shape)
       case 0:
         if(!pInfo->blabelaxes)  { /* Bottom */
           pInfo->ilabelstate++;
-          shape->numlines = 0;
+          msFreeShape(shape);
           return MS_SUCCESS;
         }
 
@@ -306,7 +318,11 @@ int msGraticuleLayerNextShape(layerObj *layer, shapeObj *shape)
 
         _FormatLabel( layer, shape, shape->line->point[0].x );
         if(_AdjustLabelPosition( layer, shape, posBottom ) != MS_SUCCESS)
-          return MS_FAILURE;
+        {
+            msFreeShape(shape);
+            pInfo->ilabelstate++;
+            return MS_SUCCESS;
+        }
 
         pInfo->ilabelstate++;
         return MS_SUCCESS;
@@ -314,7 +330,7 @@ int msGraticuleLayerNextShape(layerObj *layer, shapeObj *shape)
       case 1:
         if(!pInfo->blabelaxes) { /* Top */
           pInfo->ilabelstate++;
-          shape->numlines  = 0;
+          msFreeShape(shape);
           return MS_SUCCESS;
         }
 
@@ -333,7 +349,11 @@ int msGraticuleLayerNextShape(layerObj *layer, shapeObj *shape)
 
         _FormatLabel( layer, shape, shape->line->point[0].x );
         if(_AdjustLabelPosition( layer, shape, posTop ) != MS_SUCCESS)
-          return MS_FAILURE;
+        {
+            msFreeShape(shape);
+            pInfo->ilabelstate++;
+            return MS_SUCCESS;
+        }
 
         pInfo->ilabelstate++;
         return MS_SUCCESS;
@@ -372,7 +392,7 @@ int msGraticuleLayerNextShape(layerObj *layer, shapeObj *shape)
       case 0:
         if(!pInfo->blabelaxes) { /* Left side */
           pInfo->ilabelstate++;
-          shape->numlines    = 0;
+          msFreeShape(shape);
           return MS_SUCCESS;
         }
 
@@ -391,7 +411,11 @@ int msGraticuleLayerNextShape(layerObj *layer, shapeObj *shape)
 
         _FormatLabel( layer, shape, shape->line->point[0].y );
         if(_AdjustLabelPosition( layer, shape, posLeft ) != MS_SUCCESS)
-          return MS_FAILURE;
+        {
+            msFreeShape(shape);
+            pInfo->ilabelstate++;
+            return MS_SUCCESS;
+        }
 
         pInfo->ilabelstate++;
         return MS_SUCCESS;
@@ -399,7 +423,7 @@ int msGraticuleLayerNextShape(layerObj *layer, shapeObj *shape)
       case 1:
         if(!pInfo->blabelaxes) { /* Right side */
           pInfo->ilabelstate++;
-          shape->numlines    = 0;
+          msFreeShape(shape);
           return MS_SUCCESS;
         }
 
@@ -418,7 +442,11 @@ int msGraticuleLayerNextShape(layerObj *layer, shapeObj *shape)
 
         _FormatLabel( layer, shape, shape->line->point[0].y );
         if(_AdjustLabelPosition( layer, shape, posRight ) != MS_SUCCESS)
-          return MS_FAILURE;
+        {
+            msFreeShape(shape);
+            pInfo->ilabelstate++;
+            return MS_SUCCESS;
+        }
 
         pInfo->ilabelstate++;
         return MS_SUCCESS;
@@ -1039,7 +1067,20 @@ static int _AdjustLabelPosition( layerObj *pLayer, shapeObj *pShape, msGraticule
 
 #ifdef USE_PROJ
   if(pLayer->project)
+  {
     msProjectShape( &pLayer->projection, &pLayer->map->projection, pShape );
+
+    /* Poor man detection of reprojection failure */
+    if( pj_is_latlong(pLayer->projection.proj) != 
+        pj_is_latlong(pLayer->map->projection.proj) )
+    {
+        if( ptPoint.x == pShape->line->point[0].x &&
+            ptPoint.y == pShape->line->point[0].y )
+        {
+            return MS_FAILURE;
+        }
+    }
+  }
 #endif
 
   if(pLayer->transform) {
@@ -1067,8 +1108,8 @@ static int _AdjustLabelPosition( layerObj *pLayer, shapeObj *pShape, msGraticule
       pShape->line->point[0].y = fabs(rectLabel.maxy - rectLabel.miny) * 2 + 5;
       break;
     case posLeft:
-      pShape->line->point[1].x = 0;
-      pShape->line->point[0].x = fabs(rectLabel.maxx - rectLabel.minx) * 2 + 5;
+      pShape->line->point[0].x = 0;
+      pShape->line->point[1].x = fabs(rectLabel.maxx - rectLabel.minx) * 2 + 5;
       break;
     case posRight:
       pShape->line->point[1].x = pLayer->map->width;
@@ -1081,7 +1122,75 @@ static int _AdjustLabelPosition( layerObj *pLayer, shapeObj *pShape, msGraticule
 
 #ifdef USE_PROJ
   if(pLayer->project)
+  {
+    /* Clamp coordinates into the validity area of the projection, in the */
+    /* particular case of EPSG:3857 (WebMercator) to longlat reprojection */
+    if( strstr(pLayer->map->projection.args[0], "epsg:3857") &&
+        pj_is_latlong(pLayer->projection.proj) )
+    {
+        if( !pLayer->map->projection.gt.need_geotransform &&
+            ePosition == posLeft && pShape->line->point[0].x < -20037508)
+        {
+          pShape->line->point[1].x = -20037508 + (pShape->line->point[1].x -
+                                                  pShape->line->point[0].x);
+          pShape->line->point[0].x = -20037508;
+        }
+        else if( pLayer->map->projection.gt.need_geotransform &&
+                 ePosition == posLeft &&
+                 pLayer->map->projection.gt.geotransform[0] +
+                    pShape->line->point[0].x *
+                        pLayer->map->projection.gt.geotransform[1] +
+                    pShape->line->point[0].y *
+                        pLayer->map->projection.gt.geotransform[2] < -20037508)
+        {
+          double y_tmp;
+          double width = pShape->line->point[1].x - pShape->line->point[0].x;
+
+          y_tmp = pLayer->map->projection.gt.geotransform[3] +
+            pShape->line->point[0].x *
+                    pLayer->map->projection.gt.geotransform[4] +
+            pShape->line->point[0].y *
+                    pLayer->map->projection.gt.geotransform[5];
+          pShape->line->point[0].x =
+            pLayer->map->projection.gt.invgeotransform[0] +
+                    -20037508 * pLayer->map->projection.gt.invgeotransform[1] +
+                    y_tmp * pLayer->map->projection.gt.invgeotransform[2];
+          pShape->line->point[1].x = pShape->line->point[0].x + width;
+        }
+
+        if( !pLayer->map->projection.gt.need_geotransform &&
+            ePosition == posRight && pShape->line->point[1].x > 20037508)
+        {
+          pShape->line->point[0].x = 20037508 - (pShape->line->point[1].x -
+                                                 pShape->line->point[0].x);
+          pShape->line->point[1].x = 20037508;
+        }
+        else if( pLayer->map->projection.gt.need_geotransform &&
+                 ePosition == posRight &&
+                 pLayer->map->projection.gt.geotransform[0] +
+                    pShape->line->point[1].x *
+                        pLayer->map->projection.gt.geotransform[1] +
+                    pShape->line->point[1].y *
+                        pLayer->map->projection.gt.geotransform[2] > 20037508)
+        {
+          double y_tmp;
+          double width = pShape->line->point[1].x - pShape->line->point[0].x;
+
+          y_tmp = pLayer->map->projection.gt.geotransform[3] +
+            pShape->line->point[1].x *
+                    pLayer->map->projection.gt.geotransform[4] +
+            pShape->line->point[1].y *
+                    pLayer->map->projection.gt.geotransform[5];
+          pShape->line->point[1].x =
+            pLayer->map->projection.gt.invgeotransform[0] +
+                    20037508 * pLayer->map->projection.gt.invgeotransform[1] +
+                    y_tmp * pLayer->map->projection.gt.invgeotransform[2];
+          pShape->line->point[0].x = pShape->line->point[1].x - width;
+        }
+    }
+
     msProjectShape( &pLayer->map->projection, &pLayer->projection, pShape );
+  }
 #endif
 
   switch( ePosition ) {
diff --git a/maphash.c b/maphash.c
index c548602..1c27cc8 100644
--- a/maphash.c
+++ b/maphash.c
@@ -187,10 +187,14 @@ int msRemoveHashTable(hashTableObj *table, const char *key)
       status = MS_SUCCESS;
       if (prev_tp) {
         prev_tp->next = tp->next;
+        msFree(tp->key);
+        msFree(tp->data);
         free(tp);
         break;
       } else {
         table->items[hash(key)] = tp->next;
+        msFree(tp->key);
+        msFree(tp->data);
         free(tp);
         break;
       }
diff --git a/mapio.c b/mapio.c
index 7077e8d..10bbe49 100644
--- a/mapio.c
+++ b/mapio.c
@@ -758,6 +758,126 @@ void msIO_installStdinFromBuffer()
 }
 
 /************************************************************************/
+/*              msIO_getAndStripStdoutBufferMimeHeaders()               */
+/*                                                                      */
+/************************************************************************/
+
+hashTableObj* msIO_getAndStripStdoutBufferMimeHeaders()
+{
+  /* -------------------------------------------------------------------- */
+  /*      Find stdout buffer.                                             */
+  /* -------------------------------------------------------------------- */
+  msIOContext *ctx = msIO_getHandler( (FILE *) "stdout" );
+  msIOBuffer  *buf;
+  int start_of_mime_header, current_pos;
+  hashTableObj* hashTable;
+
+  if( ctx == NULL || ctx->write_channel == MS_FALSE
+      || strcmp(ctx->label,"buffer") != 0 ) {
+    msSetError( MS_MISCERR, "Can't identify msIO buffer.",
+                "msIO_getAndStripStdoutBufferMimeHeaders" );
+    return NULL;
+  }
+
+  buf = (msIOBuffer *) ctx->cbData;
+
+  hashTable = msCreateHashTable();
+
+  /* -------------------------------------------------------------------- */
+  /*      Loop over all headers.                                          */
+  /* -------------------------------------------------------------------- */
+  current_pos = 0;
+  while( TRUE ) {
+    int pos_of_column = -1;
+    char* key, *value;
+
+    start_of_mime_header = current_pos;
+    while( current_pos < buf->data_offset )
+    {
+        if( buf->data[current_pos] == '\r' )
+        {
+            if( current_pos + 1 == buf->data_offset ||
+                buf->data[current_pos + 1] != '\n' )
+            {
+                pos_of_column = -1;
+                break;
+            }
+            break;
+        }
+        if( buf->data[current_pos] == ':' )
+        {
+            pos_of_column = current_pos;
+            if( current_pos + 1 == buf->data_offset ||
+                buf->data[current_pos + 1] != ' ' )
+            {
+                pos_of_column = -1;
+                break;
+            }
+        }
+        current_pos++;
+    }
+
+    if( pos_of_column < 0 || current_pos == buf->data_offset ) {
+      msSetError( MS_MISCERR, "Corrupt mime headers.",
+                  "msIO_getAndStripStdoutBufferMimeHeaders" );
+      msFreeHashTable(hashTable);
+      return NULL;
+    }
+
+    key = (char*) malloc( pos_of_column - start_of_mime_header + 1 );
+    memcpy( key, buf->data+start_of_mime_header, pos_of_column - start_of_mime_header);
+    key[pos_of_column - start_of_mime_header] = '\0';
+
+    value = (char*) malloc( current_pos - (pos_of_column+2) + 1 );
+    memcpy( value, buf->data+pos_of_column+2, current_pos - (pos_of_column+2));
+    value[current_pos - (pos_of_column+2)] = '\0';
+
+    msInsertHashTable( hashTable, key, value );
+
+    msFree( key );
+    msFree( value );
+
+    /* -------------------------------------------------------------------- */
+    /*      Go to next line.                                                */
+    /* -------------------------------------------------------------------- */
+    current_pos += 2;
+    if( current_pos == buf->data_offset )
+    {
+      msSetError( MS_MISCERR, "Corrupt mime headers.",
+                  "msIO_getAndStripStdoutBufferMimeHeaders" );
+      msFreeHashTable(hashTable);
+      return NULL;
+    }
+
+    /* If next line is a '\r', this is the end of mime headers. */
+    if( buf->data[current_pos] == '\r' )
+    {
+        current_pos ++;
+        if( current_pos == buf->data_offset ||
+            buf->data[current_pos] != '\n' )
+        {
+            msSetError( MS_MISCERR, "Corrupt mime headers.",
+                        "msIO_getAndStripStdoutBufferMimeHeaders" );
+            msFreeHashTable(hashTable);
+            return NULL;
+        }
+        current_pos ++;
+        break;
+    }
+  }
+
+  /* -------------------------------------------------------------------- */
+  /*      Move data to front of buffer, and reset length.                 */
+  /* -------------------------------------------------------------------- */
+  memmove( buf->data, buf->data+current_pos,
+           buf->data_offset - current_pos );
+  buf->data[buf->data_offset - current_pos] = '\0';
+  buf->data_offset -= current_pos;
+
+  return hashTable;
+}
+
+/************************************************************************/
 /*                 msIO_stripStdoutBufferContentType()                  */
 /*                                                                      */
 /*      Strip off Content-Type header from buffer, and return to        */
diff --git a/mapio.h b/mapio.h
index f339839..cc676be 100644
--- a/mapio.h
+++ b/mapio.h
@@ -37,6 +37,7 @@
 */
 
 #include <stdarg.h>
+#include "maphash.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -105,7 +106,8 @@ extern "C" {
   void MS_DLL_EXPORT msIO_Cleanup(void);
   char MS_DLL_EXPORT *msIO_stripStdoutBufferContentType(void);
   void MS_DLL_EXPORT msIO_stripStdoutBufferContentHeaders(void);
-  
+  hashTableObj MS_DLL_EXPORT *msIO_getAndStripStdoutBufferMimeHeaders(void);
+
   msIOContext *msIO_pushStdoutToBufferAndGetOldContext(void);
   void msIO_restoreOldStdoutContext(msIOContext *context_to_restore);
 
diff --git a/maplegend.c b/maplegend.c
index b02f12c..4c2d377 100644
--- a/maplegend.c
+++ b/maplegend.c
@@ -387,6 +387,7 @@ int msDrawLegendIcon(mapObj *map, layerObj *lp, classObj *theclass,
     initTextSymbol(&ts);
     msPopulateTextSymbolForLabelAndString(&ts,theclass->labels[0],msStrdup("Az"),lp->scalefactor*image_draw->resolutionfactor,image_draw->resolutionfactor, duplicate_always);
     ts.label->size = height - 1;
+    ts.rotation = 0;
     ret = msComputeTextPath(map,&ts);
     if(UNLIKELY(ret == MS_FAILURE)) goto legend_icon_cleanup;
     textstartpt = get_metrics(&marker,MS_CC,ts.textpath,0,0,0,0,NULL);
diff --git a/mapogcfilter.c b/mapogcfilter.c
index 7da559a..f4a6dfe 100644
--- a/mapogcfilter.c
+++ b/mapogcfilter.c
@@ -164,7 +164,8 @@ char *FLTGetExpressionForValuesRanges(layerObj *lp, const char *item, const char
       if (paszElements && numelements > 0) {
         if (forcecharcter)
           bIscharacter = MS_TRUE;
-        bIscharacter= !FLTIsNumeric(paszElements[0]);
+        else
+          bIscharacter= !FLTIsNumeric(paszElements[0]);
 
         pszTmpExpression = msStringConcatenate(pszTmpExpression, "(");
         for (i=0; i<numelements; i++) {
diff --git a/mapogcsld.c b/mapogcsld.c
index 8b76ea2..26122e3 100644
--- a/mapogcsld.c
+++ b/mapogcsld.c
@@ -3418,7 +3418,7 @@ char *msSLDGetGraphicSLD(styleObj *psStyle, layerObj *psLayer,
           }
         } else
           bGenerateDefaultSymbol =1;
-      } else if (psSymbol->type == MS_SYMBOL_PIXMAP) {
+      } else if (psSymbol->type == MS_SYMBOL_PIXMAP || psSymbol->type == MS_SYMBOL_SVG) {
         if (psSymbol->name) {
           pszURL = msLookupHashTable(&(psLayer->metadata), "WMS_SLD_SYMBOL_URL");
           if (!pszURL)
@@ -3455,8 +3455,8 @@ char *msSLDGetGraphicSLD(styleObj *psStyle, layerObj *psLayer,
                 snprintf(szTmp, sizeof(szTmp), "<%sFormat>image/png</%sFormat>\n",
                          sNameSpace, sNameSpace);
             } else
-              snprintf(szTmp, sizeof(szTmp), "<%sFormat>%s</%sFormat>\n", "image/gif",
-                       sNameSpace, sNameSpace);
+              snprintf(szTmp, sizeof(szTmp), "<%sFormat>%s</%sFormat>\n", sNameSpace,
+                            (psSymbol->type ==MS_SYMBOL_SVG)?"image/svg+xml":"image/gif",sNameSpace);
 
             pszSLD = msStringConcatenate(pszSLD, szTmp);
 
diff --git a/mapogr.cpp b/mapogr.cpp
index 7012f66..5460c33 100644
--- a/mapogr.cpp
+++ b/mapogr.cpp
@@ -33,6 +33,8 @@
 #include "mapproject.h"
 #include "mapthread.h"
 #include "mapows.h"
+#include <string>
+#include <vector>
 
 #if defined(USE_OGR) || defined(USE_GDAL)
 #  include "gdal_version.h"
@@ -77,6 +79,8 @@ typedef struct ms_ogr_file_info_t {
 
   int   bPaging;
 
+  char* pszWHERE;
+
 } msOGRFileInfo;
 
 static int msOGRLayerIsOpen(layerObj *layer);
@@ -1298,6 +1302,7 @@ msOGRFileOpen(layerObj *layer, const char *connection )
   psInfo->bPaging = false;
   psInfo->bHasSpatialIndex = false;
   psInfo->pszTablePrefix = NULL;
+  psInfo->pszWHERE = NULL;
 
     // GDAL 1.x API
   OGRSFDriverH dr = OGR_DS_GetDriver(hDS);
@@ -1695,6 +1700,7 @@ static int msOGRFileClose(layerObj *layer, msOGRFileInfo *psInfo )
   msFree(psInfo->pszMainTableName);
   msFree(psInfo->pszRowId);
   msFree(psInfo->pszTablePrefix);
+  msFree(psInfo->pszWHERE);
 
   CPLFree(psInfo);
 
@@ -2170,6 +2176,9 @@ static int msOGRFileWhichShapes(layerObj *layer, rectObj rect, msOGRFileInfo *ps
                                         layer->filter.native_string ||
                                         (psInfo->bPaging && layer->maxfeatures > 0)) ) {
 
+        const bool bHasGeometry = 
+                                OGR_L_GetGeomType( psInfo->hLayer ) != wkbNone;
+
         if( psInfo->nLayerIndex == -1 && select == NULL ) {
             select = msStrdup(psInfo->pszLayerDef);
             /* If nLayerIndex == -1 then the layer is an SQL result ... free it */
@@ -2325,18 +2334,23 @@ static int msOGRFileWhichShapes(layerObj *layer, rectObj rect, msOGRFileInfo *ps
             bSpatialiteOrGPKGAddOrderByFID = true;
         }
 
-        if (psInfo->dialect) {
-            if (EQUAL(psInfo->dialect, "Spatialite") ||
-                EQUAL(psInfo->dialect, "GPKG") ||
-                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, ")");
-                }
-            }
+        const char *sql = layer->filter.native_string;
+        if (psInfo->dialect && sql && *sql != '\0' &&
+            (EQUAL(psInfo->dialect, "Spatialite") ||
+             EQUAL(psInfo->dialect, "GPKG") ||
+             EQUAL(psInfo->dialect, "PostgreSQL")) )
+        {
+            if (filter) filter = msStringConcatenate(filter, " AND ");
+            filter = msStringConcatenate(filter, "(");
+            filter = msStringConcatenate(filter, sql);
+            filter = msStringConcatenate(filter, ")");
+        }
+        else if( psInfo->pszWHERE )
+        {
+            if (filter) filter = msStringConcatenate(filter, " AND ");
+            filter = msStringConcatenate(filter, "(");
+            filter = msStringConcatenate(filter, psInfo->pszWHERE);
+            filter = msStringConcatenate(filter, ")");
         }
 
         bool bOffsetAlreadyAdded = false;
@@ -2450,8 +2464,40 @@ static int msOGRFileWhichShapes(layerObj *layer, rectObj rect, msOGRFileInfo *ps
         {
           OGR_DS_ReleaseResultSet( psInfo->hDS, psInfo->hLayer );
         }
-        psInfo->hLayer = OGR_DS_ExecuteSQL( psInfo->hDS, select, NULL, NULL );
+
+        OGRGeometryH hGeom = NULL;
+        if( psInfo->dialect == NULL &&
+            bHasGeometry && bIsValidRect ) {
+            if (rect.minx == rect.maxx && rect.miny == rect.maxy) {
+                hGeom = OGR_G_CreateGeometry( wkbPoint );
+                OGR_G_SetPoint_2D( hGeom, 0, rect.minx, rect.miny );
+            } else if (rect.minx == rect.maxx || rect.miny == rect.maxy) {
+                hGeom = OGR_G_CreateGeometry( wkbLineString );
+                OGR_G_AddPoint_2D( hGeom, rect.minx, rect.miny );
+                OGR_G_AddPoint_2D( hGeom, rect.maxx, rect.maxy );
+            } else {
+                hGeom = 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( hGeom, hRing );
+            }
+
+            if (layer->debug >= MS_DEBUGLEVEL_VVV)
+            {
+                msDebug("msOGRFileWhichShapes: Setting spatial filter to %.15g %.15g %.15g %.15g\n",
+                        rect.minx, rect.miny, rect.maxx, rect.maxy );
+            }
+        }
+
+        psInfo->hLayer = OGR_DS_ExecuteSQL( psInfo->hDS, select, hGeom, NULL );
         psInfo->nLayerIndex = -1;
+        if( hGeom != NULL )
+            OGR_G_DestroyGeometry(hGeom);
 
         if( psInfo->hLayer == NULL ) {
             RELEASE_OGR_LOCK;
@@ -2475,6 +2521,20 @@ static int msOGRFileWhichShapes(layerObj *layer, rectObj rect, msOGRFileInfo *ps
             pszOGRFilter = msStringConcatenate(pszOGRFilter, ")");
         }
 
+        if( psInfo->pszWHERE )
+        {
+            if( pszOGRFilter )
+            {
+                pszOGRFilter = msStringConcatenate(pszOGRFilter, " AND (");
+                pszOGRFilter = msStringConcatenate(pszOGRFilter, psInfo->pszWHERE);
+                pszOGRFilter = msStringConcatenate(pszOGRFilter, ")");
+            }
+            else
+            {
+                pszOGRFilter = msStringConcatenate(pszOGRFilter, psInfo->pszWHERE);
+            }
+        }
+
         ACQUIRE_OGR_LOCK;
 
         if( OGR_L_GetGeomType( psInfo->hLayer ) != wkbNone && bIsValidRect ) {
@@ -2525,12 +2585,7 @@ static int msOGRFileWhichShapes(layerObj *layer, rectObj rect, msOGRFileInfo *ps
 
             CPLErrorReset();
             if( OGR_L_SetAttributeFilter( psInfo->hLayer, pszOGRFilter ) != OGRERR_NONE ) {
-                msSetError(MS_OGRERR, "SetAttributeFilter() failed on layer %s. Check logs.", "msOGRFileWhichShapes()", layer->name?layer->name:"(null)");
-                msDebug("SetAttributeFilter(%s) failed on layer %s.\n%s\n", layer->filter.string+6, layer->name?layer->name:"(null)", CPLGetLastErrorMsg() );
-                RELEASE_OGR_LOCK;
-                msFree(pszOGRFilter);
-                msFree(select);
-                return MS_FAILURE;
+                msDebug("SetAttributeFilter(%s) failed on layer %s.\n%s\n", pszOGRFilter, layer->name?layer->name:"(null)", CPLGetLastErrorMsg() );
             }
             msFree(pszOGRFilter);
         } else
@@ -3035,6 +3090,613 @@ NextFile:
   return MS_SUCCESS;
 }
 
+/************************************************************************/
+/*                               msExprNode                             */
+/************************************************************************/
+
+class msExprNode
+{
+    public:
+        std::vector<msExprNode*> m_aoChildren;
+        int         m_nToken;
+        std::string m_osVal;
+        double      m_dfVal;
+        struct tm   m_tmVal;
+
+        msExprNode() : m_nToken(0), m_dfVal(0.0) {}
+       ~msExprNode();
+};
+
+msExprNode::~msExprNode()
+{
+    for(size_t i=0;i<m_aoChildren.size();++i)
+        delete m_aoChildren[i];
+}
+
+/************************************************************************/
+/*                        exprGetPriority()                             */
+/************************************************************************/
+
+static int exprGetPriority(int token)
+{
+    if (token == MS_TOKEN_LOGICAL_NOT)
+        return 9;
+    else if (token == '*' || token == '/' || token == '%' )
+        return 8;
+    else if (token == '+' || token == '-' )
+        return 7;
+    else if (token == MS_TOKEN_COMPARISON_GE ||
+             token == MS_TOKEN_COMPARISON_GT ||
+             token == MS_TOKEN_COMPARISON_LE ||
+             token == MS_TOKEN_COMPARISON_LT ||
+             token == MS_TOKEN_COMPARISON_IN)
+        return 6;
+    else if (token == MS_TOKEN_COMPARISON_EQ ||
+             token == MS_TOKEN_COMPARISON_IEQ ||
+             token == MS_TOKEN_COMPARISON_LIKE ||
+             token == MS_TOKEN_COMPARISON_RE ||
+             token == MS_TOKEN_COMPARISON_IRE ||
+             token == MS_TOKEN_COMPARISON_NE)
+        return 5;
+    else if (token == MS_TOKEN_LOGICAL_AND)
+        return 4;
+    else if (token == MS_TOKEN_LOGICAL_OR)
+        return 3;
+    else
+        return 0;
+}
+
+/************************************************************************/
+/*                           BuildExprTree()                            */
+/************************************************************************/
+
+static msExprNode* BuildExprTree(tokenListNodeObjPtr node,
+                                 tokenListNodeObjPtr* pNodeNext,
+                                 int nParenthesisLevel)
+{
+    msExprNode* poRet = NULL;
+    std::vector<msExprNode*> aoStackOp, aoStackVal;
+    while( node != NULL )
+    {
+        if( node->token == '(' )
+        {
+            msExprNode* subExpr = BuildExprTree(node->next, &node,
+                                                nParenthesisLevel + 1);
+            if( subExpr == NULL )
+            {
+                goto fail;
+            }
+            aoStackVal.push_back(subExpr);
+            continue;
+        }
+        else if( node->token == ')' )
+        {
+            if( nParenthesisLevel > 0 )
+            {
+                break;
+            }
+            goto fail;
+        }
+        else if( node->token == '+' ||
+                 node->token == '-' ||
+                 node->token == '*' ||
+                 node->token == '/' ||
+                 node->token == '%' ||
+                 node->token == MS_TOKEN_LOGICAL_NOT ||
+                 node->token == MS_TOKEN_LOGICAL_AND ||
+                 node->token == MS_TOKEN_LOGICAL_OR  ||
+                 node->token == MS_TOKEN_COMPARISON_GE ||
+                 node->token == MS_TOKEN_COMPARISON_GT ||
+                 node->token == MS_TOKEN_COMPARISON_LE ||
+                 node->token == MS_TOKEN_COMPARISON_LT ||
+                 node->token == MS_TOKEN_COMPARISON_EQ ||
+                 node->token == MS_TOKEN_COMPARISON_IEQ ||
+                 node->token == MS_TOKEN_COMPARISON_LIKE ||
+                 node->token == MS_TOKEN_COMPARISON_NE ||
+                 node->token == MS_TOKEN_COMPARISON_RE ||
+                 node->token == MS_TOKEN_COMPARISON_IRE ||
+                 node->token == MS_TOKEN_COMPARISON_IN )
+        {
+            while( !aoStackOp.empty() &&
+                   exprGetPriority(node->token) <=
+                        exprGetPriority(aoStackOp.back()->m_nToken))
+            {
+                msExprNode* val1 = NULL;
+                msExprNode* val2 = NULL;
+                msExprNode* newNode = NULL;
+                if (aoStackOp.back()->m_nToken != MS_TOKEN_LOGICAL_NOT)
+                {
+                    if( aoStackVal.empty() )
+                        goto fail;
+                    val2 = aoStackVal.back();
+                    aoStackVal.pop_back();
+                }
+                if( aoStackVal.empty() )
+                    goto fail;
+                val1 = aoStackVal.back();
+                aoStackVal.pop_back();
+
+                newNode = new msExprNode;
+                newNode->m_nToken = aoStackOp.back()->m_nToken;
+                newNode->m_aoChildren.push_back(val1);
+                if( val2 )
+                    newNode->m_aoChildren.push_back(val2);
+                aoStackVal.push_back(newNode);
+                delete aoStackOp.back();
+                aoStackOp.pop_back();
+            }
+
+            msExprNode* newNode = new msExprNode;
+            newNode->m_nToken = node->token;
+            aoStackOp.push_back(newNode);
+        }
+        else if( node->token == ',' )
+        {
+        }
+        else if( node->token == MS_TOKEN_COMPARISON_INTERSECTS ||
+                 node->token == MS_TOKEN_COMPARISON_DISJOINT ||
+                 node->token == MS_TOKEN_COMPARISON_TOUCHES ||
+                 node->token == MS_TOKEN_COMPARISON_OVERLAPS ||
+                 node->token == MS_TOKEN_COMPARISON_CROSSES ||
+                 node->token == MS_TOKEN_COMPARISON_DWITHIN ||
+                 node->token == MS_TOKEN_COMPARISON_BEYOND ||
+                 node->token == MS_TOKEN_COMPARISON_WITHIN ||
+                 node->token == MS_TOKEN_COMPARISON_CONTAINS ||
+                 node->token == MS_TOKEN_COMPARISON_EQUALS ||
+                 node->token == MS_TOKEN_FUNCTION_LENGTH ||
+                 node->token == MS_TOKEN_FUNCTION_TOSTRING ||
+                 node->token == MS_TOKEN_FUNCTION_COMMIFY ||
+                 node->token == MS_TOKEN_FUNCTION_AREA ||
+                 node->token == MS_TOKEN_FUNCTION_ROUND ||
+                 node->token == MS_TOKEN_FUNCTION_FROMTEXT ||
+                 node->token == MS_TOKEN_FUNCTION_BUFFER ||
+                 node->token == MS_TOKEN_FUNCTION_DIFFERENCE ||
+                 node->token == MS_TOKEN_FUNCTION_SIMPLIFY ||
+                 node->token == MS_TOKEN_FUNCTION_SIMPLIFYPT ||
+                 node->token == MS_TOKEN_FUNCTION_GENERALIZE ||
+                 node->token == MS_TOKEN_FUNCTION_SMOOTHSIA ||
+                 node->token == MS_TOKEN_FUNCTION_JAVASCRIPT ||
+                 node->token == MS_TOKEN_FUNCTION_UPPER ||
+                 node->token == MS_TOKEN_FUNCTION_LOWER ||
+                 node->token == MS_TOKEN_FUNCTION_INITCAP ||
+                 node->token == MS_TOKEN_FUNCTION_FIRSTCAP )
+        {
+            if( node->next && node->next->token == '(' )
+            {
+                msExprNode* subExpr = BuildExprTree(node->next->next, &node,
+                                                    nParenthesisLevel + 1);
+                if( subExpr == NULL )
+                {
+                    goto fail;
+                }
+                msExprNode* newNode = new msExprNode;
+                newNode->m_nToken = node->token;
+                if( subExpr->m_nToken == 0 )
+                {
+                    newNode->m_aoChildren = subExpr->m_aoChildren;
+                    subExpr->m_aoChildren.clear();
+                    delete subExpr;
+                }
+                else
+                {
+                    newNode->m_aoChildren.push_back(subExpr);
+                }
+                aoStackVal.push_back(newNode);
+                continue;
+            }
+            else
+                goto fail;
+        }
+        else if( node->token == MS_TOKEN_LITERAL_NUMBER ||
+                 node->token == MS_TOKEN_LITERAL_BOOLEAN )
+        {
+            msExprNode* newNode = new msExprNode;
+            newNode->m_nToken = node->token;
+            newNode->m_dfVal = node->tokenval.dblval;
+            aoStackVal.push_back(newNode);
+        }
+        else if( node->token == MS_TOKEN_LITERAL_STRING )
+        {
+            msExprNode* newNode = new msExprNode;
+            newNode->m_nToken = node->token;
+            newNode->m_osVal = node->tokenval.strval;
+            aoStackVal.push_back(newNode);
+        }
+        else if( node->token == MS_TOKEN_LITERAL_TIME )
+        {
+            msExprNode* newNode = new msExprNode;
+            newNode->m_nToken = node->token;
+            newNode->m_tmVal = node->tokenval.tmval;
+            aoStackVal.push_back(newNode);
+        }
+        else if( node->token == MS_TOKEN_LITERAL_SHAPE )
+        {
+            msExprNode* newNode = new msExprNode;
+            newNode->m_nToken = node->token;
+            char *wkt = msShapeToWKT(node->tokenval.shpval);
+            newNode->m_osVal = wkt;
+            msFree(wkt);
+            aoStackVal.push_back(newNode);
+        }
+        else if( node->token == MS_TOKEN_BINDING_DOUBLE ||
+                 node->token == MS_TOKEN_BINDING_INTEGER ||
+                 node->token == MS_TOKEN_BINDING_STRING ||
+                 node->token == MS_TOKEN_BINDING_TIME )
+        {
+            msExprNode* newNode = new msExprNode;
+            newNode->m_nToken = node->token;
+            newNode->m_osVal = node->tokenval.bindval.item;
+            aoStackVal.push_back(newNode);
+        }
+        else
+        {
+            msExprNode* newNode = new msExprNode;
+            newNode->m_nToken = node->token;
+            aoStackVal.push_back(newNode);
+        }
+
+        node = node->next;
+    }
+
+    while( !aoStackOp.empty() )
+    {
+        msExprNode* val1 = NULL;
+        msExprNode* val2 = NULL;
+        msExprNode* newNode = NULL;
+        if (aoStackOp.back()->m_nToken != MS_TOKEN_LOGICAL_NOT)
+        {
+            if( aoStackVal.empty() )
+                goto fail;
+            val2 = aoStackVal.back();
+            aoStackVal.pop_back();
+        }
+        if( aoStackVal.empty() )
+            goto fail;
+        val1 = aoStackVal.back();
+        aoStackVal.pop_back();
+
+        newNode = new msExprNode;
+        newNode->m_nToken = aoStackOp.back()->m_nToken;
+        newNode->m_aoChildren.push_back(val1);
+        if( val2 )
+            newNode->m_aoChildren.push_back(val2);
+        aoStackVal.push_back(newNode);
+        delete aoStackOp.back();
+        aoStackOp.pop_back();
+    }
+
+    if( aoStackVal.size() == 1 )
+        poRet = aoStackVal.back();
+    else if( aoStackVal.size() > 1 )
+    {
+        poRet = new msExprNode;
+        poRet->m_aoChildren = aoStackVal;
+    }
+
+    if( pNodeNext )
+        *pNodeNext = node ? node->next : NULL;
+
+    return poRet;
+
+fail:
+    for( size_t i=0; i<aoStackOp.size(); ++i )
+        delete aoStackOp[i];
+    for( size_t i=0; i<aoStackVal.size(); ++i )
+        delete aoStackVal[i];
+    return NULL;
+}
+
+/**********************************************************************
+ *                 msOGRExtractTopSpatialFilter()
+ **********************************************************************/
+static int  msOGRExtractTopSpatialFilter( msOGRFileInfo *info,
+                                          const msExprNode* expr,
+                                          const msExprNode** pSpatialFilterNode )
+{
+  if( expr == NULL )
+      return MS_FALSE;
+
+  if( expr->m_nToken == MS_TOKEN_COMPARISON_INTERSECTS &&
+      expr->m_aoChildren.size() == 2 &&
+      expr->m_aoChildren[1]->m_nToken == MS_TOKEN_LITERAL_SHAPE )
+  {
+        if( info->rect_is_defined )
+        {
+            // Several intersects...
+            *pSpatialFilterNode = NULL;
+            info->rect_is_defined = MS_FALSE;
+            return MS_FALSE;
+        }
+        OGRGeometryH hSpatialFilter = NULL;
+        char* wkt = const_cast<char*>(expr->m_aoChildren[1]->m_osVal.c_str());
+        OGRErr e = OGR_G_CreateFromWkt(&wkt, NULL, &hSpatialFilter);
+        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;
+            *pSpatialFilterNode = expr;
+            OGR_G_DestroyGeometry(hSpatialFilter);
+            return MS_TRUE;
+        }
+        return MS_FALSE;
+  }
+
+  if( expr->m_nToken == MS_TOKEN_LOGICAL_AND &&
+      expr->m_aoChildren.size() == 2 )
+  {
+      return msOGRExtractTopSpatialFilter(info, expr->m_aoChildren[0],
+                                          pSpatialFilterNode) &&
+             msOGRExtractTopSpatialFilter(info, expr->m_aoChildren[1],
+                                          pSpatialFilterNode);
+  }
+
+  return MS_TRUE;
+}
+
+/**********************************************************************
+ *                 msOGRTranslatePartialMSExpressionToOGRSQL()
+ *
+ * Tries to partially translate a mapserver expression to SQL
+ **********************************************************************/
+
+static std::string msOGRGetTokenText(int nToken)
+{
+    switch( nToken )
+    {
+        case '*':
+        case '+':
+        case '-':
+        case '/':
+        case '%':
+            return std::string(1, static_cast<char>(nToken));
+
+        case MS_TOKEN_COMPARISON_GE: return ">=";
+        case MS_TOKEN_COMPARISON_GT: return ">";
+        case MS_TOKEN_COMPARISON_LE: return "<=";
+        case MS_TOKEN_COMPARISON_LT: return "<";
+        case MS_TOKEN_COMPARISON_EQ: return "=";
+        case MS_TOKEN_COMPARISON_NE: return "!=";
+        case MS_TOKEN_COMPARISON_LIKE: return "LIKE";
+
+        default:
+            return std::string();
+    }
+}
+
+static std::string msOGRTranslatePartialInternal(layerObj* layer,
+                                                 const msExprNode* expr,
+                                                 const msExprNode* spatialFilterNode,
+                                                 bool& bPartialFilter)
+{
+    switch( expr->m_nToken )
+    {
+        case MS_TOKEN_LOGICAL_NOT:
+        {
+            std::string osTmp(msOGRTranslatePartialInternal(
+                layer, expr->m_aoChildren[0], spatialFilterNode, bPartialFilter ));
+            if( osTmp.empty() )
+                return std::string();
+            return "(NOT " + osTmp + ")";
+        }
+
+        case MS_TOKEN_LOGICAL_AND:
+        {
+            // We can deal with partially translated children
+            std::string osTmp1(msOGRTranslatePartialInternal(
+                layer, expr->m_aoChildren[0], spatialFilterNode, bPartialFilter ));
+            std::string osTmp2(msOGRTranslatePartialInternal( 
+                layer, expr->m_aoChildren[1], spatialFilterNode, bPartialFilter ));
+            if( !osTmp1.empty() && !osTmp2.empty() )
+            {
+                return "(" + osTmp1 + " AND " + osTmp2 + ")";
+            }
+            else if( !osTmp1.empty() )
+                return osTmp1;
+            else
+                return osTmp2;
+        }
+
+        case MS_TOKEN_LOGICAL_OR:
+        {
+            // We can NOT deal with partially translated children
+            std::string osTmp1(msOGRTranslatePartialInternal(
+                layer, expr->m_aoChildren[0], spatialFilterNode, bPartialFilter ));
+            std::string osTmp2(msOGRTranslatePartialInternal(
+                layer, expr->m_aoChildren[1], spatialFilterNode, bPartialFilter ));
+            if( !osTmp1.empty() && !osTmp2.empty() )
+            {
+                return "(" + osTmp1 + " OR " + osTmp2 + ")";
+            }
+            else
+                return std::string();
+        }
+
+        case '*':
+        case '+':
+        case '-':
+        case '/':
+        case '%':
+        case MS_TOKEN_COMPARISON_GE:
+        case MS_TOKEN_COMPARISON_GT:
+        case MS_TOKEN_COMPARISON_LE:
+        case MS_TOKEN_COMPARISON_LT:
+        case MS_TOKEN_COMPARISON_EQ:
+        case MS_TOKEN_COMPARISON_NE:
+        {
+            std::string osTmp1(msOGRTranslatePartialInternal(
+                layer, expr->m_aoChildren[0], spatialFilterNode, bPartialFilter ));
+            std::string osTmp2(msOGRTranslatePartialInternal(
+                layer, expr->m_aoChildren[1], spatialFilterNode, bPartialFilter ));
+            if( !osTmp1.empty() && !osTmp2.empty() )
+            {
+                if( expr->m_nToken == MS_TOKEN_COMPARISON_EQ &&
+                    osTmp2 == "'_MAPSERVER_NULL_'" )
+                {
+                    return "(" + osTmp1 + " IS NULL )";
+                }
+                if( expr->m_aoChildren[1]->m_nToken == MS_TOKEN_LITERAL_STRING )
+                {
+                    char md_item_name[256];
+                    snprintf( md_item_name, sizeof(md_item_name), "gml_%s_type",
+                              expr->m_aoChildren[0]->m_osVal.c_str() );
+                    const char* type =
+                        msLookupHashTable(&(layer->metadata), md_item_name);
+                    // Cast if needed (or unsure)
+                    if( type == NULL || !EQUAL(type, "Character") )
+                    {
+                        osTmp1 = "CAST(" + osTmp1 + " AS CHARACTER(4096))";
+                    }
+                }
+                return "(" + osTmp1 + " " + msOGRGetTokenText(expr->m_nToken) +
+                       " " + osTmp2 + ")";
+            }
+            else
+                return std::string();
+        }
+
+        case MS_TOKEN_COMPARISON_RE:
+        {
+            std::string osTmp1(msOGRTranslatePartialInternal(
+                layer, expr->m_aoChildren[0], spatialFilterNode, bPartialFilter ));
+            if( expr->m_aoChildren[1]->m_nToken != MS_TOKEN_LITERAL_STRING )
+            {
+                return std::string();
+            }
+            std::string osRE("'");
+            const size_t nSize = expr->m_aoChildren[1]->m_osVal.size();
+            bool bHasUsedEscape = false;
+            for( size_t i=0; i<nSize;i++ )
+            {
+                if( i == 0 && expr->m_aoChildren[1]->m_osVal[i] == '^' )
+                    continue;
+                if( expr->m_aoChildren[1]->m_osVal[i] == '.' )
+                {
+                    if( i+1<nSize &&
+                        expr->m_aoChildren[1]->m_osVal[i+1] == '*' )
+                    {
+                        osRE += "%";
+                        i++;
+                    }
+                    else
+                    {
+                        osRE += "_";
+                    }
+                }
+                else if( expr->m_aoChildren[1]->m_osVal[i] == '\\' &&
+                         i+1<nSize )
+                {
+                    bHasUsedEscape = true;
+                    osRE += 'X';
+                    osRE += expr->m_aoChildren[1]->m_osVal[i+1];
+                    i++;
+                }
+                else if( expr->m_aoChildren[1]->m_osVal[i] == 'X' ||
+                         expr->m_aoChildren[1]->m_osVal[i] == '%' ||
+                         expr->m_aoChildren[1]->m_osVal[i] == '_' )
+                {
+                    bHasUsedEscape = true;
+                    osRE += 'X';
+                    osRE += expr->m_aoChildren[1]->m_osVal[i];
+                }
+                else
+                {
+                    osRE += expr->m_aoChildren[1]->m_osVal[i];
+                }
+            }
+            osRE += "'";
+            char md_item_name[256];
+            snprintf( md_item_name, sizeof(md_item_name), "gml_%s_type",
+                        expr->m_aoChildren[0]->m_osVal.c_str() );
+            const char* type =
+                        msLookupHashTable(&(layer->metadata), md_item_name);
+            // Cast if needed (or unsure)
+            if( type == NULL || !EQUAL(type, "Character") )
+            {
+                osTmp1 = "CAST(" + osTmp1 + " AS CHARACTER(4096))";
+            }
+            std::string osRet( "(" + osTmp1 + " LIKE " + osRE );
+            if( bHasUsedEscape )
+                osRet += " ESCAPE 'X'";
+            osRet += ")";
+            return osRet;
+        }
+
+        case MS_TOKEN_COMPARISON_IN:
+        {
+            std::string osTmp1(msOGRTranslatePartialInternal(
+                layer, expr->m_aoChildren[0], spatialFilterNode, bPartialFilter ));
+            std::string osRet = "(" + osTmp1 + " IN (";
+            for( size_t i=0; i< expr->m_aoChildren[1]->m_aoChildren.size(); ++i )
+            {
+                if( i > 0 )
+                    osRet += ", ";
+                osRet += msOGRTranslatePartialInternal(
+                            layer, expr->m_aoChildren[1]->m_aoChildren[i],
+                            spatialFilterNode, bPartialFilter );
+            }
+            osRet += ")";
+            return osRet;
+        }
+
+        case MS_TOKEN_LITERAL_NUMBER:
+        case MS_TOKEN_LITERAL_BOOLEAN:
+        {
+            return std::string(CPLSPrintf("%.18g", expr->m_dfVal));
+        }
+
+        case MS_TOKEN_LITERAL_STRING:
+        {
+            char *stresc = msOGREscapeSQLParam(layer, expr->m_osVal.c_str());
+            std::string osRet("'" + std::string(stresc) + "'");
+            msFree(stresc);
+            return osRet;
+        }
+
+        case MS_TOKEN_LITERAL_TIME:
+        {
+#ifdef notdef
+            // Breaks tests in msautotest/wxs/wfs_time_ogr.map
+            return std::string(CPLSPrintf("'%04d/%02d/%02d %02d:%02d:%02d'",
+                     expr->m_tmVal.tm_year+1900,
+                     expr->m_tmVal.tm_mon+1,
+                     expr->m_tmVal.tm_mday,
+                     expr->m_tmVal.tm_hour,
+                     expr->m_tmVal.tm_min,
+                     expr->m_tmVal.tm_sec));
+#endif
+            return std::string();
+        }
+
+        case MS_TOKEN_BINDING_DOUBLE:
+        case MS_TOKEN_BINDING_INTEGER:
+        case MS_TOKEN_BINDING_STRING:
+        case MS_TOKEN_BINDING_TIME:
+        {
+            char* pszTmp = msOGRGetQuotedItem(layer, expr->m_osVal.c_str());
+            std::string osRet(pszTmp);
+            msFree(pszTmp);
+            return osRet;
+        }
+
+        case MS_TOKEN_COMPARISON_INTERSECTS:
+        {
+            if( expr != spatialFilterNode )
+                bPartialFilter = true;
+            return std::string();
+        }
+
+        default:
+        {
+            bPartialFilter = true;
+            return std::string();
+        }
+    }
+}
+
 #endif /* def USE_OGR */
 
 /* ==================================================================
@@ -3053,25 +3715,61 @@ static int msOGRTranslateMsExpressionToOGRSQL(layerObj* layer,
 #ifdef USE_OGR
     msOGRFileInfo *info = (msOGRFileInfo *)layer->layerinfo;
 
+    msFree(layer->filter.native_string);
+    layer->filter.native_string = NULL;
+
+    msFree(info->pszWHERE);
+    info->pszWHERE = NULL;
+
     // 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;
     }
 
+    tokenListNodeObjPtr node = psFilter->tokens;
+    msExprNode* expr = BuildExprTree(node, NULL, 0);
+    info->rect_is_defined = MS_FALSE;
+    const msExprNode* spatialFilterNode = NULL;
+    if( expr )
+        msOGRExtractTopSpatialFilter( info, expr, &spatialFilterNode );
+
     // more reasons to not produce native string: not a recognized driver
-    if (!info->dialect) {
+    if (!info->dialect)
+    {
+        // in which case we might still want to try to get a partial WHERE clause
+        if( filteritem == NULL && expr )
+        {
+            bool bPartialFilter = false;
+            std::string osSQL( msOGRTranslatePartialInternal(layer, expr,
+                                                             spatialFilterNode,
+                                                             bPartialFilter) );
+            if( !osSQL.empty() )
+            {
+                info->pszWHERE = msStrdup(osSQL.c_str());
+                if( bPartialFilter )
+                {
+                    msDebug("Full filter has only been partially "
+                            "translated to OGR filter %s\n",
+                            info->pszWHERE);
+                }
+            }
+            else if( bPartialFilter )
+            {
+                msDebug("Filter could not be translated to OGR filter\n");
+            }
+        }
+        delete expr;
         return MS_SUCCESS;
     }
 
     char *sql = NULL;
 
-    tokenListNodeObjPtr node = psFilter->tokens;
-    // node may be NULL if layer->filter.string != NULL and layer->filteritem != NULL
+    // node may be NULL if layer->filter.string != NULL and filteritem != NULL
     // this is simple filter but string is regex
-    if (node == NULL && layer->filteritem != NULL && layer->filter.string != NULL) {
+    if (node == NULL && filteritem != NULL && layer->filter.string != NULL) {
         sql = msStringConcatenate(sql, "\"");
-        sql = msStringConcatenate(sql, layer->filteritem);
+        sql = msStringConcatenate(sql, filteritem);
         sql = msStringConcatenate(sql, "\"");
         if (EQUAL(info->dialect, "PostgreSQL") ) {
             sql = msStringConcatenate(sql, " ~ ");
@@ -3082,54 +3780,7 @@ static int msOGRTranslateMsExpressionToOGRSQL(layerObj* layer,
         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) {
@@ -3223,12 +3874,38 @@ static int msOGRTranslateMsExpressionToOGRSQL(layerObj* layer,
     }
 
     layer->filter.native_string = sql;
+    delete expr;
     return MS_SUCCESS;
 fail:
     // error producing native string
-    fprintf(stderr, "Note: Error parsing token list, could produce only: %s\n", sql);
+    msDebug("Note: Error parsing token list, could produce only: %s. Trying in partial mode\n", sql);
     msFree(sql);
-    return MS_FAILURE;
+
+    // in which case we might still want to try to get a partial WHERE clause
+    if( expr )
+    {
+        bool bPartialFilter = false;
+        std::string osSQL( msOGRTranslatePartialInternal(layer, expr,
+                                                            spatialFilterNode,
+                                                            bPartialFilter) );
+        if( !osSQL.empty() )
+        {
+            info->pszWHERE = msStrdup(osSQL.c_str());
+            if( bPartialFilter )
+            {
+                msDebug("Full filter has only been partially "
+                        "translated to OGR filter %s\n",
+                        info->pszWHERE);
+            }
+        }
+        else if( bPartialFilter )
+        {
+            msDebug("Filter could not be translated to OGR filter\n");
+        }
+    }
+    delete expr;
+
+    return MS_SUCCESS;
 #else
   /* ------------------------------------------------------------------
    * OGR Support not included...
diff --git a/maporaclespatial.c b/maporaclespatial.c
index afc679c..2f44ebc 100644
--- a/maporaclespatial.c
+++ b/maporaclespatial.c
@@ -38,6 +38,7 @@
 
 #include "mapserver.h"
 #include "maptime.h" 
+#include "mapows.h"
 #include <assert.h>
 
 
@@ -399,8 +400,10 @@ static int msSplitData( char *data, char **geometry_column_name, char **table_na
       break; /* stop on spaces */
     /* double the size of the table_name array if necessary */
     if (i == table_name_size) {
+      size_t tgt_offset = tgt - *table_name;
       table_name_size *= 2;
       *table_name = (char *) realloc(*table_name,sizeof(char *) * table_name_size);
+      tgt = *table_name + tgt_offset;
     }
     *tgt = *src;
   }
diff --git a/mappostgis.c b/mappostgis.c
index 4bec985..cc4edf8 100644
--- a/mappostgis.c
+++ b/mappostgis.c
@@ -3636,9 +3636,13 @@ int msPostGISLayerTranslateFilter(layerObj *layer, expressionObj *filter, char *
             native_string = msStringConcatenate(native_string, "FALSE");
           break;
         case MS_TOKEN_LITERAL_NUMBER:
-	  strtmpl = "%lf";
-          snippet = (char *) msSmallMalloc(strlen(strtmpl) + 16);
-          sprintf(snippet, strtmpl, node->tokenval.dblval);
+          snippet = (char *) msSmallMalloc(32);
+          if( node->tokenval.dblval >= INT_MIN &&
+              node->tokenval.dblval <= INT_MAX &&
+              node->tokenval.dblval == (int)node->tokenval.dblval )
+              sprintf(snippet, "%d", (int)node->tokenval.dblval);
+          else
+              sprintf(snippet, "%.18g", node->tokenval.dblval);
           native_string = msStringConcatenate(native_string, snippet);
           msFree(snippet);
           break;
diff --git a/mapproject.c b/mapproject.c
index 1a10390..c90cc54 100644
--- a/mapproject.c
+++ b/mapproject.c
@@ -954,6 +954,40 @@ int msProjectRect(projectionObj *in, projectionObj *out, rectObj *rect)
   char *over = "+over";
   int ret;
   projectionObj in_over,out_over,*inp,*outp;
+
+#if USE_PROJ
+  /* Detect projecting from north polar stereographic to longlat */
+  if( in && !in->gt.need_geotransform &&
+      out && !out->gt.need_geotransform &&
+      !pj_is_latlong(in->proj) && pj_is_latlong(out->proj) )
+  {
+      pointObj p;
+      p.x = 0.0;
+      p.y = 0.0;
+      if( msProjectPoint(in, out, &p) == MS_SUCCESS &&
+          fabs(p.y - 90) < 1e-8 )
+      {
+        /* Is the pole in the rectangle ? */
+        if( 0 >= rect->minx && 0 >= rect->miny &&
+            0 <= rect->maxx && 0 <= rect->maxy )
+        {
+            if( msProjectRectAsPolygon(in, out, rect ) == MS_SUCCESS )
+            {
+                rect->minx = -180.0;
+                rect->maxx = 180.0;
+                rect->maxy = 90.0;
+                return MS_SUCCESS;
+            }
+        }
+        /* Are we sure the dateline is not enclosed ? */
+        else if( rect->maxy < 0 || rect->maxx < 0 || rect->minx > 0 )
+        {
+            return msProjectRectAsPolygon(in, out, rect );
+        }
+      }
+  }
+#endif
+
   /* 
    * Issue #4892: When projecting a rectangle we do not want proj to wrap resulting
    * coordinates around the dateline, as in practice a requested bounding box of
diff --git a/mapquery.c b/mapquery.c
index 968354a..df0b2ee 100644
--- a/mapquery.c
+++ b/mapquery.c
@@ -673,6 +673,7 @@ int msQueryByFilter(mapObj *map)
   const rectObj invalid_rect = MS_INIT_INVALID_RECT;
 
   shapeObj shape;
+  int paging;
 
   int nclasses = 0;
   int *classgroup = NULL;
@@ -732,12 +733,14 @@ int msQueryByFilter(mapObj *map)
       if((lp->mingeowidth > 0) && ((map->extent.maxx - map->extent.minx) < lp->mingeowidth)) continue;
     }
 
+    paging = msLayerGetPaging(lp);
     msLayerClose(lp); /* reset */
     status = msLayerOpen(lp);
     if(status != MS_SUCCESS) goto query_error;
+    msLayerEnablePaging(lp, paging);
 
     /* disable driver paging */
-    msLayerEnablePaging(lp, MS_FALSE);
+    // msLayerEnablePaging(lp, MS_FALSE);
         
     old_filteritem = lp->filteritem; /* cache the existing filter/filteritem */
     msInitExpression(&old_filter);
@@ -815,7 +818,7 @@ int msQueryByFilter(mapObj *map)
 #endif
 
       /* Should we skip this feature? */
-      if (!msLayerGetPaging(lp) && map->query.startindex > 1) {
+      if (!paging && map->query.startindex > 1) {
         --map->query.startindex;
         msFreeShape(&shape);
         continue;
diff --git a/mapresample.c b/mapresample.c
index c1a98b2..b0fa1c1 100644
--- a/mapresample.c
+++ b/mapresample.c
@@ -83,7 +83,8 @@ msNearestRasterResampler( imageObj *psSrcImage, rasterBufferObj *src_rb,
                           imageObj *psDstImage, rasterBufferObj *dst_rb,
                           int *panCMap,
                           SimpleTransformer pfnTransform, void *pCBData,
-                          int debug, rasterBufferObj *mask_rb )
+                          int debug, rasterBufferObj *mask_rb,
+                          int bWrapAtLeftRight )
 
 {
   double  *x, *y;
@@ -122,6 +123,9 @@ msNearestRasterResampler( imageObj *psSrcImage, rasterBufferObj *src_rb,
       nSrcX = (int) x[nDstX];
       nSrcY = (int) y[nDstX];
 
+      if( bWrapAtLeftRight && nSrcX >= nSrcXSize && nSrcX < 2 * nSrcXSize )
+          nSrcX -= nSrcXSize;
+
       /*
        * We test the original floating point values to
        * avoid errors related to asymmetric rounding around zero.
@@ -302,7 +306,8 @@ msBilinearRasterResampler( imageObj *psSrcImage, rasterBufferObj *src_rb,
                            imageObj *psDstImage, rasterBufferObj *dst_rb,
                            int *panCMap,
                            SimpleTransformer pfnTransform, void *pCBData,
-                           int debug, rasterBufferObj *mask_rb )
+                           int debug, rasterBufferObj *mask_rb,
+                           int bWrapAtLeftRight )
 
 {
   double  *x, *y;
@@ -359,31 +364,32 @@ msBilinearRasterResampler( imageObj *psSrcImage, rasterBufferObj *src_rb,
       dfRatioY2 = y[nDstX] - nSrcY;
 
       /* If we are right off the source, skip this pixel */
-      if( nSrcX2 < 0 || nSrcX >= nSrcXSize
+      if( nSrcX2 < 0 || (!bWrapAtLeftRight && nSrcX >= nSrcXSize)
           || nSrcY2 < 0 || nSrcY >= nSrcYSize )
         continue;
 
       /* Trim in stuff one pixel off the edge */
       nSrcX = MS_MAX(nSrcX,0);
       nSrcY = MS_MAX(nSrcY,0);
-      nSrcX2 = MS_MIN(nSrcX2,nSrcXSize-1);
+      if( !bWrapAtLeftRight )
+        nSrcX2 = MS_MIN(nSrcX2,nSrcXSize-1);
       nSrcY2 = MS_MIN(nSrcY2,nSrcYSize-1);
 
       memset( padfPixelSum, 0, sizeof(double) * bandCount);
 
-      msSourceSample( psSrcImage, src_rb, nSrcX, nSrcY, padfPixelSum,
+      msSourceSample( psSrcImage, src_rb, nSrcX % nSrcXSize, nSrcY, padfPixelSum,
                       (1.0 - dfRatioX2) * (1.0 - dfRatioY2),
                       &dfWeightSum );
 
-      msSourceSample( psSrcImage, src_rb, nSrcX2, nSrcY, padfPixelSum,
+      msSourceSample( psSrcImage, src_rb, nSrcX2 % nSrcXSize, nSrcY, padfPixelSum,
                       (dfRatioX2) * (1.0 - dfRatioY2),
                       &dfWeightSum );
 
-      msSourceSample( psSrcImage, src_rb, nSrcX, nSrcY2, padfPixelSum,
+      msSourceSample( psSrcImage, src_rb, nSrcX % nSrcXSize, nSrcY2, padfPixelSum,
                       (1.0 - dfRatioX2) * (dfRatioY2),
                       &dfWeightSum );
 
-      msSourceSample( psSrcImage, src_rb, nSrcX2, nSrcY2, padfPixelSum,
+      msSourceSample( psSrcImage, src_rb, nSrcX2 % nSrcXSize, nSrcY2, padfPixelSum,
                       (dfRatioX2) * (dfRatioY2),
                       &dfWeightSum );
 
@@ -1200,8 +1206,17 @@ static int msTransformMapToSource( int nDstXSize, int nDstYSize,
                             +   (dfLonWrap-180)*adfInvSrcGeoTransform[4]
                             +   dfY*adfInvSrcGeoTransform[5];
 
-                psSrcExtent->minx = MS_MIN(psSrcExtent->minx, x_out);
-                psSrcExtent->maxx = MS_MAX(psSrcExtent->maxx, x_out);
+                /* Does the raster cover a whole 360 deg range ? */
+                if( nSrcXSize == (int)(adfInvSrcGeoTransform[1] * 360 + 0.5) )
+                {
+                    psSrcExtent->minx = 0;
+                    psSrcExtent->maxx = nSrcXSize;
+                }
+                else
+                {
+                    psSrcExtent->minx = MS_MIN(psSrcExtent->minx, x_out);
+                    psSrcExtent->maxx = MS_MAX(psSrcExtent->maxx, x_out);
+                }
                 psSrcExtent->miny = MS_MIN(psSrcExtent->miny, y_out);
                 psSrcExtent->maxy = MS_MAX(psSrcExtent->maxy, y_out);
           }
@@ -1216,8 +1231,17 @@ static int msTransformMapToSource( int nDstXSize, int nDstYSize,
                             +   (dfLonWrap+180)*adfInvSrcGeoTransform[4]
                             +   dfY*adfInvSrcGeoTransform[5];
 
-                psSrcExtent->minx = MS_MIN(psSrcExtent->minx, x_out);
-                psSrcExtent->maxx = MS_MAX(psSrcExtent->maxx, x_out);
+                /* Does the raster cover a whole 360 deg range ? */
+                if( nSrcXSize == (int)(adfInvSrcGeoTransform[1] * 360 + 0.5) )
+                {
+                    psSrcExtent->minx = 0;
+                    psSrcExtent->maxx = nSrcXSize;
+                }
+                else
+                {
+                    psSrcExtent->minx = MS_MIN(psSrcExtent->minx, x_out);
+                    psSrcExtent->maxx = MS_MAX(psSrcExtent->maxx, x_out);
+                }
                 psSrcExtent->miny = MS_MIN(psSrcExtent->miny, y_out);
                 psSrcExtent->maxy = MS_MAX(psSrcExtent->maxy, y_out);
           }
@@ -1282,6 +1306,7 @@ int msResampleGDALToMap( mapObj *map, layerObj *layer, imageObj *image,
   double      dfOversampleRatio;
   rasterBufferObj src_rb, *psrc_rb = NULL, *mask_rb = NULL;
   int         bAddPixelMargin = MS_TRUE;
+  int         bWrapAtLeftRight = MS_FALSE;
 
 
   const char *resampleMode = CSLFetchNameValue( layer->processing,
@@ -1471,7 +1496,16 @@ int msResampleGDALToMap( mapObj *map, layerObj *layer, imageObj *image,
     sqrt(adfSrcGeoTransform[1] * adfSrcGeoTransform[1]
          + adfSrcGeoTransform[2] * adfSrcGeoTransform[2]);
 
-  if( (sOrigSrcExtent.maxx - sOrigSrcExtent.minx) > dfOversampleRatio * nDstXSize
+  /* Check first that the requested extent is not well beyond than the source */
+  /* raster. This might be the case for example if asking to visualize */
+  /* -180,-89,180,90 in EPSG:4326 from a raster in Arctic Polar Stereographic */
+  /* But restrict that to rasters of modest size, otherwise we may end up */
+  /* requesting very large dimensions in other legit reprojection cases */
+  /* See https://github.com/mapserver/mapserver/issues/5402 */
+  if( !(sOrigSrcExtent.minx <= -4 * nSrcXSize  && sOrigSrcExtent.miny <= -4 * nSrcYSize &&
+        sOrigSrcExtent.maxx >= 5 * nSrcXSize && sOrigSrcExtent.maxy >= 5 * nSrcYSize &&
+        nSrcXSize < 4000 && nSrcYSize < 4000)
+      && (sOrigSrcExtent.maxx - sOrigSrcExtent.minx) > dfOversampleRatio * nDstXSize
       && !CSLFetchBoolean( layer->processing, "LOAD_FULL_RES_IMAGE", FALSE ))
     sDummyMap.cellsize =
       (dfNominalCellSize * (sOrigSrcExtent.maxx - sOrigSrcExtent.minx))
@@ -1509,6 +1543,18 @@ int msResampleGDALToMap( mapObj *map, layerObj *layer, imageObj *image,
   adfSrcGeoTransform[4] *= (sDummyMap.cellsize / dfNominalCellSize);
   adfSrcGeoTransform[5] *= (sDummyMap.cellsize / dfNominalCellSize);
 
+  /* In the non-rotated case, make sure that the geotransform exactly */
+  /* matches the sSrcExtent, even if that generates non-square pixels (#1715) */
+  /* The rotated case should ideally be dealt with, but not for now... */
+  if( adfSrcGeoTransform[2] == 0 && adfSrcGeoTransform[4] == 0 &&
+      adfSrcGeoTransform[5] < 0 )
+  {
+      adfSrcGeoTransform[1] = (sSrcExtent.maxx - sSrcExtent.minx) *
+                                            dfNominalCellSize / nLoadImgXSize;
+      adfSrcGeoTransform[5] = -(sSrcExtent.maxy - sSrcExtent.miny) *
+                                            dfNominalCellSize / nLoadImgYSize;
+  }
+
   papszAlteredProcessing = CSLDuplicate( layer->processing );
   papszAlteredProcessing =
     CSLSetNameValue( papszAlteredProcessing, "RAW_WINDOW",
@@ -1629,6 +1675,13 @@ int msResampleGDALToMap( mapObj *map, layerObj *layer, imageObj *image,
   /* -------------------------------------------------------------------- */
   pACBData = msInitApproxTransformer( msProjTransformer, pTCBData, 0.333 );
 
+  if( pj_is_latlong(layer->projection.proj) )
+  {
+      /* Does the raster cover a whole 360 deg range ? */
+      if( nSrcXSize == (int)(adfInvSrcGeoTransform[1] * 360 + 0.5) )
+          bWrapAtLeftRight = MS_TRUE;
+  }
+
   /* -------------------------------------------------------------------- */
   /*      Perform the resampling.                                         */
   /* -------------------------------------------------------------------- */
@@ -1641,12 +1694,12 @@ int msResampleGDALToMap( mapObj *map, layerObj *layer, imageObj *image,
     result =
       msBilinearRasterResampler( srcImage, psrc_rb, image, rb,
                                  anCMap, msApproxTransformer, pACBData,
-                                 layer->debug, mask_rb );
+                                 layer->debug, mask_rb, bWrapAtLeftRight );
   else
     result =
       msNearestRasterResampler( srcImage, psrc_rb, image, rb,
                                 anCMap, msApproxTransformer, pACBData,
-                                layer->debug, mask_rb );
+                                layer->debug, mask_rb, bWrapAtLeftRight );
 
   /* -------------------------------------------------------------------- */
   /*      cleanup                                                         */
diff --git a/mapscript/python/pymodule.i b/mapscript/python/pymodule.i
index 08b7a6d..76b68ee 100644
--- a/mapscript/python/pymodule.i
+++ b/mapscript/python/pymodule.i
@@ -102,6 +102,46 @@ CreateTupleFromDoubleArray( double *first, unsigned int size ) {
   $result = t_output_helper($result,r);
 }
 
+
+/*
+ * Typemap hashTableObj* -> dict
+ */
+%typemap(out) hashTableObj*
+{
+  /* %typemap(out) hashTableObj* */
+  const char* key;
+  hashTableObj *hashTable = $1;
+  $result = PyDict_New();
+  key = msFirstKeyFromHashTable(hashTable);
+  while( key )
+  {
+    const char* val = msLookupHashTable(hashTable, key);
+    if( val )
+    {
+#if PY_VERSION_HEX >= 0x03000000
+        PyObject *py_key = PyUnicode_FromString(key);
+        PyObject *py_val = PyUnicode_FromString(val);
+#else
+        PyObject *py_key = PyString_FromString(key);
+        PyObject *py_val = PyString_FromString(val);
+#endif
+
+        PyDict_SetItem($result, py_key, py_val );
+        Py_DECREF(py_key);
+        Py_DECREF(py_val);
+    }
+    key = msNextKeyFromHashTable(hashTable, key);
+  }
+}
+
+%typemap(freearg) hashTableObj*
+{
+  /* %typemap(freearg) hashTableObj* */
+  msFreeHashTable( $1 );
+}
+
+
+
 /**************************************************************************
  * MapServer Errors and Python Exceptions
  **************************************************************************
diff --git a/mapscript/swiginc/msio.i b/mapscript/swiginc/msio.i
index 45fe745..3cee64d 100644
--- a/mapscript/swiginc/msio.i
+++ b/mapscript/swiginc/msio.i
@@ -45,6 +45,11 @@ void msIO_stripStdoutBufferContentHeaders(void);
 const char *msIO_getStdoutBufferString(void);
 gdBuffer msIO_getStdoutBufferBytes(void);
 
+#ifdef SWIGPYTHON
+%newobject msIO_getAndStripStdoutBufferMimeHeaders;
+hashTableObj* msIO_getAndStripStdoutBufferMimeHeaders(void);
+#endif
+
 %{
 
 const char *msIO_getStdoutBufferString() {
diff --git a/mapshape.c b/mapshape.c
index f1f71a5..7b72020 100644
--- a/mapshape.c
+++ b/mapshape.c
@@ -1934,6 +1934,10 @@ int msTiledSHPOpenFile(layerObj *layer)
 
   msTiledSHPLayerInfo *tSHP=NULL;
 
+  if (layer->layerinfo != NULL) {
+    return MS_SUCCESS;  // Nothing to do... layer is already opened
+  }
+
   if ( msCheckParentPointer(layer->map,"map")==MS_FAILURE )
     return MS_FAILURE;
 
@@ -2206,6 +2210,7 @@ int msTiledSHPNextShape(layerObj *layer, shapeObj *shape)
             continue;
           } else if(status != MS_SUCCESS) {
             msShapefileClose(tSHP->shpfile);
+            tSHP->tileshpfile->lastshape = -1;
             return(MS_FAILURE);
           }
 
@@ -2214,7 +2219,10 @@ int msTiledSHPNextShape(layerObj *layer, shapeObj *shape)
           break;
         }
 
-        if(status == MS_DONE) return(MS_DONE); /* no more tiles */
+        if(status == MS_DONE) {
+            tSHP->tileshpfile->lastshape = -1;
+            return(MS_DONE); /* no more tiles */
+        }
         else {
           msFreeShape(&tshape);
           continue; /* we've got shapes */
@@ -2248,6 +2256,7 @@ int msTiledSHPNextShape(layerObj *layer, shapeObj *shape)
               continue;
             } else if(status != MS_SUCCESS) {
               msShapefileClose(tSHP->shpfile);
+              tSHP->tileshpfile->lastshape = -1;
               return(MS_FAILURE);
             }
 
@@ -2256,7 +2265,10 @@ int msTiledSHPNextShape(layerObj *layer, shapeObj *shape)
           }
         } /* end for loop */
 
-        if(i == tSHP->tileshpfile->numshapes) return(MS_DONE); /* no more tiles */
+        if(i == tSHP->tileshpfile->numshapes) {
+            tSHP->tileshpfile->lastshape = -1;
+            return(MS_DONE); /* no more tiles */
+        }
         else continue; /* we've got shapes */
       }
     }
@@ -2304,6 +2316,8 @@ int msTiledSHPGetShape(layerObj *layer, shapeObj *shape, resultObj *record)
     return(MS_FAILURE);
   }
 
+  msTileIndexAbsoluteDir(tiFileAbsDir, layer);
+
   if((tileindex < 0) || (tileindex >= tSHP->tileshpfile->numshapes)) return(MS_FAILURE); /* invalid tile id */
 
   if(tileindex != tSHP->tileshpfile->lastshape) { /* correct tile is not currenly open so open the correct tile */
@@ -2332,6 +2346,7 @@ int msTiledSHPGetShape(layerObj *layer, shapeObj *shape, resultObj *record)
 
   msSHPReadShape(tSHP->shpfile->hSHP, shapeindex, shape);
   tSHP->shpfile->lastshape = shapeindex;
+  tSHP->tileshpfile->lastshape = tileindex;
 
   if(layer->numitems > 0 && layer->iteminfo) {
     shape->numvalues = layer->numitems;
@@ -2624,8 +2639,8 @@ int msSHPLayerOpen(layerObj *layer)
             }
             OSRDestroySpatialReference(hSRS);
         }
+      fclose(fp);
     }
-    fclose(fp);
 
     if( bOK != MS_TRUE )
     {
diff --git a/mapwms.c b/mapwms.c
index 6dc4ebf..1b09109 100644
--- a/mapwms.c
+++ b/mapwms.c
@@ -791,7 +791,6 @@ int msWMSLoadGetMapParams(mapObj *map, int nVersion,
                           const char *wms_request, owsRequestObj *ows_request)
 {
   int i, adjust_extent = MS_FALSE, nonsquare_enabled = MS_FALSE;
-  int nLayerOrder = 0;
   int transparent = MS_NOOVERRIDE;
   int bbox_pixel_is_point = MS_FALSE;
   outputFormatObj *format = NULL;
@@ -870,6 +869,7 @@ int msWMSLoadGetMapParams(mapObj *map, int nVersion,
 
     if (strcasecmp(names[i], "LAYERS") == 0) {
       int  j, k, iLayer, *layerOrder;
+      int nLayerOrder = 0;
       char ***nestedGroups = NULL;
       int *numNestedGroups = NULL;
       int *isUsedInNestedGroup = NULL;

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