Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package mapserver for openSUSE:Factory 
checked in at 2026-03-28 20:14:02
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/mapserver (Old)
 and      /work/SRC/openSUSE:Factory/.mapserver.new.8177 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "mapserver"

Sat Mar 28 20:14:02 2026 rev:11 rq:1343220 version:8.6.1

Changes:
--------
--- /work/SRC/openSUSE:Factory/mapserver/mapserver.changes      2026-03-03 
15:31:39.450841657 +0100
+++ /work/SRC/openSUSE:Factory/.mapserver.new.8177/mapserver.changes    
2026-03-28 20:15:45.131368804 +0100
@@ -1,0 +2,15 @@
+Fri Mar 27 11:52:01 UTC 2026 - Jan Engelhardt <[email protected]>
+
+- Update to release 8.6.1
+  * msSLDParseRasterSymbolizer: fix potential heap buffer overflow
+    [boo#1260869] [CVE-2026-33721]
+  * GetFeatureInfo with IDENTIFY CLASSAUTO: take into account
+    SYMBOL.ANCHORPOINT
+  * WCS 2.0: fix issue when input raster in a rotated pole lon/lat
+    CRS with lon_0 > 180
+  * UVRaster: fix WMS-Time support on layers with TILEINDEX
+    pointing to a shapefile
+  * WMS GetCapabilities response: use group title and abstract when
+    using wms_layer_group instead of GROUP
+
+-------------------------------------------------------------------

Old:
----
  mapserver-8.6.0.tar.gz

New:
----
  mapserver-8.6.1.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ mapserver.spec ++++++
--- /var/tmp/diff_new_pack.OYgnzZ/_old  2026-03-28 20:15:45.615388780 +0100
+++ /var/tmp/diff_new_pack.OYgnzZ/_new  2026-03-28 20:15:45.619388945 +0100
@@ -33,7 +33,7 @@
 %{?sle15_python_module_pythons}
 
 Name:           mapserver
-Version:        8.6.0
+Version:        8.6.1
 Release:        0
 Summary:        Environment for building spatially-enabled internet 
applications
 License:        MIT
@@ -50,8 +50,13 @@
 BuildRequires:  cmake >= 2.4
 BuildRequires:  freetype2-devel
 BuildRequires:  fribidi-devel
+%if 0%{?suse_version} < 1590
+BuildRequires:  gcc13
+BuildRequires:  gcc13-c++
+%else
 BuildRequires:  gcc
 BuildRequires:  gcc-c++
+%endif
 BuildRequires:  gd-devel >= 2.0.16
 BuildRequires:  giflib-devel
 BuildRequires:  harfbuzz-devel
@@ -205,14 +210,18 @@
 #Pre export the PREFIX ( having it on the command line doesn't expand 
correctly for
 #dynamic postgresql location
 export CMAKE_PREFIX_PATH="%{_includedir}:%{_includedir}/fastcgi:%%(pg_config 
--includedir):%%(pg_config --includedir-server):%%(pg_config --libdir)"
+%if 0%{?suse_version} < 1590
+export CC=gcc-13 CXX=g++-13
+%endif
 export CFLAGS="%{optflags} -fno-strict-aliasing"
 export CXXFLAGS="%{optflags} -fno-strict-aliasing"
 
 #specify all options and play with true/false
 #so we always know which option are included in our build.
 %{python_expand #
+origpwd="$PWD"
 mkdir b$python
-pushd b$python
+cd b$python
 cmake -DCMAKE_INSTALL_PREFIX=%{_prefix} \
         -DCMAKE_SKIP_RPATH=ON \
         -DCMAKE_INSTALL_LIBDIR=%{_libdir} \
@@ -276,7 +285,7 @@
         ..
 
 %make_build
-popd
+cd "$origpwd"
 }
 
 %check
@@ -286,9 +295,9 @@
 mkdir -p %{buildroot}/%{_cgibindir}
 
 %{python_expand #
-pushd b$python
+cd b$python
 %make_install
-popd
+cd -
 }
 
 %if 0%{with php}

++++++ _scmsync.obsinfo ++++++
--- /var/tmp/diff_new_pack.OYgnzZ/_old  2026-03-28 20:15:45.647390101 +0100
+++ /var/tmp/diff_new_pack.OYgnzZ/_new  2026-03-28 20:15:45.651390266 +0100
@@ -1,5 +1,5 @@
-mtime: 1772469939
-commit: 38fd2136019976e263221ce355a9c8470af35e741a692dc777b9949702b66ca6
+mtime: 1774624531
+commit: 529d913ae5b120e667a50862589bb50bf593708fa299424c777fac7e7b090b9e
 url: https://src.opensuse.org/jengelh/mapserver
 revision: master
 

++++++ build.specials.obscpio ++++++

++++++ build.specials.obscpio ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/.gitignore new/.gitignore
--- old/.gitignore      1970-01-01 01:00:00.000000000 +0100
+++ new/.gitignore      2026-03-27 16:15:44.000000000 +0100
@@ -0,0 +1 @@
+.osc

++++++ mapserver-8.6.0.tar.gz -> mapserver-8.6.1.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/mapserver-8.6.0/CITATION.cff 
new/mapserver-8.6.1/CITATION.cff
--- old/mapserver-8.6.0/CITATION.cff    2025-12-03 16:04:40.000000000 +0100
+++ new/mapserver-8.6.1/CITATION.cff    2026-03-23 16:36:42.000000000 +0100
@@ -1,8 +1,8 @@
 cff-version: 1.2.0
 title: MapServer
 message: If you use this software, please cite it using the metadata from this 
file.
-version: 8.6.0
-date-released: 2025-12-03
+version: 8.6.1
+date-released: 2026-03-23
 abstract: MapServer is an Open Source platform for publishing spatial data and 
interactive mapping applications to the web.
 type: software
 authors:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/mapserver-8.6.0/CMakeLists.txt 
new/mapserver-8.6.1/CMakeLists.txt
--- old/mapserver-8.6.0/CMakeLists.txt  2025-12-03 16:04:40.000000000 +0100
+++ new/mapserver-8.6.1/CMakeLists.txt  2026-03-23 16:36:42.000000000 +0100
@@ -17,7 +17,7 @@
 
 set (MapServer_VERSION_MAJOR 8)
 set (MapServer_VERSION_MINOR 6)
-set (MapServer_VERSION_REVISION 0)
+set (MapServer_VERSION_REVISION 1)
 set (MapServer_VERSION_SUFFIX "")
 
 # Set C++ version
@@ -1049,6 +1049,9 @@
 add_definitions(-D_XKEYCHECK_H=1)
 endif(WIN32)
 
+# Defines M_PI in particular
+add_definitions(-D_USE_MATH_DEFINES)
+
 
 #INSTALL(FILES mapserver-api.h ${PROJECT_BINARY_DIR}/mapserver-version.h 
DESTINATION include)
 if(USE_ORACLE_PLUGIN)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/mapserver-8.6.0/HISTORY.md 
new/mapserver-8.6.1/HISTORY.md
--- old/mapserver-8.6.0/HISTORY.md      2025-12-03 16:04:40.000000000 +0100
+++ new/mapserver-8.6.1/HISTORY.md      2026-03-23 16:36:42.000000000 +0100
@@ -13,6 +13,15 @@
 
 The online Migration Guide can be found at 
https://mapserver.org/MIGRATION_GUIDE.html
 
