[Git][debian-gis-team/mapcache][upstream] New upstream version 1.14.1

Bas Couwenberg (@sebastic) gitlab at salsa.debian.org
Fri Aug 2 15:09:11 BST 2024



Bas Couwenberg pushed to branch upstream at Debian GIS Project / mapcache


Commits:
f153b3de by Bas Couwenberg at 2024-08-02T15:56:39+02:00
New upstream version 1.14.1
- - - - -


28 changed files:

- .github/workflows/build-linux.yml
- − .travis.yml
- CMakeLists.txt
- LICENSE.md
- MIGRATION_GUIDE.txt → MIGRATION_GUIDE.md
- README.md
- − appveyor.yml
- cmake/FindBerkeleyDB.cmake
- cmake/FindGDAL.cmake
- + cmake/FindPCRE2.cmake
- cmake/FindPixman.cmake
- include/mapcache-config.h.in
- include/mapcache.h
- lib/cache_disk.c
- lib/cache_lmdb.c
- lib/cache_rest.c
- lib/configuration_xml.c
- lib/connection_pool.c
- lib/core.c
- lib/dimension.c
- lib/dimension_pg.c
- lib/http.c
- lib/imageio_png.c
- lib/service_wms.c
- lib/util.c
- nginx/ngx_http_mapcache_module.c
- release.sh
- util/mapcache_seed.c


Changes:

=====================================
.github/workflows/build-linux.yml
=====================================
@@ -6,7 +6,7 @@ jobs:
     build-matrix:
       strategy:
         matrix:
-          os: [ ubuntu-18.04, ubuntu-20.04 ]
+          os: [ ubuntu-20.04 ]
           option: [ minimal, default, maximal ]
       runs-on: ${{ matrix.os }}
       steps:
@@ -28,7 +28,7 @@ jobs:
             fi
             if [[ 'maximal' =~ ${{ matrix.option }} ]]
             then
-              sudo apt-get install -y libhiredis-dev libdb-dev libmapserver-dev
+              sudo apt-get install -y libhiredis-dev libdb-dev libmapserver-dev libpcre2-dev
             fi
 
         - name: Build MapCache
@@ -55,7 +55,8 @@ jobs:
                        -DWITH_TIFF=ON \
                        -DWITH_TIFF_WRITE_SUPPORT=ON \
                        -DWITH_GEOTIFF=ON \
-                       -DWITH_PCRE=ON \
+                       -DWITH_PCRE=OFF \
+                       -DWITH_PCRE2=ON \
                        -DWITH_MAPSERVER=ON \
                        -DWITH_RIAK=OFF"
             fi


=====================================
.travis.yml deleted
=====================================
@@ -1,64 +0,0 @@
-branches:
-  except:
-  - /^(cherry-pick-)?backport-\d+-to-/
-
-matrix:
-  fast_finish: true
-  include:
-    - os: linux
-      dist: focal
-      language: c
-      sudo: required
-      env:
-        - DISTRO=focal
-        - BUILD_TYPE=maximum
-
-    - os: linux
-      dist: focal
-      language: c
-      sudo: required
-      env:
-        - DISTRO=focal
-        - BUILD_TYPE=minimum
-
-    - os: linux
-      dist: bionic
-      language: c
-      sudo: required
-      env:
-        - DISTRO=bionic
-        - BUILD_TYPE=maximum
-
-language: c
-
-before_install:
-  - if test "$DISTRO" = "bionic"; then sudo mv /etc/apt/sources.list.d/pgdg* /tmp; fi
-  - sudo apt-get purge -y libgdal* libgeos* libspatialite*
-  - sudo add-apt-repository -y ppa:ubuntugis/ubuntugis-unstable
-  - sudo apt-get update
-  - sudo apt-get install cmake libspatialite-dev libfcgi-dev libproj-dev libgeos-dev libgdal-dev libtiff-dev libgeotiff-dev apache2-dev libpcre3-dev libsqlite3-dev libdb-dev
-# For testing
-  - sudo apt-get install libxml2-utils apache2 gdal-bin
-
-script:
-  - mkdir build
-  - cd build
-  - if test "$BUILD_TYPE" = "maximum"; then cmake .. -DCMAKE_INSTALL_PREFIX=/usr -DWITH_TIFF=ON -DWITH_GEOTIFF=ON -DWITH_TIFF_WRITE_SUPPORT=ON -DWITH_PCRE=ON -DWITH_SQLITE=ON -DWITH_BERKELEY_DB=ON; else cmake .. -DCMAKE_INSTALL_PREFIX=/usr -DWITH_TIFF=OFF -DWITH_GEOTIFF=OFF -DWITH_TIFF_WRITE_SUPPORT=OFF -DWITH_PCRE=OFF -DWITH_SQLITE=OFF -DWITH_BERKELEY_DB=OFF -DWITH_GDAL=OFF -DWITH_GEOS=OFF -DWITH_FCGI=OFF -DWITH_CGI=OFF -DWITH_APACHE=OFF -DWITH_OGR=OFF -DWITH_MAPSERVER=OFF -DWITH_MAPCACHE_DETAIL=OFF; fi
-  - make -j3
-  - sudo make install
-# Only test with Apache 2.4
-  - if [ "$BUILD_TYPE" = "maximum" ]; then 
-      cd ../tests; 
-      sh ./travis_setup.sh;
-      sh ./run_tests.sh;
-      sudo systemctl -l status apache2.service;
-      cat /tmp/mc/mapcache.xml;
-      ls -lah /tmp/mc/mapcache.xml;
-    fi
-
-notifications:
-  irc:
-    channels:
-      - "irc.libera.chat#mapcache"
-    use_notice: true
-


=====================================
CMakeLists.txt
=====================================
@@ -1,4 +1,4 @@
-cmake_minimum_required (VERSION 2.6)
+cmake_minimum_required(VERSION 3.0...3.29)
 
 project (MapCache C)
 
@@ -13,7 +13,7 @@ endif ()
 
 set (MAPCACHE_VERSION_MAJOR 1)
 set (MAPCACHE_VERSION_MINOR 14)
-set (MAPCACHE_VERSION_REVISION 0)
+set (MAPCACHE_VERSION_REVISION 1)
 
 if(NOT DEFINED CMAKE_INSTALL_LIBDIR)
    set(CMAKE_INSTALL_LIBDIR lib)
@@ -82,7 +82,7 @@ if(CMAKE_COMPILER_IS_GNUCC)
 endif()
 
 if(CMAKE_C_COMPILER_ID MATCHES "Clang")
-  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Werror=declaration-after-statement -std=c89 -Wno-comment")
+  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Werror=declaration-after-statement -Wno-comment")
 endif()
 
 #options suported by the cmake builder
@@ -97,6 +97,7 @@ option(WITH_TIFF "Use TIFFs as a cache backend" OFF)
 option(WITH_TIFF_WRITE_SUPPORT "Enable (experimental) support for writable TIFF cache backends" OFF)
 option(WITH_GEOTIFF "Allow GeoTIFF metadata creation for TIFF cache backends" OFF)
 option(WITH_PCRE "Use PCRE for regex tests" OFF)
+option(WITH_PCRE2 "Use PCRE2 for regex tests" OFF)
 option(WITH_MAPSERVER "Enable (experimental) support for the mapserver library" OFF)
 option(WITH_RIAK "Use Riak as a cache backend" OFF)
 option(WITH_GDAL "Choose if GDAL raster support should be built in" ON)
@@ -205,6 +206,18 @@ if(WITH_PCRE)
   endif(PCRE_FOUND)
 endif (WITH_PCRE)
 
