--- /dev/null
+diff --git a/CMakeLists.txt b/CMakeLists.txt
+index ff893a84..1745823 100644
+--- a/CMakeLists.txt
++++ b/CMakeLists.txt
+@@ -37,6 +37,24 @@ if (APPLE)
+ set(CMAKE_FIND_FRAMEWORK "LAST")
+ endif (APPLE)
+
++# Offer the user the choice of overriding the installation directories
++set(INSTALL_LIB_DIR lib CACHE PATH "Installation directory for libraries")
++set(INSTALL_BIN_DIR bin CACHE PATH "Installation directory for executables")
++set(INSTALL_INCLUDE_DIR include CACHE PATH "Installation directory for header files")
++if(WIN32 AND NOT CYGWIN)
++ set(DEF_INSTALL_CMAKE_DIR CMake)
++else()
++ set(DEF_INSTALL_CMAKE_DIR share/mapserver/cmake)
++endif()
++set(INSTALL_CMAKE_DIR ${DEF_INSTALL_CMAKE_DIR} CACHE PATH "Installation directory for CMake files")
++
++# Make relative paths absolute (needed later on)
++foreach(p LIB BIN INCLUDE CMAKE)
++ set(var INSTALL_${p}_DIR)
++ if(NOT IS_ABSOLUTE "${${var}}")
++ set(${var} "${CMAKE_INSTALL_PREFIX}/${${var}}")
++ endif()
++endforeach()
+
+ macro (ms_link_libraries)
+ if(BUILD_DYNAMIC)
+@@ -246,6 +264,15 @@ mapgeomtransform.c mapogroutput.c mapwfslayer.c mapagg.cpp mapkml.cpp
+ mapgeomutil.cpp mapkmlrenderer.cpp fontcache.c textlayout.c maputfgrid.cpp
+ mapogr.cpp mapcontour.c mapsmoothing.c mapv8.cpp ${REGEX_SOURCES} kerneldensity.c)
+
++set(mapserver_HEADERS
++cgiutil.h dejavu-sans-condensed.h dxfcolor.h fontcache.h hittest.h mapagg.h
++mapaxisorder.h mapcopy.h mapentities.h maperror.h mapfile.h mapgml.h maphash.h
++maphttp.h mapio.h mapkmlrenderer.h maplibxml2.h mapogcfilter.h mapogcsld.h
++mapoglcontext.h mapoglrenderer.h mapowscommon.h mapows.h mapparser.h
++mappostgis.h mapprimitive.h mapproject.h mapraster.h mapregex.h mapresample.h
++mapserver-api.h mapserver.h mapserv.h mapshape.h mapsymbol.h maptemplate.h
++mapthread.h maptile.h maptime.h maptree.h maputfgrid.h mapwcs.h uthash.h)
++
+ if(BUILD_DYNAMIC)
+ add_library(mapserver SHARED ${mapserver_SOURCES} ${agg_SOURCES} ${v8_SOURCES})
+ set_target_properties( mapserver PROPERTIES
+@@ -299,6 +326,7 @@ find_package(PNG)
+ if(PNG_FOUND)
+ include_directories(${PNG_INCLUDE_DIR})
+ ms_link_libraries( ${PNG_LIBRARIES})
++ list(APPEND ALL_INCLUDE_DIRS ${PNG_INCLUDE_DIR})
+ set(USE_PNG 1)
+ else(PNG_FOUND)
+ report_mandatory_not_found(PNG)
+@@ -308,6 +336,7 @@ find_package(JPEG)
+ if(JPEG_FOUND)
+ include_directories(${JPEG_INCLUDE_DIR})
+ ms_link_libraries( ${JPEG_LIBRARY})
++ list(APPEND ALL_INCLUDE_DIRS ${JPEG_INCLUDE_DIR})
+ set(USE_JPEG 1)
+ else(JPEG_FOUND)
+ report_mandatory_not_found(JPEG)
+@@ -319,6 +348,7 @@ if(NOT FREETYPE_FOUND)
+ endif(NOT FREETYPE_FOUND)
+ include_directories(${FREETYPE_INCLUDE_DIR})
+ ms_link_libraries( ${FREETYPE_LIBRARY})
++list(APPEND ALL_INCLUDE_DIRS ${FREETYPE_INCLUDE_DIR})
+
+
+ if(WITH_PROJ)
+@@ -328,6 +358,7 @@ if(WITH_PROJ)
+ else(NOT PROJ_FOUND)
+ include_directories(${PROJ_INCLUDE_DIR})
+ ms_link_libraries( ${PROJ_LIBRARY})
++ list(APPEND ALL_INCLUDE_DIRS ${PROJ_INCLUDE_DIR})
+ set (USE_PROJ 1)
+ endif(NOT PROJ_FOUND)
+ endif (WITH_PROJ)
+@@ -337,6 +368,7 @@ if(WITH_PIXMAN)
+ if(PIXMAN_FOUND)
+ include_directories(${PIXMAN_INCLUDE_DIR})
+ ms_link_libraries(${PIXMAN_LIBRARY})
++ list(APPEND ALL_INCLUDE_DIRS ${PIXMAN_INCLUDE_DIR})
+ set (USE_PIXMAN 1)
+ else(PIXMAN_FOUND)
+ report_optional_not_found(PIXMAN)
+@@ -358,6 +390,7 @@ if(WITH_FRIBIDI)
+ else(NOT FRIBIDI_FOUND)
+ include_directories(${FRIBIDI_INCLUDE_DIR})
+ ms_link_libraries( ${FRIBIDI_LIBRARY})
++ list(APPEND ALL_INCLUDE_DIRS ${FRIBIDI_INCLUDE_DIR})
+ set (USE_FRIBIDI 1)
+ if(FRIBIDI_LEGACY)
+ message(WARNING "Old Fribidi found, upgrade recommended")
+@@ -372,6 +405,7 @@ if(WITH_HARFBUZZ)
+ else(NOT HARFBUZZ_FOUND)
+ include_directories(${HARFBUZZ_INCLUDE_DIR})
+ ms_link_libraries( ${HARFBUZZ_LIBRARY})
++ list(APPEND ALL_INCLUDE_DIRS ${HARFBUZZ_INCLUDE_DIR})
+ set (USE_HARFBUZZ 1)
+ endif(NOT HARFBUZZ_FOUND)
+ endif (WITH_HARFBUZZ)
+@@ -389,6 +423,7 @@ if(WITH_ICONV)
+ if(ICONV_FOUND)
+ include_directories(${ICONV_INCLUDE_DIR})
+ ms_link_libraries( ${ICONV_LIBRARY})
++ list(APPEND ALL_INCLUDE_DIRS ${ICONV_INCLUDE_DIR})
+ set (USE_ICONV 1)
+ else(ICONV_FOUND)
+ report_optional_not_found(ICONV)
+@@ -405,6 +440,7 @@ if(WITH_CAIRO)
+ if(CAIRO_FOUND)
+ include_directories(${CAIRO_INCLUDE_DIRS})
+ ms_link_libraries( ${CAIRO_LIBRARY})
++ list(APPEND ALL_INCLUDE_DIRS ${CAIRO_INCLUDE_DIR})
+ set (USE_CAIRO 1)
+ else(CAIRO_FOUND)
+ report_optional_not_found(CAIRO)
+@@ -416,6 +452,7 @@ if(WITH_MYSQL)
+ if(MYSQL_FOUND)
+ include_directories(${MYSQL_INCLUDE_DIR})
+ ms_link_libraries( ${MYSQL_LIBRARY})
++ list(APPEND ALL_INCLUDE_DIRS ${MYSQL_INCLUDE_DIR})
+ set (USE_MYSQL 1)
+ else(MYSQL_FOUND)
+ report_optional_not_found(MYSQL)
+@@ -433,6 +470,7 @@ if(WITH_ORACLESPATIAL OR WITH_ORACLE_PLUGIN)
+ find_package(Oracle)
+ if(ORACLE_FOUND)
+ include_directories(${ORACLE_INCLUDE_DIR})
++ list(APPEND ALL_INCLUDE_DIRS ${ORACLE_INCLUDE_DIR})
+ else(ORACLE_FOUND)
+ report_optional_not_found(ORACLESPATIAL)
+ #FIXME: error message here could be misleading, only states ORACLESPATIAL whereas
+@@ -459,6 +497,7 @@ if(WITH_MSSQL2008)
+ add_library(msplugin_mssql2008 MODULE mapmssql2008.c)
+ target_link_libraries(msplugin_mssql2008 ${ODBC_LIBRARY} ${MAPSERVER_LIBMAPSERVER})
+ set_target_properties(msplugin_mssql2008 PROPERTIES COMPILE_FLAGS "-DUSE_MSSQL2008_PLUGIN -DUSE_MSSQL2008")
++ list(APPEND ALL_INCLUDE_DIRS ${ODBC_INCLUDE_DIR})
+ set (USE_MSSQL2008 1)
+ else(ODBC_FOUND)
+ report_optional_not_found(ODBC)
+@@ -470,6 +509,7 @@ if(WITH_FCGI)
+ if(FCGI_FOUND)
+ include_directories(${FCGI_INCLUDE_DIR})
+ target_link_libraries(mapserv ${FCGI_LIBRARY})
++ list(APPEND ALL_INCLUDE_DIRS ${FCGI_INCLUDE_DIR})
+ set (USE_FASTCGI 1)
+ else(FCGI_FOUND)
+ report_optional_not_found(FCGI)
+@@ -481,6 +521,7 @@ if(WITH_GEOS)
+ if(GEOS_FOUND)
+ include_directories(${GEOS_INCLUDE_DIR})
+ ms_link_libraries( ${GEOS_LIBRARY})
++ list(APPEND ALL_INCLUDE_DIRS ${GEOS_INCLUDE_DIR})
+ set (USE_GEOS 1)
+ else(GEOS_FOUND)
+ report_optional_not_found(GEOS)
+@@ -500,6 +541,7 @@ if(WITH_POSTGIS)
+ include_directories(${POSTGRESQL_INCLUDE_DIR})
+ ms_link_libraries( ${POSTGRESQL_LIBRARY})
+ CHECK_LIBRARY_EXISTS(pq "PQserverVersion" POSTGRESQL_LIBRARY POSTGIS_HAS_SERVER_VERSION)
++ list(APPEND ALL_INCLUDE_DIRS ${POSTGRESQL_INCLUDE_DIR})
+ set (USE_POSTGIS 1)
+ else(POSTGRESQL_FOUND)
+ report_optional_not_found(POSTGIS)
+@@ -511,6 +553,7 @@ if(WITH_GDAL)
+ if(GDAL_FOUND)
+ include_directories(${GDAL_INCLUDE_DIR})
+ ms_link_libraries( ${GDAL_LIBRARY})
++ list(APPEND ALL_INCLUDE_DIRS ${GDAL_INCLUDE_DIR})
+ set (USE_GDAL 1)
+ else(GDAL_FOUND)
+ report_optional_not_found(GDAL)
+@@ -525,6 +568,7 @@ if(WITH_SVGCAIRO)
+ if(SVGCAIRO_FOUND)
+ include_directories(${SVG_INCLUDE_DIR} ${SVGCAIRO_INCLUDE_DIR})
+ ms_link_libraries( ${SVG_LIBRARY} ${SVGCAIRO_LIBRARY})
++ list(APPEND ALL_INCLUDE_DIRS ${SVG_INCLUDE_DIR} ${SVGCAIRO_INCLUDE_DIR})
+ set (USE_SVG_CAIRO 1)
+ else(SVGCAIRO_FOUND)
+ report_optional_not_found(SVGCAIRO)
+@@ -539,8 +583,10 @@ if(WITH_RSVG)
+ if(RSVG_FOUND AND GOBJECT_FOUND)
+ include_directories(${RSVG_INCLUDE_DIRS})
+ ms_link_libraries( ${RSVG_LIBRARY} )
++ list(APPEND ALL_INCLUDE_DIRS ${RSVG_INCLUDE_DIRS})
+ include_directories(${GOBJECT_INCLUDE_DIRS})
+ ms_link_libraries( ${GOBJECT_LIBRARY} )
++ list(APPEND ALL_INCLUDE_DIRS ${GOBJECT_INCLUDE_DIRS})
+ set (USE_RSVG 1)
+ else(RSVG_FOUND AND GOBJECT_FOUND)
+ report_optional_not_found(RSVG)
+@@ -555,6 +601,7 @@ if(WITH_OGR)
+ if(GDAL_FOUND)
+ include_directories(${GDAL_INCLUDE_DIR})
+ ms_link_libraries( ${GDAL_LIBRARY})
++ list(APPEND ALL_INCLUDE_DIRS ${GDAL_INCLUDE_DIR})
+ set (USE_OGR 1)
+ else(GDAL_FOUND)
+ message(SEND_ERROR "GDAL library could not be found and is needed for OGR support.
+@@ -574,6 +621,7 @@ if(WITH_CURL)
+ if(CURL_FOUND)
+ include_directories(${CURL_INCLUDE_DIR})
+ ms_link_libraries( ${CURL_LIBRARY})
++ list(APPEND ALL_INCLUDE_DIRS ${CURL_INCLUDE_DIR})
+ set(USE_CURL 1)
+ else(CURL_FOUND)
+ report_optional_not_found(CURL)
+@@ -652,6 +700,7 @@ if(WITH_LIBXML2)
+ set(LIBXML2_LIBRARY ${LIBXML2_LIBRARIES})
+ endif()
+ ms_link_libraries( ${LIBXML2_LIBRARY})
++ list(APPEND ALL_INCLUDE_DIRS ${LIBXML2_INCLUDE_DIR})
+ set (USE_LIBXML2 1)
+ else(LIBXML2_FOUND)
+ report_optional_not_found(LIBXML2)
+@@ -716,6 +765,7 @@ if(WITH_XMLMAPFILE)
+ endif()
+ include_directories(${LIBXSLT_INCLUDE_DIR})
+ ms_link_libraries( ${LIBXSLT_LIBRARY} ${LIBXSLT_EXSLT_LIBRARY})
++ list(APPEND ALL_INCLUDE_DIRS ${LIBXSLT_INCLUDE_DIR})
+ set(USE_XMLMAPFILE 1)
+ else(LIBXSLT_FOUND)
+ message(SEND_ERROR "Xml Mapfile support requires XSLT support which was not found.
+@@ -731,6 +781,7 @@ if(WITH_GIF)
+ if(GIF_FOUND)
+ include_directories(${GIF_INCLUDE_DIR})
+ ms_link_libraries( ${GIF_LIBRARY})
++ list(APPEND ALL_INCLUDE_DIRS ${GIF_INCLUDE_DIR})
+ set(USE_GIF 1)
+ else(GIF_FOUND)
+ report_optional_not_found(GIF)
+@@ -742,6 +793,7 @@ if(WITH_EXEMPI)
+ if(LIBEXEMPI_FOUND)
+ include_directories(${LIBEXEMPI_INCLUDE_DIR})
+ ms_link_libraries( ${LIBEXEMPI_LIBRARY})
++ list(APPEND ALL_INCLUDE_DIRS ${LIBEXEMPI_INCLUDE_DIR})
+ set(USE_EXEMPI 1)
+ else(LIBEXEMPI_FOUND)
+ report_optional_not_found(EXEMPI)
+@@ -759,6 +811,7 @@ if(WITH_V8)
+ SET(USE_V8_MAPSCRIPT 1)
+ INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
+ INCLUDE_DIRECTORIES(${V8_INCLUDE})
++ list(APPEND ALL_INCLUDE_DIRS ${V8_INCLUDE})
+ MS_LINK_LIBRARIES( ${V8_LIBS})
+ ELSE(V8_FOUND)
+ MESSAGE(SEND_ERROR "V8 JavaScript support requested but not found.
+@@ -817,7 +870,9 @@ configure_file (
+ "${PROJECT_BINARY_DIR}/mapserver-version.h"
+ )
+
+-
++set_target_properties(mapserver PROPERTIES
++ PUBLIC_HEADER "${mapserver_HEADERS};${PROJECT_BINARY_DIR}/mapserver-config.h;${PROJECT_BINARY_DIR}/mapserver-version.h"
++)
+
+ macro(status_optional_component component enabled libpath)
+ if("${enabled}" EQUAL "1")
+@@ -895,7 +950,7 @@ status_optional_feature("Apache Module (Experimental)" "${USE_APACHE_MODULE}")
+
+ message(STATUS "")
+ message(STATUS "Will install files to ${CMAKE_INSTALL_PREFIX}")
+-message(STATUS "Will install libraries to ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}")
++message(STATUS "Will install libraries to ${INSTALL_LIB_DIR}")
+
+
+ include_directories("${PROJECT_BINARY_DIR}")
+@@ -908,20 +963,67 @@ endif(WIN32)
+
+ #INSTALL(FILES mapserver-api.h ${PROJECT_BINARY_DIR}/mapserver-version.h DESTINATION include)
+ if(USE_ORACLE_PLUGIN)
+- INSTALL(TARGETS msplugin_oracle DESTINATION ${CMAKE_INSTALL_LIBDIR})
++ INSTALL(TARGETS msplugin_oracle DESTINATION ${INSTALL_LIB_DIR})
+ endif(USE_ORACLE_PLUGIN)
+
+ if(USE_MSSQL2008)
+- INSTALL(TARGETS msplugin_mssql2008 DESTINATION ${CMAKE_INSTALL_LIBDIR})
++ INSTALL(TARGETS msplugin_mssql2008 DESTINATION ${INSTALL_LIB_DIR})
+ endif(USE_MSSQL2008)
+
+
+-INSTALL(TARGETS sortshp shptree shptreevis msencrypt legend scalebar tile4ms shptreetst shp2img mapserv RUNTIME DESTINATION bin LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
++INSTALL(TARGETS sortshp shptree shptreevis msencrypt legend scalebar tile4ms shptreetst shp2img mapserv
++ RUNTIME DESTINATION ${INSTALL_BIN_DIR} COMPONENT bin
++)
+
+ if(BUILD_STATIC)
+- INSTALL(TARGETS mapserver_static DESTINATION ${CMAKE_INSTALL_LIBDIR})
++ INSTALL(TARGETS mapserver_static
++ DESTINATION ${INSTALL_LIB_DIR} COMPONENT staticlib
++ )
+ endif(BUILD_STATIC)
+ if(BUILD_DYNAMIC)
+- INSTALL(TARGETS mapserver DESTINATION ${CMAKE_INSTALL_LIBDIR})
++ INSTALL(TARGETS mapserver
++ EXPORT mapserverTargets
++ ARCHIVE DESTINATION ${INSTALL_LIB_DIR} COMPONENT shlib
++ LIBRARY DESTINATION ${INSTALL_LIB_DIR} COMPONENT shlib
++ PUBLIC_HEADER DESTINATION ${INSTALL_INCLUDE_DIR}/mapserver COMPONENT dev
++ )
+ endif(BUILD_DYNAMIC)
+
++# Add all targets to the build-tree export set
++export(TARGETS mapserver
++ FILE "${PROJECT_BINARY_DIR}/mapserverTargets.cmake"
++)
++
++# Export the package for use from the build-tree
++# (this registers the build-tree with a global CMake-registry)
++export(PACKAGE mapserver)
++
++list(APPEND ALL_INCLUDE_DIRS ${INSTALL_INCLUDE_DIR})
++list(APPEND ALL_INCLUDE_DIRS ${INSTALL_INCLUDE_DIR}/mapserver)
++
++list(REMOVE_DUPLICATES ALL_INCLUDE_DIRS)
++
++# Create the mapserver-config.cmake and mapserver-config-version files
++file(RELATIVE_PATH REL_INCLUDE_DIR "${INSTALL_CMAKE_DIR}" "${ALL_INCLUDE_DIRS}")
++
++# ... for the build tree
++set(CONF_INCLUDE_DIRS "${PROJECT_SOURCE_DIR}" "${PROJECT_BINARY_DIR}")
++configure_file(mapserver-config.cmake.in "${PROJECT_BINARY_DIR}/mapserver-config.cmake" @ONLY)
++
++# ... for the install tree
++set(CONF_INCLUDE_DIRS "\${MAPSERVER_CMAKE_DIR}/${REL_INCLUDE_DIR}")
++configure_file(mapserver-config.cmake.in "${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/mapserver-config.cmake" @ONLY)
++
++# ... for both
++configure_file(mapserver-config-version.cmake.in "${PROJECT_BINARY_DIR}/mapserver-config-version.cmake" @ONLY)
++
++# Install the mapserver-config.cmake and mapserver-config-version.cmake
++install(FILES "${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/mapserver-config.cmake"
++ "${PROJECT_BINARY_DIR}/mapserver-config-version.cmake"
++ DESTINATION "${INSTALL_CMAKE_DIR}" COMPONENT dev
++)
++
++# Install the export set for use with the install-tree
++install(EXPORT mapserverTargets
++ DESTINATION "${INSTALL_CMAKE_DIR}" COMPONENT dev
++)
+diff --git a/appveyor.yml b/appveyor.yml
+new file mode 100644
+index 0000000..62b072f
+--- /dev/null
++++ b/appveyor.yml
+@@ -0,0 +1,56 @@
++platform:
++- x64
++- x86
++
++environment:
++ matrix:
++#
++# VS 2010
++# - VS_VERSION: Visual Studio 10
++#
++# VS 2012
++# - VS_VERSION: Visual Studio 11
++#
++# VS 2013
++ - VS_VERSION: Visual Studio 12
++
++shallow_clone: true
++
++build_script:
++ - echo build_script
++ - if "%platform%" == "x64" SET VS_FULL=%VS_VERSION% Win64
++ - if "%platform%" == "x86" SET VS_FULL=%VS_VERSION%
++ - if "%platform%" == "x86" SET SDK=release-1800
++ - if "%platform%" == "x64" SET SDK=release-1800-x64
++ - 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 %SDK%
++ - cd lib
++ - copy libpng.lib libpng.lib.lib
++ - cd ..
++ - cd ..
++ - cd ..
++ - set SDK_PREFIX=%CD%\sdk\%SDK%
++ - set SDK_INC=%CD%\sdk\%SDK%\include
++ - set SDK_LIB=%CD%\sdk\%SDK%\lib
++ - set SDK_BIN=%CD%\sdk\%SDK%\bin
++ - set SWIG_EXECUTABLE=%CD%\sdk\SWIG-1.3.39\swig.exe
++ - set REGEX_DIR=%CD%\sdk\regex-0.12
++ - if "%platform%" == "x86" SET PYTHON_EXECUTABLE=c:\python27\python.exe
++ - if "%platform%" == "x64" SET PYTHON_EXECUTABLE=c:\python27-x64\python.exe
++ - mkdir build
++ - cd build
++ - cmake -G "%VS_FULL%" .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH=%SDK_PREFIX% -DFREETYPE_INCLUDE_DIR_freetype2=%SDK_INC%\freetype -DFREETYPE_INCLUDE_DIR_ft2build=%SDK_INC%\freetype -DFREETYPE_LIBRARY=%SDK_LIB%\freetype2411.lib -DZLIB_INCLUDE_DIR=%SDK_INC% -DZLIB_LIBRARY=%SDK_LIB%\zlib.lib -DPNG_PNG_INCLUDE_DIR=%SDK_INC% -DPNG_LIBRARY=%SDK_LIB%\libpng.lib -DPNG_LIBRARIES=%SDK_LIB%\libpng.lib -DJPEG_INCLUDE_DIR=%SDK_INC% -DJPEG_LIBRARY=%SDK_LIB%\libjpeg.lib -DWITH_PROJ=1 -DPROJ_INCLUDE_DIR=%SDK_INC% -DPROJ_LIBRARY=%SDK_LIB%\proj_i.lib -DFRIBIDI_INCLUDE_DIR=%SDK_INC% -DFRIBIDI_LIBRARY=%SDK_LIB%\fribidi.lib -DHARFBUZZ_INCLUDE_DIR=%SDK_INC%\harfbuzz -DHARFBUZZ_LIBRARY=%SDK_LIB%\harfbuzz.lib -DICONV_INCLUDE_DIR=%SDK_INC% -DICONV_LIBRARY=%SDK_LIB%\iconv.lib -DICONV_DLL=%SDK_BIN%\iconv.dll -DCAIRO_INCLUDE_DIR=%SDK_INC% -DCAIRO_LIBRARY=%SDK_LIB%\cairo.lib -DFCGI_INCLUDE_DIR=%SDK_INC% -DFCGI_LIBRARY=%SDK_LIB%\libfcgi.lib -DGEOS_INCLUDE_DIR=%SDK_INC% -DGEOS_LIBRARY=%SDK_LIB%\geos_c.lib -DPOSTGRESQL_INCLUDE_DIR=%SDK_INC% -DPOSTGRESQL_LIBRARY=%SDK_LIB%\libpqdll.lib -DGDAL_INCLUDE_DIR=%SDK_INC% -DGDAL_LIBRARY=%SDK_LIB%\gdal_i.lib -DLIBXML2_INCLUDE_DIR=%SDK_INC%\libxml -DLIBXML2_LIBRARIES=%SDK_LIB%\libxml2.lib -DGIF_INCLUDE_DIR=%SDK_INC% -DGIF_LIBRARY=%SDK_LIB%\giflib.lib -DWITH_CURL=1 -DCURL_INCLUDE_DIR=%SDK_INC% -DCURL_LIBRARY=%SDK_LIB%\libcurl_imp.lib -DMS_EXTERNAL_LIBS=wsock32.lib -DWITH_SOS=1 -DWITH_CLIENT_WFS=1 -DWITH_CLIENT_WMS=1 -DSVG_INCLUDE_DIR=%SDK_INC% -DSVG_LIBRARY=%SDK_LIB%\libsvg.lib -DSVGCAIRO_INCLUDE_DIR=%SDK_INC% -DSVGCAIRO_LIBRARY=%SDK_LIB%\libsvg-cairo.lib -DWITH_SVGCAIRO=1 -DREGEX_DIR=%REGEX_DIR% -DWITH_POINT_Z_M=1 -DWITH_KML=1 -DWITH_THREAD_SAFETY=1 -DSWIG_EXECUTABLE=%SWIG_EXECUTABLE% -DWITH_PYTHON=1 -DPYTHON_EXECUTABLE=%PYTHON_EXECUTABLE%
++ - cmake --build . --config Release
++
++test_script:
++ - echo test_script
++
++deploy: off
+diff --git a/mapagg.cpp b/mapagg.cpp
+index a9666a0..e214d51 100644
+--- a/mapagg.cpp
++++ b/mapagg.cpp
+@@ -822,6 +822,8 @@ imageObj *agg2CreateImage(int width, int height, outputFormatObj *format, colorO
+ if( (AGG_INT64U)bufSize != bufSize64 ) {
+ msSetError(MS_MEMERR, "%s: %d: Out of memory allocating " AGG_INT64U_FRMT " bytes.\n", "agg2CreateImage()",
+ __FILE__, __LINE__, bufSize64);
++ free(image);
++ delete r;
+ return NULL;
+ }
+
+@@ -830,6 +832,7 @@ imageObj *agg2CreateImage(int width, int height, outputFormatObj *format, colorO
+ msSetError(MS_MEMERR, "%s: %d: Out of memory allocating " AGG_INT64U_FRMT " bytes.\n", "agg2CreateImage()",
+ __FILE__, __LINE__, bufSize64);
+ free(image);
++ delete r;
+ return NULL;
+ }
+ r->m_rendering_buffer.attach(r->buffer, width, height, width * 4);
+diff --git a/mapdraw.c b/mapdraw.c
+index 1a7a73a..94c95cc 100644
+--- a/mapdraw.c
++++ b/mapdraw.c
+@@ -973,6 +973,7 @@ int msDrawVectorLayer(mapObj *map, layerObj *layer, imageObj *image)
+ }
+
+ if(maxfeatures >=0 && featuresdrawn >= maxfeatures) {
++ msFreeShape(&shape);
+ status = MS_DONE;
+ break;
+ }
+@@ -995,12 +996,14 @@ int msDrawVectorLayer(mapObj *map, layerObj *layer, imageObj *image)
+ if(strcasecmp(layer->styleitem, "AUTO") == 0) {
+ if(msLayerGetAutoStyle(map, layer, layer->class[shape.classindex], &shape) != MS_SUCCESS) {
+ retcode = MS_FAILURE;
++ msFreeShape(&shape);
+ break;
+ }
+ } else {
+ /* Generic feature style handling as per RFC-61 */
+ if(msLayerGetFeatureStyle(map, layer, layer->class[shape.classindex], &shape) != MS_SUCCESS) {
+ retcode = MS_FAILURE;
++ msFreeShape(&shape);
+ break;
+ }
+ }
+@@ -1060,6 +1063,7 @@ int msDrawVectorLayer(mapObj *map, layerObj *layer, imageObj *image)
+
+ if(cache) {
+ if(insertFeatureList(&shpcache, &shape) == NULL) {
++ msFreeShape(&shape);
+ retcode = MS_FAILURE; /* problem adding to the cache */
+ break;
+ }
+diff --git a/mapimageio.c b/mapimageio.c
+index e6bdcb5..771188b 100644
+--- a/mapimageio.c
++++ b/mapimageio.c
+@@ -391,11 +391,13 @@ int readPalette(const char *palette, rgbaPixel *entries, unsigned int *nEntries,
+ continue; /* skip comments and blank lines */
+ if(!useAlpha) {
+ if(3 != sscanf(buffer,"%d,%d,%d\n",&r,&g,&b)) {
++ fclose(stream);
+ msSetError(MS_MISCERR,"failed to parse color %d r,g,b triplet in line \"%s\" from file %s","readPalette()",*nEntries+1,buffer,palette);
+ return MS_FAILURE;
+ }
+ } else {
+ if(4 != sscanf(buffer,"%d,%d,%d,%d\n",&r,&g,&b,&a)) {
++ fclose(stream);
+ msSetError(MS_MISCERR,"failed to parse color %d r,g,b,a quadruplet in line \"%s\" from file %s","readPalette()",*nEntries+1,buffer,palette);
+ return MS_FAILURE;
+ }
+@@ -1058,6 +1060,13 @@ int readGIF(char *path, rasterBufferObj *rb)
+
+ } while (recordType != TERMINATE_RECORD_TYPE);
+
++
++#if defined GIFLIB_MAJOR && GIFLIB_MINOR && ((GIFLIB_MAJOR == 5 && GIFLIB_MINOR >= 1) || (GIFLIB_MAJOR > 5))
++ if (DGifCloseFile(image, &errcode) == GIF_ERROR) {
++ msSetError(MS_MISCERR,"failed to close gif after loading: %s","readGIF()", gif_error_msg(errcode));
++ return MS_FAILURE;
++ }
++#else
+ if (DGifCloseFile(image) == GIF_ERROR) {
+ #if defined GIFLIB_MAJOR && GIFLIB_MAJOR >= 5
+ msSetError(MS_MISCERR,"failed to close gif after loading: %s","readGIF()", gif_error_msg(image->Error));
+@@ -1066,6 +1075,7 @@ int readGIF(char *path, rasterBufferObj *rb)
+ #endif
+ return MS_FAILURE;
+ }
++#endif
+
+ return MS_SUCCESS;
+ }
+@@ -1082,6 +1092,7 @@ int msLoadMSRasterBufferFromFile(char *path, rasterBufferObj *rb)
+ return MS_FAILURE;
+ }
+ if(1 != fread(signature,8,1,stream)) {
++ fclose(stream);
+ msSetError(MS_MISCERR, "Unable to read header from image file %s", "msLoadMSRasterBufferFromFile()",path);
+ return MS_FAILURE;
+ }
+diff --git a/mapjoin.c b/mapjoin.c
+index 6353d64..9bb24ed 100644
+--- a/mapjoin.c
++++ b/mapjoin.c
+@@ -362,6 +362,7 @@ int msCSVJoinConnect(layerObj *layer, joinObj *join)
+ rewind(stream);
+
+ if((joininfo->rows = (char ***) malloc(joininfo->numrows*sizeof(char **))) == NULL) {
++ fclose(stream);
+ msSetError(MS_MEMERR, "Error allocating rows.", "msCSVJoinConnect()");
+ return(MS_FAILURE);
+ }
+diff --git a/maplabel.c b/maplabel.c
+index 6b804e1..d9d40bf 100644
+--- a/maplabel.c
++++ b/maplabel.c
+@@ -328,7 +328,7 @@ int msAddLabelGroup(mapObj *map, imageObj *image, int layerindex, int classindex
+ }
+ annotext = msShapeGetLabelAnnotation(layerPtr,shape,lbl);
+ if(!annotext) {
+- for(s=0;s<lbl->numstyles;l++) {
++ for(s=0;s<lbl->numstyles;s++) {
+ if(lbl->styles[s]->_geomtransform.type == MS_GEOMTRANSFORM_LABELPOINT)
+ break; /* we have a "symbol only label, so we shouldn't skip this label */
+ }
+diff --git a/mapogcsld.c b/mapogcsld.c
+index a24dc4e..465421d 100644
+--- a/mapogcsld.c
++++ b/mapogcsld.c
+@@ -162,6 +162,12 @@ int msSLDApplySLD(mapObj *map, char *psSLDXML, int iLayer, char *pszStyleLayerNa
+ layerObj *lp = NULL;
+
+ pasLayers = msSLDParseSLD(map, psSLDXML, &nLayers);
++ if( pasLayers == NULL ) {
++ errorObj* psError = msGetErrorObj();
++ if( psError && psError->code != MS_NOERR )
++ return MS_FAILURE;
++ }
++
+ /* -------------------------------------------------------------------- */
+ /* If the same layer is given more that once, we need to */
+ /* duplicate it. */
+@@ -391,10 +397,37 @@ int msSLDApplySLD(mapObj *map, char *psSLDXML, int iLayer, char *pszStyleLayerNa
+ goto sld_cleanup;
+ }
+ } else {
++ lp = GET_LAYER(map, i);
++
++ /* The SLD might have a FeatureTypeConstraint */
++ if( pasLayers[j].filter.type == MS_EXPRESSION )
++ {
++ if( lp->filter.string && lp->filter.type == MS_EXPRESSION )
++ {
++ pszBuffer = msStringConcatenate(NULL, "((");
++ pszBuffer = msStringConcatenate(pszBuffer, lp->filter.string);
++ pszBuffer = msStringConcatenate(pszBuffer, ") AND (");
++ pszBuffer = msStringConcatenate(pszBuffer, pasLayers[j].filter.string);
++ pszBuffer = msStringConcatenate(pszBuffer, "))");
++ msFreeExpression(&lp->filter);
++ msInitExpression(&lp->filter);
++ lp->filter.string = pszBuffer;
++ lp->filter.type = MS_EXPRESSION;
++
++ pszBuffer = NULL;
++ }
++ else
++ {
++ msFreeExpression(&lp->filter);
++ msInitExpression(&lp->filter);
++ lp->filter.string = msStrdup(pasLayers[j].filter.string);
++ lp->filter.type = MS_EXPRESSION;
++ }
++ }
++
+ /*in some cases it would make sense to concatenate all the class
+ expressions and use it to set the filter on the layer. This
+ could increase performace. Will do it for db types layers #2840*/
+- lp = GET_LAYER(map, i);
+ if (lp->filter.string == NULL || (lp->filter.string && lp->filter.type == MS_STRING && !lp->filteritem)) {
+ if (lp->connectiontype == MS_POSTGIS || lp->connectiontype == MS_ORACLESPATIAL || lp->connectiontype == MS_PLUGIN) {
+ if (lp->numclasses > 0) {
+@@ -596,7 +629,15 @@ layerObj *msSLDParseSLD(mapObj *map, char *psSLDXML, int *pnLayers)
+ if (psName && psName->psChild && psName->psChild->pszValue)
+ pasLayers[iLayer].name = msStrdup(psName->psChild->pszValue);
+
+- msSLDParseNamedLayer(psNamedLayer, &pasLayers[iLayer]);
++ if( msSLDParseNamedLayer(psNamedLayer, &pasLayers[iLayer]) != MS_SUCCESS ) {
++ int i;
++ for (i=0; i<=iLayer; i++)
++ freeLayer(&pasLayers[i]);
++ msFree(pasLayers);
++ nLayers = 0;
++ pasLayers = NULL;
++ break;
++ }
+
+ psNamedLayer = psNamedLayer->psNext;
+ iLayer++;
+@@ -708,6 +749,79 @@ void _SLDApplyRuleValues(CPLXMLNode *psRule, layerObj *psLayer,
+
+ }
+
++/************************************************************************/
++/* msSLDGetCommonExpressionFromFilter */
++/* */
++/* Get a commomn expression valid from the filter valid for the */
++/* temporary layer. */
++/************************************************************************/
++static char* msSLDGetCommonExpressionFromFilter(CPLXMLNode* psFilter,
++ layerObj *psLayer)
++{
++ char *pszExpression = NULL;
++ CPLXMLNode *psTmpNextNode = NULL;
++ CPLXMLNode *psTmpNode = NULL;
++ FilterEncodingNode *psNode = NULL;
++ char *pszTmpFilter = NULL;
++ layerObj *psCurrentLayer = NULL;
++ const char *pszWmsName=NULL;
++ const char *key=NULL;
++
++ /* clone the tree and set the next node to null */
++ /* so we only have the Filter node */
++ psTmpNode = CPLCloneXMLTree(psFilter);
++ psTmpNextNode = psTmpNode->psNext;
++ psTmpNode->psNext = NULL;
++ pszTmpFilter = CPLSerializeXMLTree(psTmpNode);
++ psTmpNode->psNext = psTmpNextNode;
++ CPLDestroyXMLNode(psTmpNode);
++
++ if (pszTmpFilter) {
++ psNode = FLTParseFilterEncoding(pszTmpFilter);
++
++ CPLFree(pszTmpFilter);
++ }
++
++ if (psNode) {
++ int j;
++
++ /*preparse the filter for possible gml aliases set on the layer's metada:
++ "gml_NA3DESC_alias" "alias_name" and filter could be
++ <ogc:PropertyName>alias_name</ogc:PropertyName> #3079*/
++ for (j=0; j<psLayer->map->numlayers; j++) {
++ psCurrentLayer = GET_LAYER(psLayer->map, j);
++
++ pszWmsName = msOWSLookupMetadata(&(psCurrentLayer->metadata), "MO", "name");
++
++ if ((psCurrentLayer->name && psLayer->name &&
++ strcasecmp(psCurrentLayer->name, psLayer->name) == 0) ||
++ (psCurrentLayer->group && psLayer->name &&
++ strcasecmp(psCurrentLayer->group, psLayer->name) == 0) ||
++ (psLayer->name && pszWmsName &&
++ strcasecmp(pszWmsName, psLayer->name) == 0))
++ break;
++ }
++ if (j < psLayer->map->numlayers) {
++ /*make sure that the tmp layer has all the metadata that
++ the orinal layer has, allowing to do parsing for
++ such things as gml_attribute_type #3052*/
++ while (1) {
++ key = msNextKeyFromHashTable(&psCurrentLayer->metadata, key);
++ if (!key)
++ break;
++ else
++ msInsertHashTable(&psLayer->metadata, key,
++ msLookupHashTable(&psCurrentLayer->metadata, key));
++ }
++ FLTPreParseFilterForAliasAndGroup(psNode, psLayer->map, j, "G");
++ }
++
++ pszExpression = FLTGetCommonExpression(psNode, psLayer);
++ FLTFreeFilterEncodingNode(psNode);
++ }
++
++ return pszExpression;
++}
+
+ /************************************************************************/
+ /* msSLDParseNamedLayer */
+@@ -719,15 +833,9 @@ int msSLDParseNamedLayer(CPLXMLNode *psRoot, layerObj *psLayer)
+ CPLXMLNode *psFeatureTypeStyle, *psRule, *psUserStyle;
+ CPLXMLNode *psSLDName = NULL, *psNamedStyle=NULL;
+ CPLXMLNode *psElseFilter = NULL, *psFilter=NULL;
+- CPLXMLNode *psTmpNode = NULL;
+- FilterEncodingNode *psNode = NULL;
++ CPLXMLNode *psLayerFeatureConstraints = NULL;
+ int nNewClasses=0, nClassBeforeFilter=0, nClassAfterFilter=0;
+ int nClassAfterRule=0, nClassBeforeRule=0;
+- char *pszTmpFilter = NULL;
+- layerObj *psCurrentLayer = NULL;
+- const char *pszWmsName=NULL;
+- int j=0;
+- const char *key=NULL;
+
+ if (!psRoot || !psLayer)
+ return MS_FAILURE;
+@@ -772,67 +880,10 @@ int msSLDParseNamedLayer(CPLXMLNode *psRoot, layerObj *psLayer)
+ /* -------------------------------------------------------------------- */
+ psFilter = CPLGetXMLNode(psRule, "Filter");
+ if (psFilter && psFilter->psChild && psFilter->psChild->pszValue) {
+- CPLXMLNode *psTmpNextNode = NULL;
+- /* clone the tree and set the next node to null */
+- /* so we only have the Filter node */
+- psTmpNode = CPLCloneXMLTree(psFilter);
+- psTmpNextNode = psTmpNode->psNext;
+- psTmpNode->psNext = NULL;
+- pszTmpFilter = CPLSerializeXMLTree(psTmpNode);
+- psTmpNode->psNext = psTmpNextNode;
+- CPLDestroyXMLNode(psTmpNode);
+-
+- if (pszTmpFilter) {
+- /* nTmp = strlen(psFilter->psChild->pszValue)+17; */
+- /* pszTmpFilter = malloc(sizeof(char)*nTmp); */
+- /* sprintf(pszTmpFilter,"<Filter>%s</Filter>", */
+- /* psFilter->psChild->pszValue); */
+- /* pszTmpFilter[nTmp-1]='\0'; */
+- psNode = FLTParseFilterEncoding(pszTmpFilter);
+-
+- CPLFree(pszTmpFilter);
+- }
+-
+- if (psNode) {
+- char *pszExpression = NULL;
+- int i;
+-
+- /*preparse the filter for possible gml aliases set on the layer's metada:
+- "gml_NA3DESC_alias" "alias_name" and filter could be
+- <ogc:PropertyName>alias_name</ogc:PropertyName> #3079*/
+- for (j=0; j<psLayer->map->numlayers; j++) {
+- psCurrentLayer = GET_LAYER(psLayer->map, j);
+-
+- pszWmsName = msOWSLookupMetadata(&(psCurrentLayer->metadata), "MO", "name");
+-
+- if ((psCurrentLayer->name && psLayer->name &&
+- strcasecmp(psCurrentLayer->name, psLayer->name) == 0) ||
+- (psCurrentLayer->group && psLayer->name &&
+- strcasecmp(psCurrentLayer->group, psLayer->name) == 0) ||
+- (psLayer->name && pszWmsName &&
+- strcasecmp(pszWmsName, psLayer->name) == 0))
+- break;
+- }
+- if (j < psLayer->map->numlayers) {
+- /*make sure that the tmp layer has all the metadata that
+- the orinal layer has, allowing to do parsing for
+- such things as gml_attribute_type #3052*/
+- while (1) {
+- key = msNextKeyFromHashTable(&psCurrentLayer->metadata, key);
+- if (!key)
+- break;
+- else
+- msInsertHashTable(&psLayer->metadata, key,
+- msLookupHashTable(&psCurrentLayer->metadata, key));
+- }
+- FLTPreParseFilterForAliasAndGroup(psNode, psLayer->map, j, "G");
+- }
+-
+- pszExpression = FLTGetCommonExpression(psNode, psLayer);
+- FLTFreeFilterEncodingNode(psNode);
+- psNode = NULL;
+-
+- if (pszExpression) {
++ char* pszExpression = msSLDGetCommonExpressionFromFilter(psFilter,
++ psLayer);
++ if (pszExpression) {
++ int i;
+ nNewClasses =
+ nClassAfterFilter - nClassBeforeFilter;
+ for (i=0; i<nNewClasses; i++) {
+@@ -846,8 +897,6 @@ int msSLDParseNamedLayer(CPLXMLNode *psRoot, layerObj *psLayer)
+ }
+ msFree(pszExpression);
+ pszExpression = NULL;
+- }
+-
+ }
+ }
+ nClassAfterRule = psLayer->numclasses;
+@@ -899,6 +948,47 @@ int msSLDParseNamedLayer(CPLXMLNode *psRoot, layerObj *psLayer)
+ }
+ }
+
++ /* Deal with LayerFeatureConstraints */
++ psLayerFeatureConstraints = CPLGetXMLNode(psRoot, "LayerFeatureConstraints");
++ if( psLayerFeatureConstraints != NULL ) {
++ CPLXMLNode* psIter = psLayerFeatureConstraints->psChild;
++ CPLXMLNode* psFeatureTypeConstraint = NULL;
++ for(; psIter != NULL; psIter = psIter->psNext ) {
++ if( psIter->eType == CXT_Element &&
++ strcmp(psIter->pszValue, "FeatureTypeConstraint") == 0 ) {
++ if( psFeatureTypeConstraint == NULL ) {
++ psFeatureTypeConstraint = psIter;
++ } else {
++ msSetError(MS_WMSERR, "Only one single FeatureTypeConstraint element "
++ "per LayerFeatureConstraints is supported", "");
++ return MS_FAILURE;
++ }
++ }
++ }
++ if( psFeatureTypeConstraint != NULL ) {
++ if( CPLGetXMLNode(psFeatureTypeConstraint, "FeatureTypeName") != NULL ) {
++ msSetError(MS_WMSERR, "FeatureTypeName element is not "
++ "supported in FeatureTypeConstraint", "");
++ return MS_FAILURE;
++ }
++ if( CPLGetXMLNode(psFeatureTypeConstraint, "Extent") != NULL ) {
++ msSetError(MS_WMSERR, "Extent element is not "
++ "supported in FeatureTypeConstraint", "");
++ return MS_FAILURE;
++ }
++ psFilter = CPLGetXMLNode(psFeatureTypeConstraint, "Filter");
++ if (psFilter && psFilter->psChild && psFilter->psChild->pszValue) {
++ char* pszExpression = msSLDGetCommonExpressionFromFilter(psFilter,
++ psLayer);
++ if (pszExpression) {
++ msInitExpression(&psLayer->filter);
++ psLayer->filter.string = pszExpression;
++ psLayer->filter.type = MS_EXPRESSION;
++ }
++ }
++ }
++ }
++
+ return MS_SUCCESS;
+ }
+
+@@ -4714,7 +4804,6 @@ FilterEncodingNode *BuildExpressionTree(char *pszExpression,
+ {
+ int nLength = 0;
+ int nOperators=0;
+- char *pszFinalExpression = NULL;
+ char *pszComparionValue=NULL, *pszAttibuteName=NULL;
+ char *pszAttibuteValue=NULL;
+ char *pszLeftExpression=NULL, *pszRightExpression=NULL, *pszOperator=NULL;
+@@ -4722,9 +4811,6 @@ FilterEncodingNode *BuildExpressionTree(char *pszExpression,
+ if (!pszExpression || (nLength = strlen(pszExpression)) <=0)
+ return NULL;
+
+- pszFinalExpression = (char *)malloc(sizeof(char)*(nLength+1));
+- pszFinalExpression[0] = '\0';
+-
+ /* -------------------------------------------------------------------- */
+ /* First we check how many logical operators are there : */
+ /* - if none : It means It is a comparision operator (like =, */
+@@ -4845,7 +4931,6 @@ FilterEncodingNode *BuildExpressionTree(char *pszExpression,
+
+ return psNode;
+ } else {
+- msFree(pszFinalExpression);
+ return NULL;
+ }
+ }
+diff --git a/mapogr.cpp b/mapogr.cpp
+index 1708d1c..07acdba 100644
+--- a/mapogr.cpp
++++ b/mapogr.cpp
+@@ -901,6 +901,14 @@ static char **msOGRGetValues(layerObj *layer, OGRFeatureH hFeature)
+ msDebug(MSOGR_SYMBOLPARAMNAME " = \"%s\"\n", values[i]);
+ }
+ else {
++ msFreeCharArray(values,i);
++
++ OGR_SM_Destroy(hStyleMgr);
++ OGR_ST_Destroy(hLabelStyle);
++ OGR_ST_Destroy(hPenStyle);
++ OGR_ST_Destroy(hBrushStyle);
++ OGR_ST_Destroy(hSymbolStyle);
++
+ msSetError(MS_OGRERR,"Invalid field index!?!","msOGRGetValues()");
+ return(NULL);
+ }
+diff --git a/mapogroutput.c b/mapogroutput.c
+index 770dd3f..c307fc5 100644
+--- a/mapogroutput.c
++++ b/mapogroutput.c
+@@ -175,8 +175,15 @@ static void msOGRCleanupDS( const char *datasource_name )
+ char **file_list;
+ char path[MS_MAXPATHLEN];
+ int i;
++ VSIStatBufL sStatBuf;
++
++ if( VSIStatL( datasource_name, &sStatBuf ) != 0 )
++ return;
++ if( VSI_ISDIR( sStatBuf.st_mode ) )
++ strlcpy( path, datasource_name, sizeof(path) );
++ else
++ strlcpy( path, CPLGetPath( datasource_name ), sizeof(path) );
+
+- strlcpy( path, CPLGetPath( datasource_name ), sizeof(path) );
+ file_list = CPLReadDir( path );
+
+ for( i = 0; file_list != NULL && file_list[i] != NULL; i++ ) {
+@@ -195,11 +202,7 @@ static void msOGRCleanupDS( const char *datasource_name )
+ if( VSI_ISREG( sStatBuf.st_mode ) ) {
+ VSIUnlink( full_filename );
+ } else if( VSI_ISDIR( sStatBuf.st_mode ) ) {
+- char fake_ds_name[MS_MAXPATHLEN];
+- strlcpy( fake_ds_name,
+- CPLFormFilename( full_filename, "abc.dat", NULL ),
+- sizeof(fake_ds_name) );
+- msOGRCleanupDS( fake_ds_name );
++ msOGRCleanupDS( full_filename );
+ }
+ }
+
+@@ -681,6 +684,7 @@ int msOGRWriteFromQuery( mapObj *map, outputFormatObj *format, int sendheaders )
+ char **layer_options = NULL;
+ char **file_list = NULL;
+ int iLayer, i;
++ int bDataSourceNameIsRequestDir = FALSE;
+
+ /* -------------------------------------------------------------------- */
+ /* Fetch the output format driver. */
+@@ -805,26 +809,15 @@ int msOGRWriteFromQuery( mapObj *map, outputFormatObj *format, int sendheaders )
+ if( EQUAL(CPLGetExtension(datasource_name), "") ) {
+ strcat(datasource_name, ".dat");
+ }
+- else if( EQUAL(CPLGetExtension(datasource_name), "shp") )
+- {
+- int nNonEmptyLayers = 0;
+- for( iLayer = 0; iLayer < map->numlayers; iLayer++ ) {
+- layerObj *layer = GET_LAYER(map, iLayer);
+- if( !layer->resultcache || layer->resultcache->numresults == 0 )
+- continue;
+- nNonEmptyLayers ++;
+- }
+- /* The shapefile driver will be somehow confused if trying to create */
+- /* a datasource named foo.shp when there are several layers in it */
+- /* It would create the first layer as datasource_name.shp and the next ones */
+- /* with layer_name.shp */
+- /* so remove the shp extension in that case, so that all layers are */
+- /* exported with their names */
+- if( nNonEmptyLayers > 1 )
+- {
+- *strrchr(datasource_name, '.') = '\0';
+- }
+- }
++ }
++
++ /* Shapefile and MapInfo driver only properly work with multiple layers */
++ /* if the output dataset name is a directory */
++ if( EQUAL(format->driver+4, "ESRI Shapefile") ||
++ EQUAL(format->driver+4, "MapInfo File") )
++ {
++ bDataSourceNameIsRequestDir = TRUE;
++ strcpy(datasource_name, request_dir);
+ }
+ }
+ else
+@@ -959,9 +952,9 @@ int msOGRWriteFromQuery( mapObj *map, outputFormatObj *format, int sendheaders )
+ OGR_DS_Destroy( hDS );
+ msOGRCleanupDS( datasource_name );
+ msSetError( MS_MISCERR,
+- "OGR CreateDataSource failed for '%s' with driver '%s'.",
++ "OGR OGR_DS_CreateLayer failed for layer '%s' with driver '%s'.",
+ "msOGRWriteFromQuery()",
+- datasource_name,
++ layer->name,
+ format->driver+4 );
+ return MS_FAILURE;
+ }
+@@ -1139,8 +1132,13 @@ int msOGRWriteFromQuery( mapObj *map, outputFormatObj *format, int sendheaders )
+ } else {
+ char datasource_path[MS_MAXPATHLEN];
+
+- strncpy( datasource_path, CPLGetPath( datasource_name ), MS_MAXPATHLEN-1 );
+- file_list = msOGRRecursiveFileList( datasource_path );
++ if( bDataSourceNameIsRequestDir )
++ file_list = msOGRRecursiveFileList( datasource_name );
++ else
++ {
++ strncpy( datasource_path, CPLGetPath( datasource_name ), MS_MAXPATHLEN-1 );
++ file_list = msOGRRecursiveFileList( datasource_path );
++ }
+ }
+
+ /* -------------------------------------------------------------------- */
+diff --git a/mapproject.c b/mapproject.c
+index 49ebf31..fb234ad 100644
+--- a/mapproject.c
++++ b/mapproject.c
+@@ -1030,6 +1030,10 @@ static projectionObj* msGetProjectNormalized( const projectionObj* p )
+ memmove(pnew->args + i, pnew->args + i + 1,
+ sizeof(char*) * (pnew->numargs - 1 -i ));
+ }
++ else
++ {
++ msFree(pnew->args[i]);
++ }
+ pnew->numargs --;
+ i --;
+ continue;
+diff --git a/maprendering.c b/maprendering.c
+index 4a50d62..7ee3692 100644
+--- a/maprendering.c
++++ b/maprendering.c
+@@ -1024,7 +1024,6 @@ int msDrawTextSymbol(mapObj *map, imageObj *image, pointObj labelPnt, textSymbol
+ if(MS_VALID_COLOR(ts->label->outlinecolor))
+ oc = &ts->label->outlinecolor;
+ ow = MS_NINT((double)ts->label->outlinewidth * ((double)ts->textpath->glyph_size / (double)ts->label->size));
+- msDebug("setting outlinewidth to %d (%d, %d, %d)\n",ow,ts->label->outlinewidth, ts->textpath->glyph_size, ts->label->size);
+ if(!renderer->renderGlyphs) return MS_FAILURE;
+ return renderer->renderGlyphs(image,ts->textpath,c,oc,ow);
+
+diff --git a/mapscript/csharp/examples/drawquery.cs b/mapscript/csharp/examples/drawquery.cs
+index 457320f..e78d8a7 100644
+--- a/mapscript/csharp/examples/drawquery.cs
++++ b/mapscript/csharp/examples/drawquery.cs
+@@ -55,7 +55,7 @@ class DrawQuery
+ QueryByAttribute(args[1], map, ZoomToResults);
+
+ map.querymap.status = mapscript.MS_ON;
+- map.querymap.color.setRGB(0,0,255);
++ map.querymap.color.setRGB(0,0,255,255);
+ map.querymap.style = (int)MS_QUERYMAP_STYLES.MS_HILITE;
+
+ try
+diff --git a/mapserver-config-version.cmake.in b/mapserver-config-version.cmake.in
+new file mode 100644
+index 0000000..251e401
+--- /dev/null
++++ b/mapserver-config-version.cmake.in
+@@ -0,0 +1,11 @@
++set(PACKAGE_VERSION "@MapServer_VERSION_STRING@")
++
++# Check whether the requested PACKAGE_FIND_VERSION is compatible
++if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}")
++ set(PACKAGE_VERSION_COMPATIBLE FALSE)
++else()
++ set(PACKAGE_VERSION_COMPATIBLE TRUE)
++ if ("${PACKAGE_VERSION}" VERSION_EQUAL "${PACKAGE_FIND_VERSION}")
++ set(PACKAGE_VERSION_EXACT TRUE)
++ endif()
++endif()
+diff --git a/mapserver-config.cmake.in b/mapserver-config.cmake.in
+new file mode 100644
+index 0000000..91828d8
+--- /dev/null
++++ b/mapserver-config.cmake.in
+@@ -0,0 +1,18 @@
++# - Config file for the mapserver package
++# It defines the following variables
++# MAPSERVER_INCLUDE_DIRS - include directories for mapserver
++# MAPSERVER_LIBRARIES - libraries to link against
++# MAPSERVER_EXECUTABLES - executables build for mapserver
++
++# Compute paths
++get_filename_component(MAPSERVER_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH)
++set(MAPSERVER_INCLUDE_DIRS "@CONF_INCLUDE_DIRS@")
++
++# Our library dependencies (contains definitions for IMPORTED targets)
++if(NOT TARGET mapserver AND NOT MapServer_BINARY_DIR)
++ include("${MAPSERVER_CMAKE_DIR}/mapserverTargets.cmake")
++endif()
++
++# These are IMPORTED targets created by mapserverTargets.cmake
++set(MAPSERVER_LIBRARIES mapserver)
++set(MAPSERVER_EXECUTABLES sortshp shptree shptreevis msencrypt legend scalebar tile4ms shptreetst shp2img mapserv)
+diff --git a/mapshape.c b/mapshape.c
+index 75ab867..f1f71a5 100644
+--- a/mapshape.c
++++ b/mapshape.c
+@@ -268,6 +268,7 @@ SHPHandle msSHPOpen( const char * pszLayer, const char * pszAccess )
+ psSHP->fpSHX = fopen(pszFullname, pszAccess );
+ }
+ if( psSHP->fpSHX == NULL ) {
++ fclose(psSHP->fpSHP);
+ msFree(pszBasename);
+ msFree(pszFullname);
+ msFree(psSHP);
+diff --git a/maptemplate.c b/maptemplate.c
+index 6488292..d091bdf 100644
+--- a/maptemplate.c
++++ b/maptemplate.c
+@@ -1951,13 +1951,11 @@ static int processShpxyTag(layerObj *layer, char **line, shapeObj *shape)
+
+ double scale_x, scale_y;
+
+-
+ char *projectionString=NULL;
+
+ shapeObj tShape;
+ char *coords=NULL, point[128];
+
+-
+ if(!*line) {
+ msSetError(MS_WEBERR, "Invalid line pointer.", "processShpxyTag()");
+ return(MS_FAILURE);
+@@ -2059,7 +2057,6 @@ static int processShpxyTag(layerObj *layer, char **line, shapeObj *shape)
+ if(argValue)
+ if(strcasecmp(argValue,"true") == 0) centroid = MS_TRUE;
+
+-
+ argValue = msLookupHashTable(tagArgs, "proj");
+ if(argValue) projectionString = argValue;
+ }
+@@ -2121,9 +2118,7 @@ static int processShpxyTag(layerObj *layer, char **line, shapeObj *shape)
+
+ switch(tShape.type) {
+ case(MS_SHAPE_POINT):
+- /* at this point we only convert the first point of the first shape */
+- tShape.line[0].point[0].x = MS_MAP2IMAGE_X(tShape.line[0].point[0].x, layer->map->extent.minx, layer->map->cellsize);
+- tShape.line[0].point[0].y = MS_MAP2IMAGE_Y(tShape.line[0].point[0].y, layer->map->extent.maxy, layer->map->cellsize);
++ /* no clipping necessary */
+ break;
+ case(MS_SHAPE_LINE):
+ msClipPolylineRect(&tShape, layer->map->extent);
+diff --git a/mapuvraster.c b/mapuvraster.c
+index 6cbfd33..52d92a5 100644
+--- a/mapuvraster.c
++++ b/mapuvraster.c
+@@ -91,6 +91,7 @@ static int msUVRASTERLayerInitItemInfo(layerObj *layer)
+ uvRasterLayerInfo *uvlinfo = (uvRasterLayerInfo *) layer->layerinfo;
+ int i;
+ int *itemindexes;
++ int failed=0;
+
+ if (layer->numitems == 0)
+ return MS_SUCCESS;
+@@ -115,7 +116,7 @@ static int msUVRASTERLayerInitItemInfo(layerObj *layer)
+ /* OGR style strings. We use special attribute snames. */
+ if (EQUAL(layer->items[i], MSUVRASTER_ANGLE))
+ itemindexes[i] = MSUVRASTER_ANGLEINDEX;
+- if (EQUAL(layer->items[i], MSUVRASTER_MINUS_ANGLE))
++ else if (EQUAL(layer->items[i], MSUVRASTER_MINUS_ANGLE))
+ itemindexes[i] = MSUVRASTER_MINUSANGLEINDEX;
+ else if (EQUAL(layer->items[i], MSUVRASTER_LENGTH))
+ itemindexes[i] = MSUVRASTER_LENGTHINDEX;
+@@ -125,17 +126,17 @@ static int msUVRASTERLayerInitItemInfo(layerObj *layer)
+ itemindexes[i] = MSUVRASTER_UINDEX;
+ else if (EQUAL(layer->items[i], MSUVRASTER_V))
+ itemindexes[i] = MSUVRASTER_VINDEX;
+-
+- if(itemindexes[i] == -1) {
++ else {
++ itemindexes[i] = -1;
+ msSetError(MS_OGRERR,
+ "Invalid Field name: %s",
+ "msUVRASTERLayerInitItemInfo()",
+ layer->items[i]);
+- return(MS_FAILURE);
++ failed=1;
+ }
+ }
+
+- return(MS_SUCCESS);
++ return failed ? (MS_FAILURE) : (MS_SUCCESS);
+ }
+
+
+@@ -234,7 +235,7 @@ int msUVRASTERLayerClose(layerObj *layer)
+ if( uvlinfo != NULL ) {
+ uvlinfo->refcount--;
+
+- if( uvlinfo->refcount < 0 )
++ if( uvlinfo->refcount < 1 )
+ msUVRasterLayerInfoFree( layer );
+ }
+ return MS_SUCCESS;
+@@ -278,9 +279,11 @@ static char **msUVRASTERGetValues(layerObj *layer, float *u, float *v)
+ if(layer->numitems == 0)
+ return(NULL);
+
+- if(!layer->iteminfo) /* Should not happen... but just in case! */
++ if(!layer->iteminfo) { /* Should not happen... but just in case! */
+ if (msUVRASTERLayerInitItemInfo(layer) != MS_SUCCESS)
+ return NULL;
++ itemindexes = (int*)layer->iteminfo; /* reassign after malloc */
++ }
+
+ if((values = (char **)malloc(sizeof(char *)*layer->numitems)) == NULL) {
+ msSetError(MS_MEMERR, NULL, "msUVRASTERGetValues()");
+@@ -323,7 +326,9 @@ static char **msUVRASTERGetValues(layerObj *layer, float *u, float *v)
+ } else if (itemindexes[i] == MSUVRASTER_VINDEX) {
+ snprintf(tmp, 100, "%f",*v);
+ values[i] = msStrdup(tmp);
+- }
++ } else {
++ values[i] = NULL;
++ }
+ }
+
+ return values;
+@@ -456,6 +461,13 @@ int msUVRASTERLayerWhichShapes(layerObj *layer, rectObj rect, int isQuery)
+ if (msDrawRasterLayerLow(map_tmp, layer, image_tmp, NULL ) == MS_FAILURE) {
+ msSetError(MS_MISCERR, "Unable to draw raster data.", "msUVRASTERLayerWhichShapes()");
+ layer->mask = saved_layer_mask;
++
++ if (alteredProcessing != NULL) {
++ layer->processing = savedProcessing;
++ CSLDestroy(alteredProcessing);
++ }
++ msFreeMap(map_tmp);
++ msFreeImage(image_tmp);
+ return MS_FAILURE;
+ }
+
+@@ -477,7 +489,7 @@ int msUVRASTERLayerWhichShapes(layerObj *layer, rectObj rect, int isQuery)
+ }
+
+ if (uvlinfo->v) {
+- for (i=0; i<uvlinfo->height; ++i) {
++ for (i=0; i<uvlinfo->width; ++i) {
+ free(uvlinfo->v[i]);
+ }
+ free(uvlinfo->v);
+diff --git a/mapv8.cpp b/mapv8.cpp
+index c3b5244..01b5d9a 100644
+--- a/mapv8.cpp
++++ b/mapv8.cpp
+@@ -92,6 +92,8 @@ static Handle<Value> msV8ReadFile(V8Context *v8context, const char *path)
+ for (int i = 0; i < size;) {
+ int read = static_cast<int>(fread(&chars[i], 1, size - i, file));
+ if (read == 0) {
++ delete [] chars;
++ fclose(file);
+ msDebug("msV8ReadFile: error while reading file '%s'\n", path);
+ return Undefined();
+ }
+diff --git a/mapwcs20.c b/mapwcs20.c
+index ac2fb89..2c1e3ca 100644
+--- a/mapwcs20.c
++++ b/mapwcs20.c
+@@ -3982,10 +3982,10 @@ static int msWCSSetFormatParams20(outputFormatObj* format, char** format_options
+ else if (EQUAL(key, "geotiff:tiling") && is_geotiff) {
+ /* TILED=YES */
+ if (EQUAL(value, "true")) {
+- msSetOutputFormatOption(format, "TILING", "YES");
++ msSetOutputFormatOption(format, "TILED", "YES");
+ }
+ else if (EQUAL(value, "false")) {
+- msSetOutputFormatOption(format, "TILING", "NO");
++ msSetOutputFormatOption(format, "TILED", "NO");
+ }
+ else {
+ msSetError(MS_WCSERR, "Invalid boolean value '%s'.",
+diff --git a/mapwms.c b/mapwms.c
+index 578c71e..96389d0 100644
+--- a/mapwms.c
++++ b/mapwms.c
+@@ -333,7 +333,7 @@ void msWMSPrepareNestedGroups(mapObj* map, int nVersion, char*** nestedGroups, i
+ //Create array to hold unique groups
+ int maxgroups = 2000;
+ int maxgroupiter = 1;
+- char** uniqgroups = malloc(maxgroups * sizeof(char*));
++ char** uniqgroups = msSmallMalloc(maxgroups * sizeof(char*));
+ int uniqgroupcount = 0;
+
+
+@@ -391,6 +391,9 @@ void msWMSPrepareNestedGroups(mapObj* map, int nVersion, char*** nestedGroups, i
+ }
+ }
+ }
++
++ /* free uniqgroups */
++ free(uniqgroups);
+ }
+
+
+diff --git a/scalebar.c b/scalebar.c
+index 8c7167b..67ba5f4 100644
+--- a/scalebar.c
++++ b/scalebar.c
+@@ -36,6 +36,7 @@ int main(int argc, char *argv[])
+ mapObj *map=NULL;
+ imageObj *image = NULL;
+
++ msSetup();
+ if(argc > 1 && strcmp(argv[1], "-v") == 0) {
+ printf("%s\n", msGetVersion());
+ exit(0);
+diff --git a/xmlmapfile/mapfile.xsd b/xmlmapfile/mapfile.xsd
+index 2d778bc..07f73e7 100644
+--- a/xmlmapfile/mapfile.xsd
++++ b/xmlmapfile/mapfile.xsd
+@@ -346,9 +346,9 @@
+ </xs:simpleType>
+ </xs:union>
+ </xs:simpleType>
+- <xs:element name="maxScaleDenom" type="xs:double" minOccurs="0"/>
+- <xs:element name="minScaleDenom" type="xs:double" minOccurs="0"/>
+ </xs:element>
++ <xs:element name="maxScaleDenom" type="xs:double" minOccurs="0"/>
++ <xs:element name="minScaleDenom" type="xs:double" minOccurs="0"/>
+ <xs:element name="Style" type="ms:Style" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="text" type="xs:string" minOccurs="0"/>
+ <xs:element name="wrap" type="xs:string" minOccurs="0"/>