+8.6.1 release (2026-03-23)
+--------------------------
+
+- security: fix potential heap buffer overflow (#7461)
+
+- No longer depend on GDAL's cpl_port.h MIN/MAX/ABS macros (#7438)
+
+see detailed changelog for other fixes
+
 8.6.0 release (2025-12-03)
 --------------------------
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/mapserver-8.6.0/LICENSE.md 
new/mapserver-8.6.1/LICENSE.md
--- old/mapserver-8.6.0/LICENSE.md      2025-12-03 16:04:40.000000000 +0100
+++ new/mapserver-8.6.1/LICENSE.md      2026-03-23 16:36:42.000000000 +0100
@@ -4,7 +4,7 @@
 MapServer General
 -----------------
 
-Copyright (c) 2008-2025 Open Source Geospatial Foundation.  
+Copyright (c) 2008-2026 Open Source Geospatial Foundation.  
 Copyright (c) 1996-2008 Regents of the University of Minnesota.
 
 Permission is hereby granted, free of charge, to any person obtaining a copy 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/mapserver-8.6.0/ci/ubuntu/build.sh 
new/mapserver-8.6.1/ci/ubuntu/build.sh
--- old/mapserver-8.6.0/ci/ubuntu/build.sh      2025-12-03 16:04:40.000000000 
+0100
+++ new/mapserver-8.6.1/ci/ubuntu/build.sh      2026-03-23 16:36:42.000000000 
+0100
@@ -47,10 +47,10 @@
 echo "PHP version"
 php -v
 PHPVersionMinor=$(php --version | head -n 1 | cut -d " " -f 2 | cut -c 1,3)
-if [ ${PHPVersionMinor} -gt 82 ]; then
-    cd php && curl -LO https://phar.phpunit.de/phpunit-12.phar
+if [ ${PHPVersionMinor} -gt 83 ]; then
+    cd php && curl -LO https://phar.phpunit.de/phpunit-13.phar
     echo "PHPUnit version"
-    php phpunit-12.phar --version
+    php phpunit-13.phar --version
 else
     cd php && curl -LO https://phar.phpunit.de/phpunit-10.phar
     echo "PHPUnit version"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/mapserver-8.6.0/src/idw.c 
new/mapserver-8.6.1/src/idw.c
--- old/mapserver-8.6.0/src/idw.c       2025-12-03 16:04:40.000000000 +0100
+++ new/mapserver-8.6.1/src/idw.c       2026-03-23 16:36:42.000000000 +0100
@@ -69,7 +69,7 @@
   if (interpParamsProcessing) {
     interpParams->radius = atof(interpParamsProcessing);
   } else {
-    interpParams->radius = MAX(layer->map->width, layer->map->height);
+    interpParams->radius = MS_MAX(layer->map->width, layer->map->height);
   }
 
   interpParamsProcessing =
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/mapserver-8.6.0/src/mapcontour.c 
new/mapserver-8.6.1/src/mapcontour.c
--- old/mapserver-8.6.0/src/mapcontour.c        2025-12-03 16:04:40.000000000 
+0100
+++ new/mapserver-8.6.1/src/mapcontour.c        2026-03-23 16:36:42.000000000 
+0100
@@ -59,6 +59,10 @@
   OGRDataSourceH hOGRDS;
   double cellsize;
 
+  /* set if the map->extent and map->projection are
+     valid in msContourLayerWhichShapes() */
+  mapObj *mapToUseForWhichShapes;
+
 } contourLayerInfo;
 
 static int msContourLayerInitItemInfo(layerObj *layer) {
@@ -226,12 +230,7 @@
   src_xsize = GDALGetRasterXSize(clinfo->hOrigDS);
   src_ysize = GDALGetRasterYSize(clinfo->hOrigDS);
 
-  /* set the Dataset extent */
   msGetGDALGeoTransform(clinfo->hOrigDS, map, layer, adfGeoTransform);
-  clinfo->extent.minx = adfGeoTransform[0];
-  clinfo->extent.maxy = adfGeoTransform[3];
-  clinfo->extent.maxx = adfGeoTransform[0] + src_xsize * adfGeoTransform[1];
-  clinfo->extent.miny = adfGeoTransform[3] + src_ysize * adfGeoTransform[5];
 
   if (layer->transform) {
     if (layer->debug)
@@ -240,12 +239,41 @@
     InvGeoTransform(adfGeoTransform, adfInvGeoTransform);
 
     mapRect = rect;
-    if (map->cellsize == 0) {
-      map->cellsize = msAdjustExtent(&mapRect, map->width, map->height);
-    }
-    map_cellsize_x = map_cellsize_y = map->cellsize;
+
     /* if necessary, project the searchrect to source coords */
     if (msProjectionsDiffer(&(map->projection), &(layer->projection))) {
+
+      /* Deal with request in WebMercator, overlapping the anti-meridian,
+       * and raster in geographic coordinates within (approximatively)
+       * [-180,180] longitude range.
+       */
+      double map_cellsize_x_override = 0;
+      if (clinfo->mapToUseForWhichShapes) {
+        mapRect = clinfo->mapToUseForWhichShapes->extent;
+        const double WEB_MERCATOR_MAX_X = 20037508.34;
+        if (clinfo->mapToUseForWhichShapes->projection.numargs == 1 &&
+            strcmp(clinfo->mapToUseForWhichShapes->projection.args[0],
+                   "init=epsg:3857") == 0 &&
+            (clinfo->mapToUseForWhichShapes->extent.minx <
+                 -WEB_MERCATOR_MAX_X ||
+             clinfo->mapToUseForWhichShapes->extent.maxx >
+                 WEB_MERCATOR_MAX_X) &&
+            msProjIsGeographicCRS(&layer->projection) &&
+            clinfo->extent.minx > -180 - 2 * adfGeoTransform[1] &&
+            clinfo->extent.maxx < 180 + 2 * adfGeoTransform[1]) {
+
+          // First do a reprojection with +over to compute cellsize_x
+          msProjectRect(&map->projection, &layer->projection, &mapRect);
+          map_cellsize_x_override =
+              MS_CELLSIZE(mapRect.minx, mapRect.maxx, map->width);
+
+          // Then clamp to +/- 180 deg
+          mapRect = clinfo->mapToUseForWhichShapes->extent;
+          mapRect.minx = MS_MAX(mapRect.minx, -WEB_MERCATOR_MAX_X);
+          mapRect.maxx = MS_MIN(mapRect.maxx, WEB_MERCATOR_MAX_X);
+        }
+      }
+
       if (msProjectRect(&map->projection, &layer->projection, &mapRect) !=
           MS_SUCCESS) {
         msDebug("msContourLayerReadRaster(%s): unable to reproject map request 
"
@@ -254,7 +282,10 @@
         return MS_FAILURE;
       }
 
-      map_cellsize_x = MS_CELLSIZE(mapRect.minx, mapRect.maxx, map->width);
+      map_cellsize_x =
+          map_cellsize_x_override != 0
+              ? map_cellsize_x_override
+              : MS_CELLSIZE(mapRect.minx, mapRect.maxx, map->width);
       map_cellsize_y = MS_CELLSIZE(mapRect.miny, mapRect.maxy, map->height);
 
       /* if the projection failed to project the extent requested, we need to
@@ -279,6 +310,11 @@
         map_cellsize_y = MS_CONVERT_UNIT(
             src_unit, dst_unit, MS_CELLSIZE(rect.miny, rect.maxy, 
map->height));
       }
+    } else {
+      if (map->cellsize == 0) {
+        map->cellsize = msAdjustExtent(&mapRect, map->width, map->height);
+      }
+      map_cellsize_x = map_cellsize_y = map->cellsize;
     }
 
     if (map_cellsize_x == 0 || map_cellsize_y == 0) {
@@ -309,19 +345,21 @@
      * there is no point in interpolating the data for contours in this case.
      */
 
-    virtual_grid_step_x = (int)floor(map_cellsize_x / ABS(adfGeoTransform[1]));
+    virtual_grid_step_x =
+        (int)floor(map_cellsize_x / MS_ABS(adfGeoTransform[1]));
     if (virtual_grid_step_x < 1)
       virtual_grid_step_x =
           1; /* Do not interpolate data if grid sampling step < 1 */
 
-    virtual_grid_step_y = (int)floor(map_cellsize_y / ABS(adfGeoTransform[5]));
+    virtual_grid_step_y =
+        (int)floor(map_cellsize_y / MS_ABS(adfGeoTransform[5]));
     if (virtual_grid_step_y < 1)
       virtual_grid_step_y =
           1; /* Do not interpolate data if grid sampling step < 1 */
 
     /* target cellsize is a multiple of raw data cellsize based on grid step*/
-    dst_cellsize_x = ABS(adfGeoTransform[1]) * virtual_grid_step_x;
-    dst_cellsize_y = ABS(adfGeoTransform[5]) * virtual_grid_step_y;
+    dst_cellsize_x = MS_ABS(adfGeoTransform[1]) * virtual_grid_step_x;
+    dst_cellsize_y = MS_ABS(adfGeoTransform[5]) * virtual_grid_step_y;
 
     /* Compute overlap between source and target views */
 
@@ -750,6 +788,19 @@
   } else
     clinfo->hOrigDS = NULL;
 
+  if (clinfo->hOrigDS) {
+    const int src_xsize = GDALGetRasterXSize(clinfo->hOrigDS);
+    const int src_ysize = GDALGetRasterYSize(clinfo->hOrigDS);
+
+    /* set the Dataset extent */
+    double adfGeoTransform[6];
+    msGetGDALGeoTransform(clinfo->hOrigDS, layer->map, layer, adfGeoTransform);
+    clinfo->extent.minx = adfGeoTransform[0];
+    clinfo->extent.maxy = adfGeoTransform[3];
+    clinfo->extent.maxx = adfGeoTransform[0] + src_xsize * adfGeoTransform[1];
+    clinfo->extent.miny = adfGeoTransform[3] + src_ysize * adfGeoTransform[5];
+  }
+
   msReleaseLock(TLOCK_GDAL);
 
   if (clinfo->hOrigDS == NULL) {
@@ -758,24 +809,6 @@
     return MS_FAILURE;
   }
 
-  /* Open the raster source */
-  if (msContourLayerReadRaster(layer, layer->map->extent) != MS_SUCCESS)
-    return MS_FAILURE;
-
-  /* Generate Contour Dataset */
-  if (msContourLayerGenerateContour(layer) != MS_SUCCESS)
-    return MS_FAILURE;
-
-  if (clinfo->hDS) {
-    GDALClose(clinfo->hDS);
-    clinfo->hDS = NULL;
-    free(clinfo->buffer);
-  }
-
-  /* Open our virtual ogr layer */
-  if (clinfo->hOGRDS && (msLayerOpen(&clinfo->ogrLayer) != MS_SUCCESS))
-    return MS_FAILURE;
-
   return MS_SUCCESS;
 }
 
@@ -833,7 +866,13 @@
     layer->items[layer->numitems++] = msStrdup(elevItem);
   }
 
-  return msLayerGetItems(&clinfo->ogrLayer);
+  return MS_SUCCESS;
+}
+
+void msContourLayerUseMapExtentAndProjectionForNextWhichShapes(layerObj *layer,
+                                                               mapObj *map) {
+  contourLayerInfo *clinfo = (contourLayerInfo *)layer->layerinfo;
+  clinfo->mapToUseForWhichShapes = map;
 }
 
 int msContourLayerWhichShapes(layerObj *layer, rectObj rect, int isQuery) {
@@ -900,7 +939,8 @@
     clinfo->ogrLayer.items[i] = msStrdup(layer->items[i]);
   }
 