+if(WITH_PCRE2)
+  find_package(PCRE2)
+  if(PCRE2_FOUND)
+    include_directories(${PCRE2_INCLUDE_DIR})
+    target_link_libraries(mapcache PCRE2::PCRE2-8)
+    set (USE_PCRE2 1)
+    add_definitions(-DPCRE2_CODE_UNIT_WIDTH=8)
+  else(PCRE2_FOUND)
+    report_optional_not_found(PCRE2)
+  endif(PCRE2_FOUND)
+endif (WITH_PCRE2)
+
 if(WITH_SQLITE)
   find_package(SQLITE)
   if(SQLITE_FOUND)
@@ -357,6 +370,7 @@ status_optional_component("TIFF" "${USE_TIFF}" "${TIFF_LIBRARY}")
 status_optional_component("GeoTIFF" "${USE_GEOTIFF}" "${GEOTIFF_LIBRARY}")
 status_optional_component("Experimental TIFF write support" "${USE_TIFF_WRITE}" "${TIFF_LIBRARY}")
 status_optional_component("PCRE" "${USE_PCRE}" "${PCRE_LIBRARY}")
+status_optional_component("PCRE2" "${USE_PCRE2}" "${PCRE2-8_LIBRARY}")
 status_optional_component("Experimental mapserver support" "${USE_MAPSERVER}" "${MAPSERVER_LIBRARY}")
 status_optional_component("RIAK" "${USE_RIAK}" "${RIAK_LIBRARY}")
 status_optional_component("GDAL" "${USE_GDAL}" "${GDAL_LIBRARY}")


=====================================
LICENSE.md
=====================================
@@ -1,7 +1,7 @@
 MapCache Licensing
 ==================
 
-Copyright (c) 2008-2023 Open Source Geospatial Foundation.  
+Copyright (c) 2008-2024 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


=====================================
MIGRATION_GUIDE.txt → MIGRATION_GUIDE.md
=====================================
@@ -1,34 +1,35 @@
-Migrating from Mapcache 1.12 to 1.14
+Migrating from MapCache 1.12 to 1.14
 ====================================
 
-* No backward compatibility issue is expected.
-  See [MapCache 1.14 Changelog](https://mapserver.org/development/changelog/mapcache/changelog-1-114.html)
-  for a list of bug fixes and new features.
+* This is a security release, to handle a string formatting injection vulnerability, 
+  and includes other changes.
+  No backward compatibility issue is expected.
+  See [MapCache 1.14 Changelog](https://mapserver.org/development/changelog/mapcache/changelog-1-14.html).
 
-Migrating from Mapcache 1.10 to 1.12
-===================================
+Migrating from MapCache 1.10 to 1.12
+====================================
 
 * No backward compatibility issue is expected.
   See [MapCache 1.12 Changelog](https://mapserver.org/development/changelog/mapcache/changelog-1-12.html)
   for a list of bug fixes and new features.
 
-Migrating from Mapcache 1.8 to 1.10
+Migrating from MapCache 1.8 to 1.10
 ===================================
 
 * No backward compatibility issue is expected.
   See [MapCache 1.10 Changelog](https://mapserver.org/development/changelog/mapcache/changelog-1-10.html)
   for a list of bug fixes and new features.
 
-Migrating from Mapcache 1.6 to 1.8
-===================================
+Migrating from MapCache 1.6 to 1.8
+==================================
 
 * <dimensions type="time" ...>...<query>SQL</query> should be replaced by
   <dimensions type="time" ...>...<validate_query>SQL</validate_query><list_query>...</list_query> or
   <dimensions type="sqlite" time="true" ...>...<validate_query>SQL</validate_query><list_query>...</list_query>
-  (see [RFC-121](http://mapserver.org/development/rfc/ms-rfc-121.html) for full examples)
+  (see [RFC-121](https://mapserver.org/development/rfc/ms-rfc-121.html) for full examples)
 
-Migrating from Mapcache 1.4 to 1.6
-===================================
+Migrating from MapCache 1.4 to 1.6
+==================================
 
 * The <timedimension> tileset child has been removed. Time dimensions are now added with <dimension type="time">
 


=====================================
README.md
=====================================
@@ -1,8 +1,8 @@
 MapCache
 ========
 
-[![Build Status](https://travis-ci.org/MapServer/mapcache.svg?branch=main)](https://travis-ci.org/MapServer/mapcache)
-[![Appveyor Build Status](https://ci.appveyor.com/api/projects/status/7al5utxjh83ig71v?svg=true)](https://ci.appveyor.com/project/mapserver/mapcache)
+[![Build MapCache on Linux Status](https://github.com/MapServer/mapcache/actions/workflows/build-linux.yml/badge.svg)](https://github.com/MapServer/mapcache/actions?query=workflow%3A%22Build%20MapCache%20on%20Linux%22%20branch%3Amain)
+[![Build MapCache on Windows Status](https://github.com/MapServer/mapcache/actions/workflows/build-windows.yml/badge.svg)](https://github.com/MapServer/mapcache/actions?query=workflow%3A%22Build%20MapCache%20on%20Windows%22%20branch%3Amain)
 
 Summary
 -------


=====================================
appveyor.yml deleted
=====================================
@@ -1,81 +0,0 @@
-image: Visual Studio 2019
-
-platform:
-- x64
-
-environment:
-  matrix:
-  - VS_VERSION: Visual Studio 16 2019
-
-shallow_clone: true
-
-build_script:
-  - echo build_script
-  - set "BUILD_FOLDER=%APPVEYOR_BUILD_FOLDER:\=/%"
-  - if "%platform%" == "x64" SET VS_FULL=%VS_VERSION%
-  - if "%platform%" == "x64" SET VS_ARCH=x64
-  - if "%platform%" == "x86" SET VS_FULL=%VS_VERSION%
-  - if "%platform%" == "x86" SET VS_ARCH=Win32 
-  - if "%platform%" == "x86" SET SDK=release-1928
-  - if "%platform%" == "x64" SET SDK=release-1928-x64
-  - if "%platform%" == "x64" call "C:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Auxiliary/Build/vcvars64.bat"
-  - if "%platform%" == "x86" call "C:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Auxiliary/Build/vcvars32.bat"
-  - echo "%VS_FULL%"
-  - set SDK_ZIP=%SDK%-dev.zip
-  - set SDK_URL=http://download.gisinternals.com/sdk/downloads/%SDK_ZIP%
-  - echo "%SDK_ZIP%"
-  - echo "%SDK_URL%"
-  - mkdir sdk
-  - cd sdk
-  - appveyor DownloadFile "%SDK_URL%"
-  - 7z x "%SDK_ZIP%" > nul
-  - cd %APPVEYOR_BUILD_FOLDER%
-  - set SDK_PREFIX=%BUILD_FOLDER%/sdk/%SDK%
-  - set SDK_INC=%BUILD_FOLDER%/sdk/%SDK%/include
-  - set SDK_LIB=%BUILD_FOLDER%/sdk/%SDK%/lib
-  - set SDK_BIN=%BUILD_FOLDER%/sdk/%SDK%/bin
-  - set REGEX_DIR=%BUILD_FOLDER%/sdk/support/regex-0.12
-
-  - cd %SDK_LIB%
-  - copy "%SDK_LIB%/libfcgi.lib" "%SDK_LIB%/fcgi.lib" /Y
-  - copy "%SDK_LIB%/apr-1.lib" "%SDK_LIB%/apr-1-1.lib" /Y
-  - copy "%SDK_LIB%/libapr-1.lib" "%SDK_LIB%/apr-1.lib" /Y > nul
-  - copy "%SDK_LIB%/aprutil-1.lib" "%SDK_LIB%/aprutil-1-1.lib" /Y > nul
-  - copy "%SDK_LIB%/libaprutil-1.lib" "%SDK_LIB%/aprutil-1.lib" /Y > nul
-
-  - cd %APPVEYOR_BUILD_FOLDER%
-
-  - mkdir build
-  - cd build
-  - cmake -G "%VS_FULL%" -A %VS_ARCH% 
-        -DWITH_APACHE=OFF 
-        -DWITH_FCGI=ON 
-        -DWITH_PCRE=ON 
-        -DWITH_TIFF=OFF 
-        -DCMAKE_PREFIX_PATH=%SDK_PREFIX% ..
-  - cmake --build . --config Release
-
-  - copy "Release\*dll" "%SDK_BIN%" /Y > nul
-  - copy "cgi\Release\*exe" "%SDK_BIN%" /Y > nul
-  - copy "util\Release\*exe" "%SDK_BIN%" /Y > nul
-
-after_build:
-  - cd %SDK_BIN%
-  - 7z a %APPVEYOR_BUILD_FOLDER%\mapcache.zip mapcache.dll
-        mapcache.fcgi.exe mapcache_seed.exe %APPVEYOR_BUILD_FOLDER%\mapcache.xml
-
-test_script:
-  - cd %SDK_BIN%
-  - set MAPCACHE_CONFIG_FILE=%APPVEYOR_BUILD_FOLDER%\mapcache.xml
-  - set PATH_INFO="/"
-  - set REQUEST_METHOD=GET
-  - set QUERY_STRING="SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&STYLES=&FORMAT=image/png&SRS=EPSG:4326&BBOX=0,0,10,10&WIDTH=256&HEIGHT=256&LAYERS=test&TRANSPARENT=TRUE"
-  - mapcache.fcgi.exe
-  - mapcache_seed.exe -h
-
-deploy: off
-
-artifacts:
-  - path: mapcache.zip
-    name: mapcache
-    type: zip


=====================================
cmake/FindBerkeleyDB.cmake
=====================================
@@ -83,5 +83,5 @@ endif (BERKELEYDB_FIND_VERSION AND BERKELEYDB_FOUND_TMP)
 set(BERKELEYDB_INCLUDE_DIRS ${BERKELEYDB_INCLUDE_DIR})
 set(BERKELEYDB_LIBRARIES ${BERKELEYDB_LIBRARY})
 include(FindPackageHandleStandardArgs)
-find_package_handle_standard_args(BERKELEYDB DEFAULT_MSG BERKELEYDB_LIBRARY BERKELEYDB_INCLUDE_DIR)
+find_package_handle_standard_args(BerkeleyDB DEFAULT_MSG BERKELEYDB_LIBRARY BERKELEYDB_INCLUDE_DIR)
 mark_as_advanced(BERKELEYDB_LIBRARY BERKELEYDB_INCLUDE_DIR)


=====================================
cmake/FindGDAL.cmake
=====================================
@@ -73,7 +73,7 @@ if(UNIX)
     )
 
     if(GDAL_CONFIG)
-        exec_program(${GDAL_CONFIG} ARGS --libs OUTPUT_VARIABLE GDAL_CONFIG_LIBS)
+        execute_process(COMMAND ${GDAL_CONFIG} --libs OUTPUT_VARIABLE GDAL_CONFIG_LIBS)
         if(GDAL_CONFIG_LIBS)
             string(REGEX MATCHALL "-l[^ ]+" _gdal_dashl ${GDAL_CONFIG_LIBS})
             string(REGEX REPLACE "-l" "" _gdal_lib "${_gdal_dashl}")


=====================================
cmake/FindPCRE2.cmake
=====================================
@@ -0,0 +1,27 @@
+# Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+# file COPYING-CMAKE-SCRIPTS or https://cmake.org/licensing for details.
+
+#.rst
+# FindPCRE2
+# ~~~~~~~~~
+# Copyright (C) 2017-2018, Hiroshi Miura
+#
+# Find the native PCRE2 headers and libraries.
+
+find_path(PCRE2_INCLUDE_DIR NAMES pcre2.h)
+find_library(PCRE2-8_LIBRARY NAMES pcre2-8 pcre2-8d pcre2-8-static pcre2-8-staticd NAMES_PER_DIR)
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(PCRE2
+                                  REQUIRED_VARS PCRE2-8_LIBRARY PCRE2_INCLUDE_DIR)
+mark_as_advanced(PCRE2_INCLUDE_DIR PCRE2-8_LIBRARY)
+if(PCRE2_FOUND)
+    list(APPEND PCRE2_LIBRARIES "${PCRE2-8_LIBRARY}")
+    set(PCRE2_INCLUDE_DIRS "${PCRE2_INCLUDE_DIR}")
+    if(NOT TARGET PCRE2::PCRE2-8)
+        add_library(PCRE2::PCRE2-8 UNKNOWN IMPORTED)
+        set_target_properties(PCRE2::PCRE2-8 PROPERTIES
+                              INTERFACE_INCLUDE_DIRECTORIES "${PCRE2_INCLUDE_DIR}"
+                              IMPORTED_LINK_INTERFACE_LANGUAGES "C"
+                              IMPORTED_LOCATION "${PCRE2-8_LIBRARY}")
+    endif()
+endif()


=====================================
cmake/FindPixman.cmake
=====================================
@@ -21,5 +21,5 @@ FIND_LIBRARY(PIXMAN_LIBRARY
 set(PIXMAN_INCLUDE_DIRS ${PIXMAN_INCLUDE_DIR})
 set(PIXMAN_LIBRARIES ${PIXMAN_LIBRARY})
 include(FindPackageHandleStandardArgs)
-find_package_handle_standard_args(PIXMAN DEFAULT_MSG PIXMAN_LIBRARY PIXMAN_INCLUDE_DIR)
+find_package_handle_standard_args(Pixman DEFAULT_MSG PIXMAN_LIBRARY PIXMAN_INCLUDE_DIR)
 mark_as_advanced(PIXMAN_LIBRARY PIXMAN_INCLUDE_DIR)


=====================================
include/mapcache-config.h.in
=====================================
@@ -13,6 +13,7 @@
 #cmakedefine USE_TIFF_WRITE 1
 #cmakedefine USE_GEOTIFF 1
 #cmakedefine USE_PCRE 1
+#cmakedefine USE_PCRE2 1
 #cmakedefine USE_MAPSERVER 1
 #cmakedefine USE_RIAK 1
 #cmakedefine USE_GDAL 1


=====================================
include/mapcache.h
=====================================
@@ -1199,6 +1199,14 @@ struct mapcache_tileset {
    */
   int auto_expire;
 
+  /**
+   * Cache-Control directives to be set for a tiled response (MAPCACHE_REQUEST_GET_TILE)
+   *
+   * complements expiration set by the #expires parameter.
+   * \sa expires
+   */
+  const char *cache_control;
+
   int read_only;
   int subdimension_read_only;
 
@@ -1749,6 +1757,12 @@ struct mapcache_dimension {
   apr_array_header_t* (*get_all_ogc_formatted_entries)(mapcache_context *ctx, mapcache_dimension *dimension,
                        mapcache_tileset *tileset, mapcache_extent *extent, mapcache_grid *grid);
 
+  /**
+   * \brief return all value to override default value
+   */
+  apr_array_header_t* (*get_default_value)(mapcache_context *ctx, mapcache_dimension *dimension,
+                       mapcache_tileset *tileset, mapcache_extent *extent, mapcache_grid *grid);
+
   /**
    * \brief parse the value given in the configuration
    */


=====================================
lib/cache_disk.c
=====================================
@@ -196,29 +196,29 @@ static void _mapcache_cache_disk_tilecache_tile_key(mapcache_context *ctx, mapca
                          tile->tileset->format?tile->tileset->format->extension:"png");
   } else {
     *path = cache->filename_template;
-    *path = mapcache_util_str_replace(ctx->pool,*path, "{tileset}", tile->tileset->name);
-    *path = mapcache_util_str_replace(ctx->pool,*path, "{grid}", tile->grid_link->grid->name);
-    *path = mapcache_util_str_replace(ctx->pool,*path, "{ext}",
+    *path = mapcache_util_str_replace_all(ctx->pool,*path, "{tileset}", tile->tileset->name);
+    *path = mapcache_util_str_replace_all(ctx->pool,*path, "{grid}", tile->grid_link->grid->name);
+    *path = mapcache_util_str_replace_all(ctx->pool,*path, "{ext}",
                                       tile->tileset->format?tile->tileset->format->extension:"png");
     if(strstr(*path,"{x}"))
-      *path = mapcache_util_str_replace(ctx->pool,*path, "{x}",
+      *path = mapcache_util_str_replace_all(ctx->pool,*path, "{x}",
                                         apr_psprintf(ctx->pool,"%d",tile->x));
     else
-      *path = mapcache_util_str_replace(ctx->pool,*path, "{inv_x}",
+      *path = mapcache_util_str_replace_all(ctx->pool,*path, "{inv_x}",
                                         apr_psprintf(ctx->pool,"%d",
                                             tile->grid_link->grid->levels[tile->z]->maxx - tile->x - 1));
     if(strstr(*path,"{y}"))
-      *path = mapcache_util_str_replace(ctx->pool,*path, "{y}",
+      *path = mapcache_util_str_replace_all(ctx->pool,*path, "{y}",
                                         apr_psprintf(ctx->pool,"%d",tile->y));
     else
-      *path = mapcache_util_str_replace(ctx->pool,*path, "{inv_y}",
+      *path = mapcache_util_str_replace_all(ctx->pool,*path, "{inv_y}",
                                         apr_psprintf(ctx->pool,"%d",
                                             tile->grid_link->grid->levels[tile->z]->maxy - tile->y - 1));
     if(strstr(*path,"{z}"))
-      *path = mapcache_util_str_replace(ctx->pool,*path, "{z}",
+      *path = mapcache_util_str_replace_all(ctx->pool,*path, "{z}",
                                         apr_psprintf(ctx->pool,"%d",tile->z));
     else
-      *path = mapcache_util_str_replace(ctx->pool,*path, "{inv_z}",
+      *path = mapcache_util_str_replace_all(ctx->pool,*path, "{inv_z}",
                                         apr_psprintf(ctx->pool,"%d",
                                             tile->grid_link->grid->nlevels - tile->z - 1));
     if(tile->dimensions && strstr(*path,"{dim")) {
@@ -245,10 +245,10 @@ static void _mapcache_cache_disk_tilecache_tile_key(mapcache_context *ctx, mapca
         dimstring = apr_pstrcat(ctx->pool,dimstring,"#",entry->dimension->name,"#",dimval,NULL);
         single_dim = apr_pstrcat(ctx->pool,"{dim:",entry->dimension->name,"}",NULL);
         if(strstr(*path,single_dim)) {
-          *path = mapcache_util_str_replace(ctx->pool,*path, single_dim, dimval);
+          *path = mapcache_util_str_replace_all(ctx->pool,*path, single_dim, dimval);
         }
       }
-      *path = mapcache_util_str_replace(ctx->pool,*path, "{dim}", dimstring);
+      *path = mapcache_util_str_replace_all(ctx->pool,*path, "{dim}", dimstring);
     }
   }
   if(!*path) {
@@ -260,30 +260,30 @@ static void _mapcache_cache_disk_template_tile_key(mapcache_context *ctx, mapcac
 {
 
   *path = cache->filename_template;
-  *path = mapcache_util_str_replace(ctx->pool,*path, "{tileset}", tile->tileset->name);
-  *path = mapcache_util_str_replace(ctx->pool,*path, "{grid}", tile->grid_link->grid->name);
-  *path = mapcache_util_str_replace(ctx->pool,*path, "{ext}",
+  *path = mapcache_util_str_replace_all(ctx->pool,*path, "{tileset}", tile->tileset->name);
+  *path = mapcache_util_str_replace_all(ctx->pool,*path, "{grid}", tile->grid_link->grid->name);
+  *path = mapcache_util_str_replace_all(ctx->pool,*path, "{ext}",
                                     tile->tileset->format?tile->tileset->format->extension:"png");
 
   if(strstr(*path,"{x}"))
-    *path = mapcache_util_str_replace(ctx->pool,*path, "{x}",
+    *path = mapcache_util_str_replace_all(ctx->pool,*path, "{x}",
                                       apr_psprintf(ctx->pool,"%d",tile->x));
   else
-    *path = mapcache_util_str_replace(ctx->pool,*path, "{inv_x}",
+    *path = mapcache_util_str_replace_all(ctx->pool,*path, "{inv_x}",
                                       apr_psprintf(ctx->pool,"%d",
                                           tile->grid_link->grid->levels[tile->z]->maxx - tile->x - 1));
   if(strstr(*path,"{y}"))
-    *path = mapcache_util_str_replace(ctx->pool,*path, "{y}",
+    *path = mapcache_util_str_replace_all(ctx->pool,*path, "{y}",
                                       apr_psprintf(ctx->pool,"%d",tile->y));
   else
-    *path = mapcache_util_str_replace(ctx->pool,*path, "{inv_y}",
+    *path = mapcache_util_str_replace_all(ctx->pool,*path, "{inv_y}",
                                       apr_psprintf(ctx->pool,"%d",
                                           tile->grid_link->grid->levels[tile->z]->maxy - tile->y - 1));
   if(strstr(*path,"{z}"))
-    *path = mapcache_util_str_replace(ctx->pool,*path, "{z}",
+    *path = mapcache_util_str_replace_all(ctx->pool,*path, "{z}",
                                       apr_psprintf(ctx->pool,"%d",tile->z));
   else
-    *path = mapcache_util_str_replace(ctx->pool,*path, "{inv_z}",
+    *path = mapcache_util_str_replace_all(ctx->pool,*path, "{inv_z}",
                                       apr_psprintf(ctx->pool,"%d",
                                           tile->grid_link->grid->nlevels - tile->z - 1));
   if(tile->dimensions && strstr(*path,"{dim")) {
@@ -310,10 +310,10 @@ static void _mapcache_cache_disk_template_tile_key(mapcache_context *ctx, mapcac
       dimstring = apr_pstrcat(ctx->pool,dimstring,"#",entry->dimension->name,"#",dimval,NULL);
       single_dim = apr_pstrcat(ctx->pool,"{dim:",entry->dimension->name,"}",NULL);
       if(strstr(*path,single_dim)) {
-        *path = mapcache_util_str_replace(ctx->pool,*path, single_dim, dimval);
+        *path = mapcache_util_str_replace_all(ctx->pool,*path, single_dim, dimval);
       }
     }
-    *path = mapcache_util_str_replace(ctx->pool,*path, "{dim}", dimstring);
+    *path = mapcache_util_str_replace_all(ctx->pool,*path, "{dim}", dimstring);
   }
 
   if(!*path) {


=====================================
lib/cache_lmdb.c
=====================================
@@ -69,23 +69,24 @@ static int _mapcache_cache_lmdb_has_tile(mapcache_context *ctx, mapcache_cache *
   MDB_val key, data;
   MDB_txn *txn;
   mapcache_cache_lmdb *cache = (mapcache_cache_lmdb*)pcache;
-  char *skey = mapcache_util_get_tile_key(ctx,tile,cache->key_template,NULL,NULL);
+  char *skey;
 
   if (lmdb_env->is_open == 0) {
     ctx->set_error(ctx,500,"lmdb is not open %s",cache->basedir);
     return MAPCACHE_FALSE;
   }
+
+  skey = mapcache_util_get_tile_key(ctx,tile,cache->key_template,NULL,NULL);
+  key.mv_size = strlen(skey)+1;
+  key.mv_data = skey;
+
   rc = mdb_txn_begin(lmdb_env->env, NULL, MDB_RDONLY, &txn);
   if (rc) {
     ctx->set_error(ctx,500,"lmdb failed to begin transaction for has_tile in %s:%s",cache->basedir,mdb_strerror(rc));
     return MAPCACHE_FALSE;
   }
 
-  key.mv_size = strlen(skey)+1;
-  key.mv_data = skey;
-
   rc = mdb_get(txn, lmdb_env->dbi, &key, &data);
-
   if(rc == 0) {
     ret = MAPCACHE_TRUE;
   } else if(rc == MDB_NOTFOUND) {
@@ -107,24 +108,27 @@ static int _mapcache_cache_lmdb_has_tile(mapcache_context *ctx, mapcache_cache *
 static void _mapcache_cache_lmdb_delete(mapcache_context *ctx, mapcache_cache *pcache, mapcache_tile *tile)
 {
   int rc;
-  MDB_val key, data;
+  MDB_val key;
   MDB_txn *txn;
   mapcache_cache_lmdb *cache = (mapcache_cache_lmdb*)pcache;
-  char *skey = mapcache_util_get_tile_key(ctx,tile,cache->key_template,NULL,NULL);
+  char *skey;
 
   if (lmdb_env->is_open == 0) {
     ctx->set_error(ctx,500,"lmdb is not open %s",cache->basedir);
     return;
   }
+
+  skey = mapcache_util_get_tile_key(ctx,tile,cache->key_template,NULL,NULL);
+  key.mv_size = strlen(skey)+1;
+  key.mv_data = skey;
+
   rc = mdb_txn_begin(lmdb_env->env, NULL, 0, &txn);
   if (rc) {
     ctx->set_error(ctx,500,"lmdb failed to begin transaction for delete in %s:%s",cache->basedir,mdb_strerror(rc));
     return;
   }
 
-  key.mv_size = strlen(skey)+1;
-  key.mv_data = skey;
-  rc = mdb_del(txn, lmdb_env->dbi, &key, &data);
+  rc = mdb_del(txn, lmdb_env->dbi, &key, NULL);
   if (rc) {
     if (rc == MDB_NOTFOUND) {
       ctx->log(ctx,MAPCACHE_DEBUG,"attempt to delete tile %s absent in the db %s",skey,cache->basedir);
@@ -152,18 +156,18 @@ static int _mapcache_cache_lmdb_get(mapcache_context *ctx, mapcache_cache *pcach
     ctx->set_error(ctx,500,"lmdb is not open %s",cache->basedir);
     return MAPCACHE_FALSE;
   }
+
+  skey = mapcache_util_get_tile_key(ctx,tile,cache->key_template,NULL,NULL);
+  key.mv_size = strlen(skey)+1;
+  key.mv_data = skey;
+
   rc = mdb_txn_begin(lmdb_env->env, NULL, MDB_RDONLY, &txn);
   if (rc) {
     ctx->set_error(ctx,500,"lmdb failed to begin transaction for get in %s:%s",cache->basedir,mdb_strerror(rc));
     return MAPCACHE_FALSE;
   }
 
-  skey = mapcache_util_get_tile_key(ctx,tile,cache->key_template,NULL,NULL);
-  key.mv_size = strlen(skey)+1;
-  key.mv_data = skey;
-
   rc = mdb_get(txn, lmdb_env->dbi, &key, &data);
-
   if(rc == 0) {
     if(((char*)(data.mv_data))[0] == '#') {
       tile->encoded_data = mapcache_empty_png_decode(ctx,tile->grid_link->grid->tile_sx, tile->grid_link->grid->tile_sy, (unsigned char*)data.mv_data,&tile->nodata);
@@ -232,6 +236,7 @@ static void _mapcache_cache_lmdb_set(mapcache_context *ctx, mapcache_cache *pcac
     ctx->set_error(ctx,500,"lmdb is not open %s",cache->basedir);
     return;
   }
+
   rc = mdb_txn_begin(lmdb_env->env, NULL, 0, &txn);
   if (rc) {
     ctx->set_error(ctx,500,"lmdb failed to begin transaction for set in %s:%s",cache->basedir,mdb_strerror(rc));
@@ -264,6 +269,7 @@ static void _mapcache_cache_lmdb_multiset(mapcache_context *ctx, mapcache_cache
     ctx->set_error(ctx,500,"lmdb is not open %s",cache->basedir);
     return;
   }
+
   rc = mdb_txn_begin(lmdb_env->env, NULL, 0, &txn);
   if (rc) {
     ctx->set_error(ctx,500,"lmdb failed to begin transaction for multiset in %s:%s",cache->basedir,mdb_strerror(rc));


=====================================
lib/cache_rest.c
=====================================
@@ -108,6 +108,7 @@ struct mapcache_cache_s3 {
   mapcache_cache_rest cache;
   char *id;
   char *secret;
+  char *session_token;
   char *region;
   char *credentials_file;
 };
@@ -868,16 +869,18 @@ static void _mapcache_cache_s3_headers_add(mapcache_context *ctx, const char* me
     if((rv=apr_file_open(&f, s3->credentials_file,
                        APR_FOPEN_READ|APR_FOPEN_BUFFERED|APR_FOPEN_BINARY,APR_OS_DEFAULT,
                        ctx->pool)) == APR_SUCCESS) {
-      char line[2048];
-      if( (rv = apr_file_gets(line,2048,f))== APR_SUCCESS) {
+      // Line length buffer increased to handle longer session tokens; see:
+      // https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_request.html
+      char line[4096];
+      if( (rv = apr_file_gets(line,4096,f))== APR_SUCCESS) {
         _remove_lineends(line);
         aws_access_key_id = apr_pstrdup(ctx->pool,line);
       }
-      if( (rv = apr_file_gets(line,2048,f))== APR_SUCCESS) {
+      if( (rv = apr_file_gets(line,4096,f))== APR_SUCCESS) {
         _remove_lineends(line);
         aws_secret_access_key = apr_pstrdup(ctx->pool,line);
       }
-      if( (rv = apr_file_gets(line,2048,f))== APR_SUCCESS) {
+      if( (rv = apr_file_gets(line,4096,f))== APR_SUCCESS) {
         _remove_lineends(line);
         aws_security_token = apr_pstrdup(ctx->pool,line);
       }
@@ -894,7 +897,7 @@ static void _mapcache_cache_s3_headers_add(mapcache_context *ctx, const char* me
   } else {
     aws_access_key_id = s3->id;
     aws_secret_access_key = s3->secret;
-    aws_security_token = NULL;
+    aws_security_token = s3->session_token;
   }
 
   if(!strcmp(method,"PUT")) {
@@ -1366,6 +1369,13 @@ static void _mapcache_cache_s3_configuration_parse_xml(mapcache_context *ctx, ez
       ctx->set_error(ctx,400,"s3 cache (%s) is missing required <secret> child or AWS_SECRET_ACCESS_KEY environment", cache->name);
       return;
     }
+    if ((cur_node = ezxml_child(node,"session_token")) != NULL) {
+      s3->session_token = apr_pstrdup(ctx->pool, cur_node->txt);
+    } else if ( getenv("AWS_SESSION_TOKEN")) {
+      s3->session_token = apr_pstrdup(ctx->pool,getenv("AWS_SESSION_TOKEN"));
+    } else {
+      s3->session_token = NULL;
+    }
   }
   if ((cur_node = ezxml_child(node,"region")) != NULL) {
     s3->region = apr_pstrdup(ctx->pool, cur_node->txt);


=====================================
lib/configuration_xml.c
=====================================
@@ -1163,6 +1163,11 @@ void parseTileset(mapcache_context *ctx, ezxml_t node, mapcache_cfg *config)
     }
   }
 
+  tileset->cache_control = NULL;
+  if ((cur_node = ezxml_child(node,"cache-control")) != NULL) {
+    tileset->cache_control = apr_pstrdup(ctx->pool, cur_node->txt);
+  }
+
   if ((cur_node = ezxml_child(node,"metabuffer")) != NULL) {
     char *endptr;
     tileset->metabuffer = (int)strtol(cur_node->txt,&endptr,10);


=====================================
lib/connection_pool.c
=====================================
@@ -140,6 +140,7 @@ mapcache_pooled_connection* mapcache_connection_pool_get_connection(mapcache_con
   pc->private->next = pcc->head;
   pc->private->pcc = pcc;
   
+  pcc->max_list_size = ctx->config->cp_hmax;
   if(count == pcc->max_list_size) {
     /* max number of connections atained, we must destroy the last one that was used */
     mapcache_pooled_connection *opc;


=====================================
lib/core.c
=====================================
@@ -346,11 +346,22 @@ mapcache_http_response *mapcache_core_get_tile(mapcache_context *ctx, mapcache_r
     apr_time_t now = apr_time_now();
     apr_time_t additional = apr_time_from_sec(expires);
     apr_time_t texpires = now + additional;
-    apr_table_set(response->headers, "Cache-Control",apr_psprintf(ctx->pool, "max-age=%d", expires));
     timestr = apr_palloc(ctx->pool, APR_RFC822_DATE_LEN);
     apr_rfc822_date(timestr, texpires);
     apr_table_setn(response->headers, "Expires", timestr);
   }
+  if (expires || req_tile->tiles[0]->tileset->cache_control) {
+    apr_table_set(
+        response->headers, "Cache-Control",
+        apr_pstrcat(
+            ctx->pool,
+            expires ? apr_psprintf(ctx->pool, "max-age=%d", expires) : "",
+            expires && req_tile->tiles[0]->tileset->cache_control ? ", " : "",
+            req_tile->tiles[0]->tileset->cache_control
+                ? req_tile->tiles[0]->tileset->cache_control
+                : "",
+            NULL));
+  }
 
   return response;
 }


=====================================
lib/dimension.c
=====================================
@@ -31,7 +31,9 @@
 #include <apr_strings.h>
 #include <math.h>
 #include <sys/types.h>
-#ifdef USE_PCRE
+#if defined(USE_PCRE2)
+#include <pcre2.h>
+#elif defined(USE_PCRE)
 #include <pcre.h>
 #else
 #include <regex.h>
@@ -51,7 +53,9 @@ struct mapcache_dimension_values {
 struct mapcache_dimension_regex {
   mapcache_dimension dimension;
   char *regex_string;
-#ifdef USE_PCRE
+#if defined(USE_PCRE2)
+  pcre2_code *pcregex;
+#elif defined(USE_PCRE)
   pcre *pcregex;
 #else
   regex_t *regex;
@@ -127,7 +131,13 @@ static apr_array_header_t* _mapcache_dimension_regex_get_entries_for_value(mapca
 {
   mapcache_dimension_regex *dimension = (mapcache_dimension_regex*)dim;
   apr_array_header_t *values = apr_array_make(ctx->pool,1,sizeof(char*));
-#ifdef USE_PCRE
+#if defined(USE_PCRE2)
+  pcre2_match_data *match_data;
+  int rc = pcre2_match(dimension->pcregex,(PCRE2_SPTR)value,strlen(value),0,0,match_data,NULL);
+  if(rc>0) {
+    APR_ARRAY_PUSH(values,char*) = apr_pstrdup(ctx->pool,value);
+  }
+#elif defined(USE_PCRE)
   int ovector[30];
   int rc = pcre_exec(dimension->pcregex,NULL,value,strlen(value),0,0,ovector,30);
   if(rc>0) {
@@ -168,7 +178,18 @@ static void _mapcache_dimension_regex_parse_xml(mapcache_context *ctx, mapcache_
     ctx->set_error(ctx,400,"failed to parse %s regex: no <regex> child supplied",dim->class_name);
     return;
   }
-#ifdef USE_PCRE
+#if defined(USE_PCRE2)
+  {
+    int pcre_err;
+    PCRE2_SIZE *pcre_offset;
+    dimension->pcregex = pcre2_compile((PCRE2_SPTR8)dimension->regex_string,strlen(dimension->regex_string), 0, &pcre_err, pcre_offset, NULL);
+    if(!dimension->pcregex) {
+      ctx->set_error(ctx,400,"failed to compile regular expression \"%s\" for %s \"%s\": %d",
+                     dimension->regex_string,dim->class_name,dim->name,pcre_err);
+      return;
+    }
+  }
+#elif defined(USE_PCRE)
   {
     const char *pcre_err;
     int pcre_offset;
@@ -294,7 +315,7 @@ mapcache_dimension* mapcache_dimension_regex_create(mapcache_context *ctx, apr_p
   mapcache_dimension_regex *dimension = apr_pcalloc(pool, sizeof(mapcache_dimension_regex));
   dimension->dimension.type = MAPCACHE_DIMENSION_REGEX;
   dimension->dimension.class_name = "dimension";
-#ifndef USE_PCRE
+#if !defined(USE_PCRE) && !defined(USE_PCRE2)
   dimension->regex = (regex_t*)apr_pcalloc(pool, sizeof(regex_t));
 #endif
   dimension->dimension._get_entries_for_value = _mapcache_dimension_regex_get_entries_for_value;


=====================================
lib/dimension_pg.c
=====================================
@@ -40,8 +40,10 @@ struct mapcache_dimension_postgresql {
   char *dbconnection;
   char *get_values_for_entry_query;
   char *get_all_values_query;
+  char *get_default_value_query;
   apr_hash_t  *get_values_indexes;
   apr_hash_t  *get_all_indexes;
+  apr_hash_t  *get_default_value_indexes;
 };
 
 struct postgresql_dimension_conn {
@@ -74,9 +76,10 @@ static int qparam(mapcache_context *ctx, char *qstring, const char *param, int i
 static void parse_queries(mapcache_context *ctx, mapcache_dimension_postgresql *dim) {
   const char *keys[9] = {":tileset",":dim",":gridsrs",":minx",":maxx",":miny",":maxy",":start_timestamp",":end_timestamp"};
   int i;
-  int gaidx=1,gvidx=1;
+  int gaidx=1,gvidx=1,gdidx=1;
   dim->get_all_indexes = apr_hash_make(ctx->pool);
   dim->get_values_indexes = apr_hash_make(ctx->pool);
+  dim->get_default_value_indexes = apr_hash_make(ctx->pool);
   for(i=0;i<9;i++) {
     if(qparam(ctx,dim->get_all_values_query,keys[i],gaidx)) {
       apr_hash_set(dim->get_all_indexes,keys[i],APR_HASH_KEY_STRING,INT2VOIDP(gaidx));
@@ -86,6 +89,12 @@ static void parse_queries(mapcache_context *ctx, mapcache_dimension_postgresql *
       apr_hash_set(dim->get_values_indexes,keys[i],APR_HASH_KEY_STRING,INT2VOIDP(gvidx));
       gvidx++;
     }
+    if (dim->get_default_value_query){
+      if(qparam(ctx,dim->get_default_value_query,keys[i],gdidx)) {
+        apr_hash_set(dim->get_default_value_indexes,keys[i],APR_HASH_KEY_STRING,INT2VOIDP(gdidx));
+        gdidx++;
+      }
+    }
   }
 }
 
@@ -220,6 +229,14 @@ void mapcache_postgresql_dimension_connection_constructor(mapcache_context *ctx,
     *conn_ = NULL;
     return;
   }
+  if (dim->get_default_value_query){
+    prepare_query(ctx,conn->pgconn, "get_default_value", dim->get_default_value_query, dim->get_default_value_indexes);
+    if(GC_HAS_ERROR(ctx)) {
+      PQfinish(conn->pgconn);
+      *conn_ = NULL;
+      return;
+    }
+  }
 }
 
 void mapcache_postgresql_dimension_connection_destructor(void *conn_)
@@ -330,6 +347,47 @@ static apr_array_header_t* _mapcache_dimension_postgresql_get_all_entries(mapcac
 
 }
 
+static apr_array_header_t* _mapcache_dimension_postgresql_get_default_entries(mapcache_context *ctx, mapcache_dimension *dim,
+       mapcache_tileset *tileset, mapcache_extent *extent, mapcache_grid *grid) {
+  mapcache_dimension_postgresql *sdim = (mapcache_dimension_postgresql*)dim;
+  PGresult *res;
+  apr_array_header_t *time_ids = NULL;
+  mapcache_pooled_connection *pc;
+  struct postgresql_dimension_conn *conn;
+  int nParams, *paramLengths,*paramFormats,i;
+  char **paramValues;
+
+  if (sdim->get_default_value_query == NULL){
+    return NULL;
+  }
+  pc = _postgresql_dimension_get_conn(ctx,tileset,sdim);
+  if (GC_HAS_ERROR(ctx)) {
+    return NULL;
+  }
+  conn = pc->connection;
+  _mapcache_dimension_postgresql_bind_parameters(ctx,sdim->get_all_indexes,NULL,tileset,extent,grid,0,0,&nParams,&paramValues,&paramLengths,&paramFormats);
+  if(GC_HAS_ERROR(ctx)) {
+    _postgresql_dimension_release_conn(ctx, pc);
+    return NULL;
+  }
+  res = PQexecPrepared(conn->pgconn,"get_default_value",nParams,(const char *const*)paramValues,paramLengths,paramFormats,0);
+  if (PQresultStatus(res) != PGRES_TUPLES_OK) {
+    //ctx->set_error(ctx, 500, "postgresql query: %s", PQerrorMessage(conn->pgconn));
+    PQclear(res);
+    _postgresql_dimension_release_conn(ctx, pc);
+    return NULL;
+  }
+
+  time_ids = apr_array_make(ctx->pool,0,sizeof(char*));
+  for(i=0;i<PQntuples(res);i++) {
+    APR_ARRAY_PUSH(time_ids, char *) = apr_pstrdup(ctx->pool, PQgetvalue(res,i,0));
+  }
+  PQclear(res);
+  _postgresql_dimension_release_conn(ctx, pc);
+  return time_ids;
+
+}
+
 static void _mapcache_dimension_postgresql_parse_xml(mapcache_context *ctx, mapcache_dimension *dim,
     ezxml_t node)
 {
@@ -359,6 +417,14 @@ static void _mapcache_dimension_postgresql_parse_xml(mapcache_context *ctx, mapc
     ctx->set_error(ctx,400,"postgresql dimension \"%s\" has no <list_query> node", dim->name);
     return;
   }
+  child = ezxml_child(node,"default_query");
+  if(child) {
+    dimension->get_default_value_query = apr_pstrdup(ctx->pool, child->txt);
+  } else {
+    dimension->get_default_value_query = NULL;
+  //   ctx->set_error(ctx,400,"postgresql dimension \"%s\" has no <default_query> node", dim->name);
+  //   return;
+  }
   parse_queries(ctx,dimension);
   //printf("q1: %s\n",dimension->get_all_values_query);
   //printf("q2: %s\n",dimension->get_values_for_entry_query);
@@ -377,6 +443,7 @@ mapcache_dimension* mapcache_dimension_postgresql_create(mapcache_context *ctx,
   dimension->dimension.configuration_parse_xml = _mapcache_dimension_postgresql_parse_xml;
   dimension->dimension.get_all_entries = _mapcache_dimension_postgresql_get_all_entries;
   dimension->dimension.get_all_ogc_formatted_entries = _mapcache_dimension_postgresql_get_all_entries;
+  dimension->dimension.get_default_value = _mapcache_dimension_postgresql_get_default_entries;
   return (mapcache_dimension*)dimension;
 #else
   ctx->set_error(ctx,400,"postgresql dimension support requires POSTGRESQL support to be built in");


=====================================
lib/http.c
=====================================
@@ -40,6 +40,8 @@ struct _header_struct {
   mapcache_context *ctx;
 };
 
+char *base64_encode(apr_pool_t *pool, const unsigned char *data, size_t input_length);
+
 size_t _mapcache_curl_memory_callback(void *ptr, size_t size, size_t nmemb, void *data)
 {
   mapcache_buffer *buffer = (mapcache_buffer*)data;
@@ -414,8 +416,43 @@ mapcache_http* mapcache_http_configuration_parse_xml(mapcache_context *ctx, ezxm
       apr_table_set(req->headers, header_node->name, header_node->txt);
     }
   }
+
+  /* Parse auth and append to headers for simplicity */
+  if ((http_node = ezxml_child(node, "auth")) != NULL) {
+    if (ezxml_attr(http_node, "scheme") &&
+        strcmp(ezxml_attr(http_node, "scheme"), "basic") == 0) {
+      ezxml_t user_node, pass_node;
+      char *credentials, *str2enc;
+      user_node = ezxml_child(http_node, "user");
+      pass_node = ezxml_child(http_node, "pass");
+      if (!user_node || !pass_node) {
+        ctx->set_error(ctx, 400,
+                       "both <http> <auth> username (<user>) and password "
+                       "(<pass>) elements must be provided");
+        return NULL;
+      }
+      str2enc =
+          apr_pstrcat(ctx->pool, user_node->txt, ":", pass_node->txt, NULL);
+      credentials = base64_encode(ctx->pool, (unsigned char *)str2enc,
+                                  sizeof(unsigned char) * strlen(str2enc));
+      memset(str2enc, '\0', sizeof(char) * strlen(str2enc));
+      if (credentials == NULL) {
+        ctx->set_error(ctx, 400, "error encoding <http> <auth> credentials");
+        return NULL;
+      }
+      apr_table_set(req->headers, "Authorization",
+                    apr_pstrcat(ctx->pool, "Basic ", credentials, NULL));
+      memset(credentials, '\0', sizeof(char) * strlen(credentials));
+    } else {
+      ctx->set_error(ctx, 400,
+                     "invalid or missing <http> <auth> scheme (only 'basic' "
+                     "scheme supported)");
+      return NULL;
+    }
+  }
+
   return req;
-  /* TODO: parse <proxy> and <auth> elements */
+  /* TODO: parse <proxy> element */
 }
 
 


=====================================
lib/imageio_png.c
=====================================
@@ -33,10 +33,7 @@
 #include <apr_strings.h>
 
 #ifdef _WIN32
-typedef unsigned char     uint8_t;
-typedef unsigned short    uint16_t;
-typedef unsigned int      uint32_t;
-typedef unsigned long int uint64_t;
+#include <stdint.h>
 #endif
 
 #ifndef Z_BEST_SPEED


=====================================
lib/service_wms.c
=====================================
@@ -314,6 +314,7 @@ void _create_capabilities_wms(mapcache_context *ctx, mapcache_request_get_capabi
     if(tileset->dimensions) {
       for(i=0; i<tileset->dimensions->nelts; i++) {
         apr_array_header_t *values;
+        apr_array_header_t *default_value;
         int value_idx;
         char *dimval = NULL;
         mapcache_dimension *dimension = APR_ARRAY_IDX(tileset->dimensions,i,mapcache_dimension*);
@@ -337,6 +338,11 @@ void _create_capabilities_wms(mapcache_context *ctx, mapcache_request_get_capabi
         if(dimval) {
           ezxml_set_txt(dimxml,dimval);
         }
+        default_value = dimension->get_default_value(ctx,dimension,tileset,NULL,NULL);
+        if (default_value){
+          dimension->default_value = APR_ARRAY_IDX(default_value,0,char *);
+          ezxml_set_attr(dimxml,"default",dimension->default_value);
+        }
       }
     }
 
@@ -886,7 +892,7 @@ void _mapcache_service_wms_parse_request(mapcache_context *ctx, mapcache_service
           mapcache_dimension *dimension = APR_ARRAY_IDX(tileset->dimensions,i,mapcache_dimension*);
           const char *value;
           if((value = (char*)apr_table_get(params,dimension->name)) != NULL) {
-            mapcache_map_set_cached_dimension(ctx,&fi->map,dimension->name,value);
+            mapcache_map_set_requested_dimension(ctx,&fi->map,dimension->name,value);
             GC_CHECK_ERROR(ctx);
           }
         }


=====================================
lib/util.c
=====================================
@@ -45,10 +45,7 @@
 #endif
 
 #ifdef _WIN32
-typedef unsigned char     uint8_t;
-typedef unsigned short    uint16_t;
-typedef unsigned int      uint32_t;
-typedef unsigned long int uint64_t;
+#include <stdint.h>
 #endif
 
 const double mapcache_meters_per_unit[MAPCACHE_UNITS_COUNT] = {1.0,6378137.0 * 2.0 * M_PI / 360,0.3048};


=====================================
nginx/ngx_http_mapcache_module.c
=====================================
@@ -300,7 +300,7 @@ ngx_http_mapcache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
     ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "no mapcache <service>s configured/enabled, no point in continuing.");
     return NGX_CONF_ERROR;
   }
-  mapcache_cache_child_init(ctx,ctx->cfg,ctx->pool);
+  mapcache_cache_child_init(ctx,ctx->config,ctx->pool);
   if(GC_HAS_ERROR(ctx)) {
     ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,ctx->get_error_message(ctx));
     return NGX_CONF_ERROR;


=====================================
release.sh
=====================================
@@ -26,7 +26,7 @@ fi
 echo "#"
 echo "# Make sure:"
 echo "# - you are on branch-$ms_version_major-$ms_version_minor"
-echo "# - you have edited MIGRATION_GUIDE.txt with changes related to this release"
+echo "# - you have edited MIGRATION_GUIDE.md with changes related to this release"
 echo "#"
 echo ""
 


=====================================
util/mapcache_seed.c
=====================================
@@ -318,8 +318,9 @@ int ogr_features_intersect_tile(mapcache_context *ctx, mapcache_tile *tile)
 {
   mapcache_metatile *mt = mapcache_tileset_metatile_get(ctx,tile);
   GEOSCoordSequence *mtbboxls = GEOSCoordSeq_create(5,2);
-  GEOSGeometry *mtbbox = GEOSGeom_createLinearRing(mtbboxls);
-  GEOSGeometry *mtbboxg = GEOSGeom_createPolygon(mtbbox,NULL,0);
+  // linearring and polygon creation moved after coords - more recent GEOS seems to assume coordinates are set
+  GEOSGeometry *mtbbox = NULL;
+  GEOSGeometry *mtbboxg = NULL;
   int i;
   int intersects = 0;
   GEOSCoordSeq_setX(mtbboxls,0,mt->map.extent.minx);
@@ -332,6 +333,10 @@ int ogr_features_intersect_tile(mapcache_context *ctx, mapcache_tile *tile)
   GEOSCoordSeq_setY(mtbboxls,3,mt->map.extent.maxy);
   GEOSCoordSeq_setX(mtbboxls,4,mt->map.extent.minx);
   GEOSCoordSeq_setY(mtbboxls,4,mt->map.extent.miny);
+  // moved after coords - more recent GEOS seems to assume coordinates are set
+  mtbbox = GEOSGeom_createLinearRing(mtbboxls);
+  mtbboxg = GEOSGeom_createPolygon(mtbbox,NULL,0);
+
   for(i=0; i<nClippers; i++) {
     const GEOSPreparedGeometry *clipper = clippers[i];
     if(GEOSPreparedIntersects(clipper,mtbboxg)) {
@@ -485,7 +490,23 @@ void cmd_recurse(mapcache_context *cmd_ctx, mapcache_tile *tile)
   if(sig_int_received || error_detected) { //stop if we were asked to stop by hitting ctrl-c
     //remove all items from the queue
     struct seed_cmd entry;
-    while (trypop_queue(&entry)!=APR_EAGAIN) /*do nothing*/;
+    int retry_count = 0;
+    int ret = trypop_queue(&entry);
+    while (ret != APR_EAGAIN) {
+      // try to empty queue with a graceful retreat up to 55 seconds
+      // for retries before forcefully terminating threads
+      if (ret == APR_EOF)
+        break;
+      if (ret != APR_SUCCESS)
+        retry_count++;
+      if (retry_count > 10) {
+        printf("Feed worker threads failed to terminate. Stopping forcefully.\n");
+        apr_queue_interrupt_all(work_queue);
+        break;
+      }
+      apr_sleep(retry_count * 1000000);
+      ret = trypop_queue(&entry);
+    }
     return;
   }
 
@@ -614,7 +635,23 @@ void feed_worker()
       if(sig_int_received || error_detected) { //stop if we were asked to stop by hitting ctrl-c
         //remove all items from the queue
         struct seed_cmd entry;
-        while (trypop_queue(&entry)!=APR_EAGAIN) /* do nothing */;
+        int retry_count = 0;
+        int ret = trypop_queue(&entry);
+        while (ret != APR_EAGAIN) {
+          // try to empty queue with a graceful retreat up to 55 seconds
+          // for retries before forcefully terminating threads
+          if (ret == APR_EOF)
+            break;
+          if (ret != APR_SUCCESS)
+            retry_count++;
+          if (retry_count > 10) {
+            printf("Feed worker threads failed to terminate. Stopping forcefully.\n");
+            apr_queue_interrupt_all(work_queue);
+            break;
+          }
+          apr_sleep(retry_count * 1000000);
+          ret = trypop_queue(&entry);
+        }
         break;
       }
       if(iteration_mode == MAPCACHE_ITERATION_LOG) {



View it on GitLab: https://salsa.debian.org/debian-gis-team/mapcache/-/commit/f153b3de63b87ac1cb87eb703d054d7062562c0f

-- 
View it on GitLab: https://salsa.debian.org/debian-gis-team/mapcache/-/commit/f153b3de63b87ac1cb87eb703d054d7062562c0f
You're receiving this email because of your account on salsa.debian.org.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/pkg-grass-devel/attachments/20240802/3fc8cf47/attachment-0001.htm>


More information about the Pkg-grass-devel mailing list