-  return msLayerWhichShapes(&clinfo->ogrLayer, rect, isQuery);
+  const rectObj invalid_rect = MS_INIT_INVALID_RECT;
+  return msLayerWhichShapes(&clinfo->ogrLayer, invalid_rect, isQuery);
 }
 
 int msContourLayerGetShape(layerObj *layer, shapeObj *shape,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/mapserver-8.6.0/src/mapcopy.c 
new/mapserver-8.6.1/src/mapcopy.c
--- old/mapserver-8.6.0/src/mapcopy.c   2025-12-03 16:04:40.000000000 +0100
+++ new/mapserver-8.6.1/src/mapcopy.c   2026-03-23 16:36:42.000000000 +0100
@@ -56,7 +56,7 @@
  **********************************************************************/
 
 int msCopyProjectionExtended(projectionObj *dst, const projectionObj *src,
-                             char **args, int num_args) {
+                             const char *const *args, int num_args) {
   MS_COPYSTELEM(numargs);
   MS_COPYSTELEM(gt);
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/mapserver-8.6.0/src/mapdraw.c 
new/mapserver-8.6.1/src/mapdraw.c
--- old/mapserver-8.6.0/src/mapdraw.c   2025-12-03 16:04:40.000000000 +0100
+++ new/mapserver-8.6.1/src/mapdraw.c   2026-03-23 16:36:42.000000000 +0100
@@ -1163,6 +1163,8 @@
 
         searchrect = msUVRASTERGetSearchRect(layer, map);
         bDone = MS_TRUE;
+      } else if (layer->connectiontype == MS_CONTOUR) {
+        msContourLayerUseMapExtentAndProjectionForNextWhichShapes(layer, map);
       }
 
       if (!bDone)
@@ -1183,6 +1185,8 @@
     msUVRASTERLayerUseMapExtentAndProjectionForNextWhichShapes(layer, NULL);
   } else if (layer->connectiontype == MS_RASTER_LABEL) {
     msRasterLabelLayerUseMapExtentAndProjectionForNextWhichShapes(layer, NULL);
+  } else if (layer->connectiontype == MS_CONTOUR) {
+    msContourLayerUseMapExtentAndProjectionForNextWhichShapes(layer, NULL);
   }
 
   if (status == MS_DONE) { /* no overlap */
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/mapserver-8.6.0/src/mapdrawgdal.c 
new/mapserver-8.6.1/src/mapdrawgdal.c
--- old/mapserver-8.6.0/src/mapdrawgdal.c       2025-12-03 16:04:40.000000000 
+0100
+++ new/mapserver-8.6.1/src/mapdrawgdal.c       2026-03-23 16:36:42.000000000 
+0100
@@ -601,7 +601,7 @@
 
       const int j =
           bScaleColors
-              ? MAX(0, MIN(255, (int)((i - dfScaleMin) * dfScaleRatio)))
+              ? MS_MAX(0, MS_MIN(255, (int)((i - dfScaleMin) * dfScaleRatio)))
               : i;
 
       pixel.red = sEntry.c1;
@@ -685,7 +685,7 @@
       GDALGetColorEntryAsRGB(hColorMap, i, &sEntry);
       const int j =
           bScaleColors
-              ? MAX(0, MIN(255, (int)((i - dfScaleMin) * dfScaleRatio)))
+              ? MS_MAX(0, MS_MIN(255, (int)((i - dfScaleMin) * dfScaleRatio)))
               : i;
 
       if (sEntry.c4 != 0 &&
@@ -1497,7 +1497,7 @@
     pabyBuffer = pabyWholeBuffer + iColorIndex * nPixelCount;
 
     if (iColorIndex == 0 && bGotNoData)
-      *ppbIsNoDataBuffer = (bool *)calloc(nPixelCount, 1);
+      *ppbIsNoDataBuffer = (bool *)calloc(nPixelCount, sizeof(bool));
 
     for (i = 0; i < nPixelCount; i++) {
       float fScaledValue;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/mapserver-8.6.0/src/mapogcsld.cpp 
new/mapserver-8.6.1/src/mapogcsld.cpp
--- old/mapserver-8.6.0/src/mapogcsld.cpp       2025-12-03 16:04:40.000000000 
+0100
+++ new/mapserver-8.6.1/src/mapogcsld.cpp       2026-03-23 16:36:42.000000000 
+0100
@@ -2894,7 +2894,7 @@
         } else if (strcasecmp(psNode->pszValue, "Threshold") == 0) {
           papszThresholds[nThresholds] = psNode->psChild->pszValue;
           nThresholds++;
-          if (nValues == nMaxThreshold) {
+          if (nThresholds == nMaxThreshold) {
             nMaxThreshold += 100;
             papszThresholds = (char **)msSmallRealloc(
                 papszThresholds, sizeof(char *) * nMaxThreshold);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/mapserver-8.6.0/src/mapogr.cpp 
new/mapserver-8.6.1/src/mapogr.cpp
--- old/mapserver-8.6.0/src/mapogr.cpp  2025-12-03 16:04:40.000000000 +0100
+++ new/mapserver-8.6.1/src/mapogr.cpp  2026-03-23 16:36:42.000000000 +0100
@@ -33,6 +33,8 @@
 #include "mapproject.h"
 #include "mapthread.h"
 #include "mapows.h"
+
+#include <algorithm>
 #include <string>
 #include <vector>
 
@@ -2223,10 +2225,10 @@
      * 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);
+      rect.minx = std::max(psInfo->rect.minx, rect.minx);
+      rect.miny = std::max(psInfo->rect.miny, rect.miny);
+      rect.maxx = std::min(psInfo->rect.maxx, rect.maxx);
+      rect.maxy = std::min(psInfo->rect.maxy, rect.maxy);
       bIsValidRect = true;
     }
     psInfo->rect = rect;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/mapserver-8.6.0/src/mappostgis.cpp 
new/mapserver-8.6.1/src/mappostgis.cpp
--- old/mapserver-8.6.0/src/mappostgis.cpp      2025-12-03 16:04:40.000000000 
+0100
+++ new/mapserver-8.6.1/src/mappostgis.cpp      2026-03-23 16:36:42.000000000 
+0100
@@ -54,9 +54,6 @@
 **
 */
 
-/* required for MSVC */
-#define _USE_MATH_DEFINES
-
 #include <assert.h>
 #include <string.h>
 #include <math.h>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/mapserver-8.6.0/src/mapproject.c 
new/mapserver-8.6.1/src/mapproject.c
--- old/mapserver-8.6.0/src/mapproject.c        2025-12-03 16:04:40.000000000 
+0100
+++ new/mapserver-8.6.1/src/mapproject.c        2026-03-23 16:36:42.000000000 
+0100
@@ -1056,7 +1056,11 @@
     }
   }
 
-  if (!(!in->gt.need_geotransform && !msProjIsGeographicCRS(in) &&
+  const bool isRotatedPole =
+      msProjIsGeographicCRS(in) && in->proj &&
+      proj_crs_is_derived(in->proj_ctx->proj_ctx, in->proj);
+  if (!(!in->gt.need_geotransform &&
+        (!msProjIsGeographicCRS(in) || isRotatedPole) &&
         (msProjIsGeographicCRS(out) ||
          (out->numargs == 1 && strcmp(out->args[0], "init=epsg:3857") == 0)))) 
{
     reprojector->lineCuttingCase = LINE_CUTTING_NONE;
@@ -1065,6 +1069,7 @@
 
   int srcIsPolar;
   double extremeLongEasting;
+  double extremeLatNorthing;
   if (msProjIsGeographicCRS(out)) {
     pointObj p;
     double gt3 = out->gt.need_geotransform ? out->gt.geotransform[3] : 0.0;
@@ -1075,6 +1080,7 @@
     srcIsPolar = msProjectPointEx(reprojector, &p) == MS_SUCCESS &&
                  fabs(gt3 + p.x * gt4 + p.y * gt5 - 90) < 1e-8;
     extremeLongEasting = 180;
+    extremeLatNorthing = 90;
   } else {
     pointObj p1;
     pointObj p2;
@@ -1087,44 +1093,143 @@
                  msProjectPointEx(reprojector, &p2) == MS_SUCCESS &&
                  fabs((p1.x - p2.x) * gt1) > 20e6;
     extremeLongEasting = 20037508.3427892;
+    extremeLatNorthing = extremeLongEasting;
   }
-  if (!srcIsPolar) {
+  if (!srcIsPolar && !isRotatedPole) {
     reprojector->lineCuttingCase = LINE_CUTTING_NONE;
     return reprojector->lineCuttingCase;
   }
 
   pointObj p = {0}; // initialize
-  double invgt0 = out->gt.need_geotransform ? out->gt.invgeotransform[0] : 0.0;
-  double invgt1 = out->gt.need_geotransform ? out->gt.invgeotransform[1] : 1.0;
-  double invgt3 = out->gt.need_geotransform ? out->gt.invgeotransform[3] : 0.0;
-  double invgt4 = out->gt.need_geotransform ? out->gt.invgeotransform[4] : 0.0;
+  const double invgt0 =
+      out->gt.need_geotransform ? out->gt.invgeotransform[0] : 0.0;
+  const double invgt1 =
+      out->gt.need_geotransform ? out->gt.invgeotransform[1] : 1.0;
+  const double invgt3 =
+      out->gt.need_geotransform ? out->gt.invgeotransform[3] : 0.0;
+  const double invgt4 =
+      out->gt.need_geotransform ? out->gt.invgeotransform[4] : 0.0;
+  const double invgt5 =
+      out->gt.need_geotransform ? out->gt.invgeotransform[5] : 1.0;
 
   lineObj newLine = {0, NULL};
 
-  p.x = invgt0 + -extremeLongEasting * (1 - EPS) * invgt1;
-  p.y = invgt3 + -extremeLongEasting * (1 - EPS) * invgt4;
-  /* coverity[swapped_arguments] */
-  msProjectPoint(out, in, &p);
-  pointObj first = p;
-  msAddPointToLine(&newLine, &p);
-
-  p.x = invgt0 + extremeLongEasting * (1 - EPS) * invgt1;
-  p.y = invgt3 + extremeLongEasting * (1 - EPS) * invgt4;
-  /* coverity[swapped_arguments] */
-  msProjectPoint(out, in, &p);
-  msAddPointToLine(&newLine, &p);
-
-  p.x = 0;
-  p.y = 0;
-  msAddPointToLine(&newLine, &p);
+  if (isRotatedPole) {
+    // Thresholds determined experimentally...
+    const double EPSILON = 1e-5;
+    if (msProjIsGeographicCRS(out)) {
+      const int stepCountMiddleLat = 400;
+      const int stepCountHighLat = 100;
+      const double middleLat = 80;
+      const double poleLat = 90;
+
+      for (int j = 0; j <= stepCountHighLat; j++) {
+        p.x = invgt0 + extremeLongEasting * (1 - EPSILON) * invgt1;
+        p.y =
+            invgt3 +
+            (-poleLat + (poleLat - middleLat) * j / stepCountHighLat) * invgt5;
+        /* coverity[swapped_arguments] */
+        msProjectPoint(out, in, &p);
+        msAddPointToLine(&newLine, &p);
+      }
+
+      for (int j = 0; j <= stepCountMiddleLat; j++) {
+        p.x = invgt0 + extremeLongEasting * (1 - EPSILON) * invgt1;
+        p.y = invgt3 +
+              (-middleLat + (2 * middleLat) * j / stepCountMiddleLat) * invgt5;
+        /* coverity[swapped_arguments] */
+        msProjectPoint(out, in, &p);
+        msAddPointToLine(&newLine, &p);
+      }
+
+      for (int j = 0; j <= stepCountHighLat; ++j) {
+        p.x = invgt0 + extremeLongEasting * (1 - EPSILON) * invgt1;
+        p.y =
+            invgt3 +
+            (middleLat + (poleLat - middleLat) * j / stepCountHighLat) * 
invgt5;
+        /* coverity[swapped_arguments] */
+        msProjectPoint(out, in, &p);
+        msAddPointToLine(&newLine, &p);
+      }
+
+      for (int j = stepCountHighLat; j >= 0; --j) {
+        p.x = invgt0 - extremeLongEasting * (1 - EPSILON) * invgt1;
+        p.y =
+            invgt3 +
+            (middleLat + (poleLat - middleLat) * j / stepCountHighLat) * 
invgt5;
+        /* coverity[swapped_arguments] */
+        msProjectPoint(out, in, &p);
+        msAddPointToLine(&newLine, &p);
+      }
+
+      for (int j = stepCountMiddleLat; j >= 0; --j) {
+        p.x = invgt0 - extremeLongEasting * (1 - EPSILON) * invgt1;
+        p.y = invgt3 +
+              (-middleLat + (2 * middleLat) * j / stepCountMiddleLat) * invgt5;
+        /* coverity[swapped_arguments] */
+        msProjectPoint(out, in, &p);
+        msAddPointToLine(&newLine, &p);
+      }
+
+      for (int j = stepCountHighLat; j >= 0; --j) {
+        p.x = invgt0 - extremeLongEasting * (1 - EPSILON) * invgt1;
+        p.y =
+            invgt3 +
+            (-poleLat + (poleLat - middleLat) * j / stepCountHighLat) * invgt5;
+        /* coverity[swapped_arguments] */
+        msProjectPoint(out, in, &p);
+        msAddPointToLine(&newLine, &p);
+      }
+    } else {
+      const int stepCountHalf = 200;
+      for (int j = 0; j <= 2 * stepCountHalf; j++) {
+        p.x = invgt0 + extremeLongEasting * (1 - EPSILON) * invgt1;
+        p.y = invgt3 +
+              (-extremeLatNorthing + extremeLatNorthing * j / stepCountHalf) *
+                  invgt5;
+        /* coverity[swapped_arguments] */
+        msProjectPoint(out, in, &p);
+        msAddPointToLine(&newLine, &p);
+      }
+
+      for (int j = 2 * stepCountHalf; j >= 0; j--) {
+        p.x = invgt0 - extremeLongEasting * (1 - EPSILON) * invgt1;
+        p.y = invgt3 +
+              (-extremeLatNorthing + extremeLatNorthing * j / stepCountHalf) *
+                  invgt5;
+        /* coverity[swapped_arguments] */
+        msProjectPoint(out, in, &p);
+        msAddPointToLine(&newLine, &p);
+      }
+    }
 
-  msAddPointToLine(&newLine, &first);
+    pointObj firstPoint = newLine.point[0];
+    msAddPointToLine(&newLine, &firstPoint);
+  } else {
+    p.x = invgt0 + -extremeLongEasting * (1 - EPS) * invgt1;
+    p.y = invgt3 + -extremeLongEasting * (1 - EPS) * invgt4;
+    /* coverity[swapped_arguments] */
+    msProjectPoint(out, in, &p);
+    pointObj first = p;
+    msAddPointToLine(&newLine, &p);
+
+    p.x = invgt0 + extremeLongEasting * (1 - EPS) * invgt1;
+    p.y = invgt3 + extremeLongEasting * (1 - EPS) * invgt4;
+    msProjectPoint(out, in, &p);
+    msAddPointToLine(&newLine, &p);
+
+    p.x = 0;
+    p.y = 0;
+    msAddPointToLine(&newLine, &p);
+
+    msAddPointToLine(&newLine, &first);
+  }
 
   msInitShape(&(reprojector->splitShape));
   reprojector->splitShape.type = MS_SHAPE_POLYGON;
   msAddLineDirectly(&(reprojector->splitShape), &newLine);
 
-  reprojector->lineCuttingCase = LINE_CUTTING_FROM_POLAR;
+  reprojector->lineCuttingCase = LINE_CUTTING_WITH_SHAPE;
   return reprojector->lineCuttingCase;
 }
 #endif
@@ -1219,7 +1324,7 @@
   int use_splitShape = MS_FALSE;
   int use_splitShape_check_intersects = MS_FALSE;
   if (shape->type == MS_SHAPE_LINE &&
-      msProjectGetLineCuttingCase(reprojector) == LINE_CUTTING_FROM_POLAR) {
+      msProjectGetLineCuttingCase(reprojector) == LINE_CUTTING_WITH_SHAPE) {
     use_splitShape = MS_TRUE;
     use_splitShape_check_intersects = MS_TRUE;
   } else if (shape->type == MS_SHAPE_LINE &&
@@ -1864,7 +1969,7 @@
 /************************************************************************/
 
 int msProjectRect(projectionObj *in, projectionObj *out, rectObj *rect) {
-  char *over = "+over";
+  const char *over = "+over";
   int ret;
   int bFreeInOver = MS_FALSE;
   int bFreeOutOver = MS_FALSE;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/mapserver-8.6.0/src/mapproject.h 
new/mapserver-8.6.1/src/mapproject.h
--- old/mapserver-8.6.0/src/mapproject.h        2025-12-03 16:04:40.000000000 
+0100
+++ new/mapserver-8.6.1/src/mapproject.h        2026-03-23 16:36:42.000000000 
+0100
@@ -49,7 +49,7 @@
 typedef enum {
   LINE_CUTTING_UNKNOWN = -1,
   LINE_CUTTING_NONE = 0,
-  LINE_CUTTING_FROM_POLAR = 1,
+  LINE_CUTTING_WITH_SHAPE = 1,
   LINE_CUTTING_FROM_LONGLAT_WRAP0 = 2
 } msLineCuttingCase;
 #endif
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/mapserver-8.6.0/src/mapquery.cpp 
new/mapserver-8.6.1/src/mapquery.cpp
--- old/mapserver-8.6.0/src/mapquery.cpp        2025-12-03 16:04:40.000000000 
+0100
+++ new/mapserver-8.6.1/src/mapquery.cpp        2026-03-23 16:36:42.000000000 
+0100
@@ -1981,6 +1981,8 @@
       int classindex = -1;
       styleObj *style = nullptr;
       imageObj *cachedImage = nullptr;
+      double center_x_in_map = 0;
+      double center_y_in_map = 0;
 
       SearchSymbol(mapObj *map) : m_map(map) {}
       ~SearchSymbol() {
@@ -2014,6 +2016,8 @@
         classindex = other.classindex;
         std::swap(style, other.style);
         std::swap(cachedImage, other.cachedImage);
+        center_x_in_map = other.center_x_in_map;
+        center_y_in_map = other.center_y_in_map;
       }
       SearchSymbol &operator=(SearchSymbol &&other) {
         m_map = other.m_map;
@@ -2021,6 +2025,8 @@
         classindex = other.classindex;
         std::swap(style, other.style);
         std::swap(cachedImage, other.cachedImage);
+        center_x_in_map = other.center_x_in_map;
+        center_y_in_map = other.center_y_in_map;
         return *this;
       }
     };
@@ -2066,16 +2072,21 @@
             computeSymbolStyle(&s, style, symbol, style->scalefactor,
                                resolutionfactor);
 
+            double pos_offset_x = 0;
+            double pos_offset_y = 0;
+            if (msAdjustMarkerPos(map, style, symbol, &pos_offset_x,
+                                  &pos_offset_y, style->scalefactor,
+                                  s.rotation) != MS_SUCCESS) {
+              continue;
+            }
+
             double center_x =
                 MS_MAP2IMAGE_X(map->query.point.x, map->extent.minx, cellx);
             double center_y =
                 MS_MAP2IMAGE_Y(map->query.point.y, map->extent.maxy, celly);
 
-            if (msAdjustMarkerPos(map, style, symbol, &center_x, &center_y,
-                                  style->scalefactor,
-                                  s.rotation) != MS_SUCCESS) {
-              continue;
-            }
+            center_x -= pos_offset_x;
+            center_y -= pos_offset_y;
 
             center_x = MS_IMAGE2MAP_X(center_x, map->extent.minx, cellx);
             center_y = MS_IMAGE2MAP_Y(center_y, map->extent.maxy, celly);
@@ -2116,6 +2127,8 @@
             SearchSymbol searchSymbol(map);
             searchSymbol.style = style;
             searchSymbol.classindex = classindex;
+            searchSymbol.center_x_in_map = center_x;
+            searchSymbol.center_y_in_map = center_y;
 
             lineObj line = {0, NULL};
             line.numpoints = 5;
@@ -2135,14 +2148,18 @@
 
             searchSymbols.push_back(std::move(searchSymbol));
 
-            rect.minx = MIN(rect.minx,
-                            center_x + MIN(MIN(P1_X, P2_X), MIN(P3_X, P4_X)));
-            rect.miny = MIN(rect.miny,
-                            center_y + MIN(MIN(P1_Y, P2_Y), MIN(P3_Y, P4_Y)));
-            rect.maxx = MAX(rect.maxx,
-                            center_x + MAX(MAX(P1_X, P2_X), MAX(P3_X, P4_X)));
-            rect.maxy = MAX(rect.maxy,
-                            center_y + MAX(MAX(P1_Y, P2_Y), MAX(P3_Y, P4_Y)));
+            rect.minx =
+                std::min(rect.minx, center_x + std::min(std::min(P1_X, P2_X),
+                                                        std::min(P3_X, P4_X)));
+            rect.miny =
+                std::min(rect.miny, center_y + std::min(std::min(P1_Y, P2_Y),
+                                                        std::min(P3_Y, P4_Y)));
+            rect.maxx =
+                std::max(rect.maxx, center_x + std::max(std::max(P1_X, P2_X),
+                                                        std::max(P3_X, P4_X)));
+            rect.maxy =
+                std::max(rect.maxy, center_y + std::max(std::max(P1_Y, P2_Y),
+                                                        std::max(P3_Y, P4_Y)));
           }
         }
       };
@@ -2327,10 +2344,10 @@
                 pointObj imCenter;
                 imCenter.x = searchSymbol.cachedImage->width / 2;
                 imCenter.y = searchSymbol.cachedImage->height / 2;
-                if (msDrawMarkerSymbol(map, searchSymbol.cachedImage, 
&imCenter,
-                                       searchSymbol.style,
-                                       searchSymbol.style->scalefactor) !=
-                    MS_SUCCESS) {
+                if (msDrawMarkerSymbolInternal(
+                        map, searchSymbol.cachedImage, &imCenter,
+                        searchSymbol.style, searchSymbol.style->scalefactor,
+                        /* adjustMarkerPos = */ false) != MS_SUCCESS) {
                   msSetError(MS_MISCERR, "Unable to draw symbol image.",
                              "msQueryByPoint()");
                   return (MS_FAILURE);
@@ -2347,10 +2364,12 @@
 
                 const int test_x = static_cast<int>(std::round(
                     searchSymbol.cachedImage->width / 2 +
-                    (map->query.point.x - shape.line[0].point[0].x) / cellx));
+                    (searchSymbol.center_x_in_map - shape.line[0].point[0].x) /
+                        cellx));
                 const int test_y = static_cast<int>(std::round(
                     searchSymbol.cachedImage->height / 2 -
-                    (map->query.point.y - shape.line[0].point[0].y) / celly));
+                    (searchSymbol.center_y_in_map - shape.line[0].point[0].y) /
+                        celly));
 
                 // Check that the queried pixel hits a non-transparent pixel of
                 // the symbol
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/mapserver-8.6.0/src/maprendering.c 
new/mapserver-8.6.1/src/maprendering.c
--- old/mapserver-8.6.0/src/maprendering.c      2025-12-03 16:04:40.000000000 
+0100
+++ new/mapserver-8.6.1/src/maprendering.c      2026-03-23 16:36:42.000000000 
+0100
@@ -899,6 +899,13 @@
 
 int msDrawMarkerSymbol(mapObj *map, imageObj *image, pointObj *p,
                        styleObj *style, double scalefactor) {
+  return msDrawMarkerSymbolInternal(map, image, p, style, scalefactor,
+                                    /* adjustMarkerPos =*/true);
+}
+
+int msDrawMarkerSymbolInternal(mapObj *map, imageObj *image, pointObj *p,
+                               styleObj *style, double scalefactor,
+                               bool adjustMarkerPos) {
   int ret = MS_SUCCESS;
   if (!p)
     return MS_SUCCESS;
@@ -937,7 +944,8 @@
       p_x = p->x;
       p_y = p->y;
 
-      if (MS_UNLIKELY(MS_FAILURE == msAdjustMarkerPos(map, style, symbol, &p_x,
+      if (adjustMarkerPos &&
+          MS_UNLIKELY(MS_FAILURE == msAdjustMarkerPos(map, style, symbol, &p_x,
                                                       &p_y, scalefactor,
                                                       s.rotation))) {
         return MS_FAILURE;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/mapserver-8.6.0/src/mapserver.h 
new/mapserver-8.6.1/src/mapserver.h
--- old/mapserver-8.6.0/src/mapserver.h 2025-12-03 16:04:40.000000000 +0100
+++ new/mapserver-8.6.1/src/mapserver.h 2026-03-23 16:36:42.000000000 +0100
@@ -73,6 +73,12 @@
 #define MS_UNLIKELY(x) (x)
 #endif
 
+/** Macro to compute the minimum of 2 values */
+#define MS_MIN(a, b) (((a) < (b)) ? (a) : (b))
+
+/** Macro to compute the maximum of 2 values */
+#define MS_MAX(a, b) (((a) > (b)) ? (a) : (b))
+
 /* definition of  ms_int32/ms_uint32 */
 #include <limits.h>
 #ifndef _WIN32
@@ -3303,6 +3309,9 @@
     layerObj *layer, mapObj *map);
 rectObj msRasterLabelGetSearchRect(layerObj *layer, mapObj *map);
 
+void msContourLayerUseMapExtentAndProjectionForNextWhichShapes(layerObj *layer,
+                                                               mapObj *map);
+
 /* ==================================================================== */
 /*      Prototypes for functions in mapdraw.c                           */
 /* ==================================================================== */
@@ -3351,6 +3360,12 @@
 MS_DLL_EXPORT int WARN_UNUSED msDrawMarkerSymbol(mapObj *map, imageObj *image,
                                                  pointObj *p, styleObj *style,
                                                  double scalefactor);
+
+int WARN_UNUSED msDrawMarkerSymbolInternal(mapObj *map, imageObj *image,
+                                           pointObj *p, styleObj *style,
+                                           double scalefactor,
+                                           bool adjustMarkerPos);
+
 MS_DLL_EXPORT int WARN_UNUSED msDrawLineSymbol(mapObj *map, imageObj *image,
                                                shapeObj *p, styleObj *style,
                                                double scalefactor);
@@ -3718,7 +3733,8 @@
                                    const projectionObj *src);
 MS_DLL_EXPORT int msCopyProjectionExtended(projectionObj *dst,
                                            const projectionObj *src,
-                                           char **args, int num_args);
+                                           const char *const *args,
+                                           int num_args);
 int msCopyExpression(expressionObj *dst, const expressionObj *src);
 int msCopyProjection(projectionObj *dst, const projectionObj *src);
 MS_DLL_EXPORT int msCopyRasterBuffer(rasterBufferObj *dst,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/mapserver-8.6.0/src/mapstring.cpp 
new/mapserver-8.6.1/src/mapstring.cpp
--- old/mapserver-8.6.0/src/mapstring.cpp       2025-12-03 16:04:40.000000000 
+0100
+++ new/mapserver-8.6.1/src/mapstring.cpp       2026-03-23 16:36:42.000000000 
+0100
@@ -2515,7 +2515,7 @@
   if (sb->length + nAppendLen >= sb->alloc_size) {
     size_t newAllocSize1 = sb->alloc_size + sb->alloc_size / 3;
     size_t newAllocSize2 = sb->length + nAppendLen + 1;
-    size_t newAllocSize = MAX(newAllocSize1, newAllocSize2);
+    size_t newAllocSize = std::max(newAllocSize1, newAllocSize2);
     void *newStr = realloc(sb->str, newAllocSize);
     if (newStr == NULL) {
       msSetError(MS_MEMERR, "Not enough memory", "msStringBufferAppend()");
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/mapserver-8.6.0/src/mapuvraster.cpp 
new/mapserver-8.6.1/src/mapuvraster.cpp
--- old/mapserver-8.6.0/src/mapuvraster.cpp     2025-12-03 16:04:40.000000000 
+0100
+++ new/mapserver-8.6.1/src/mapuvraster.cpp     2026-03-23 16:36:42.000000000 
+0100
@@ -57,42 +57,48 @@
 #define MSUVRASTER_LAT "lat"
 #define MSUVRASTER_LATINDEX -107
 
-typedef struct {
+struct uvRasterLayerInfo {
 
   /* query cache results */
-  int query_results;
+  int query_results = 0;
 
-  int refcount;
+  int refcount = 0;
 
-  float *u; /* u values */
-  float *v; /* v values */
-  int width;
-  int height;
-  rectObj extent;
-  int next_shape;
+  float *u = nullptr; /* u values */
+  float *v = nullptr; /* v values */
+  int width = 0;
+  int height = 0;
+  rectObj extent{};
+  int next_shape = 0;
 
   /* To improve performance of GetShape() when queried on increasing shapeindex
    */
-  long last_queried_shapeindex; // value in [0, query_results[ range
-  size_t last_raster_off;       // value in [0, width*height[ range
+  long last_queried_shapeindex = 0; // value in [0, query_results[ range
+  size_t last_raster_off = 0;       // value in [0, width*height[ range
 
-  bool needsLonLat;
-  reprojectionObj *reprojectorToLonLat;
+  bool needsLonLat = false;
+  reprojectionObj *reprojectorToLonLat = nullptr;
 
-  mapObj
-      *mapToUseForWhichShapes; /* set if the map->extent and map->projection 
are
-                                  valid in msUVRASTERLayerWhichShapes() */
+  /* set if the map->extent and map->projection are
+     valid in msUVRASTERLayerWhichShapes() */
+  mapObj *mapToUseForWhichShapes = nullptr;
+
+  std::string timestring{};
+  std::string timefield{};
+};
 
-} uvRasterLayerInfo;
+static uvRasterLayerInfo *getLayerInfo(layerObj *layer) {
+  return static_cast<uvRasterLayerInfo *>(layer->layerinfo);
+}
 
 void msUVRASTERLayerUseMapExtentAndProjectionForNextWhichShapes(layerObj 
*layer,
                                                                 mapObj *map) {
-  uvRasterLayerInfo *uvlinfo = (uvRasterLayerInfo *)layer->layerinfo;
+  uvRasterLayerInfo *uvlinfo = getLayerInfo(layer);
   uvlinfo->mapToUseForWhichShapes = map;
 }
 
 static int msUVRASTERLayerInitItemInfo(layerObj *layer) {
-  uvRasterLayerInfo *uvlinfo = (uvRasterLayerInfo *)layer->layerinfo;
+  uvRasterLayerInfo *uvlinfo = getLayerInfo(layer);
   int i;
   int *itemindexes;
   int failed = 0;
@@ -154,19 +160,14 @@
 }
 
 static void msUVRasterLayerInfoInitialize(layerObj *layer) {
-  uvRasterLayerInfo *uvlinfo = (uvRasterLayerInfo *)layer->layerinfo;
+  uvRasterLayerInfo *uvlinfo = getLayerInfo(layer);
 
   if (uvlinfo != NULL)
     return;
 
-  uvlinfo = (uvRasterLayerInfo *)msSmallCalloc(1, sizeof(uvRasterLayerInfo));
+  uvlinfo = new uvRasterLayerInfo;
   layer->layerinfo = uvlinfo;
 
-  uvlinfo->u = NULL;
-  uvlinfo->v = NULL;
-  uvlinfo->width = 0;
-  uvlinfo->height = 0;
-
   /* Set attribute type to Real, unless the user has explicitly set */
   /* something else. */
   {
@@ -189,7 +190,7 @@
 static void msUVRasterLayerInfoFree(layerObj *layer)
 
 {
-  uvRasterLayerInfo *uvlinfo = (uvRasterLayerInfo *)layer->layerinfo;
+  uvRasterLayerInfo *uvlinfo = getLayerInfo(layer);
 
   if (uvlinfo == NULL)
     return;
@@ -201,7 +202,7 @@
     msProjectDestroyReprojector(uvlinfo->reprojectorToLonLat);
   }
 
-  free(uvlinfo);
+  delete uvlinfo;
 
   layer->layerinfo = NULL;
 }
@@ -213,7 +214,7 @@
   if (layer->layerinfo == NULL)
     return MS_FAILURE;
 
-  uvRasterLayerInfo *uvlinfo = (uvRasterLayerInfo *)layer->layerinfo;
+  uvRasterLayerInfo *uvlinfo = getLayerInfo(layer);
 
   uvlinfo->refcount = uvlinfo->refcount + 1;
 
@@ -227,7 +228,7 @@
 }
 
 int msUVRASTERLayerClose(layerObj *layer) {
-  uvRasterLayerInfo *uvlinfo = (uvRasterLayerInfo *)layer->layerinfo;
+  uvRasterLayerInfo *uvlinfo = getLayerInfo(layer);
 
   if (uvlinfo != NULL) {
     uvlinfo->refcount--;
@@ -239,7 +240,7 @@
 }
 
 int msUVRASTERLayerGetItems(layerObj *layer) {
-  uvRasterLayerInfo *uvlinfo = (uvRasterLayerInfo *)layer->layerinfo;
+  uvRasterLayerInfo *uvlinfo = getLayerInfo(layer);
 
   if (uvlinfo == NULL)
     return MS_FAILURE;
@@ -273,7 +274,7 @@
   char tmp[100];
   float size_scale;
   int *itemindexes = (int *)layer->iteminfo;
-  uvRasterLayerInfo *uvlinfo = (uvRasterLayerInfo *)layer->layerinfo;
+  uvRasterLayerInfo *uvlinfo = getLayerInfo(layer);
   double lon = HUGE_VAL;
   double lat = HUGE_VAL;
 
@@ -452,7 +453,7 @@
 }
 
 int msUVRASTERLayerWhichShapes(layerObj *layer, rectObj rect, int isQuery) {
-  uvRasterLayerInfo *uvlinfo = (uvRasterLayerInfo *)layer->layerinfo;
+  uvRasterLayerInfo *uvlinfo = getLayerInfo(layer);
   imageObj *image_tmp;
   outputFormatObj *outputformat = NULL;
   mapObj *map_tmp;
@@ -753,7 +754,26 @@
    */
   saved_layer_mask = layer->mask;
   layer->mask = NULL;
-  ret = msDrawRasterLayerLow(map_tmp, layer, image_tmp, NULL);
+
+  if (layer->tileindex) {
+    expressionObj old_filter;
+    if (!uvlinfo->timestring.empty()) {
+      msInitExpression(&old_filter);
+      msCopyExpression(&old_filter, &layer->filter); /* save existing filter */
+      msFreeExpression(&layer->filter);
+      msLayerMakeBackticsTimeFilter(layer, uvlinfo->timestring.c_str(),
+                                    uvlinfo->timefield.c_str());
+    }
+
+    ret = msDrawRasterLayerLow(map_tmp, layer, image_tmp, NULL);
+
+    if (!uvlinfo->timestring.empty()) {
+      msCopyExpression(&layer->filter, &old_filter); /* restore old filter */
+      msFreeExpression(&old_filter);
+    }
+  } else {
+    ret = msDrawRasterLayerLow(map_tmp, layer, image_tmp, NULL);
+  }
 
   /* restore layer attributes if we went through the above on-the-fly VRT */
   if (oldLayerData) {
@@ -825,7 +845,7 @@
 
 int msUVRASTERLayerGetShape(layerObj *layer, shapeObj *shape,
                             resultObj *record) {
-  uvRasterLayerInfo *uvlinfo = (uvRasterLayerInfo *)layer->layerinfo;
+  uvRasterLayerInfo *uvlinfo = getLayerInfo(layer);
   lineObj line;
   pointObj point;
   const long shapeindex = record->shapeindex;
@@ -889,7 +909,7 @@
 }
 
 int msUVRASTERLayerNextShape(layerObj *layer, shapeObj *shape) {
-  uvRasterLayerInfo *uvlinfo = (uvRasterLayerInfo *)layer->layerinfo;
+  uvRasterLayerInfo *uvlinfo = getLayerInfo(layer);
 
   if (uvlinfo->next_shape < 0 ||
       uvlinfo->next_shape >= uvlinfo->query_results) {
@@ -1029,12 +1049,20 @@
   /* -------------------------------------------------------------------- */
   /*      If we are using a local shapefile as our tileindex (that is     */
   /*      to say, the tileindex name is not of another layer), then we    */
-  /*      just install a backtics style filter on the raster layer.       */
-  /*      This is propagated to the "working layer" created for the       */
-  /*      tileindex by code in mapraster.c.                               */
+  /*      will install a backtics style filter later.                     */
   /* -------------------------------------------------------------------- */
-  if (tilelayerindex == -1)
-    return msLayerMakeBackticsTimeFilter(layer, timestring, timefield);
+  if (tilelayerindex == -1) {
+    if (layer->layerinfo == NULL)
+      msUVRasterLayerInfoInitialize(layer);
+    if (layer->layerinfo == NULL)
+      return MS_FAILURE;
+    uvRasterLayerInfo *uvlinfo = getLayerInfo(layer);
+    if (timestring)
+      uvlinfo->timestring = timestring;
+    if (timefield)
+      uvlinfo->timefield = timefield;
+    return MS_SUCCESS;
+  }
 
   /* -------------------------------------------------------------------- */
   /*      Otherwise we invoke the tileindex layers SetTimeFilter          */
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/mapserver-8.6.0/src/mapwcs.cpp 
new/mapserver-8.6.1/src/mapwcs.cpp
--- old/mapserver-8.6.0/src/mapwcs.cpp  2025-12-03 16:04:40.000000000 +0100
+++ new/mapserver-8.6.1/src/mapwcs.cpp  2026-03-23 16:36:42.000000000 +0100
@@ -1970,7 +1970,7 @@
         int nDstBand = i + 1;
         GDALRasterBandH hBand = GDALGetRasterBand(hDS, nSrcBand);
         if (hBand) {
-          char **papszMD = GDALGetMetadata(hBand, NULL);
+          CSLConstList papszMD = GDALGetMetadata(hBand, NULL);
           const char *pszMDI = CSLFetchNameValue(papszMD, "GRIB_IDS");
           // Make sure it is a GRIB2 band
           if (pszMDI) {
@@ -2307,9 +2307,9 @@
       }
 
       {
-        char **papszMD = GDALGetMetadata(hDS, NULL);
+        CSLConstList papszMD = GDALGetMetadata(hDS, NULL);
         if (papszMD) {
-          for (char **papszIter = papszMD; *papszIter; ++papszIter) {
+          for (CSLConstList papszIter = papszMD; *papszIter; ++papszIter) {
             // Copy netCDF global attributes, as well as the ones
             // of the extra dimension for 3D netCDF files
             if (STARTS_WITH(*papszIter, "NC_GLOBAL#") ||
@@ -2334,9 +2334,9 @@
         int nDstBand = i + 1;
         GDALRasterBandH hBand = GDALGetRasterBand(hDS, nSrcBand);
         if (hBand) {
-          char **papszMD = GDALGetMetadata(hBand, NULL);
+          CSLConstList papszMD = GDALGetMetadata(hBand, NULL);
           if (papszMD) {
-            for (char **papszIter = papszMD; *papszIter; ++papszIter) {
+            for (CSLConstList papszIter = papszMD; *papszIter; ++papszIter) {
               char *pszKey = nullptr;
               const char *pszValue = CPLParseNameValue(*papszIter, &pszKey);
               if (pszKey && pszValue && !EQUAL(pszKey, "grid_name") &&
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/mapserver-8.6.0/src/mapwcs20.cpp 
new/mapserver-8.6.1/src/mapwcs20.cpp
--- old/mapserver-8.6.0/src/mapwcs20.cpp        2025-12-03 16:04:40.000000000 
+0100
+++ new/mapserver-8.6.1/src/mapwcs20.cpp        2026-03-23 16:36:42.000000000 
+0100
@@ -39,6 +39,7 @@
 #include "mapows.h"
 #include "mapwcs.h"
 #include "mapgdal.h"
+#include <cmath>
 #include <float.h>
 #include "gdal.h"
 #include "cpl_port.h"
@@ -4641,14 +4642,16 @@
           subsetInImageProj.maxy =
               MS_MIN(subsetInImageProj.maxy, layer->extent.maxy);
           {
-            double total = ABS(layer->extent.maxx - layer->extent.minx);
-            double part = ABS(subsetInImageProj.maxx - subsetInImageProj.minx);
+            double total = std::abs(layer->extent.maxx - layer->extent.minx);
+            double part =
+                std::abs(subsetInImageProj.maxx - subsetInImageProj.minx);
             widthFromComputationInImageCRS =
                 MS_NINT((part * map->width) / total);
           }
           {
-            double total = ABS(layer->extent.maxy - layer->extent.miny);
-            double part = ABS(subsetInImageProj.maxy - subsetInImageProj.miny);
+            double total = std::abs(layer->extent.maxy - layer->extent.miny);
+            double part =
+                std::abs(subsetInImageProj.maxy - subsetInImageProj.miny);
             heightFromComputationInImageCRS =
                 MS_NINT((part * map->height) / total);
           }
@@ -4656,6 +4659,15 @@
       }
 
       msProjectRect(&imageProj, &subsetProj, &(layer->extent));
+      if (msProjIsGeographicCRS(&subsetProj)) {
+        if (layer->extent.minx > 180 && subsets.maxx <= 180) {
+          layer->extent.minx -= 360;
+          layer->extent.maxx -= 360;
+        } else if (layer->extent.maxx < -180 && subsets.minx >= -180) {
+          layer->extent.minx += 360;
+          layer->extent.maxx += 360;
+        }
+      }
       map->extent = layer->extent;
       msFreeProjection(&(map->projection));
       map->projection = subsetProj;
@@ -4710,10 +4722,10 @@
   } else {
     if (widthFromComputationInImageCRS != 0) {
       params->width = widthFromComputationInImageCRS;
-    } else if (ABS(bbox.maxx - bbox.minx) !=
-               ABS(map->extent.maxx - map->extent.minx)) {
-      double total = ABS(map->extent.maxx - map->extent.minx),
-             part = ABS(bbox.maxx - bbox.minx);
+    } else if (std::abs(bbox.maxx - bbox.minx) !=
+               std::abs(map->extent.maxx - map->extent.minx)) {
+      double total = std::abs(map->extent.maxx - map->extent.minx),
+             part = std::abs(bbox.maxx - bbox.minx);
       params->width = MS_NINT((part * map->width) / total);
     } else {
       params->width = map->width;
@@ -4735,10 +4747,10 @@
   } else {
     if (heightFromComputationInImageCRS != 0) {
       params->height = heightFromComputationInImageCRS;
-    } else if (ABS(bbox.maxy - bbox.miny) !=
-               ABS(map->extent.maxy - map->extent.miny)) {
-      double total = ABS(map->extent.maxy - map->extent.miny),
-             part = ABS(bbox.maxy - bbox.miny);
+    } else if (std::abs(bbox.maxy - bbox.miny) !=
+               std::abs(map->extent.maxy - map->extent.miny)) {
+      double total = std::abs(map->extent.maxy - map->extent.miny),
+             part = std::abs(bbox.maxy - bbox.miny);
       params->height = MS_NINT((part * map->height) / total);
     } else {
       params->height = map->height;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/mapserver-8.6.0/src/mapwms.cpp 
new/mapserver-8.6.1/src/mapwms.cpp
--- old/mapserver-8.6.0/src/mapwms.cpp  2025-12-03 16:04:40.000000000 +0100
+++ new/mapserver-8.6.1/src/mapwms.cpp  2026-03-23 16:36:42.000000000 +0100
@@ -3028,8 +3028,32 @@
                       : "");
       msIO_printf("%s      <Name>%s</Name>\n", indent.c_str(),
                   nestedGroups[index][level]);
-      msIO_printf("%s      <Title>%s</Title>\n", indent.c_str(),
-                  nestedGroups[index][level]);
+
+      {
+        const char *value;
+        if ((value = msOWSLookupMetadataWithLanguage(
+                 &(GET_LAYER(map, index)->metadata), "MO", "GROUP_TITLE",
+                 validated_language))) {
+          char *encoded = msEncodeHTMLEntities(value);
+          msIO_printf("%s      <Title>%s</Title>\n", indent.c_str(), encoded);
+          msFree(encoded);
+        } else {
+          msIO_printf("%s      <Title>%s</Title>\n", indent.c_str(),
+                      nestedGroups[index][level]);
+        }
+      }
+      {
+        const char *value;
+        if ((value = msOWSLookupMetadataWithLanguage(
+                 &(GET_LAYER(map, index)->metadata), "MO", "GROUP_ABSTRACT",
+                 validated_language))) {
+          char *encoded = msEncodeHTMLEntities(value);
+          msIO_printf("%s      <Abstract>%s</Abstract>\n", indent.c_str(),
+                      encoded);
+          msFree(encoded);
+        }
+      }
+
       groupAdded = true;
     }
 

Reply via email to